> For the complete documentation index, see [llms.txt](https://docs.nexusglobalpayments.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nexusglobalpayments.org/nexus-operation-apis/track-and-trace.md).

# Track And Trace

Track and Trace: the latest known state of a single transaction by UETR. Served on the Payment Processing host under payment API authentication, not the Operations reporting path.

## Track and trace a payment

> Return the current status of a single transaction by UETR, to help the IPSO answer a customer enquiry. Use it when a customer asks about a payment and the IPSO has sent the pacs.008 but has not received the pacs.002; where the IPSO already holds the pacs.002 it answers from its own records. Exactly one UETR per request: no bulk or list queries. The published request rate is shared across the Track and Trace screen and API callers, and exceeding it returns 429 RATE\_LIMIT\_EXCEEDED with Retry-After. This is not a polling service or a way to reconstruct the Operational Data Feed.\
> \
> Unlike the other operations in this document, Track and Trace uses the Payment Processing authentication, host and network path rather than the separate Operations reporting ones: a payment-realm certificate-bound access token, mutual TLS, and an RFC 9421 message signature produced with the IPSO's payment signing key pair rather than its Operations signing key pair. Nexus signs the 200 response, and the IPSO verifies it before use. Operations reporting tokens are not accepted.\
> \
> The enquiry does not update the IPSO's records and does not replace pacs.028. Where a pacs.002 does not arrive, the IPSO must still send a pacs.028 and process the resulting pacs.002 to close the payment in its own journal. The IPSO is identified from its credentials and no participant identifier is passed in the request; a PSP enquiry goes to its IPSO, which queries Nexus. Nexus holds only the UETR, so the IPSO maps its own domestic reference to it.

```json
{"openapi":"3.1.0","info":{"title":"Nexus Operations IPSO API","version":"0.4.0"},"tags":[{"name":"TrackAndTrace","description":"Track and Trace: the latest known state of a single transaction by UETR. Served on the Payment Processing host under payment API authentication, not the Operations reporting path."}],"servers":[{"url":"https://{environment}.payments.nexus.net","description":"Track and Trace is served on the Payment Processing host, not the Operations reporting host, because it reads live payment records and uses payment API authentication.","variables":{"environment":{"default":"prod","enum":["pat","prod"],"description":"Deployment environment subdomain."}}}],"security":[{"paymentsOAuth":["trackandtrace.read"],"mutualTLS":[]}],"components":{"securitySchemes":{"paymentsOAuth":{"type":"oauth2","description":"Payment Processing client-credentials access token, used only by Track and Trace. It is issued by the payment authorization server, not the Operations one, and Operations reporting tokens are not accepted on this operation and vice versa. Present the payment client certificate at token issuance and verify its SHA-256 thumbprint against cnf.x5t#S256 on every call. Every request additionally carries an RFC 9421 message signature (Signature-Input, Signature) produced with the IPSO's payment signing key pair, not its Operations signing key pair. The scope name is a publication gate.","flows":{"clientCredentials":{"tokenUrl":"https://auth.nexus.net/realms/nexus/protocol/openid-connect/token","scopes":{"trackandtrace.read":"Read the latest known state of a single transaction the IPSO is party to, by UETR"}}}}},"schemas":{"Uetr":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},"TrackAndTraceResult":{"description":"Latest known state for one transaction within the retained history window, typically available within seconds. This lookup reads live payment records; it does not change payment records and is not for polling or bulk retrieval.","allOf":[{"$ref":"#/components/schemas/TransactionState"}],"type":"object","unevaluatedProperties":false,"required":["authoritative","dataAsOf","dataQuality"],"properties":{"authoritative":{"const":false},"dataAsOf":{"type":"string","format":"date-time"},"dataQuality":{"$ref":"#/components/schemas/DataQuality"}}},"TransactionState":{"type":"object","required":["uetr","status","statusSource","acceptedAt","updatedAt"],"allOf":[{"if":{"required":["status"],"properties":{"status":{"const":"PDNG"}}},"then":{"not":{"required":["finalStatusAt"]}},"else":{"required":["finalStatusAt"],"not":{"required":["pendingReason"]}}},{"if":{"required":["status"],"properties":{"status":{"const":"RJCT"}}},"then":{"required":["rejectionReason"]},"else":{"not":{"required":["rejectionReason"]}}}],"description":"Optional facts are omitted if unavailable, never fabricated. Status rules: finalStatusAt is present for ACCC, RJCT and BLCK and absent for PDNG; rejectionReason is present only for RJCT; pendingReason only for PDNG. No raw messages, customer PII or full event history.","properties":{"uetr":{"$ref":"#/components/schemas/Uetr"},"status":{"$ref":"#/components/schemas/PaymentStatus"},"statusSource":{"$ref":"#/components/schemas/StatusSource"},"acceptedAt":{"type":"string","format":"date-time","description":"The instant Nexus recorded the transaction as accepted. It assigns the Nexus Day and is the basis of the date filters; pending age is measured from it. No camt.054 counterpart."},"updatedAt":{"type":"string","format":"date-time","description":"Timestamp of the latest source payment-state update."},"finalStatusAt":{"type":"string","format":"date-time","description":"Present for ACCC, RJCT and BLCK; absent for PDNG."},"rejectionReason":{"$ref":"#/components/schemas/Reason","description":"Present only for RJCT, where it is required. camt.054 carries the status code but no status reason, so this fact has no counterpart in the file."},"pendingReason":{"$ref":"#/components/schemas/PendingReason","description":"Only for current PDNG. Omitted for any other status and whenever the reason is unknown. camt.054 carries the status code but no status reason, so this fact has no counterpart in the file."}}},"PaymentStatus":{"type":"string","enum":["ACCC","RJCT","PDNG","BLCK"],"description":"Nexus-observed source state, not a domestic balance or booking. The same values as camt.054 Ntry/Sts/Prtry; the file does not use Ntry/Sts/Cd. ACWP is received by Nexus but never sent, so it does not appear in this feed or in report totals."},"StatusSource":{"type":"string","enum":["NEXUS","DESTINATION"]},"Reason":{"type":"object","additionalProperties":false,"required":["code","description"],"properties":{"code":{"type":"string","minLength":1},"description":{"type":"string","minLength":1,"description":"Approved PII-free reason text, not raw participant/customer free text."}}},"PendingReason":{"type":"object","additionalProperties":false,"required":["code","description"],"description":"Why the payment is currently PDNG. Present only when the reason is known; absence is a missing fact, never an inferred outcome. Reporting classifies the reason from source facts and does not change payment state.","properties":{"code":{"$ref":"#/components/schemas/PendingReasonCode"},"description":{"type":"string","minLength":1,"description":"Approved PII-free reason text, not raw participant/customer free text."},"destinationReasonCode":{"type":"string","minLength":1,"description":"ISO 20022 StsRsnInf/Rsn/Cd exactly as supplied by the destination IPSO on its interim pacs.002. Omitted whenever the destination supplied no reason, and only ever present with code DESTINATION_PROCESSING. Never populated by Nexus from its own classification."}}},"PendingReasonCode":{"type":"string","enum":["AWAITING_DESTINATION_RESPONSE","DESTINATION_DELIVERY_UNCONFIRMED","DESTINATION_UNREACHABLE","UNDER_INVESTIGATION","INVALID_STATUS_RECEIVED","DESTINATION_PROCESSING"],"description":"Closed set of reasons a payment is currently PDNG. No value implies finality, a rejection or a completed payment, and none of them is a payment status in its own right. The first five are Nexus-observed (statusSource NEXUS); DESTINATION_PROCESSING is reported by the destination IPSO (statusSource DESTINATION). The set is closed: a response never carries a value outside it.\n\n| Code | Meaning |\n| --- | --- |\n| AWAITING_DESTINATION_RESPONSE | Dispatched to the destination IPSO; no status returned and the settlement timer has not expired. |\n| DESTINATION_DELIVERY_UNCONFIRMED | Delivery to the destination IPSO could not be confirmed after the retry policy was exhausted. Delivery is uncertain, not refused. |\n| DESTINATION_UNREACHABLE | Persistent connectivity, authentication or routing failure to the destination IPSO. |\n| UNDER_INVESTIGATION | The settlement timer expired and the enquiry cadence is running. This remains the reason for as long as enquiry continues, including after the investigation window closes; internal escalation and ticketing do not change it. |\n| INVALID_STATUS_RECEIVED | A destination status message arrived but failed validation, so no status was applied. A valid status message is still awaited. |\n| DESTINATION_PROCESSING | The destination IPSO reported the payment as still in progress. |"},"DataQuality":{"type":"string","enum":["complete","partial","stale"]},"Error":{"type":"object","additionalProperties":false,"required":["statusCode","reasonCode","name","description"],"description":"Payment Processing-compatible rejection envelope. RJCT concerns this API request, not a payment state. Reason code and name must match the defined pair. Description is PII-free and does not reveal unauthorised object existence.","properties":{"statusCode":{"const":"RJCT"},"reasonCode":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","minLength":1}},"oneOf":[{"properties":{"reasonCode":{"const":"TE001"},"name":{"const":"INVALID_REQUEST"}}},{"properties":{"reasonCode":{"const":"TE099"},"name":{"const":"INTERNAL_ERROR"}}},{"properties":{"reasonCode":{"const":"AE001"},"name":{"const":"AUTH_TOKEN_MISSING"}}},{"properties":{"reasonCode":{"const":"AE002"},"name":{"const":"AUTH_TOKEN_INVALID"}}},{"properties":{"reasonCode":{"const":"AE003"},"name":{"const":"MTLS_AUTH_FAILED"}}},{"properties":{"reasonCode":{"const":"AE004"},"name":{"const":"ACCESS_DENIED"}}},{"properties":{"reasonCode":{"const":"AE005"},"name":{"const":"MESSAGE_SIGNATURE_INVALID"}}},{"properties":{"reasonCode":{"const":"BE901"},"name":{"const":"REPORT_NOT_FOUND"}}},{"properties":{"reasonCode":{"const":"BE902"},"name":{"const":"REPORT_NOT_READY"}}},{"properties":{"reasonCode":{"const":"BE903"},"name":{"const":"REPORT_OUTSIDE_RETRIEVAL_WINDOW"}}},{"properties":{"reasonCode":{"const":"BE904"},"name":{"const":"TRANSACTION_NOT_FOUND"}}},{"properties":{"reasonCode":{"const":"BE905"},"name":{"const":"RANGE_TOO_WIDE"}}},{"properties":{"reasonCode":{"const":"BE906"},"name":{"const":"QUERY_TOO_LARGE"}}},{"properties":{"reasonCode":{"const":"BE907"},"name":{"const":"RESULT_TOO_LARGE"}}},{"properties":{"reasonCode":{"const":"BE908"},"name":{"const":"RATE_LIMIT_EXCEEDED"}}},{"properties":{"reasonCode":{"const":"BE909"},"name":{"const":"CONCURRENCY_LIMIT_EXCEEDED"}}},{"properties":{"reasonCode":{"const":"BE910"},"name":{"const":"DAILY_ALLOWANCE_EXCEEDED"}}},{"properties":{"reasonCode":{"const":"BE911"},"name":{"const":"IDENTICAL_QUERY_TOO_SOON"}}},{"properties":{"reasonCode":{"const":"BE912"},"name":{"const":"IDEMPOTENCY_KEY_CONFLICT"}}}]}},"parameters":{"SignatureInputBodyless":{"name":"Signature-Input","in":"header","required":true,"description":"RFC 9421 signature metadata for a request without a body, per the Nexus HTTP Message Signature Profile v1 (RFC 9421, RFC 9530). One dictionary member labelled `nexus` whose covered components are exactly `\"@method\" \"@authority\" \"@path\" \"@query\"`, followed by `\"if-none-match\"` when that header is sent. `@query` is always covered; an empty query serialises as `?`, so query parameters cannot be added or removed undetected. Signature parameters, emitted in this order: `created` and `expires` (Unix seconds; `expires` = `created` + 300; the receiver rejects `created` more than ±5 minutes from its clock or a signature past `expires`), `keyid` (base64url SHA-256 thumbprint of the signer's signing public key, registered at onboarding; a missing, unknown, expired or revoked key id is rejected - never resolved to a default key), `alg` (always `rsa-pss-sha512`) and `tag` (always `nexus-v1`). The signature parameters are signed through the `@signature-params` line of the signature base. A missing, malformed or non-conforming value is rejected with AE005.","schema":{"type":"string","maxLength":512,"pattern":"^nexus=\\(\"@method\" \"@authority\" \"@path\" \"@query\"( \"if-none-match\")?\\);created=[0-9]{1,15};expires=[0-9]{1,15};keyid=\"[A-Za-z0-9_-]{43}\";alg=\"rsa-pss-sha512\";tag=\"nexus-v1\"$"}},"Signature":{"name":"Signature","in":"header","required":true,"description":"RFC 9421 signature value: one dictionary member labelled `nexus` holding an RFC 8941 byte sequence - the **standard base64** (not base64url) RSASSA-PSS signature using SHA-512 (`rsa-pss-sha512`), computed over the RFC 9421 signature base built from the components and parameters declared in `Signature-Input`. Produced with the sender's own signing private key; the receiver verifies it against the sender's registered signing public key resolved from `keyid`. With the minimum RSA-3072 key the signature is 384 bytes, i.e. 512 base64 characters. A missing, malformed or non-verifying signature is rejected with AE005. The signing key depends on the API path: operations on the Operations host are signed with the IPSO's Operations signing key pair, and Track and Trace, which uses the Payment Processing security model, with the IPSO's payment signing key pair. A key registered for the other path does not verify and is rejected with AE005.","schema":{"type":"string","minLength":520,"maxLength":1400,"pattern":"^nexus=:[A-Za-z0-9+/]+={0,2}:$"}}},"headers":{"NoStore":{"description":"Prevent HTTP caching of participant responses and signed URLs. Authorised processing and retention of retrieved business data in IPSO systems is governed separately.","schema":{"type":"string","const":"no-store"}},"ResponseSignatureInput":{"description":"RFC 9421 signature metadata for a GET response, per the Nexus HTTP Message Signature Profile v1 (RFC 9421, RFC 9530). Signed by Nexus with its signing private key for this API path (the Nexus Operations signing key on the Operations host). Covered components: `\"@status\" \"content-type\" \"content-digest\"` on 200, or `\"@status\" \"etag\"` on 304, followed in both cases by the request-bound components `\"@method\";req \"@path\";req \"@query\";req`, which tie the response to the resource that was requested. Same `created`, `expires`, `keyid`, `alg` and `tag` rules as requests. The client MUST verify the response signature before using the response and MUST discard a response that fails verification.","required":true,"schema":{"type":"string","maxLength":512,"pattern":"^nexus=\\(\"@status\" (\"content-type\" \"content-digest\"|\"etag\") \"@method\";req \"@path\";req \"@query\";req\\);created=[0-9]{1,15};expires=[0-9]{1,15};keyid=\"[A-Za-z0-9_-]{43}\";alg=\"rsa-pss-sha512\";tag=\"nexus-v1\"$"}},"ResponseSignature":{"description":"RFC 9421 response signature: one dictionary member labelled `nexus` holding the standard base64 `rsa-pss-sha512` signature produced by the responding server over the signature base declared in the response `Signature-Input`. Verified by the client against the server's registered signing public key.","required":true,"schema":{"type":"string","minLength":520,"maxLength":1400,"pattern":"^nexus=:[A-Za-z0-9+/]+={0,2}:$"}},"ResponseContentDigest":{"description":"RFC 9530 SHA-512 digest of the exact response body bytes, covered by the response signature.","required":true,"schema":{"type":"string","pattern":"^sha-512=:[A-Za-z0-9+/]{86}==:$"}},"RetryAfter":{"description":"Mandatory on every policy 429 and on 409 REPORT_NOT_READY. Positive delay-seconds, rounded up to the earliest permitted retry; where several controls block the request, the longest known blocking delay is returned. A concurrency-only rejection does not reserve a slot. Honour this value as a minimum before bounded exponential backoff with jitter.","required":true,"schema":{"type":"integer","minimum":1}}},"responses":{"BadRequest":{"description":"400 TE001 INVALID_REQUEST. Reject malformed, repeated/unknown parameters, unsupported query modes, invalid dates or identifiers. Do not retry unchanged.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"properties":{"name":{"const":"INVALID_REQUEST"}}}]}}}},"Unauthorized":{"description":"401 AE001 AUTH_TOKEN_MISSING, AE002 AUTH_TOKEN_INVALID, AE003 MTLS_AUTH_FAILED or AE005 MESSAGE_SIGNATURE_INVALID. Includes wrong issuer or audience, certificate-binding mismatch, and presenting an Operations reporting token to Track and Trace or a payment token to a reporting operation. AE005 applies to every operation: the RFC 9421 signature is missing, malformed, does not cover the required components or does not verify, the keyid is unknown, expired, revoked or registered for the other (payment or Operations) path, created/expires is outside the tolerance window, or the Content-Digest does not match the body. A TLS handshake rejection may have no HTTP response.","headers":{"WWW-Authenticate":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"403 AE004 ACCESS_DENIED. Valid credentials lack the operation scope, active IPSO identity or environment entitlement. Machine scopes and human Portal grants are independent; no participant identity supplied in a query can override the credential-derived scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"TransactionMissing":{"description":"404 BE904 TRANSACTION_NOT_FOUND. Identical for absent, outside-retention and unauthorised UETRs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"429 BE908 RATE_LIMIT_EXCEEDED. The IPSO's published request rate for this capability is exhausted; for Track and Trace the rate is shared between the screen and API callers. Retry-After is mandatory; wait as indicated and use bounded exponential backoff with jitter for repeated failures.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"properties":{"name":{"const":"RATE_LIMIT_EXCEEDED"}}}]}}}},"InternalError":{"description":"500 TE099 INTERNAL_ERROR. Use bounded backoff within the applicable usage controls; contact the Service Desk if persistent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"503 native response: source/publication/quota service unavailable or token validation cannot safely complete. Fail closed, never return false empty/ready data or bypass limits. Retry only within published limits.","headers":{"Retry-After":{"description":"Optional suggested positive delay-seconds for transient unavailability; when supplied, honour it within the usage controls.","schema":{"type":"integer","minimum":1}}}},"PerimeterError":{"description":"Native HTTP perimeter response, including 405 (Allow header), 502 and 504. No Nexus JSON error-body guarantee for these failures. Per-IPSO policy 429 responses use the explicit typed contract. Bounded retry only for transient failures."}}},"paths":{"/v1/track-and-trace/{uetr}":{"get":{"tags":["TrackAndTrace"],"operationId":"trackAndTrace","summary":"Track and trace a payment","description":"Return the current status of a single transaction by UETR, to help the IPSO answer a customer enquiry. Use it when a customer asks about a payment and the IPSO has sent the pacs.008 but has not received the pacs.002; where the IPSO already holds the pacs.002 it answers from its own records. Exactly one UETR per request: no bulk or list queries. The published request rate is shared across the Track and Trace screen and API callers, and exceeding it returns 429 RATE_LIMIT_EXCEEDED with Retry-After. This is not a polling service or a way to reconstruct the Operational Data Feed.\n\nUnlike the other operations in this document, Track and Trace uses the Payment Processing authentication, host and network path rather than the separate Operations reporting ones: a payment-realm certificate-bound access token, mutual TLS, and an RFC 9421 message signature produced with the IPSO's payment signing key pair rather than its Operations signing key pair. Nexus signs the 200 response, and the IPSO verifies it before use. Operations reporting tokens are not accepted.\n\nThe enquiry does not update the IPSO's records and does not replace pacs.028. Where a pacs.002 does not arrive, the IPSO must still send a pacs.028 and process the resulting pacs.002 to close the payment in its own journal. The IPSO is identified from its credentials and no participant identifier is passed in the request; a PSP enquiry goes to its IPSO, which queries Nexus. Nexus holds only the UETR, so the IPSO maps its own domestic reference to it.","parameters":[{"name":"uetr","in":"path","required":true,"description":"Exactly one UUID v4, identifying the single transaction. No bulk or list form of this operation exists.","schema":{"$ref":"#/components/schemas/Uetr"}},{"$ref":"#/components/parameters/SignatureInputBodyless"},{"$ref":"#/components/parameters/Signature"}],"responses":{"200":{"description":"Latest known status, with the rejection or pending reason where applicable and key event timestamps. For customer enquiries, not journal updates. If pacs.002 is missing, send pacs.028 and process the resulting pacs.002 to update the IPSO journal.","headers":{"Cache-Control":{"$ref":"#/components/headers/NoStore"},"Signature-Input":{"$ref":"#/components/headers/ResponseSignatureInput"},"Signature":{"$ref":"#/components/headers/ResponseSignature"},"Content-Digest":{"$ref":"#/components/headers/ResponseContentDigest"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackAndTraceResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/TransactionMissing"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"default":{"$ref":"#/components/responses/PerimeterError"}}}}}}
```
