Skip to content

feat(reject): add an ISO 20022 reason code to Reject - #18

Merged
thomasjsk merged 2 commits into
mainfrom
feat/reject-code
Oct 1, 2026
Merged

thomasjsk merged 2 commits into
mainfrom
feat/reject-code

Conversation

@thomasjsk

@thomasjsk thomasjsk commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

A TAP Reject says why only in reason, which TAIP-4 defines as a human-readable message. A receiver that wants to act on the reason, not just show it, has to parse prose, and the prose differs between implementations. The case that prompted this: a beneficiary VASP answers a wallet-confirmation ask with "that settlement address isn't ours", and the originator should stop treating the address as that VASP's. Today it can only guess from the text.

This adds an optional code to RejectBody, next to reason. reason stays free text for people; code is what a receiver acts on.

Codes come from ISO 20022

The values come from the ISO 20022 ExternalStatusReason1Code list, not from a new TAP list.

  • TAIP-19 already maps a Reject onto ISO's status report (RJCT) and says to "include reason code", but no TAIP says where that code goes.
  • TAP has adopted an ISO list before: TAIP-13 purpose codes are ISO's 4-letter codes.
  • With ISO codes, a bank-side gateway can pass the code through without translating it.

There is one value for now:

  • RejectCodeInvalidCreditorAccountNumber = AC03 ("Creditor account number invalid or missing");
  • it means the beneficiary side does not hold the settlement address.

Strict when sending, lenient when reading

  • code is a named type, RejectCode.
  • NewRejectMessage refuses any code this library doesn't define and returns ErrInvalidBody, so a typo or an invented code fails when the message is built. Allowing another code means adding a constant.
  • ParseBody keeps whatever code arrives. Another implementation may send an ISO value we don't define yet; a receiver ignores it instead of dropping the whole Reject. This is the same send-strict, read-lenient split as for in fix(taip-5): require for on address agents #15.
  • An empty code is left out of the JSON, so a Reject without one is byte-for-byte what it was.

Needs the matching TAIPs change

The TAIPs JSON schema for Reject sets additionalProperties: false. So a peer that validates strictly against it will refuse a Reject carrying code until TAIP-4 and schemas/messages/reject.json gain the field.

@thomasjsk
thomasjsk marked this pull request as ready for review September 30, 2026 06:20
@thomasjsk
thomasjsk merged commit 6debef9 into main Oct 1, 2026
3 checks passed
@thomasjsk
thomasjsk deleted the feat/reject-code branch October 1, 2026 10:08
@thomasjsk thomasjsk mentioned this pull request Oct 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant