Skip to content

UTA ↔ J.P. Morgan Global Payments 2 Integration Specification — v3.0

Bank: J.P. Morgan Chase — Global Payments 2 (GP2) platform + ancillary APIs UTA System: Client Processing (replacing NetSuite AR) Document Status: Draft v3.0 — In ReviewLast Updated: 2026-05-12 Supersedes: UTA JPM GP2 Integration Specification v2.2.md (retained for historical reference; do not edit) Authors: Cliff Song & Andrew (Product), with engineering review by Amir Hajizadeh; pending input from JPM Integration Manager


How to Read This Document

This spec is organized by integration capability. Each service is documented in one place, with its confirmation status, channel choice, and rollout sequencing attached as metadata. If you want to see what's shipping first, see §11 Rollout Sequencing — but every service lives in its capability section regardless of when we build it.

Scope boundary — and who owns what. This document covers the JPM ↔ UTA integration boundary only at two layers:

  1. The wire contract — what data crosses, in what format, on what schedule, via which channel, with which credentials. Documented per service in §6 / §7.
  2. The business requirements UTA imposes on each call at the integration boundarywhen to call each endpoint, what to do with the response payload, how to handle each exception class at the integration boundary. Examples already documented inline: §6.1's postCode Pending-vs-Settled treatment, §6.5's Payment Receipts dedup-by-endToEndId rule, §7.1's Pre-Flight pass/fail/manual-review gate, §7.2–§7.5's idempotency + polling-fallback rules, §7.9's Positive Pay Phase-1 decisioning posture, §7.11's inbound-credit-refund rail-selection, §8 polling cadences, §9 Three-Way Match. Cliff (Product) owns this layer.

Three-document set required for full implementation:

DocOwnerCoversStatus
(A) This spec — JPM ↔ UTA integration specCliffThe integration boundary: wire contract + integration-boundary requirements (above)In flight (~99% populated; open items in §12)
(B) Client Processing behavior spec — what inside Client Processing triggers integration calls and processes the resulting payloadsCliff (Product)The upstream business-rules layer: e.g., "when an athlete's commission is finalized, schedule a settlement payout that fires §7.2 / §7.3 / §7.5"; refund-authorization workflow; rail-selection policy; AR-side matching rules; GL-posting cadence; manual-review queue ownershipNot yet started — Cliff to scope and draft
(C) Engineering design doc — class decomposition, queue architecture, retry semantics, error-handling matrices, callback-receiver structureAmir's engineering teamThe technical implementation of (A) + (B)Drafted by Amir's team after (A) and (B) are both ready

This spec (A) alone is not sufficient input for engineering — (C) needs both the integration contract (A) AND the Client Processing behavior (B) to design against. Without (B), the engineering team can build the JPM-facing plumbing but won't know what inside Client Processing fires it or how the data is consumed once received.

Within this spec (A) only: if implementation surfaces a requirement gap at the integration boundary (an exception class with no documented handling rule, an unspecified call cadence on a JPM endpoint), Amir's team flags it back to Cliff for a requirements decision, which gets landed in this spec — not in the engineering design. Requirement gaps inside Client Processing (when to trigger, business-rule branching, refund authorization) land in (B), not (A).

If you are...Read sections
Business stakeholder (skim, 5 min)§1 Executive Summary, §2 What's Changed in v3.0, §11 Rollout Sequencing
JPM Integration Manager / RM§1, §3 Architecture, §6 Inbound Data, §7 Outbound Payments, §8 Status, §12 Open Items
Dev team (Amir and engineers)All sections; a separate engineering design doc will follow
Product team (Andrew + Cliff)All sections; §11 Rollout, §12 Open Items, §13 Next Actions

Source citation policy: Every endpoint, field, schedule, and behavior is cited to either (a) the JPM developer portal page (URL inline on each "Source basis" line, plus a consolidated index in §14 References), (b) the 2026_GP2_Client_Integration_Guide_Version_2_2.pdf with page number, or (c) a dated conversation with the JPM Integration Manager. Anything inferred or not yet confirmed is tagged [CONFIRM with JPM]. No Dev Test Cases or UAT Scenarios are written against a feature with open [CONFIRM] items — those features carry a Confirm-Blocked tag at the feature level.

Per-service metadata block: Each service in §6–§7 carries a small header block:

Status:    Cleared | Confirm-Blocked | Deferred | Not Yet Discussed
Channel:   REST | Webhook | Polling
Sequence:  (which rollout wave, see §11)

No cross-bank contamination. This document covers JPM only. CNB EASI-Link and BofA references must never appear here. Likewise, JPM-specific patterns (CloudEvents, mTLS + JWS) must not bleed into the CNB or BofA specs.


1. Executive Summary

UTA is replacing the AR functions of NetSuite with a custom system (Client Processing). This document specifies the integration between Client Processing and J.P. Morgan Chase via the Global Payments 2 (GP2) platform and its ancillary APIs.

The all-REST architecture (no SFTP, no SOAP):

  1. REST / JSON over mTLS + JWS — All outbound payment submissions, status inquiries, validation, account/transaction reporting, and check management. Authentication is X.509 mutual TLS for transport identity plus a separate Digital Signature certificate that signs each POST body via JWS/RS256, plus an OAuth Bearer token (signed JWT assertion in CAT/Prod) carrying authorization.
  2. CloudEvents Webhooks (push) — JPM pushes real-time status updates for every outbound payment (GP2 Callbacks) and notifications for every inbound RTP credit (Payment Receipts API). UTA hosts the callback receiver; JPM authenticates to it via a callback certificate.

No BAI2 SFTP file delivery is in scope for the GP2 surface. Account-level balances come from the Account Balances API (§6.2) and transaction history from the Transaction Details API (§6.1) — both REST products with BAI codes embedded in the JSON transaction objects. BDC (FDX v6) is JPM's commercial-segment alternative; UTA is corporate-segment and ineligible (per Jessica Jin 2026-05-12). If UTA later requires bulk BAI2 batch files, that is a separate JPM Treasury Services product outside this spec.

Current state (2026-05-12):

  • All inbound flows scope-locked or Confirm-Blocked. GP2 Callbacks (outbound status), Payment Receipts (inbound RTP credits), Transaction Details API + Account Balances API (intraday + prior-day reporting, EOD balance lock), Check Image retrieval. Inbound wire and inbound ACH credits depend on Transaction Details API polling (§6.1) — no webhook product covers them today.
  • All outbound payment flows scope-locked on REST. RTP (US TCH + FedNow), ACH (both credit disbursements and authorized debit pulls, with NACHA SEC codes), Domestic Wire (same-currency), Cross-Currency Wire / FX (RFQ Quote → Trade → GP2 Wire with /FXA/<contractId> — see §7.6), Stop Payment, Check Revoke, Check Issuance, Check Print.
  • Status strategy locked: Webhook-first via GP2 Callbacks (CloudEvents 1.0). Polling fallback via GET /payment/v2/payments/{paymentId} only if no callback is received within rail SLA (§8).
  • Phase 1 deferrals: Positive Pay exception decisioning REST API (still pending JPM GA), Push to Card / Push to Wallet / Zelle / Kinexys / Interac (out-of-scope rails on the same GP2 endpoint), JPM Wallet (separate product not in scope unless required for FX wires per §7.6).
  • GP2 pilot status: As of March 2026, GP2 was in pilot phase per JPM Integration Manager. UTA evaluated as strong candidate for the pilot program. v2.2 of this spec captured this; the developer portal 2026-03-20 changelog and continued public publication of GP2 docs imply broader access today, but UTA's enrollment status must be confirmed before production go-live — see §12 Open Item #1.
  • PoC status: No live PoC has been executed against JPM. CNB's PoC validated end-to-end on SOAP. JPM PoC is a §13 next action.

Production target: October 2026 (~5 months out) — same target as the CNB integration to keep the program coherent. Test readiness: 2–3 months for connectivity, callback configuration, validation, and API testing. The 13-step JPM onboarding process documented in the GP2 Integration Guide is estimated at 29–75 business days, which fits the 2–3 month window only if onboarding starts immediately after this spec is approved.

Open items from JPM:

  • JPM Integration Manager owes (a) the inbound webhook signature scheme for GP2 Callbacks + Payment Receipts — no public docs surface mTLS-reverse, HMAC, or signature-header semantics (§12 #2), (b) the complete CloudEvent type enumeration per rail — public portal shows only Payment.Completed and Payment.Rejected, OAS implies many more (§12 #3, #25), (c) Payment Receipts rail coverage for inbound wire and inbound ACH credits — OAS schema is rail-agnostic but public narrative framed RTP-only (§12 #36), (d) Positive Pay decisioning REST API GA timing — Q2 2026 tentative per Jessica Jin 2026-03-03 (§12 #7).
  • JPM RM owes UTA's GP2 pilot enrollment confirmation and the certificate exchange to enable Client Acceptance Testing (CAT) access.

Open items from UTA:

  • Stand up the callback receiver endpoint (HTTPS) UTA will publish to JPM for both GP2 Callbacks and Payment Receipts. Architecture TBD — pending Amir's review (candidate approach floated in early discussions: AWS API Gateway + Lambda fronted by an mTLS-terminating load balancer, but not confirmed by UTA Engineering). The callback cert UTA installs is JPM's, not UTA's. [ACTION — Amir, UTA Engineering: confirm or propose alternative architecture]
  • Klutch account list for CAT entitlement — confirmed 2026-05-12. JPM serves Klutch only (touring, endorsements, and voiceovers are at CNB). Accounts in scope: 900867182 (KSG Operating USD) and 900867232 (KSG Client Trust USD). Closes §12 #18.

2. What's Changed in v3.0 (vs. v2.2)

Areav2.2 saidv3.0 saysWhy it changed
Document organizationOutbound Command Layer / Inbound Audit Layer / Reconciliation / ErrorsCapability-organized with per-service Status / Channel / Sequence metadata blocks; matches the CNB v5 structure for cross-bank consistencyEditorial — easier to read, easier to keep in sync with CNB and BofA specs
GP2 endpoint pathPOST https://api.payments.jpmorgan.com/payment/v2POST https://api.payments.jpmorgan.com/payment/v2/payments (note trailing /payments). Sibling endpoints: GET /payment/v2/payments/{paymentId} (status), POST /payment/v2/payments/returns (RTP returns only), GET /payment/v2/payments/returns/{returnId} (return status). Optional ?view=FULL|SUMMARY on GET.Confirmed against developer portal RTP/ACH/Wire how-to pages
Sandbox hostapi-mock.payments.jpmorgan.comapi-sandbox.payments.jpmorgan.com (the actual sandbox host per JPM public certs page). api-mock.payments.jpmorgan.com is the mock host. The global sandbox tier is api-sandbox.*.Public certs page enumerates Sandbox / CAT / Production hosts
OAuth audience / scopeSandbox client_credentials with scope jpm:payments:sandboxAudience format is jpm:uri:environment:product (e.g., jpm:uri:prod:payments). Sandbox uses Basic auth (client_id + client_secret); CAT and Production use signed-JWT assertion. Scopes are optional.OAuth page at developer portal
Certificate stack4 cert types (mTLS, Digital Signature, Callback, Encryption)5 cert types — adds the OAuth Signed-JWT Assertion certificate (used to sign client_assertion in CAT/Prod). All 5 documented in §5.1.Authentication page at developer portal
Cert validityNot specifiedCannot exceed 1 year from issuance. Max 2 certificates may share the same Common Name.Authentication page
Cert installation cadenceNot specifiedJPM publishes a 2026 callback/encryption cert installation calendar with 24 release windows (~every 2 weeks). Cutoff dates are strict — "Certificates submitted after the listed cutoff date will be installed in the next available release window. Exceptions cannot be accommodated."Environments page at developer portal
Inbound reporting product direction"Account Balances API" + "Transaction Details API" as standalone ancillary productsConfirmed permanent. Earlier v3.0 drafts pointed at BDC (FDX v6 REST API) as the modern consolidation path. Jessica Jin clarified 2026-05-12 that BDC is JPM's commercial-segment product and UTA (corporate-segment) is ineligible — standalone Transaction Details API v3.1.8 (§6.1) and Account Balances API v1.0.5 (§6.2) are UTA's permanent reporting path. See §14.9 BDC entry marked OUT OF SCOPE.Jessica Jin 2026-05-12 (closes §12 #9 / #10 / #11 / #26 / #28)
Payment Receipts / Credit Confirmation APIDocumented but PDP path partially correctConfirmed live and separate. Path on UTA's side: {YOUR-SERVER-DOMAIN.com}/creditConfirmation. JPM-side OAS path: /webhook/credit-confirmation. Webhook event paymentReceipts. Currently RTP-network only — TCH, FedNow, UK FPS, SEPA Inst, AU NPP, HK FPS, ID/MY/SG/MX SPEI/BR PIX. Wire and ACH inbound credits are NOT documented as supported — UTA's only inbound visibility for wire/ACH is Transaction Details API polling (§6.1).Payment Receipts overview + OAS at developer portal
NACHA SEC codes (ACH debit)Not specifiedpaymentTypeInformation.localInstrumentCode.code must be set to CCD, PPD, WEB, TEL, or IAT for ACH debit (transferType = DEBIT). These map to the NACHA SEC codes UTA already uses on the existing legacy ACH file flow.ACH debit parameters page
endToEndId reuse windowConflated 24h vs 60dPer-rail clarification. ACH and Wire: 60 days. RTP: not explicitly published — treat as 24h conservative until JPM confirms. Duplicate detection fires as 11585 / 11587 / 11630 (HTTP 4xx).ACH debit parameters + Wire resources pages
endToEndId lengthGeneric 32-char hexPer-rail. RTP: 1–35 chars alphanumeric. ACH: 1–15 chars alphanumeric only (stricter). Wire: max 35 chars; industry best practice 16.Per-rail parameters pages
Cross-currency wire / FX flowThree-step RFQ: Quote → Trade → inject Contract ID via instructionForDebtorAgent: /FXA/<id>Cleared — end-to-end flow documented (2026-05-11). Upstream RFQ now anchored on Request for Quote API v1.0.1 OAS: POST /tsapi/v1/quotes/tsapi/v1/trades, returning jpmContractId (T… 30-char). Wire-body field instructionForDebtorAgent: /FXA/<jpmContractId> confirmed by Jessica Jin (2026-03-03). FX Rate Sheet API v1.0.2 documented as alternative published-rate path (CNB §5.6 functional equivalent). See §7.6.1–§7.6.6; §12 #4 closed.Request for Quote API v1.0.1 OAS + FX Rate Sheet API v1.0.2 OAS + Jessica Jin 2026-03-03
Wire returnsNot specifiedWires are irrevocable. GP2 has no /returns endpoint for paymentType=WIRE. Recall must be initiated bilaterally with JPMC ops.Same-currency wire overview
ACH returnsPollingNo client-initiated return endpoint for ACH. RDFI returns surface as a status update on the original payment: paymentStatus = RETURNED. Only RTP supports client-initiated returns via POST /payment/v2/payments/returns, and currently only for Brazil PIX.RTP returns + ACH overview
Payment CancellationPOST /payment/v2/payments/{paymentId}/cancel [CONFIRM]Still [CONFIRM]. Cancellation is referenced verbally ("possible while paymentStatus is PROCESSING with sub-statuses SCHEDULED or PENDING_COMPLIANCE_REVIEW") but the exact endpoint path is not surfaced in any public docs. JPM Integration Manager owes the canonical path.Developer portal does not expose path
GP2 Callbacks / CloudEventsPayment.Accepted, Payment.Processing, Payment.Settlement.Sent, Payment.Completed, Payment.RejectedThe public portal documents ONLY Payment.Completed and Payment.Rejected verbatim. The OAS callbacks block (paymentEvent callback under createPayment, x-tags: Webhooks) implies many more event types per rail (Push to Card, ACH Batch, RTP-BR PIX Return) but does not enumerate them. JPM Integration Manager owes the complete type enum.GP2 Callbacks page + GP2 OAS
Inbound webhook signature schemeNot specifiedNot specified on the public portal either. The OAS security stub is x-jpmc-security: {} — empty placeholder. UTA must require JPM to provide the inbound webhook authentication contract (mTLS reverse, HMAC, JWT bearer, signature header, or other) before opening the callback receiver to JPM's source IPs.GP2 Callbacks page + Payment Receipts OAS
Checks API base URLapi-mock.payments.jpmorgan.com/payable/v2Confirmed by Jessica Jin 2026-03-03: mock api-mock.payments.jpmorgan.com/payable/v2; production analog api.payments.jpmorgan.com/payable/v2. v2.2 was correct on the base. Sub-paths reconciled against Checks API v2.1.1 OAS in §7.7 / §7.8 deep-scan. §12 #5 closed.Jessica Jin 2026-03-03 + Checks API v2.1.1 OAS
Multi-payee payees[] arrayConfirmed for issuanceConfirmed in OAS v2.1.1 — both Issuance and Print support payees[] with priority, but with different limits. Issuance: up to 3 payees, names 1–50 chars, priority 1–3. Print: up to 2 payees, names 1–40 chars, priority 1–2. v2.2's claim about multi-payee on Issuance was correct; the v3.0 draft's framing (drawn from dev-portal narrative) was wrong and is corrected here.Checks API v2.1.1 OAS
Stop vs Revoke vs CancelConflated as "Cancellation"Three distinct flows, all confirmed via Checks API v2.1.1 OAS (§12 #6 closed 2026-05-11). Cancellation (POST /checks/cancellations) — pre-issuance void before print/release. Stop (POST /checks/stops) — forward-looking; block before clearance. Revoke (POST /checks/stops/revoke) — unwinds a prior Stop using the stopId.Checks API v2.1.1 OAS
Positive Pay decisioning"Q2 launch tentative"Still pending GA. Public developer portal does not expose any Positive Pay REST decisioning surface as of 2026-05-08. Until live, exception decisions remain manual via J.P. Morgan Access.Developer portal Checks markdown
PACMan APIReferenced in older Integration Guide PDF, never sourcedConfirmed live at …/treasury/pacman/doc.md. Provides outage notifications and partner-bank availability, with webhook support specifically for U.S. RTP partner bank outages. New in v3.0 — recommend wiring into the RTP send path as an optional pre-flight check to pre-empt rejections. See §10.Developer portal PACMan overview
GP2 changelog trackingNot in v2.2Documented in §12. No breaking changes for UTA's RTP/ACH/Wire scope in last 6 months; v2.2.5 (2026-03-20) is the latest at time of writing. The 2025-10-22 release added transactionIdentifier field descriptions in callbacks/GET status — relevant for AR reconciliation joining.GP2 Changelog page
Out-of-scope GP2 rails (one-line)Not enumeratedDocumented (§7.10). Push to Card, Push to Wallet, Zelle, Kinexys Digital Payments, Interac e-Transfer all reachable via the same POST /payment/v2/payments endpoint by paymentType value but not in scope for UTA.GP2 capabilities page
Production targetNot pinnedOctober 2026 (~5 months out from 2026-05-08). Same target as CNB to keep the program coherent.Cliff/Andrew alignment
Test-env readiness"29–75 business days" onboarding2–3 months for connectivity, callback configuration, and API testing. The 13-step onboarding starts after this spec is approved and overlaps with development.Cliff/Andrew alignment

3. Integration Architecture at a Glance

JPM exposes the channels v3.0 uses for non-overlapping purposes. Unlike CNB (SOAP over a single EASISubmit operation + SFTP for files), JPM is all REST/JSON with CloudEvents webhooks — there is no SFTP or SOAP in this integration.

┌─────────────────────────────────────────────────────────────────────┐
│                       J.P. Morgan Chase                             │
└─────────────────────────────────────────────────────────────────────┘
                  │                              │
                  ▼                              ▼
        ┌──────────────────┐           ┌──────────────────────┐
        │ REST / JSON      │           │ CloudEvents Webhooks │
        │ (UTA → JPM)      │           │ (JPM → UTA)          │
        ├──────────────────┤           ├──────────────────────┤
        │ mTLS (transport) │           │ Mutual TLS to UTA's  │
        │ + JWS RS256      │           │ callback receiver    │
        │   on POST bodies │           │ + JPM callback cert  │
        │ + OAuth Bearer   │           │ Inbound webhook      │
        │   (signed JWT in │           │ signing scheme:      │
        │   CAT/Prod)      │           │ [CONFIRM with JPM]   │
        ├──────────────────┤           ├──────────────────────┤
        │ GP2 Payments     │           │ GP2 Callbacks        │
        │  (RTP, ACH,      │           │  Payment.Completed,  │
        │   Wire)          │           │  Payment.Rejected,   │
        │ Validation Svcs  │           │  + per-rail variants │
        │ Transaction      │           │ Payment Receipts     │
        │   Details API    │           │  /webhook/credit-    │
        │ Account Balances │           │  confirmation        │
        │   API            │           │  (RTP only — not     │
        │ Checks API       │           │   wire/ACH)          │
        │                  │           │                      │
        └──────────────────┘           └──────────────────────┘
                  │                              │
                  └──────────────┬───────────────┘

                      ┌───────────────────────────┐
                      │  UTA Client Processing    │
                      │  (consumer system)        │
                      └───────────────────────────┘

Single GP2 operation across rails: every GP2 payment uses POST /payment/v2/payments over https://api.payments.jpmorgan.com/payment/v2/payments (Production) or https://api-sandbox.payments.jpmorgan.com/payment/v2/payments (Sandbox). The JSON body's paymentType field (RTP | ACH | WIRE) routes the rail; the transferType field (CREDIT | DEBIT) routes credit-push vs. debit-pull.

Status visibility via push, not pull: UTA's primary status path is the GP2 Callbacks webhook, not polling. Polling GET /payment/v2/payments/{paymentId} is a fallback used only when a callback has not arrived within rail SLA.

No raw bank data in NetSuite. NetSuite continues to receive Journal Entries only; raw GP2 callbacks, Transaction Details API responses, and check images stay inside Client Processing.


4. Authentication & Connectivity

4.1 Certificate Stack

JPM requires five distinct certificate types, each scoped to a specific function.

Per-environment, multi-cert math. "Separate credentials are required per environment (Client Testing and Production)" [JPM Authentication]. With 5 cert types × 2 environments = 10 unique certificates UTA must generate, install, rotate, and renew. CAT certs and Production certs share neither private keys nor lifecycle — they are independent stacks. Plan annual rotation (JPM hard-caps validity at 1 year) for all 10 in a single cycle to avoid per-bank fire drills — coordinate with the cross-bank cert ops runbook owned by Amir.

Client Authentication EKU is required on all UTA-presented mTLS certs. All UTA-presented mTLS certs must carry the Client Authentication Enhanced Key Usage (EKU) field. Some CAs (DigiCert specifically flagged by Jessica Jin 2026-05-12) are deprecating this from default cert templates as part of an industry shift toward narrower-purpose certs. UTA must explicitly request the Client Authentication EKU at order time; Server-Auth-only certs will be rejected by JPM. If the chosen CA can't include it on the current template, switch CAs from JPM's approved list before ordering. Tracked as §12 #40.

CertRequired forPurposeNotes
Transport (mTLS)All REST calls in CAT/ProdTLS host identity ("carries no access permissions")SSL cert from JPM-approved CA list (25+ CAs: Amazon, DigiCert, GlobalSign, Let's Encrypt, Microsoft, Sectigo, etc.)
Digital SignatureAll POST/mutating GP2 callsSigns request body via JWS / RS256Different key from mTLS; uploaded separately
OAuth Signed-JWT AssertionCAT + Production OAuth token requestsSigns client_assertion JWT (RS256)Sandbox uses Basic auth instead — no JWT cert needed
CallbackGP2 Callbacks + Payment Receipts (JPM → UTA)Auths JPM's webhook pushes to UTA's receiverUTA installs JPM's callback cert; mTLS cert may be reused
Encryption (optional)Payload-level / PII-field encryptionOptional defense-in-depthRecommended for PII; not required by GP2

Validity: "Certificate validity cannot exceed one year from issuance" [JPM Authentication]. Common Name limit: "Maximum of two certificates can share the same Common Name" [JPM mTLS+Digital Signature]. Upload role: "API Security role" required to upload certificates to the Developer Portal [JPM mTLS+Digital Signature].

Rotation: JPM rotates its public certs in advance — clients must "transition to the new certificate before the listed rotation date" [JPM Public Certificates]. No automatic-rotation feature on UTA's side; manual rotation required.

4.2 OAuth

Token endpoint (CAT and Prod, unified): https://login.jpmorgan.com/oauth2/token

Grant: client_credentials. Audience parameter: jpm:uri:<env>:<product> (e.g., jpm:uri:prod:payments, jpm:uri:cat:payments). Scopes are optional.

Sandbox flow (Basic auth):

bash
curl --location 'https://id.payments.jpmorgan.com/am/oauth2/alpha/access_token' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=client_credentials' \
  --data-urlencode 'client_id=<client_id>' \
  --data-urlencode 'client_secret=<client_secret>'

CAT / Production flow (signed JWT assertion):

bash
curl --request POST 'https://login.jpmorgan.com/oauth2/token' \
  --data-urlencode 'grant_type=client_credentials' \
  --data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \
  --data-urlencode 'audience=jpm:uri:prod:payments' \
  --data-urlencode 'client_assertion=<RS256-signed JWT>'

JWT assertion shape:

ClaimValue
Header algRS256
Header kidThumbprint from Developer Portal Security page
sub + issClientId from Developer Portal Security page
audhttps://login.jpmorgan.com/oauth2/token
iatCurrent Unix timestamp
expiat + 30 (30-second JWT lifetime; the access token below is much longer-lived)
nbfOptional; iat if present
jtiOptional unique JWT ID

Token response:

json
{ "access_token": "eyJhbGciOiJSUzI1NiIs...", "token_type": "Bearer", "expires_in": 28800 }
API surfaceAccess token TTLRefresh model
GP2, Validation Services, Checks, PACMan, Transaction Details, Account Balances28,800 sec (8 h)Re-issue (no refresh token); proactive re-issue at ~7 h

Critical: never reactively refresh on 401. A background job re-issues on schedule per surface.

4.3 Digital Signature on POST Bodies

POST/mutating calls must sign the JSON body using JWS RS256:

  1. UTF-8-encode the JSON payload, Base64URL-encode it
  2. Populate the JWS header with alg: RS256
  3. Load the Digital Signature private key
  4. Sign the encoded payload with SHA256withRSA (Java) / SHA256 (JS)
  5. Construct the JWS as <encodedHeader>.<encodedBody>.<signature>

Header on the wire: Content-Type: application/jose (vs. application/json for unsigned GETs). Example:

bash
curl --request POST --url <API endpoint> \
  --header "Content-Type: application/jose" \
  --header "Authorization: Bearer <access_token>" \
  --cert <transport-cert> --key <transport-key> \
  --data '<signed JWS payload>'

Reporting / GET-only APIs (Account Balances, Transaction Details, GET status) require mTLS but do not require Digital SignatureContent-Type: application/json is fine on GETs.

4.4 Environments

Reconciled against the GP2 OAS v2.4.7 servers block (2026-05-08), the Transaction Details API v3.1.8 + Account Balances API v1.0.5 OAS servers blocks, and the developer-portal public-certs page:

TierHostsOAS-confirmed assignmentUse
Mock (stub responses)api-mock.payments.jpmorgan.comGP2 OAS: "MOCK" tierFunctional development against simulated responses; no real auth required
Client Acceptance Testing (CAT) / Sandboxapi-sandbox.payments.jpmorgan.comGP2 OAS labels this host "CLIENT TESTING - MTLS" — i.e., CAT, not standalone sandbox. UAT happens here with real mTLS + OAuth flowPre-production validation against JPM-side test environment with full auth stack
CAT (older alias)api-cat.payments.jpmorgan.com, apigatewayqaf.jpmorgan.comListed on the JPM public-certs page; [CONFIRM with JPM] whether api-cat is deprecated in favor of api-sandbox or both are active for different productsSome JPM products may still route CAT through api-cat
Productionapi.payments.jpmorgan.com, apigateway.jpmorgan.comGP2 OAS: "PRODUCTION - MTLS"; Transaction Details / Account Balances: apigateway.jpmorgan.com/tsapi/v3 (mTLS) and openbanking.jpmorgan.com/tsapi/v3 (OAuth)Live
PCIdedicated PCI PROD / CAT / UAT endpointsCard-present / Push-to-Card; out of scope for UTA

Important correction from earlier v3.0 drafts: earlier drafts of this spec listed api-sandbox.payments.jpmorgan.com under "Sandbox / Mock" tier. The GP2 OAS explicitly labels it CAT (Client Testing). api-mock is the true sandbox/mock host. Use api-mock for stub testing; use api-sandbox only once CAT is provisioned and certs are exchanged.

Credential separation: "Separate certificates and credentials must be managed independently for each environment. Certificates cannot be shared across environments." [JPM Authentication].

JPM public certificate expirations (most recent published):

  • Production api.payments.jpmorgan.com mTLS — valid through 2030-07-02
  • Production apigateway.jpmorgan.com mTLS — valid through 2026-05-28 and 2026-10-22 (two certs; verify which UTA pins)
  • CAT api-cat.payments.jpmorgan.com mTLS — valid through 2030

UTA must monitor these dates and re-pin before expiry. The apigateway.jpmorgan.com 2026-05-28 expiry is the earliest material risk — it lands inside our development window; track it explicitly.

2026 callback / encryption certificate installation calendar. JPM does not install client-side callback or encryption certificates automatically. There are 24 release windows in 2026 (~every 2 weeks). Each has a strict cutoff:

"Production callback and encryption certificate installations follow a scheduled release calendar and are not processed automatically. Certificates submitted after the listed cutoff date will be installed in the next available release window. Exceptions cannot be accommodated." [JPM Environments]

Earliest cutoff: 2025-12-26 → install 2026-01-15. Latest cutoff: 2026-11-27 → install 2026-12-17. Releases on 2026-07-16, 2026-07-30, 2026-11-19, 2026-12-17 are flagged with double asterisks (significance not documented — [CONFIRM with JPM]). UTA's certificate-rotation runbook must align with this calendar.

4.5 Callback Receiver Configuration (UTA hosts; JPM pushes)

For both GP2 Callbacks and Payment Receipts, UTA hosts the HTTPS receiver and JPM pushes to it.

Conceptual primer. A callback is JPM pushing data TO UTA — the reverse of UTA calling JPM's API. Normal direction: UTA → POST → JPM, JPM responds synchronously. Callback direction: at some later time (seconds/minutes after the original call), JPM has new info — payment status changed, RTP credit landed, payment returned — and JPM POSTs that event to a URL UTA hosts. Without callbacks, UTA must poll GET /payment/v2/payments/{paymentId} to discover status changes (wasteful + minutes-of-delay). With callbacks, JPM pushes status changes in near-real-time and UTA's sub-ledger reacts immediately.

For UTA's Phase 1, two callback URLs are required — one per JPM product (GP2 Callbacks for outbound payment status across all rails; Payment Receipts for inbound RTP credits). PACMan's webhook (POST /client-domain) is a third potential URL deferred to Phase 2 per §10.

Authentication on inbound: when UTA submits a callback URL to JPM via the Payments Developer Portal (PDP), UTA also associates the JPM-issued Callback Certificate with that URL — JPM presents this cert when calling UTA's receiver so UTA's server can verify the inbound POST is genuinely from JPM (not a spoof).

UTA-side configuration steps:

  1. Stand up the HTTPS callback receiver. Architecture TBD pending Amir's review — candidate approach is AWS API Gateway + Lambda fronted by an mTLS-terminating ALB, but UTA Engineering owns the final design decision.
  2. Generate the URL UTA will publish to JPM (e.g., https://callbacks.uta.example/jpm/gp2/payment-events and https://callbacks.uta.example/jpm/payment-receipts/credit-confirmation). Both endpoints will be specified in §6.
  3. Install JPM's callback certificate on the load balancer (downloaded from the JPM developer portal Security tab).
  4. Optionally upload UTA's encryption certificate if PII-field encryption is enabled.

JPM-side configuration steps:

  1. UTA's representative goes to the Global Payments screen → Security tab in the Payments Developer Portal.
  2. Selects the environment (CAT or Production).
  3. Under Response → Callbacks, clicks "Configure callbacks".
  4. Enters UTA's callback URL.
  5. Selects/uploads the authentication certificate (mTLS cert may be reused).
  6. Optionally uploads UTA's Encryption Certificate.
  7. Clicks "Configure callbacks" and confirms the configuration is active.
  8. Submits the callback cert via the cert-installation calendar window (§4.4).

Inbound webhook signature scheme: [CONFIRM with JPM]. The public developer portal does not document an HMAC, JWT, or signature-header scheme on inbound webhooks — both the GP2 Callbacks OAS and the Payment Receipts OAS show x-jpmc-security: {} (empty placeholder). Until JPM provides the contract, UTA's callback receiver must validate JPM's source identity via mTLS only (the callback cert in step 3 above) and must not open authenticated processing to traffic that lacks a valid mTLS handshake against that cert.


5. Onboarding & Connectivity Sequence

Spec basis: GP2 Integration Guide v2.2 (2026_GP2_Client_Integration_Guide_Version_2_2.pdf) onboarding section, plus developer portal Treasury Global Payments getting-started page.

The 13-step onboarding process (estimated 29–75 business days) gates production go-live behind two checkpoints: Client Testing Environment and Production Verification Testing. Both require certificate exchange between JPM and UTA before access is granted [Developer Portal — Treasury Global Payments getting-started].

UTA prerequisites — confirm before formal kickoff (per Jessica Jin 2026-05-12):

Before sending the formal implementation request to Sam Bomes + Joey at JPM, UTA must have ready:

  1. Accounts in scope — confirmed 2026-05-12. Two Klutch accounts at JPM: 900867182 (KSG Operating USD) and 900867232 (KSG Client Trust USD). JPM provisions these for CAT and Production entitlement (closes §12 #18).
  2. Payment types in scope — explicit list of which paymentType values UTA will use in Phase 1 (RTP, ACH credit, ACH debit, Wire, FX Wire, plus Checks: Issuance, Print, Cancel, Stop, Revoke). The book-transfer use case (§7.5.1) is paymentType: WIRE with intra-JPMC routing — no separate scope flag needed.
  3. Certificates obtained — all 5 cert types per §4.1. Note: Jessica flagged industry-wide DigiCert renewal-timeline changes (§12 #40) — research current DigiCert timelines before generating UTA's certs to avoid window misalignment with the JPM 2026 cert-installation calendar.
  4. POC list registered in JPM's Developer Portal (PDP) — per Jessica 2026-05-12: "All POCs will have to be registered within PDP, even though they are not utilizing the tech first hand." UTA's POC slate: Cliff (Product), Andrew (Product), Amir (Engineering — API Security role for cert ops), Stan (Business sponsor — read-only / compliance visibility). Each registers their own named account; UTA does not use a shared-mailbox account.

Items to cover during the JPM implementation kickoff call (with Jessica + the assigned technical implementation manager + Sam Bomes / Joey):

  1. PDP organization + project structure. UTA preference: single broadly-named project (e.g., "UTA — JPMorgan Payments" or "UTA Bank Integration — JPM"), not Klutch-specific. UTA serves Klutch on JPM today but plans to add other UTA entities to JPM over time; a non-entity-specific project name allows additive expansion without spinning new projects per entity. Confirm with the implementation team that the single-project pattern is the recommended approach for multi-entity corporate clients (vs. one project per entity).
  2. PDP POC roles and accounts. UTA's proposed account structure (per prerequisite #4 above): Amir on API Security; Cliff, Andrew as Product roles; Stan as business-sponsor read-only. Confirm role taxonomy and any other JPM-required roles UTA must fill.
  3. Validation Services per-customer values (§12 #38). The x-client-id and x-program-id values for each Validation Services profile UTA enables (Standard, Global, Account Confidence Score, Microdeposit) are issued at customer onboarding. Get these assigned during kickoff.
  4. Inbound webhook authentication scheme (§12 #2). Public OAS shows x-jpmc-security: {} (empty placeholder) for both GP2 Callbacks and Payment Receipts. UTA needs the canonical scheme JPM uses when calling UTA's receiver — mTLS-reverse, HMAC, JWT, signature header, or other.
  5. CloudEvent type enum per rail (§12 #3, #25). Public portal documents only Payment.Completed / Payment.Rejected. OAS implies many more event types per rail. UTA's callback dispatcher routing depends on the complete enum — request the full list during kickoff.
  6. Positive Pay Phase 1 decisioning posture (§7.9). Positive Pay protection is active in Phase 1 via §7.7 Issuance (every UTA-issued check is registered with JPM, exceptions are flagged on mismatch). The programmatic decisioning REST API is Q2 2026 launch tentative (§12 #7) — so for Phase 1 UTA must choose how exceptions get decisioned: (a) Manual JPM Access UI — UTA operator(s) log in daily during JPM's cutoff window to review exceptions and click PAY/RETURN, OR (b) Default decisioning rules configured at onboarding (e.g., auto-return-all, or auto-pay-below-$X). UTA decisions to lock in during kickoff: which path; if (a), which UTA operator(s) own the daily workflow + escalation path; if (b), what the default-rule policy is. The JPM REST decisioning API will be wired in additively in Wave 3 when GA — no Phase 1 architectural pre-investment needed.

Stages relevant to UTA:

  1. Formal implementation request to Sam Bomes + Joey at JPM (per Jessica 2026-05-12) — triggers implementation-team assignment + UAT environment setup. Jessica will be on the kickoff call to provide context.
  2. Spec approval (this document).
  3. Cert Authority chosen + certs generated (UTA side, all 5 types per §4.1) — see prerequisite #3 + §12 #40 (DigiCert timelines).
  4. JPM enables UTA's account in the Developer Portal Security tab.
  5. UTA uploads certs through the Security tab.
  6. Certificate exchange — JPM sends callback cert to UTA; UTA's mTLS pinned on JPM side.
  7. CAT access opened.
  8. Test plan executed — every service in §6 + §7 with a positive and negative test.
  9. Production Verification Testing — small-volume validation runs in Prod.
  10. Go-live.

Account list for CAT entitlement — confirmed 2026-05-12. Two Klutch accounts UTA needs JPM to provision: 900867182 (KSG Operating USD) and 900867232 (KSG Client Trust USD). JPM serves Klutch only — touring, endorsements, and voiceovers are at CNB and out of scope for this spec. These accounts are included in the formal implementation request to Sam Bomes + Joey (closes §12 #18).

Onboarded Accounts verification (one-time, at CAT-access opened and again at Prod go-live). Use the JPM Onboarded Accounts API v1.0.1 (Playbook/Onboarded Accounts 1.0.1.yaml) to enumerate Klutch's provisioned accounts and the JPM products active on each at each environment transition. Confirms (a) the account list matches what UTA requested, (b) entitlements for all in-scope products (Transaction Details, Account Balances, GP2, Checks, Validation Services, FX Rate Sheet, Payment Receipts, Request for Quote) are active, and (c) no unexpected accounts or products are attached. One-time verification at the env-transition checkpoint — not part of UTA's per-transaction request flow.


6. Inbound Data Services

Every service in this section delivers data from JPM into UTA's environment. The data-feed services (Transaction Details API, Account Balances API, Statements — manual download in Phase 1, Check Images) come first because they are the structural equivalent of CNB v5's §5.1–§5.9 — the bank-side ledger feed UTA reconciles against. The push-event services (Payment Receipts, GP2 Callbacks) follow because they ride on top of the same accounts and arrive only when something happens on those accounts.

Two inbound channels — when each one fires:

ServiceWhat it coversChannelLatency
§6.1 Transaction Details APIComprehensive — every transaction that hits the account (inbound wires, ACH credits/debits, check deposits, lockbox items, RTP credits, fees, returns, reversals)REST polling (every 15 min during business hours)Up to 15 min + JPM posting cadence
§6.5 Payment Receipts APIInbound RTP credits only (TCH RTP, FedNow) — a narrow, push-notified subset of what Transaction Details also reportsWebhook push (JPM → UTA receiver)Seconds

The two are complementary, not redundant. Transaction Details is UTA's authoritative ledger feed for reconciliation (§9 Three-Way Match) and covers every rail. Payment Receipts is a narrow real-time push for the one rail where the funds are final-and-irrevocable on arrival (RTP) and where the originator typically expects an acknowledgement faster than a 15-min poll cycle can provide.

Overlap vs disparate data:

  • RTP credits appear in both channels — Payment Receipts pushes within seconds; Transaction Details surfaces the same item on the next poll cycle with full BAI-coded ledger context. UTA's reconciler must dedupe by endToEndId / bank reference, treating the Transaction Details record as the system-of-record entry and the Payment Receipts event as the early-trigger signal.
  • Inbound wire, ACH, and check deposits — visible only through Transaction Details polling. Payment Receipts does not cover these rails.
  • Outbound payment status — handled by GP2 Callbacks (§6.6), a separate webhook product, not Payment Receipts.

Why both channels in Phase 1 (the non-latency case): Even setting aside the seconds-vs-minutes argument, Payment Receipts adds value for RTP specifically because (a) settlement certainty — an RTP credit pushed via Payment Receipts is final the moment it arrives, so downstream auto-application can fire immediately rather than waiting for the next poll to confirm; (b) scalability headroom — if RTP credit volume grows, push-on-event scales independently of the polling cadence and does not require shortening the poll interval (which would multiply API call cost across all accounts); and (c) cost decoupling — the polling cost stays flat regardless of RTP volume.

For UTA's reconciliation model: Transaction Details + Account Balances together feed the EOD Three-Way Match (§9 Brakes). Payment Receipts is an operational accelerator for the RTP receivables sub-flow, not part of the ledger-of-record reconciliation chain.

6.1 Transaction Details API — Intraday + Prior-Day Activity (CNB §5.1 + §5.2 replacement)

Status: Cleared (Phase 1) — JPM-prescribed product per the Treasury Reporting Playbook  |  Channel: REST polling (OAuth or mTLS)  |  Sequence: Wave 1

Purpose: Intraday + prior-day transaction detail with explicit BAI Type Codes — the direct functional replacement for CNB's BAI2 DDA Current Day (§5.1) and DDA Prior Day (§5.2) feeds, plus richer EDI 820 NACHA equivalent (CNB §5.3) and lockbox deposit detail (CNB §5.4) embedded in the response. JPM's implementation manager prescribes this API for UTA's treasury reporting; see US JPM API Playbook — Reporting v1.

OAS verified against Transaction Details API v3.1.8 OpenAPI 3.0.0 spec on 2026-05-11 — see Playbook/Transaction Details API 3.1.8.yaml. Lifecycle: LIVE but flagged tier: LEGACY — production-ready today; LEGACY tier reflects that JPM's commercial-segment clients use BDC (FDX v6), but UTA is corporate-segment and ineligible for BDC per Jessica Jin 2026-05-12. Transaction Details API is UTA's permanent inbound transaction-reporting path, not a transitional one.

Why Transaction Details API is the right product for UTA (not BDC). Earlier v3.0 drafts pointed at BDC v6.2.16 because BDC's OAS mentioned BAI codes and the dev portal positions BDC as the modern FDX-v6 successor. The JPM-issued Reporting Playbook actually prescribes Transaction Details API for UTA's tier of client, and Jessica Jin reconfirmed 2026-05-12 that BDC is JPM's commercial-segment product — UTA (corporate-segment, on Access platform) cannot use it. Transaction Details API is purpose-built for the BAI2-replacement use case: explicit baiType.typeCode field (not buried in a generic commercialCode), built-in CURRENT_DAY / PRIOR_DAY query modes, multi-account in a single call, lockbox remitter + invoiceDetail shapes, ACH batch + addenda inline, wire-specific fields (wireType, repairCode, reversal), and a postCode field (P/I) that signals prior-day vs intraday in every record.

AttributeValue
EndpointGET /transactions (operationId getTransactions) — single endpoint, mode-switched by query params
Base URLs (from OAS)Production OAuth: https://openbanking.jpmorgan.com/tsapi/v3 · Production mTLS: https://apigateway.jpmorgan.com/tsapi/v3 · CAT OAuth: https://openbankingcat.jpmorgan.com/tsapi/v3 · UAT OAuth: https://openbanking-uat.jpmorgan.com/tsapi/v3 · CAT mTLS: https://apigatewaycat.jpmorgan.com/tsapi/v3 · QAF mTLS: https://apigatewayqaf.jpmorgan.com/tsapi/v3
Auth modelmTLS and/or OAuth 2.0 (JPMC-OAuth2 with Reader role for read-side). Per OAS x-jpmc-security, either auth method is accepted on its own; mTLS+OAuth combined is the production recommendation
CNB §5.1 equivalent — IntradayGET /transactions?accountIds=<ids>&relativeDateType=CURRENT_DAY — returns same-day posted + memo-posted activity. Direct replacement for CNB BAI2 Current Day file
CNB §5.2 equivalent — Prior DayGET /transactions?accountIds=<ids>&relativeDateType=PRIOR_DAY — returns settled prior-day activity. Direct replacement for CNB BAI2 Prior Day file
Multi-account in one callaccountIds is an array (comma-separated). One call returns transactions across multiple accounts — on-par with CNB's whole-relationship BAI2 file
Optional date range (alternative to relativeDateType)startDate + endDate (both YYYY-MM-DD). Cannot be combined with relativeDateType (errors: GCA-018 for startDate+relativeDateType conflict, GCA-019 for endDate+relativeDateType). Maximum window: 5 days (error GCA-065) — for back-fill / catch-up only, not steady-state polling
Lockbox enrichmentlockbox information=true query param (note the literal space in the parameter name per the OAS) — returns full lockbox remitter, lockboxPaymentDetail, and invoiceDetail blocks for any credit transactions sourced from a lockbox deposit. Direct replacement for CNB §5.4 Image Deposit Item File metadata (image retrieval is separate — see §6.5)
PaginationOffset-based via pageNumber query param (integer, ≥1). Response pagination block carries pageSize, totalPages, pageNumber, totalRecords
OAS schema markerx-jpmc-api-maturity: { lifecycle-status: LIVE, tier: LEGACY }. LEGACY reflects JPM's commercial-segment migration path (to BDC), not UTA's situation. UTA is corporate-segment and stays on Transaction Details API permanently (Jessica Jin 2026-05-12 — closes §12 #28). No migration abstraction layer needed

Response payload — top-level shape:

json
{
  "pagination": {
    "pageSize": 100,
    "totalPages": 3,
    "pageNumber": 1,
    "totalRecords": 257
  },
  "data": [ /* array of transaction objects — see below */ ]
}

data[] transaction object — fields (verified against OAS v3.1.8):

FieldTypeNotes — CNB BAI2 equivalent and UTA usage
account.accountIdstringUTA's account number for this transaction
account.accountNamestringFriendly account label
account.bankIdstringRouting transit number (US) or SWIFT BIC (international) or multibank info
account.branchId, account.bankNamestringBranch + bank descriptor
account.currency.codestringISO 4217 (Klutch is USD)
account.aba, account.swiftstringRouting identifiers per network
receivedTimestampISO 8601 date-timeWhen JPM made this transaction available for reporting — the API's freshness anchor; differs from posting time
asOfDatestring (date)When transaction posted to the account (T-0 for intraday; T-1 for prior-day)
valueDatestring (date)When funds become available (credits) or cease to be available (debits)
debitCreditCodestringD (Debit) or C (Credit) — primary direction indicator
baiType.typeCodestringTHE BAI Type Code — direct replacement for CNB BAI2 Type Code (e.g., 165 for wire debit, 115 for wire credit, 195 for ACH credit, 475 for ACH debit). UTA's existing BAI2 parser keys off this exact code
baiType.descriptionstringHuman-readable BAI category (e.g., "Wire In", "ACH Credit")
baiType.btrsTypeCodestringX9 BTRS/BTR3 equivalent (FDX-standard transaction code)
fundsTypeCodeenumAvailability: 0 = Immediate, 1 = Day-1, 2 = Two+ Days, S = Distributed (split), V = Value-dated, Z = Unknown
currency.codestringTransaction currency (ISO 4217)
amountnumberTransaction amount in account currency (decimal, e.g., 7783.94)
immediateAvailable, day1Available, day2Available, day2PlusAvailable, day3PlusAvailablenumberFloat availability tracking — replicates CNB BAI2 fund-type breakdown for cash-position calculations
bankReferenceSearchable.standardValuestringBank-assigned reference (trace number for ACH, Fed Reference for wire) — primary join key for outbound payment reconciliation
customerReferenceSearchable.standardValuestringCustomer-assigned reference (check number, lockbox number, originator's endToEndId) — primary join key for AR auto-match
repairCodestringWire-only; non-null if JPM repair desk modified the wire instruction
reversalstringNon-null if this entry is a reversal of a prior posting
wireTypestringWire transaction subtype
shortDescriptionstringTransaction type summary
postCodestringP = prior-day (settled), I = intraday (memo-posted, may not yet be settled) — the freshness signal that lets UTA's AR auto-match distinguish provisional from final
checkNumbernumberCheck number for check-related entries
lockboxobjectReturned for lockbox deposit credits: { lockboxSequenceCode, lockboxItems, lockboxNumber, lockboxDepositDate, lockboxDepositTime }
lockboxInformationobjectRich lockbox detail (when lockbox information=true is queried): { number, siteName, remitter: { batchNumber, batchItemCount, batchAmount, debitCreditCode, entryDate, creditDate, depositDate, depositTime, transactionDescriptionType (LBX/ACH/WIRE/PCX/BRANCH/MISC/VRD/VRM), ddaNumber, lockboxPaymentDetail: { itemNumber, remitterBank, checkNumber, routingNumber, itemAmount, remitterName, transactionId, paymentSequenceNumber, invoiceDetail: { invoiceNumber, invoiceAmount, invoiceDate, invoiceRefNumber } } } }
narrativeTextobjectFree-form narrative; VRN (Virtual Reference Number) information carried after the VXR tag (per OAS description). VRN is a JPM virtual account / sub-account identifier — see Playbook §10
sepaDetailsXmlstringFull SEPA payment detail (XML blob) for SEPA transactions — not applicable to UTA's US-only flows
supplementalTextSet, supplementalText, supplementalTextRecordListobject/string/arrayNarrative text in additional languages (for international wires)
achBatchItems[]array of AchBatchWithItemsThe CNB §5.3 EDI 820 NACHA equivalent — INLINE, no separate file. Each batch carries: achCompanyDescription, achCompanyId, achCompanyName, batchCreditAmount, batchDebitAmount, batchItemCount, batchNetAmount, debitCreditCode, entryDate, originatorBatchSequenceNumber, standardEntryClass (NACHA SEC: CCD/PPD/WEB/TEL/etc.), items[] of AchIndividualItem (each with baiTypeCode, clientOriginatingTraceNumber, dfiAccountId, dfiBankId, individualId, individualName, itemAmount, and achAddendaList[] with addenda text records)
addendastringRaw addenda text (additional to the achBatchItems structured breakdown)
transactionIdstringUnique within Current Day, unique within Historical — but NOT across. Per OAS: "Cannot be used to uniquely identify a transaction in the Current Day, and then identify that same transaction days later after the transaction has been hard-posted." UTA's reconciliation must rely on bankReferenceSearchable.standardValue + customerReferenceSearchable.standardValue for cross-day joins, not transactionId

Treatment of same-day wire credits — UTA DECISION: Conservative (Pending). Current-day wire credits with postCode: "I" (intraday) are treated as memo-posted / not finalized until the prior-day pass with postCode: "P" settles them. The postCode field gives UTA a direct, per-record signal — UTA's parser branches on this value. AR auto-match (§6.5) and the Three-Way Match (§9) gate cash application on postCode: "P", not on intraday appearance.

ApproachDescriptionStatus
Conservative (Pending)Treat postCode: "I" entries as unposted until same record returns with postCode: "P"✅ Selected. Lower risk; delays same-day cash application
Aggressive (Booked)Treat any wire credit visible in the API as fully booked, regardless of postCodeRejected — UTA chose lower-risk path

Rationale: Wires are technically irrevocable on JPM's side once received, so Aggressive would have been defensible. UTA chose Conservative because (a) the postCode field gives explicit JPM-side acknowledgment of which entries are final, (b) overnight reconciliation catches any sanctions-driven reversal or beneficiary dispute before it touches AR, and (c) the operational benefit of same-day cash application is small relative to the audit clarity of waiting for postCode: "P".

Recommended polling cadence (carries from v2.2 + Playbook §5):

Use caseCadenceQuery
Intraday refresh (Current Day)Every 15 minutes during business hours (4 AM – 7:45 PM PT Mon-Fri)?relativeDateType=CURRENT_DAY
Prior-day confirmOnce daily at ~7:30 AM local time?relativeDateType=PRIOR_DAY
Back-fill / catch-up (after outage)On demand, max 5-day window?startDate=YYYY-MM-DD&endDate=YYYY-MM-DD

Sandbox example (Postman / curl) — to be validated once UTA has Transaction Details API mock or CAT access. Mock URL [CONFIRM with JPM Integration Manager] — the OAS only declares production + CAT servers, no separate mock.

Intraday call (CNB §5.1 equivalent):

GET https://openbanking.jpmorgan.com/tsapi/v3/transactions
  ?accountIds=123456789,987654321
  &relativeDateType=CURRENT_DAY
  &lockbox%20information=true
Headers:
  Accept: application/json
  Authorization: Bearer <OAuth-access-token>      ← Reader role required
  (mTLS handshake at the transport layer)

Prior-day call (CNB §5.2 equivalent):

GET https://openbanking.jpmorgan.com/tsapi/v3/transactions
  ?accountIds=123456789,987654321
  &relativeDateType=PRIOR_DAY
  &lockbox%20information=true
Headers: same as above

Custom range (backfill, max 5 days):

GET https://openbanking.jpmorgan.com/tsapi/v3/transactions
  ?accountIds=123456789
  &startDate=2026-05-06
  &endDate=2026-05-10
  &lockbox%20information=true
  &pageNumber=1

Note on lockbox information parameter: the OAS literally declares the parameter name with a space — name: lockbox information. URL-encoded that's lockbox%20information. Test in CAT whether JPM's validator accepts the literal space or only the URL-encoded form; some HTTP clients refuse to send unencoded spaces in query strings. [CONFIRM in Postman / CAT]

Error codes (verbatim from OAS v3.1.8):

HTTPCodeMeaning
400GCA-006End Date cannot be less than the Start Date
400GCA-018Invalid parameter combination: startDate + relativeDateType
400GCA-019Invalid parameter combination: endDate + relativeDateType
400GCA-020relativeDateType value invalid (must be CURRENT_DAY or PRIOR_DAY)
400GCA-026Date format invalid (use yyyy-MM-dd)
400GCA-065Date range cannot exceed 5 days
400GCA-106lockbox information must be true or false
400GCA-107Date format invalid (use yyyy-MM-ddTHH:mm:ss.SSSSSS) — applies to a sub-field
400GCA-132pageNumber must be greater than 0
403GCA-001 / GCA-003Client not eligible for the API service
403GCA-009The requested accounts were not found
403GCA-022No eligible accounts were found
503GCA-099System is unavailable

Error envelope shape: { "errorCode": "GCA-006", "errorMsg": "End Date cannot be less than the Start Date" }. Flat envelope with no nested context[] array.

Open items specific to this section:

  • The OAS doesn't declare a Mock server, only Production + multiple CAT/UAT — confirm whether sandbox testing is via CAT (with sandbox credentials) or via a separate mock host. [CONFIRM with JPM Integration Manager]
  • BAI Type Code list — the OAS doesn't enumerate every BAI Type Code JPM returns. UTA's existing CNB BAI2 parser already handles the standard BAI2 codes (115, 165, 195, 475, 935 RETURN WIRE, etc.); confirm JPM uses the same code dictionary. [CONFIRM with JPM]
  • lockbox information parameter — literal space vs URL-encoded space — see note above
  • EOL timeline for Transaction Details API (LEGACY tier)closed/de-prioritized 2026-05-12 (§12 #28). Per Jessica Jin, UTA cannot migrate to BDC regardless of EOL timing (corporate-segment ineligibility). Re-open only if JPM announces an Access-platform replacement for corporate clients.

6.2 Account Balances API — EOD Balance Anchor for Three-Way Match (CNB §9 "Brakes")

Status: Cleared (Phase 1) — JPM-prescribed product per the Treasury Reporting Playbook  |  Channel: REST polling (OAuth or mTLS)  |  Sequence: Wave 1

Purpose: Bank-side balance snapshot for the "Brakes" half of the Three-Way Match (§9). Confirms the closed-cycle ledger balance UTA's sub-ledger must match against before closing each reconciliation cycle. Companion to §6.1 Transaction Details API; both are prescribed by JPM's Reporting Playbook.

OAS verified against Account Balances API v1.0.5 OpenAPI 3.0.0 spec on 2026-05-11 — see Playbook/Account Balances API 1.0.5.yaml.

AttributeValue
EndpointPOST /balance (operationId retrieve-balances). NOTE: this is a POSTaccountList and date params live in the request body, not query string
Base URLs (from OAS)Production OAuth: https://openbanking.jpmorgan.com/accessapi · Production mTLS: https://apigateway.jpmorgan.com/accessapi · CAT/UAT OAuth: https://openbankinguat.jpmorgan.com/accessapi · CAT mTLS: https://apigatewayqaf.jpmorgan.com/accessapi. Different base path than Transaction Details (/accessapi vs /tsapi/v3) — UTA's HTTP client config must support both
Auth modelOAS x-jpmc-security: {} is an empty placeholder, but the server descriptions explicitly call out OAUTH and MTLS tiers — same dual-auth model as Transaction Details. [CONFIRM with JPM] the exact OAuth scope/role for the Account Balances API
Request modes (mutually exclusive)(A) Date range: startDate + endDate (both YYYY-MM-DD), max 31-day window (error GCA-005) — more lenient than Transaction Details' 5-day cap, which makes sense for balance snapshots that don't change minute-to-minute. (B) Relative date: relativeDateType: CURRENT_DAY | PRIOR_DAY
Multi-account in one callaccountList[] array of { accountId } objects — single POST returns balances across multiple accounts
Conflict errorsGCA-018/019 if startDate/endDate combined with relativeDateType; GCA-021 if accountId missing

Request body shape (verified against OAS):

json
{
  "relativeDateType": "CURRENT_DAY",       // OR: startDate + endDate
  "accountList": [
    { "accountId": "00000000000000304266256" },
    { "accountId": "00000000000000010962009" }
  ]
}

OR for a date range:

json
{
  "startDate": "2026-05-06",
  "endDate": "2026-05-10",
  "accountList": [
    { "accountId": "00000000000000304266256" }
  ]
}

Response body shape (verified against OAS):

json
{
  "accountList": [
    {
      "accountId": "123456789",
      "accountName": "ABC INC",
      "branchId": "",
      "bankId": "2100002",
      "bankName": "JPMORGAN CHASE BANK, N.A. - NEW YORK",
      "currency": {
        "code": "USD",
        "currencySequence": 0,
        "decimalLocation": 2,
        "description": "US DOLLAR"
      },
      "balanceList": [
        {
          "asOfDate": "2023-01-17",
          "recordTimestamp": "2023-01-17T13:47:41Z",
          "currentDay": true,
          "openingAvailableAmount": 7783394.91,
          "openingLedgerAmount": 7783394.91,
          "endingAvailableAmount": 21311879.19,
          "endingLedgerAmount": 21311879.19
        }
      ]
    }
  ]
}

Balance fields explained (carry into §9 Three-Way Match):

FieldMeaningUTA usage
asOfDateThe business date this balance representsMatch against UTA's GL cycle date
recordTimestampWhen JPM recorded this balance snapshot (ISO 8601 datetime, UTC)For audit trail
currentDay (boolean)true = this is today's balance; false = historical/prior-dayUTA's logic distinguishes provisional vs settled
openingAvailableAmountAvailable balance at start of day (excludes float not yet available)T-1 closing should match T0 opening
openingLedgerAmountLedger balance at start of day (includes all posted items, no float adjustment)Audit ledger continuity
endingAvailableAmountAvailable balance at end of dayPRIMARY "Brakes" field for Three-Way Match §9
endingLedgerAmountLedger balance at end of dayCross-check against endingAvailableAmount to detect float discrepancies

Recommended polling cadence (carries from v2.2 + Reporting Playbook):

Use caseCadenceMode
End-of-day balance lock~10:00 PM local time Mon–FrirelativeDateType: CURRENT_DAY — captures endingLedgerAmount after settlement
Prior-day opening balance confirm~7:30 AM local time Mon–SatrelativeDateType: PRIOR_DAY — confirms T-1 ending matched UTA's books
Back-fill / catch-upOn demand, max 31-day windowstartDate + endDate

Unavailability fallback (carries from prior spec drafts): if the API is unavailable at the scheduled EOD close: (1) log failure with timestamp, (2) retry at 10-min intervals for up to 60 min, (3) if still unavailable, flag the cycle as PENDING_BANK_CONFIRMATION and alert the GL manager. Do not close the reconciliation cycle without a confirmed bank balance.

Sandbox example (Postman / curl) — to be validated once CAT access is provisioned:

End-of-day balance lock (current-day):

POST https://openbanking.jpmorgan.com/accessapi/balance
Headers:
  Accept: application/json
  Content-Type: application/json
  Authorization: Bearer <OAuth-access-token>
  (mTLS handshake at transport layer)
Body:
{
  "relativeDateType": "CURRENT_DAY",
  "accountList": [ { "accountId": "<klutch-account-number>" } ]
}

Prior-day confirm:

POST https://openbanking.jpmorgan.com/accessapi/balance
Headers: (same)
Body:
{
  "relativeDateType": "PRIOR_DAY",
  "accountList": [ { "accountId": "<klutch-account-number>" } ]
}

Error codes (verbatim from OAS v1.0.5 — note: many return HTTP 200 with an errors[] body, per the OAS 200 Errors response):

CodeDescription
GCA-001 / GCA-003Unauthorized Access
GCA-005Date range cannot exceed 31 days (more lenient than Transaction Details' 5 days)
GCA-006End Date cannot be less than the Start Date
GCA-009The requested accounts were not found
GCA-010The account was not found
GCA-018Invalid parameter combination: startDate + relativeDateType
GCA-019Invalid parameter combination: endDate + relativeDateType
GCA-020relativeDateType value invalid (must be CURRENT_DAY or PRIOR_DAY)
GCA-021Account ID is required
GCA-022No eligible accounts were found
GCA-023Request format invalid
GCA-024No transaction was found for this transaction on the requested day
GCA-025No transactions were found for this account in the requested date range
GCA-026Date format invalid (use yyyy-MM-dd)
GCA-068Access Denied to all accounts: Not entitled to the required countries via the Preta Registry Role
GCA-076Access Denied: Not entitled to required country via Preta Registry Role
GCA-099System is Unavailable

Error envelope shape: { "errors": [ { "errorCode": "GCA-006", "errorMsg": "..." } ] }. Slightly different from Transaction Details (which uses a flat { errorCode, errorMsg } not an errors[] wrapper).

Open items specific to this section:

  • OAS x-jpmc-security: {} is an empty placeholder. [CONFIRM with JPM Integration Manager] the exact OAuth scope/role for Account Balances (likely "Reader" by analogy to Transaction Details, but unverified)
  • Preta Registry Role error codes (GCA-068, GCA-076) suggest country-level entitlements. [CONFIRM with JPM] what Preta Registry Role UTA needs for US accounts
  • HTTP status codes for errors — OAS bundles them as "200 Errors". Test in CAT whether errors actually come back with HTTP 200 + errors[] body, or with non-200 status codes. [CONFIRM in Postman/CAT]

Source basis: Account Balances API OAS v1.0.5 — authoritative · US JPM API Playbook — Reporting v1 — Account Balances JSON sample on Playbook p. 36.

6.3 Monthly Statements (PDF) — Out of API scope in Phase 1

Status: Deferred — no API path available to UTA  |  Channel: Manual download from JPM Access UI (Phase 1); API path [CONFIRM with JPM]  |  Sequence: Phase 2

Purpose: Monthly statement PDF retrieval for retention/compliance archive.

State (2026-05-12): JPM's documented Statements PDF API lives inside the Business Direct Connect (FDX v6) product — not available to UTA. Per Jessica Jin 2026-05-12, BDC is JPM's commercial-segment product; UTA is corporate-segment on the Access platform and cannot use BDC (see §14.9 BDC entry marked OUT OF SCOPE, §12 #9 / #10 / #11 / #26 / #28).

Phase 1 workaround: UTA's compliance team continues to download monthly PDF statements manually from the JPM Access UI, same as today's pre-integration workflow.

Open question for kickoff call with Jessica's implementation team: does JPM offer an Access-platform statement-retrieval API (analogous to BDC's /accounts/{accountId}/statements/{statementId} but on the corporate-segment side)? If yes, scope it into Phase 2. If no, the manual JPM Access download remains UTA's only path. Tracked as §12 #41.

Source basis: Jessica Jin 2026-05-12 (BDC ineligibility for UTA) · §14.9 Local Documents — OAS files BDC v6.2.16 row marked OUT OF SCOPE.

6.4 Check Image Retrieval — outgoing checks cleared

Status: Cleared (full OAS verified)  |  Channel: REST POST  |  Sequence: Wave 2

Purpose: Retrieve front + back images of cleared outgoing checks for audit and dispute support. (Electronic checks do not have associated images, per OAS CheckType enum.)

OAS verified against Checks API v2.1.1 OpenAPI 3.1.0 spec on 2026-05-12 — see Playbook/Checks API 2.1.1.yaml.

AttributeValue
Production base URLhttps://api.payments.jpmorgan.com/payable/v2
Mock base URLhttps://api-mock.payments.jpmorgan.com/payable/v2 (matches Jessica Jin 2026-03-03 confirmation)
EndpointPOST /checks/images/search
AuthmTLS
Required body fieldsdebtor (with accountNumber), checks (with checkNumbers[] 1–5 items OR checkRange.{start, end})
Filter fieldsissueDateGte/issueDateLte (1-year window), postedDateGte/postedDateLte (1-year window), amountGte/amountLte, checkSequenceNumber
Paginationlimit (1–10, default 5; range searches max 10), offset (0–999)
imageFormatTIFF | PNG | JPEG (default PNG)
Response shapeCheckImageCollectionResponsecheckImages[] with frontImage and backImage as base64-encoded strings, plus pagination metadata and requestInvocationId

Sample request — single check image:

json
{
  "debtor":      { "accountNumber": "1234567" },
  "checks":      { "checkNumbers": ["1005"] },
  "issueDateGte":"2026-01-01",
  "issueDateLte":"2026-03-31",
  "imageFormat": "TIFF",
  "limit": 1, "offset": 0
}

Sample response (verbatim shape from OAS example):

json
{
  "checkImages": [{
    "checkNumber": "1005",
    "checkAmount": { "amount": "205.05", "currency": "USD" },
    "debtor":      { "accountNumber": "1234567" },
    "paidDate":    "2026-04-01",
    "frontImage":  "<base64...>",
    "backImage":   "<base64...>",
    "imageFormat": "TIFF",
    "checkType":   "CUSTOMER_CHECK"
  }],
  "pagination":          { "offset": 0, "limit": 1, "totalCount": 1 },
  "requestInvocationId": "n8a40v3r-3769-4o79-9z0l-ale1edc90389"
}

Source basis: Checks API v2.1.1 OAS — authoritative · Checks → Check Image overview · Check Image parameters · Jessica Jin 2026-03-03 (mock base URL confirmation).

6.5 Payment Receipts API — inbound RTP credit confirmation

Status: Cleared (full OAS verified) — RTP only  |  Channel: Webhook (JPM → UTA)  |  Sequence: Wave 1

Purpose: Real-time push of every inbound credit on UTA's accounts — eliminates manual polling for incoming client payments (deal-payment intake from sports teams, brands, and sponsors on Trust; commission / agency-fee credits on Operating) on supported RTP networks. Conceptually a real-time alternative to discovering the same credit later via §6.1 Transaction Details API polling.

OAS verified against Payment Receipts v1.2.0 OpenAPI 3.0.0 spec on 2026-05-11 — see Playbook/Payment Receipts 1.2.0.yaml. Title in OAS: "Payment Receipts."

AttributeValue
MechanismWebhook push (JPM → UTA) — JPM-side declares this as a sample callback endpoint; UTA hosts the actual receiver
JPM-side OAS callback path/webhook/credit-confirmation (POST, JSON body)
Receiver path (UTA-side){YOUR-SERVER-DOMAIN}/creditConfirmation per OAS callback example — UTA's actual URL will be configured during onboarding
Auth modelOAS x-jpmc-security: {} is empty placeholder. [CONFIRM with JPM Integration Manager] the inbound webhook signature scheme — same gap as GP2 Callbacks (§6.6, §12 #2)
Network coverageRTP-only at time of writing. OAS examples cover Singapore IRCT, UK FPS Agency Banking. Per developer-portal narrative, also supports: US RTP (TCH), US FedNow, SEPA Inst, AU NPP, HK FPS, IDR, MYR, SGD, MXN SPEI, BRL PIX
No US RTP example in OASThe OAS schema supports US RTP (clearing-system IDs, BIC, accountType: DDA, all present) but the 2 verbatim examples in the OAS are Singapore and UK — not US. The schema covers it; verify shape in CAT. [CONFIRM in CAT] the exact US RTP payload shape
Network coverage — wire / ACHNOT documented as supported. UTA's only inbound visibility for wire / ACH credits is Transaction Details API polling (§6.1) and Account Balances API at EOD (§6.2) — [CONFIRM with JPM] whether wire / ACH inbound webhook is on the roadmap

Webhook payload — top-level shape (verified against OAS):

json
{
  "creditConfirmation": {
    "eventId": "e24534b3-0251-4198-b408-e8f85a257d7e",
    "createDateTime": "2021-12-13T14:00:57.751Z",
    "transactionDetails": { /* see fields below */ }
  }
}

creditConfirmation.transactionDetails fields (full OAS v1.2.0 schema):

FieldTypeNotes — UTA usage
Identifiers
endToEndIdstringCustomer-assigned reference; max length varies by market (UK FPS: 31 chars per OAS). Primary AR auto-match key
firmRootIdstringJPM-assigned unique ID for this transaction. Preferred for cross-system joins within UTA's sub-ledger
bankReferenceNumberstringBank-assigned reference (trace number, Fed Reference for wire)
clearingSystemReferencestringReference assigned by the clearing system (Central Bank, RTP network)
transactionIdstringUnique ID from the first instructing agent (passed unchanged through interbank chain)
instructionIdstringUnique instruction ID from instructing party for instructed party
Amounts and dates
valueDatedate (YYYY-MM-DD)When funds become available to UTA (the creditor)
statusstringTransaction status (example: COMPLETED)
paymentAmountnumberAmount credited to UTA
paymentCurrencystring (ISO 4217)Klutch credits will be USD
Payment type
paymentTypeInformation.localInstrument.prtrystring (pattern ^[-_.A-Z0-9]{1,35}$)Proprietary local-instrument code (e.g., ImmediatePayment for UK FPS)
relatedParties.debtorobjectThe party SENDING the money TO UTA
relatedParties.debtor.debtorNamestringRequired for some markets
relatedParties.debtor.countryOfResidencestring (2-char ISO)
relatedParties.debtor.postalAddressobjectFull postal address with addressType (enum: ADDR/BIZZ/DLVY/HOME/MLTO/PBOX), streetName, buildingNumber, postalCode, townName, countrySubDvsn, country, addressLine[] (1-4 lines, max 40 chars each)
relatedParties.debtor.debtorAccount.accountIdstringDebtor's account at the sending bank
relatedParties.debtor.debtorAccount.accountTypeenum: DDACurrently only DDA in OAS
relatedParties.debtor.debtorAccount.accountCurrencystring
relatedParties.debtor.ultimateDebtorobjectIf the payment passed through an intermediary, the originator of the funds
relatedParties.creditorobjectUTA (the party RECEIVING the money)
relatedParties.creditor.creditorNamestringUTA's account name; required for India, UK, US RTP, SEPA Instant
relatedParties.creditor.creditorAccount.accountIdstringUTA's Klutch account number
relatedParties.creditor.creditorAccount.accountTypestringDDA expected
relatedAgents
relatedAgents.debtorAgent.financialInstitutionId.bicstring (max 11)Sending bank's SWIFT BIC; required for UK/India/SG/AU/MY
relatedAgents.debtorAgent.financialInstitutionId.clearingSystemId.idstringSending bank's clearing-system ID (alt to BIC)
relatedAgents.creditorAgent.financialInstitutionId.bicstringJPM's BIC (CHASGB2L, CHASUS33, etc.) — receiving bank
Purpose
purpose.codestringPayment purpose code (e.g., GDDS for goods)
purpose.typeenum: CODE | PROPRIETARY
remittanceInformationobjectPRIMARY auto-match payload — read this for invoice numbers
remittanceInformation.unstructuredInformationarray of stringsFree-form text remittance — example: ["FOR INVOICE: 2020-078-07-00001"]. Max 1 line × 140 chars for UK FPS. UTA's parser regex-matches invoice numbers out of this field. Shape note: outbound GP2 wires (§7.5) use [{text: "..."}] (array of objects) per Jessica Jin 2026-05-12 — UTA's builder/parser code must handle both directional shapes
remittanceInformation.structuredInformation[].creditReferencestring (max 140)Structured payment reference — when present, contains the unambiguous payment reference. UTA matches on this directly
remittanceInformation.structuredInformation[].additionalRemittanceInformationstring (max 250)Applicable to MY FPS and UK FPS. Carries additional structured remittance
relatedTransactions[]arrayOptional. If this payment is a response to a Request-for-Payment, links back to the original RFP transaction by endToEndId/firmRootId/bankReferenceNumber
taxInformationobjectMexico-specific (mandatory for MX credit confirmations)
taxInformation.debtorTaxInformation.taxIdstring12 chars for corporates, 13 for individuals (Mexico)
taxInformation.debtorTaxInformation.taxpayerCategoryenum: INDIVIDUAL | CORPORATE
taxInformation.taxAmountnumber

OAS verbatim example — UK FPS Agency Banking inbound credit (GBP 250):

json
{
  "creditConfirmation": {
    "eventId": "972cf023-c185-4ffb-b63e-d47940c6c1e2",
    "createDateTime": "2025-04-01T11:00:57.751Z",
    "transactionDetails": {
      "endToEndId": "RGB7000800901",
      "bankReferenceNumber": "0RNFV599KLMN",
      "clearingSystemReference": "KACE89HGT090877",
      "firmRootId": "2ee43056-92df-496c-832d-da6453b3d6ad",
      "valueDate": "2025-04-01",
      "status": "COMPLETED",
      "paymentTypeInformation": { "localInstrument": { "prtry": "ImmediatePayment" } },
      "paymentAmount": 250,
      "paymentCurrency": "GBP",
      "relatedParties": {
        "debtor": {
          "debtorName": "Emily Davis",
          "countryOfResidence": "UK",
          "debtorAccount": { "accountType": "DDA", "accountCurrency": "GBP", "accountId": "8880000000" }
        },
        "creditor": {
          "creditorName": "Softech Inc",
          "creditorAccount": { "accountType": "DDA", "accountCurrency": "GBP", "accountId": "7770000000" }
        }
      },
      "relatedAgents": {
        "debtorAgent": { "financialInstitutionId": { "bic": "CHASGB2L" } },
        "creditorAgent": { "financialInstitutionId": { "bic": "CHASGB2L" } }
      },
      "purpose": { "code": "GDDS", "type": "CODE" },
      "remittanceInformation": {
        "structuredInformation": [{
          "additionalRemittanceInformation": "/TPP/0014H00001lFE7VQAW/SWI/SOFTWAREID/"
        }]
      }
    }
  }
}

AR auto-match logic for UTA:

  1. First pass: match on remittanceInformation.structuredInformation[].creditReference (when present) against UTA's open invoice list — exact match
  2. Second pass: regex-extract invoice number patterns from remittanceInformation.unstructuredInformation[] strings (e.g., INV-\d{4,}, PO-\d+)
  3. Third pass (fallback): match on endToEndId if UTA originated a Request-for-Payment with that reference
  4. Unmatched credits: queue for manual GL review with all received metadata for human disambiguation

Source basis: Payment Receipts OAS v1.2.0 — authoritative · OAS examples for Singapore IRCT and UK FPS Agency Banking verbatim · sandbox verification when CAT lands.

6.6 GP2 Callbacks — outbound payment status events (CloudEvents)

Status: Confirm-Blocked (event type enum; signature scheme)  |  Channel: Webhook  |  Sequence: Wave 1

Purpose: Real-time push of every status change on UTA-initiated GP2 payments — the primary status surface for outbound RTP, ACH, and Wire flows. Documented here in §6 because it arrives via webhook from JPM, but the polling fallback contract for the same events lives in §8 alongside the rest of the Status Inquiry strategy.

OAS verified against Global Payments v2.4.7 OpenAPI 3.0.1 spec on 2026-05-08. Webhook composition: Webhook = Event + PaymentEventData (per OAS Webhook schema, allOf: [Event, PaymentEventData]).

AttributeValue
MechanismWebhook push (JPM → UTA) — declared as a callbacks block under the createPayment operation in the GP2 OAS
EnvelopeCloudEvents v1.0 (Event schema's specversion field defaults to "1.0")
Receiver path (UTA-side)https://callbacks.uta.example/jpm/gp2/payment-events (UTA-defined; example)
OAS-required envelope fieldsid (string), specversion ("1.0"), type (string), time (RFC 3339 date-time), source (URI-reference), data (object). dataschema is optional
data payload type`oneOf: PaymentEvent
data.payments[] (PaymentEvent case)Array of PaymentStatus objects, 1–50 items per webhook (per OAS — webhook can batch up to 50 status updates in one delivery)
data.returns[] (PaymentReturnEvent case)Array of PaymentReturnStatus objects, always 1 item (OAS minItems: 1, maxItems: 1)
Documented event examples in OASAlternate Payments - Push To Card Status, Alternate Payments - Push To Card - TP3 Status, Alternate Payments - Push To Card - TP3 Rejected Status, Alternate Payments - Kinexys Digital Payments (DDA to BDA) Completed Status, ACH Batch, RTP - BR PIX Payment Return. The exact CloudEvent type string for each (e.g., Payment.Completed, Payment.Rejected, or rail-specific variants) is NOT enumerated in the OAS[CONFIRM with JPM] for the complete type enum
PaymentStatus.paymentStatus enum (7 values)RECEIVED | ACCEPTED | PROCESSING | CANCELED | REJECTED | COMPLETED | RETURNED
PaymentStatus.paymentSubStatus enum (17 values)RECEIVED, ACCEPTED, PROCESSING_BY_JPM, PENDING_CLIENT_ACTION, PENDING_COMPLIANCE_REVIEW, PENDING_FRAUD_REVIEW, PENDING_FUNDING_REVIEW, PENDING_JPM_REVIEW, SCHEDULED, PENDING_POSTING, CANCELED, REJECTED, REJECTED_BY_JPM, COMPLETED_BY_JPM, SENT_TO_CLEARING, DELIVERED_TO_RECIPIENT, RETURNED
PaymentStatus required fieldspaymentId, paymentStatus, statusUpdatedAt, paymentIdentifiers, paymentType, transferType, requestedExecutionDate
PaymentStatus join keyspaymentId (JPM UUID — primary), paymentIdentifiers.endToEndId (UTA-supplied), clearingSystem.reference (network reference), and paymentIdentifiers.otherPaymentReferences.uetr (SWIFT GPI 36-char tracking, for wires/cross-border)
PaymentStatus.exceptions[]When status is REJECTED or CANCELED, populated with ErrorContext[] (1–100 items) carrying the 5-digit JPMC error code, message, location, field, and optional additionalContext (ISO 20022 / NACHA standard codes via StandardCodeContext)
PaymentStatus.fxInformationRead-only FX details on settled cross-currency wires — exchangeRate, exchangeRateType, rateId, contractId
PaymentStatus.gpi.statusSWIFT GPI status for wire payments — separate from JPM's internal status, sourced from the SWIFT network directly
Delivery SLA"Typically within 30 seconds" of the status change (per developer-portal docs; not stated in OAS)
Retry behavior"Automatically retry the request until the error is resolved" (per developer-portal docs). Backoff curve, max attempts, and DLQ behavior [CONFIRM with JPM]
Ordering guaranteesNot specified — [CONFIRM with JPM]
Inbound signature schemeOAS shows no security block on the webhook operation. [CONFIRM with JPM] what authentication JPM uses when pushing to UTA's receiver (mTLS-only, HMAC, JWT, etc.) — see §4.5
IdempotencyUse the CloudEvent id field (Event.id) as UTA's dedup key. The contract is implied but not stated — [CONFIRM with JPM]

Sample payload — Payment Completed:

json
{
  "specversion": "1.0",
  "id": "ec521d12-416e-4f48-a1b8-1d61e40146d2",
  "time": "2025-07-18T07:03:22.503+00:00",
  "type": "Payment.Completed",
  "source": "payment/v2/payments?endToEndId=IMPS_0718123057",
  "dataschema": "urn:com.jpmorgan.payments/payment-event",
  "data": {
    "payments": [{
      "paymentId": "01981c56-0e48-7000-bfec-6fb5be1b3cc0",
      "requestedExecutionDate": "2025-01-06",
      "paymentStatus": "COMPLETED",
      "paymentSubStatus": "COMPLETED_BY_JPM",
      "statusUpdatedAt": "2025-07-18T07:03:22.503+00:00",
      "paymentIdentifiers": { "endToEndId": "IMPS_0718123057" },
      "paymentType": "RTP",
      "transferType": "CREDIT",
      "clearingSystem": { "reference": "D49KMSHY8GG2" }
    }]
  }
}

Sub-ledger action mapping (subset; full table in §8):

paymentStatus × paymentSubStatusGL action
ACCEPTED × ACCEPTEDCreate draft sub-ledger entry
PROCESSING × PROCESSING_BY_JPMNo action; await next event
PROCESSING × PENDING_COMPLIANCE_REVIEWFlag for monitoring; do not post
COMPLETED × COMPLETED_BY_JPMPost to NetSuite GL
COMPLETED × DELIVERED_TO_RECIPIENTPost to NetSuite GL
REJECTED × REJECTED_BY_JPMReverse draft entry; parse exceptions[].code
RETURNED × RETURNEDPost return JE; notify AR

Source basis: GP2 Callbacks · GP2 OpenAPI Spec · GP2 Status Responses & Error Codes · JPM Integration Manager (2026-03).


7. Outbound Payment Services

Every service in this section initiates an action from UTA into JPM via REST.

7.1 Validation Services — "Pre-Flight"

Status: Cleared (full OAS verified) — Pre-Flight gates §7.2–§7.5  |  Channel: REST POST (sync) + optional {client-url}/status callback (async)  |  Sequence: Wave 1

Purpose: Validate beneficiary account ownership AND entity identity/screening before any payment initiation. UTA runs every new payee through this gate before its first outbound payment, and re-runs on any payee whose details have changed. Reduces misdirected funds, mitigates fraud loss, and lowers payment-return rates.

OAS verified against Validation Services API v2.2.3 OpenAPI 3.0.1 spec on 2026-05-12 — see Playbook/Validation Services API 2.2.3.yaml. Title in OAS: "Validation Services API."

AttributeValue
Production base URL (mTLS)https://apigateway.jpmorgan.com/tsapi/v2
CAT base URL (mTLS)https://apigatewaycat.jpmorgan.com/tsapi/v2
Mock base URLhttps://api-mock.payments.jpmorgan.com/tsapi/v2
Entity validation endpointPOST /validations/entities
Account validation endpointPOST /validations/accounts
Request body shapeArray — both endpoints accept a batch of validations in one call (minItems: 0, no upper bound documented). Response is also an array, item-by-item correlated by requestId
Required headersx-client-id (per-customer ID assigned at onboarding), x-program-id (per Validation Services product, e.g., VERIAUTH, VERIAUTHMULTI, VERIAUTHNONUS, VERIAUTHUS, SUREPAYVOP)
Optional headerx-program-id-type — defaults to AVS; identifies processing settings selected for the product
AuthmTLS only — x-jpmc-securityDefinitions: MutualTLS (type: x509). No Digital Signature requirement on this API — distinct from GP2's JWS+RS256 stack. Closes the [CONFIRM] from v2.2
Async callback supportBoth endpoints declare a validationStatus callback at {client-url}/status (POST). Async path is used for validators that cannot return synchronously — primarily microdeposit Challenge flows. Callback payload = same ResponseCollection schema as the synchronous 200
Per-customer valuesx-client-id / x-program-id actual values are issued at customer onboarding (§12 #38 carries this open item)

Profile selection (profileName body field, per OAS examples):

Profilex-program-id exampleUse case
Standard Account Validation (no profileName)VERIAUTHSynchronous account-ownership check — UTA's default for new US payees
Multi-line account validationVERIAUTHMULTIBatched account validation calls with transactions[] populated
Global Account ValidationVERIAUTHNONUSInternational accounts (accountNumberType: IBAN, idType: SWIFT_ID / BIC) — UTA's path for cross-border wire beneficiaries
Account Confidence Score (ACS)VERIAUTHUSReturns RAG-banded numeric score in addition to verification — US-only
Microdeposit (profileName: verificationauth)PROGRAMIDTwo-step flow: Initial call sends two small deposits to the target account; Challenge call asks the customer to confirm the amounts. ACH (idType: ABA) and RTP (idType: RTPABA) variants both supported
SurePay VOP (profileName: SPIndividual / SPOrganization)SUREPAYVOPVerification of Payee for European IBAN beneficiaries

Account Confidence Score (ACS) — OAS vs dev-portal mismatch (must resolve with Jessica before relying on ACS in Pre-Flight logic):

The OAS-confirmed AccountScore schema (lines 1093–1112 of Validation Services API 2.2.3.yaml) is {code: integer, message: string} — example values 1109 "Information Found" / 1209 "No Information Found". No numeric 0–1000 score field appears anywhere in the OAS. JPM's dev portal narrative documents a 0–1000 RAG-banded numeric score; the OAS does not expose it. Possibilities to confirm:

  • The numeric score is returned inside the details block for VERIAUTHUS-profile responses (undocumented in OAS).
  • The dev-portal narrative is out of step with the current schema (OAS supersedes).
  • The numeric score is computed internally and only the coded bucket (1109/1209) surfaces.

Filed as §12 #42 — confirm with Jessica which slot/field carries the 0–1000 score for the ACS profile, or whether the only consumable signal is the coded AccountScore.code.

ACS bucketing per dev-portal narrative (treat as unconfirmed against OAS):

ScoreRAGMeaning
0REDHigh risk of potential fraud or compromise
1–199REDLow-confidence range
200–599AMBERMedium-confidence range
600–1000GREENHigh-confidence range

ACS code prefixes per OAS examples: 11## = "Information Found", 12## = "No Information Found." US-only.

Account validation request fields — AccountDetails schema:

FieldTypeNotes
requestId (required)string (max 75, ^[a-zA-Z0-9\-]+$)UTA-generated unique ID per validation request; UUID recommended
clientReferenceIdstring (max 75)Optional UTA-side reference (e.g., payee record ID) — echoed back
account.accountNumber (required)string (4–17 chars, alphanumeric)The beneficiary account number
account.accountNumberTypestringExamples: CLABE, DDA, IBAN
account.financialInstitutionId.clearingSystemId.id (required)stringRouting number / BIC / IBAN-derived ID
account.financialInstitutionId.clearingSystemId.idType (required)enumCLABE | INFSC | IBAN | ABA | RTPABA | SWIFT_ID
account.financialInstitutionId.bicstringOptional alternate to clearingSystemId for SWIFT-routed accounts
entityoneOf: Individual | OrganizationOptional but recommended — drives ownership-match logic populating Result.authentication
transactions[]array of TransactionRequired for microdeposit Challenge calls; carries the amounts the customer is confirming. Each item: context: ACCOUNT_VALIDATION, amount.{amount, currency}
profileNamestringSelects the validation profile (see table above)

Provider list (verbatim from OAS Response.provider description):

EndpointProviders
/validations/accountsJPMC, JPMC_BENE, JPMC_ACH, GIACT, MICRODEPOSITS, EWS, EWS_VA, PATTERN_MATCH (OAS examples also show SUREPAY_VOP for the SurePay profile)
/validations/entitiesJPMC, JPMC_SCREENING, LEXISNEXIS, LEXISNEXIS_INSTANT_ID, LEXISNEXIS_BUSINESS_V2, GIACT_BUSINESS, GIACT_INDIVIDUAL, TRULIOO_INDIVIDUAL, TRULIOO_BUSINESS

(Note: v2.2 spec listed SUREPAY_IBAN and JPMC_LIINK_CONFIRM — neither appears in OAS v2.2.3. Treat as deprecated/renamed; trust the OAS list.)

Response — ResponseCollection shape (echoed requestId, batch-aligned by index):

json
{
  "requestId":         "<echoed back>",
  "clientReferenceId": "<echoed back>",
  "profileName":       "<echoed back>",
  "responses": [
    {
      "codes":    { /* ResultCollection — see below */ },
      "provider": "JPMC_ACH",
      "details":  { /* provider-specific shape */ }
    }
  ]
}

ResultCollection — named result slots (Pre-Flight reads only the slots that apply to the profile run):

SlotUsed forExample code
verificationAccount is open and valid1002 "Open Valid"
authenticationAccount ownership matches the entity payload5002 "Ownership Match"
individualIDIndividual identity verification (Entity Validation)1101 "Pass"
businessIDOrganization identity verification (Entity Validation)2101 "Pass"
individualScreeningSanctions / PEP screening for an individual4609 "Potential Hit"
businessScreeningSanctions / PEP screening for an organization5609 "Potential Hit"
verificationMicrodepositMicrodeposit flow — verification step
authenticationMicrodepositMicrodeposit flow — authentication step
limitAmountTransaction-limit verification
accountScoreACS numeric score (separate AccountScore shape: {code, message})1109 Information Found
errorOperational error (see error-code table below)9005 Bad Request

Result.message semantics — first digit of Result.code indicates result class (per OAS Result.message description):

First digitClass
1Open Valid / Pass
2Closed Invalid
3No Information Found
4Debit Return Likely / Potential Hit (screening)
5Ownership Match
6Ownership No Match
7No Information Found
9Operational error (see error-code table below)

Sample request — Standard US account validation:

json
[
  {
    "requestId": "123e4567-e89b-12d3-a456-426614174000",
    "clientReferenceId": "UTA-payee-12345",
    "account": {
      "accountNumber": "12345",
      "financialInstitutionId": {
        "clearingSystemId": { "id": "122199983", "idType": "ABA" }
      }
    },
    "entity": {
      "individual": { "firstName": "Jane", "lastName": "Abbot", "fullName": "Jane Abbot" }
    }
  }
]

Sample response — Account open, ownership matches (verbatim from OAS):

json
[
  {
    "requestId": "123e4567-e89b-12d3-a456-426614174000",
    "clientReferenceId": "UTA-payee-12345",
    "responses": [
      {
        "codes": {
          "verification":   { "code": 1002, "message": "Open Valid" },
          "authentication": { "code": 5002, "message": "Ownership Match" }
        },
        "provider": "JPMC_ACH",
        "details": {
          "paymentCheckContributingStatus": "Contributed",
          "accountNumber": "XXXX5",
          "financialInstitutionId": {
            "clearingSystemId": { "id": "122199983", "idType": "ABA" }
          }
        }
      }
    ]
  }
]

Sample response — Account Confidence Score (ACS) profile, x-program-id: VERIAUTHUS (synthesized from the OAS AccountScore schema — the OAS does not publish a full ACS response example; flagged as §12 #42):

json
[
  {
    "requestId": "123e4567-e89b-12d3-a456-426614174000",
    "clientReferenceId": "UTA-payee-12345",
    "responses": [
      {
        "codes": {
          "verification":   { "code": 1002, "message": "Open Valid" },
          "authentication": { "code": 5002, "message": "Ownership Match" },
          "accountScore":   { "code": 1109, "message": "Information Found" }
        },
        "provider": "JPMC_ACH",
        "details": {
          "paymentCheckContributingStatus": "Contributed",
          "accountNumber": "XXXX5",
          "financialInstitutionId": {
            "clearingSystemId": { "id": "122199983", "idType": "ABA" }
          }
        }
      }
    ]
  }
]

Note on ACS shape: OAS-confirmed accountScore is {code, message} only. If JPM returns a numeric 0–1000 score (per dev-portal narrative), expected locations are (a) an additional field inside details for VERIAUTHUS profile, or (b) an undocumented field that may be added in a future OAS version. Until Jessica confirms (§12 #42), UTA's Pre-Flight ACS logic should key off accountScore.code first-digit 1 (Information Found) vs 2 (No Information Found), not the un-located 0–1000 number.

Sub-ledger gate — Pre-Flight pass/fail logic for UTA:

  1. PASS → proceed to §7.2–§7.5: codes.verification.code first digit is 1 AND codes.authentication.code first digit is 5 AND no individualScreening/businessScreening "Potential Hit" / "Hit"
  2. MANUAL REVIEW → block + queue for GL manager: any individualScreening or businessScreening with message: "Potential Hit" / "Hit"; any authentication first digit 6 (Ownership No Match); any verification first digit 4 (Debit Return Likely)
  3. FAIL → reject the payee record: verification first digit 2 (Closed Invalid); error slot populated with any 9### code
  4. MICRODEPOSIT REQUIRED → when synchronous result returns first digit 3 (No Information Found) on a US ACH/RTP beneficiary: switch to profileName: verificationauth two-step flow (Initial + Challenge), receive Challenge result via {client-url}/status async callback

A payee that fails Pre-Flight must not proceed to §7.2–§7.5 without manual GL-manager override and audit-log entry.

Error codes:

CodeHTTPMeaning
9001200Data Provider Error
9002200Processing Error
9003200Timeout Error
9004200Client Configuration Error
9005200 / 429Bad Request — or rate-limit breached
GCA-023400Please re-send request in valid format
GCA-129400ProgramId is required
GCA-001 / GCA-003403Unauthorized Access
GCA-103403programId was not found
GCA-099500System is Unavailable

Note: 9### codes are returned inside a normal 200 OK body in the error slot of ResultCollection, not as HTTP 4xx — UTA's client must inspect the body, not just the HTTP status.

Source basis: Validation Services API v2.2.3 OAS — authoritative · Validation Services overview · Account Validation overview · Account Validation parameters · Account Confidence Score how-to · Global Account Validation how-to · Verify Bank Account Status how-to · Entity Validation overview · Entity Validation parameters · Account Validation Global Coverage · Validation Services error codes.

7.2 RTP — Real-Time Payments

Status: Cleared  |  Channel: REST POST + Webhook callback  |  Sequence: Wave 1

Purpose: Instant credit-push payments on US TCH and FedNow rails (and other RTP networks if needed in future phases).

OAS verified against Global Payments v2.4.7 OpenAPI 3.0.1 spec on 2026-05-08 — see JPM/Playbook/Global Payments 2.4.7.yaml.

AttributeValue
Initiate endpointPOST /payment/v2/payments (operationId createPayment)
Single-payment status endpointGET /payment/v2/payments/{paymentId} (operationId getPayment) with optional `?view=SUMMARY
Search-by-id endpointGET /payment/v2/payments?endToEndId=...&paymentType=... (operationId getPayments) — useful to look up by endToEndId if paymentId is lost
Returns endpointPOST /payment/v2/payments/returns (operationId createPaymentReturns). Currently the OAS only shows a RealTimeBRPIXPaymentReturn example — i.e., Brazil PIX is the only verified return-supported rail. US TCH/FedNow client-initiated returns are not documented; must be initiated bilaterally with JPMC ops
Return status endpointGET /payment/v2/payments/returns/{returnId} (operationId getPaymentReturn)
paymentType"RTP" (fixed)
transferType"CREDIT" (fixed; RTP is credit-push only)
Required headersIdempotency-Key (string, max 36 chars; example 1b036f9c-8c84-4ce6-b1dd-5979472945a1); Request-Id (string, max 128 chars); Authorization: Bearer <JWT>
IdempotencyIdempotency-Key reuse rules below; endToEndId reuse window not explicitly published in OAS — treat as 24h conservative for RTP
LimitsUS TCH: USD 1,000,000. US FedNow: USD 500,000 (UTA's primary domestic RTP rail)
Hours / cutoffs24/7 — no cutoffs
SettlementSeconds; immediate availability; irrevocable on COMPLETED

Required body fields (per OAS Payment base schema — 8 required):

  • requestedExecutionDate (string, format: date, ISO 8601 YYYY-MM-DD; must be current or future date)
  • paymentIdentifiers.endToEndId (string, min 1, max 128 chars per EndToEndId schema — much wider than my v3.0 spec's earlier "1-35 chars" claim. Rail-specific validators MAY be stricter than the base schema upper bound; [CONFIRM with JPM] the actual RTP-specific length validator in CAT before locking the AR generator)
  • value.currency (Iso4217CurrencyCode enum), value.amount (STRING with decimal, e.g. "122.08", not a number — verified against OAS RTP example RealTimeUSRTPWalletWithdrawals)
  • transferType = "CREDIT"
  • paymentType = "RTP"
  • debtor.account.accountNumber (string, max 128; USA RTP rail-specific max is 31 per OAS AccountId description), debtor.name (string)
  • debtorAgent.financialInstitutionIds[] with id (9-digit ABA for US, e.g., 021000021) and idType (USABA for US ABA, BIC for SWIFT BIC, CLEARING_SYSTEM_ID for clearing scheme IDs)
  • creditor.account.accountNumber or creditor.account.alternateAccountIdentifiers (proxy: EMAL, MOBN, NIDN, EVP, QRCD)

Note: creditorAgent is NOT in the OAS Payment.required[] list, but rail-specific validators likely require it for RTP. [CONFIRM with JPM] whether RTP requires creditorAgent always or only when creditor.alternateAccountIdentifiers is not used.

AccountType enum (full OAS list — debtor.account.accountType / creditor.account.accountType): DDA | BDA | CARD | LOAN | ODFT | NREX | CACC | SVGS | CACR | NROR | SNRR | TRAN | CLABE | VOSTRO | IBAN | BBAN. UTA's commercial accounts are DDA (Demand Deposit Account); my earlier spec's DDA | VAM was wrong (VAM is not in this enum).

About the OAS example name "Wallet Withdrawal": JPM's OAS labels this example RealTimeUSRTPWalletWithdrawals / "RTP - Wallet Withdrawals Initiation - US RTP", but the payload is an ordinary outbound RTP credit-push to a third-party account — exactly the shape UTA uses to pay an athlete or loanout. Two carryovers in JPM's product-marketing taxonomy make the name misleading: (1) "Wallet" is product-line carryover from the separate JPM Wallet holding-account product (§12 #20 — closed; JPM Wallet is not required for UTA). The debtor account in this example (123456789) is a plain DDA, not a Wallet account. (2) "Withdrawal" is the debtor-account-side framing of a credit-push — funds are withdrawn from the debtor and credited to the creditor. Same operation UTA naturally describes as "paying the athlete." No special enrollment, no different field shape, no different endpoint.

OAS example — US RTP outbound credit-push initiation (from RealTimeUSRTPWalletWithdrawals — the misleading name notwithstanding):

json
{
  "requestedExecutionDate": "2025-02-07",
  "paymentIdentifiers": { "endToEndId": "USRTPWALLETTEST" },
  "transferType": "CREDIT",
  "value": { "currency": "USD", "amount": "122.08" },
  "paymentType": "RTP",
  "debtor": {
    "name": "John Doe",
    "account": { "accountNumber": "123456789" }
  },
  "debtorAgent": {
    "financialInstitutionIds": [{ "id": "021000021", "idType": "USABA" }]
  },
  "creditor": {
    "account": { "accountNumber": "98765432100" },
    "name": "Jane Doe"
  },
  "creditorAgent": {
    "financialInstitutionIds": [{ "id": "063100277", "idType": "USABA" }]
  }
}

Optional fields used by sub-ledger:

  • additionalParties.ultimateDebtor and ultimateCreditor
  • remittanceInformation.unstructuredInformation[].text (array per OAS, each item with .text)
  • remittanceInformation.structuredInformation[].creditReference.reference (max 140)
  • paymentPurpose.categoryPurpose.proprietary (e.g., SALA, CXBSNS, ACCTVERIFY)
  • paymentIdentifiers.otherPaymentReferences.uetr (36-char SWIFT GPI tracking; primarily for wires)

Note: instructionForDebtorAgent is not in the OAS Payment schema — do not attempt to use it. FX context lives on fxInformation (see §7.6).

Optional fields used by sub-ledger:

  • additionalParties.ultimateDebtor and ultimateCreditor
  • remittanceInformation.unstructuredInformation.text (70–140 chars)
  • remittanceInformation.structuredInformation[].creditReference.reference (max 140)
  • paymentPurpose.categoryPurpose.proprietary (e.g., SALA, CXBSNS)

Note: instructionForDebtorAgent is not documented for RTP — do not attempt to use it on RTP payments.

Status lifecycle:

  • paymentStatus: RECEIVED, ACCEPTED, PROCESSING, CANCELED, REJECTED, COMPLETED, RETURNED
  • Terminal: COMPLETED, REJECTED, RETURNED, CANCELED. Polling MUST stop on terminal.
  • Non-terminal: RECEIVED, ACCEPTED, PROCESSING

Idempotency:

  • Idempotency-Key reused with same payload → returns prior response
  • Idempotency-Key reused with different payload → error 10106 (HTTP 422)
  • Concurrent same key → error 10107 (HTTP 409) — wait + poll status; do not retry immediately

Optional reliability uplift: before initiating RTP, optionally call PACMan (§10) to check partner-bank availability and pre-empt rejections.

Source basis: RTP overview · RTP payment parameters · RTP resources (rails, limits, response types) · Initiate a Real-Time Payment request how-to · Retrieve transaction status how-to · Initiate a return request how-to · Return status how-to · GP2 error codes.

7.3 ACH — Credit Disbursements

Status: Cleared  |  Channel: REST POST + Webhook callback  |  Sequence: Wave 1

Purpose: Standard NACHA credit-push disbursements — UTA's primary use case is settlement payouts to athletes and loanouts (per the volume analysis: ~236/month to 357 distinct CustJob entities). UTA does not have a traditional Accounts-Payable function on the Klutch JPM accounts; outbound ACH on this integration is payout, not vendor payment.

OAS verified against Global Payments v2.4.7 OpenAPI 3.0.1 spec on 2026-05-08.

AttributeValue
Initiate / status endpointsSame as RTP: POST /payment/v2/payments, GET /payment/v2/payments/{paymentId}
paymentType"ACH"
transferType"CREDIT"
paymentTypeInformation.serviceLevelCode"NURG" (Non-Urgent — default for ACH per OAS example). Other valid ServiceLevelCode enum values: SEPA, SDVA (Same Day Value), URNS (Urgent Net Settlement), BKTR (Book), URGP (Urgent)
paymentTypeInformation.localInstrumentCode.codeNACHA SEC code. Mandatory 3-char for US ACH. Full OAS enum: SDCL, IN, CCD, IAT, PPD, CTX, CIE, ARC, POP, RCK, BOC, POS, WEB, TEL. Most common for UTA's flows: CCD (Corporate Credit/Debit — example uses this), PPD (Pre-arranged Payment), CTX (Corporate Trade Exchange)
endToEndIdOAS EndToEndId schema: min 1, max 128 chars, no character pattern restriction in the schema (OAS example USACHCRTEST is 11 alphanumeric chars). The 1-15 char "alphanumeric only" claim in earlier spec drafts was from developer-portal docs that may reflect rail-specific NACHA file format constraints, not the API schema. [CONFIRM with JPM] the rail-specific max for US ACH in CAT
endToEndId reuse window60 days for ACH (per developer-portal docs)
requestedExecutionDateOAS format: date, YYYY-MM-DD, current or future (per Payment schema description). US ACH allows future dating per dev-portal docs
value.currency"USD" (or "CLP" for Chile). Iso4217CurrencyCode enum is wider but US ACH is USD-only
value.amountSTRING with decimal, e.g. "1.00" (verified against OAS AchUSCreditTransfer example) — NOT a number
LimitsUSD 1M same-day / USD 99,999,999.99 next/2nd-day (per dev-portal docs)
Hours / cutoffs (US)Same-day ACH: 13:10 ET prefunded / 14:10 ET non-prefunded. Next-day ACH: 21:10 ET prefunded / 22:55 ET non-prefunded
No client-initiated return endpointRDFI returns surface as a status update (paymentStatus = RETURNED) on the original payment. OAS confirms only Brazil PIX returns are exemplified
CancellationPossible on SCHEDULED (future-dated) — mechanism [CONFIRM with JPM]

Additional fields used by US ACH (from OAS AchUSCreditTransfer example):

  • debtor.account.accountNumber (string, US ACH non-IAT max 17 chars per OAS AccountId description; US ACH IAT max 35 chars)
  • debtor.account.companyId (string, 10 chars — NACHA Company ID — required for US ACH origination, identifies the originator on the NACHA file)
  • debtor.name, debtor.postalAddress (country, buildingNumber, streetName, city, postalCode, countrySubDivision)
  • debtorAgent.financialInstitutionIds[] with id = 9-digit ABA, idType = "USABA"
  • creditor.name, creditor.account.accountNumber, creditor.account.accountCurrency (e.g., "USD")
  • creditor.partyId.individualIds[] with individualId (e.g., taxpayer ID — used for IAT and per-rail compliance)
  • creditorAgent.financialInstitutionIds[] (same shape as debtorAgent)
  • creditor.postalAddress (full address)

Sub-ledger / reconciliation fields:

  • remittanceInformation.unstructuredInformation[]array per OAS (each item with text); example uses text: "MISC services INV#09900". For US ACH the NACHA file format constrains this to ~80 chars per line; UTA's serializer must respect that
  • paymentPurpose.categoryPurpose.proprietary (e.g., ACCTVERIFY in OAS example; PAYROLL, PURCHASE also used)
  • taxInformation.type (e.g., TAX_PAYMENT)
  • paymentIdentifiers.otherPaymentReferences.relatedReferenceId — per OAS, "applicable for ACH and WIRES only"

OAS example — US ACH Credit Transfer (verbatim from AchUSCreditTransfer):

json
{
  "requestedExecutionDate": "2025-01-10",
  "paymentIdentifiers": { "endToEndId": "USACHCRTEST" },
  "value": { "currency": "USD", "amount": "1.00" },
  "transferType": "CREDIT",
  "paymentType": "ACH",
  "paymentTypeInformation": {
    "serviceLevelCode": "NURG",
    "localInstrumentCode": { "code": "CCD" }
  },
  "debtor": {
    "account": { "accountNumber": "12345678910", "companyId": "1115559990" },
    "name": "John Doe",
    "postalAddress": { "country": "US", "buildingNumber": "000", "streetName": "Smoking Lane", "city": "Chicago", "postalCode": "60603", "countrySubDivision": "IL" }
  },
  "debtorAgent": {
    "name": "JP Morgan Chase",
    "financialInstitutionIds": [{ "id": "021000021", "idType": "USABA" }],
    "postalAddress": { "country": "US" }
  },
  "creditor": {
    "name": "Jane Doe",
    "account": { "accountNumber": "987654321", "accountCurrency": "USD" },
    "postalAddress": { /* ... */ "country": "US" },
    "partyId": { "individualIds": [{ "individualId": "4444444" }] }
  },
  "creditorAgent": {
    "name": "JP Morgan Chase",
    "financialInstitutionIds": [{ "id": "021000021", "idType": "USABA" }],
    "postalAddress": { "country": "US" }
  },
  "remittanceInformation": {
    "unstructuredInformation": [{ "text": "MISC services INV#09900" }]
  },
  "paymentPurpose": { "categoryPurpose": { "proprietary": "ACCTVERIFY" } },
  "taxInformation": { "type": "TAX_PAYMENT" }
}

Status lifecycle: Use the canonical PaymentStatus/PaymentSubStatus enums from §6.6 (7 paymentStatus values × 17 paymentSubStatus values). Terminal: COMPLETED (sub: COMPLETED_BY_JPM), REJECTED, RETURNED.

Source basis: GP2 OpenAPI Specification v2.4.7AchUSCreditTransfer example, Payment, PaymentTypeInformation, LocalInstrument schemas · ACH overview · ACH payment parameters (credit) · ACH resources (limits, cutoffs).

7.4 ACH — Authorized Debit Pulls

Status: Cleared  |  Channel: REST POST + Webhook callback  |  Sequence: Wave 2

Purpose: UTA pulls funds from a third-party account where UTA holds a valid NACHA authorization (e.g., recurring producer settlements). Authorization capture / storage / R-code handling are UTA's responsibility outside JPM.

OAS verified against Global Payments v2.4.7 OpenAPI 3.0.1 spec on 2026-05-08AchUSDebitTransfer example.

AttributeValue
paymentType"ACH"
transferType"DEBIT" (the only routing difference vs. credit; Party blocks for debtor and creditor are also swapped — see example below)
paymentTypeInformation.serviceLevelCode"NURG" (OAS debit example uses this; same enum as credit)
paymentTypeInformation.localInstrumentCode.codeFull enum same as §7.3 credit: SDCL, IN, CCD, IAT, PPD, CTX, CIE, ARC, POP, RCK, BOC, POS, WEB, TEL. Per NACHA rules, the SEC code selected dictates which authorization rules apply (e.g., PPD for consumer authorizations, CCD for corporate, WEB/TEL for internet/telephone authorizations). OAS debit example uses PPD
endToEndIdSame as §7.3: OAS base schema max 128; rail-specific max [CONFIRM with JPM]. Reuse window 60 days (per dev-portal docs)
value.amountSTRING with decimal, e.g., "3.00" (verified against AchUSDebitTransfer example)
Amount limitsUSD 1,000,000 same-day; USD 99,999,999.99 next/2nd-day
Authorization (mandate) storageUTA's responsibility — GP2 does not store mandates. UTA must retain the signed authorization per NACHA rules

Important on debit semantics — debtor is the funding party, NOT UTA. For a debit pull, debtor is the third party whose account UTA is pulling from (the funding source), and creditor is UTA (the destination of the funds). This is the inverse of the credit case where debtor is UTA.

OAS example — US ACH Debit Pull (verbatim from AchUSDebitTransfer):

json
{
  "requestedExecutionDate": "2025-07-10",
  "paymentIdentifiers": { "endToEndId": "USACHDBTEST" },
  "value": { "currency": "USD", "amount": "3.00" },
  "transferType": "DEBIT",
  "paymentType": "ACH",
  "paymentTypeInformation": {
    "serviceLevelCode": "NURG",
    "localInstrumentCode": { "code": "PPD" }
  },
  "creditor": {
    "account": { "accountNumber": "0616759257", "companyId": "1590925701" },
    "name": "John Doe",
    "postalAddress": { /* ... */ }
  },
  "creditorAgent": {
    "name": "JP Morgan Chase",
    "financialInstitutionIds": [{ "id": "021000021", "idType": "USABA" }],
    "postalAddress": { "country": "US" }
  },
  "debtor": {
    "name": "Jane Doe",
    "account": { "accountNumber": "9876543210", "accountCurrency": "USD" },
    "postalAddress": { /* ... */ }
  },
  "debtorAgent": {
    "name": "JP morgan Chase",
    "financialInstitutionIds": [{ "id": "021000021", "idType": "USABA" }],
    "postalAddress": { "country": "US" }
  },
  "remittanceInformation": {
    "unstructuredInformation": [{ "text": "Music services INV#09900" }]
  },
  "paymentPurpose": { "categoryPurpose": { "proprietary": "ACCTVERIFY" } },
  "taxInformation": { "type": "TAX_PAYMENT" }
}

All other fields and lifecycle behavior match §7.3.

Source basis: GP2 OpenAPI Specification v2.4.7AchUSDebitTransfer example, TransferType, LocalInstrument schemas · ACH payment parameters (debit) · ACH overview · Cliff direction post-2026-03 to expand ACH scope to debits.

7.5 Wire — Same-Currency (Domestic + Cross-Border Same-Currency)

Status: Cleared — sample request body confirmed by Jessica Jin 2026-05-12  |  Channel: REST POST + Webhook callback  |  Sequence: Wave 2

Purpose: High-value same-currency wire credit transfers via Fedwire / CHIPS / SWIFT MT103 — for corporate customers like UTA, originated from UTA's Klutch operating account.

Product distinction — Wire Payments 2 API is NOT UTA's path. JPM publishes a separate product called "Wire Payments" / "Wire Payments 2 API" v2.0.5 (OAS at Playbook/Wire Payments 2 API 2.0.5.yaml). That product is for Financial Institutions (FI-to-FI wires, correspondent banking, cover payments via SWIFT MT103) — its OAS explicitly requires initiatingParty.id.organizationId.other.id: "BANK" and all examples are "US FI to FI." UTA is a corporate, not an FI; UTA's wires go through GP2 (POST /payment/v2/payments with paymentType: "WIRE"), not through Wire Payments 2 API.

US Wire request body — sample confirmed by Jessica Jin 2026-05-12. GP2 v2.4.7 OAS lists WIRE in the paymentType enum and exposes paymentTypeInformation.paymentContext (FI | CUSTOMER) for wire flows but contains no verbatim US Wire request example (RTP and ACH samples only). Jessica's 2026-05-12 reply provided the canonical body below — closes §12 #23.

Endpoint + headers:

POST https://api-mock.payments.jpmorgan.com/payment/v2/payments
Accept: application/json
Content-Type: application/json
Idempotency-Key: <UUID>
Request-Id: <UUID>

Verbatim sample request body (US same-currency Fedwire, USD 1.00 — Jessica Jin 2026-05-12):

json
{
  "requestedExecutionDate": "2026-01-14",
  "paymentIdentifiers": { "endToEndId": "US_WIRETEST_123" },
  "value":         { "currency": "USD", "amount": "1" },
  "transferType":  "CREDIT",
  "paymentType":   "WIRE",
  "debtor": {
    "account": { "accountNumber": "12311871", "accountCurrency": "USD" }
  },
  "debtorAgent": {
    "financialInstitutionIds": [
      { "id": "021000021", "idType": "USABA" },
      { "id": "CHASUS33",  "idType": "BIC"   }
    ],
    "postalAddress": { "country": "US" }
  },
  "creditor": {
    "name":          "JPMCHASE",
    "account":       { "accountNumber": "123456789", "accountCurrency": "USD" },
    "postalAddress": { "country": "US" }
  },
  "creditorAgent": {
    "financialInstitutionIds": [
      { "id": "021000021", "idType": "USABA" }
    ]
  },
  "paymentPurpose":         { "purpose": { "code": "GDDS" } },
  "paymentTypeInformation": { "paymentContext": "CUSTOMER" },
  "remittanceInformation": {
    "unstructuredInformation": [
      { "text": "Payment for Macbook batteries Receipt #AXF23-LGG" }
    ]
  }
}

Key shape notes from Jessica's sample:

  • debtorAgent.financialInstitutionIds[] accepts multiple entries — Jessica's sample populates both USABA (021000021) and BIC (CHASUS33) for the debtor agent. UTA should provide both routing forms when known.
  • creditor.name is populated even for intra-JPMC routing ("JPMCHASE" in the example).
  • paymentTypeInformation.paymentContext: "CUSTOMER" is the value for corporate-originated wires (UTA's case); "FI" is for FI-to-FI (not UTA).
  • paymentPurpose.purpose.code uses ISO 20022 codes — Jessica's example uses GDDS (Goods); other ISO codes apply per UTA's payment purpose.
  • remittanceInformation.unstructuredInformation outbound shape is [{text: "..."}] (array of objects with text field). This is distinct from §6.5 Payment Receipts inbound which delivers unstructuredInformation as array of strings. UTA's serializer + parser must handle both shapes by direction.
AttributeValue
EndpointPOST /payment/v2/payments
paymentType"WIRE"
transferType"CREDIT"
paymentTypeInformation.paymentContext"CUSTOMER" (UTA-originated) or "FI" (financial-institution-initiated; not UTA's case)
endToEndIdOAS base schema max 128 chars; [CONFIRM with JPM] the rail-specific Fedwire/CHIPS validator length (industry practice is 16 chars in the IMAD/OMAD format). Reuse window 60 days per dev-portal docs
value.amountSTRING with decimal, e.g., "50000.00" — same format as ACH/RTP per OAS AmountValue schema
paymentIdentifiers.otherPaymentReferences.uetrOptional but recommended for wires — 36-char SWIFT GPI tracking reference (per OAS OtherPaymentReferences.uetr). Lets UTA join GP2 status events to SWIFT GPI tracker entries
paymentIdentifiers.otherPaymentReferences.relatedReferenceIdOptional; per OAS "applicable for ACH and WIRES only"
LimitsFed/CHIPS: USD 9.9 billion max per wire. Book transfer (intra-JPMC): USD 25 billion max (per dev-portal docs)
CutoffsFedwire: 15:00–18:15 ET (varies by transaction type). CHIPS: 17:30 ET straight-through; 17:00 ET operator repair. SWIFT: 16:30 ET across USD channels (per dev-portal docs)
Returns / cancellationsWires are irrevocable. No /returns endpoint. Recall must be bilateral with JPMC ops

Required fields: paymentType = "WIRE", transferType = "CREDIT", paymentTypeInformation.paymentContext = "CUSTOMER", requestedExecutionDate, paymentIdentifiers.endToEndId, value.currency, value.amount, debtorAgent.financialInstitutionIds[].id (BIC or USABA), idType ("BIC" or "USABA"), creditorAgent.financialInstitutionIds[].id and idType.

Sub-ledger / reconciliation fields referenced in sample bodies but not enumerated in the parameters page: instructionForDebtorAgent, instructionForCreditorAgent, remittanceInformation (structured + unstructured), ultimateDebtor, ultimateCreditor, intermediaryAgent, chargeBearer, paymentPurpose. Action: pull the full GP2 OAS for the wire schema before implementation — the markdown parameters page is incomplete.

Status lifecycle: paymentStatus: ACCEPTED (sub: ACCEPTED), COMPLETED (sub: COMPLETED_BY_JPM), REJECTED (sub: REJECTED), RETURNED (sub: RETURNED). Terminal: COMPLETED, REJECTED, RETURNED.

Source basis: Same-Currency Wire overview · Wire payment parameters · Wire resources (limits, cutoffs) · Initiate a wire payment how-to · Get wire status how-to · GP2 OpenAPI Spec.

7.5.1 Intra-JPMC Book Transfer

For DDA-to-DDA transfers between two JPM accounts (e.g., funding a Klutch sub-account, treasury sweeps within JPM, prefunding a check-printing fund), use the same POST /payment/v2/payments endpoint with paymentType: WIRE. JPM auto-detects intra-bank routing when both debtorAgent.financialInstitutionIds[].id and creditorAgent.financialInstitutionIds[].id resolve to a JPM BIC (e.g., CHASUS33); no separate paymentType value exists for book transfer (the GP2 OAS paymentType enum is RTP | WIRE | ACH | CARD | VENMO | PAYPAL | BLOCKCHAIN | INTERAC | ZELLE | DEFAULT — no BOOK_TRANSFER).

AttributeValue
EndpointPOST /payment/v2/payments (same as §7.5)
paymentType"WIRE"
Detection ruleJPM auto-routes as a Book Wire when both debtor and creditor agents resolve to a JPM BIC. No client-side flag per dev-portal narrative — [CONFIRM in CAT] if JPM's validator expects an explicit indicator
SettlementSame-day, intra-bank — does not transit Fedwire or CHIPS
LimitUSD 25 billion per transfer (vs. USD 9.9 billion for Fed/CHIPS-routed wires)
FeeSignificantly lower than Fedwire/CHIPS (Book Wire rate per dev-portal docs); exact fee per UTA's JPM treasury services pricing
GL postingTwo offsetting Journal Entries — debit source account, credit destination account, using JPM's response paymentId as the memo. Never post as a single net entry (mirrors CNB DEC-010 for cross-bank consistency)
Status / callbacksSame as §7.5 wire — GP2 Callbacks (§6.6) for status; polling fallback via GET /payment/v2/payments/{paymentId}
Use cases for UTA(a) Funding a sub-account for check-printing, (b) treasury moves between Klutch sub-accounts, (c) FX wire prefunding, (d) any internal allocation that doesn't need to leave JPM

Sample request — USD 10,000 book transfer (Klutch operating → check-printing fund):

json
{
  "paymentType":  "WIRE",
  "transferType": "CREDIT",
  "paymentTypeInformation": { "paymentContext": "CUSTOMER" },
  "requestedExecutionDate": "2026-10-15",
  "paymentIdentifiers": { "endToEndId": "UTA-BT-2026-10-15-001" },
  "value":  { "currency": "USD", "amount": "10000.00" },
  "debtor": { /* UTA Klutch operating account */ },
  "debtorAgent":   { "financialInstitutionIds": [{ "id": "CHASUS33", "idType": "BIC" }] },
  "creditor": { /* UTA Klutch check-printing fund */ },
  "creditorAgent": { "financialInstitutionIds": [{ "id": "CHASUS33", "idType": "BIC" }] }
}

Source basis: Wire resources (limits, cutoffs) (Book Wire limit + intra-JPMC fee guidance) · GP2 OAS v2.4.7 (paymentType enum — confirms no separate BOOK_TRANSFER value).

7.6 Wire — Cross-Currency / FX

Status: Cleared — end-to-end flow documented  |  Channel: REST POST (RFQ Quote → RFQ Trade → GP2 Wire)  |  Sequence: Wave 3

Purpose: International wire with FX-locked GL posting amount, so the USD debit amount is fixed on UTA's books before the wire executes.


7.6.1 The end-to-end flow

┌───────────────────────────────────────────────────────────────────┐
│   STEP 1 — RFQ Quote (real-time pricing)                          │
│   POST /tsapi/v1/quotes  →  returns jpmQuoteId (R… 30-char)       │
└───────────────────────────────────────────────────────────────────┘


┌───────────────────────────────────────────────────────────────────┐
│   STEP 2 — RFQ Trade (lock the rate)                              │
│   POST /tsapi/v1/trades  →  returns jpmContractId (T… 30-char)    │
│   Locked rate; UTA's GL amount is now committed                   │
└───────────────────────────────────────────────────────────────────┘


┌───────────────────────────────────────────────────────────────────┐
│   STEP 3 — GP2 Wire Payment                                       │
│   POST /payment/v2/payments with:                                 │
│   {                                                                │
│     "paymentType": "WIRE",                                         │
│     "transferType": "CREDIT",                                      │
│     "value": { "currency": <foreign>, "amount": <foreign-amt> },  │
│     "debtor": { ... UTA USD account ... },                         │
│     "creditor": { ... beneficiary ... },                           │
│     "instructionForDebtorAgent": "/FXA/<jpmContractId>"            │
│   }                                                                │
└───────────────────────────────────────────────────────────────────┘


                  Wire executes at the locked rate.
                  GL variance: zero.

Optional Step 0: UTA can pre-fetch published rates via the FX Rate Sheet API (§7.6.3 below) for non-real-time pricing scenarios. Returns Rate IDs (R…) that can be used in §7.6.4 in place of running a fresh RFQ Quote, subject to the sheet's transaction-size bounds and expiry.

Optional Step 4: Cancel a booked trade if no wire is initiated yet — POST /tsapi/v1/trades/cancel with clientTradeId or jpmContractId.


7.6.2 RFQ Quote — Step 1 (real-time pricing)

Authoritative spec: Playbook/Request for Quote API 1.0.1.yaml

AttributeValue
EndpointPOST /tsapi/v1/quotes (operationId request-quote)
Base URLsProduction mTLS: https://apigateway.jpmorgan.com/tsapi/v1 · CAT mTLS: https://apigatewayqaf.jpmorgan.com/tsapi/v1
Auth modelmTLS only (no OAuth servers declared in the RFQ OAS) · Digital Signature Required on all 3 RFQ operations (per OAS endpoint descriptions)
BatchingUp to 50 quote requests in a single API call (ERR_1324 if exceeded)

Request body shape:

json
{
  "data": {
    "accountId": "796706786",            // UTA's debit account (must match clientSellCcy)
    "clientSellCcy": "USD",               // ISO 4217, 3 chars; must be account currency
    "quoteType": "EXECUTABLE",            // or "INDICATIVE"
    "quote": [
      {
        "clientRequestId": "CBQID20200618120921052",  // UTA-supplied, max 26 chars, unique
        "clientBuyCcy": "CAD",                         // ISO 4217 target currency
        "buyCcyAmt": 0.24,                             // OR sellCcyAmt — exactly one of the two
        "paymentDetail": {
          "paymentMethod": "WIRE"                       // or DRAFT or ACH
        }
      }
    ]
  }
}

Required for ACH paymentMethod (not for WIRE): beneficiaryType, senderType, beneBankCountryCode, recipientAccountUri, senderAccountUri, bankCode (per OAS).

Response shape (key fields):

json
{
  "_metadata": {
    "msgType": "quoteResponse",
    "sendingTimeUTC": "20200618-12:09:21Z"
  },
  "data": {
    "accountId": "796706786",
    "clientSellCcy": "USD",
    "quoteType": "EXECUTABLE",
    "quote": [{
      "clientRequestId": "CBQID20200618120921052",
      "status": "ACCEPTED",                                   // or REJECTED
      "jpmQuoteId": "R3CC77CEAE64623BE9706A5A807207",         // ← THE RATE ID
      "clientBuyCcy": "CAD",
      "buyCcyAmt": 0.24,
      "sellCcyAmt": 0.31,                                       // implied USD debit
      "fxValueDate": "20200618",
      "expirationTimeUTC": "20200618-12:09:41Z",               // ← Quote expiry
      "clientRate": 1.3134,                                     // ← Quote rate
      "baseCcy": "USD",
      "fromBuyCcyToSellCcy": "Divide"
    }]
  }
}

jpmQuoteId format: Always 30 chars, pattern R[A-Za-z0-9]{29} per OAS rateReferenceId schema.

Error catalog (selected; full list in OAS): GCA-021 accountId required · GCA-119 clientSellCcy required · ERR_1304 invalid clientSellCcy · ERR_1303 invalid clientBuyCcy · ERR_1305 two identical currencies · ERR_1308 invalid clientRequestId · ERR_1311 invalid paymentMethod · ERR_1318 missing amount · ERR_1319 two amounts provided · ERR_1324 exceeded 50 quote requests · ERR_1325 restricted currency · ERR_1326 ERISA account · ERR_1329 outside branch trading hours · ERR_1330 outside currency trading hours · ERR_1335 amount too large · ERR_1369 outside onshore CNY trading hours.


7.6.3 RFQ Trade — Step 2 (lock the rate)

AttributeValue
EndpointPOST /tsapi/v1/trades (operationId book-trades)
Auth + base URLsSame as Quote (mTLS only, Digital Signature Required)
BatchingUp to 50 trade requests per call (ERR_2529)

Request body shape:

json
{
  "data": {
    "accountId": "719532764",
    "clientSellCcy": "USD",
    "trade": [{
      "clientTradeId": "CBTID20200618120925899",        // UTA-supplied, max 26 chars
      "jpmQuoteId": "R3CC77CEAE64623BE9706A5A807207",   // ← from Step 1 Quote
      "clientBuyCcy": "CAD",
      "clientRate": 1.3134,                              // ← must match quote response
      "fxValueDate": "20200618",                         // ← must match quote response
      "buyCcyAmt": 0.1,                                  // OR sellCcyAmt
      "paymentDetail": {
        "paymentMethod": "WIRE"                           // ← must match quote
      }
    }]
  }
}

Critical: every field on the trade request must match what JPM returned on the quote (currency, rate, value date, payment method, etc.). Mismatch errors are numerous: ERR_2553-ERR_2562 catch the various dimensions.

Response shape:

json
{
  "_metadata": { "msgType": "tradeResponse", "sendingTimeUTC": "..." },
  "data": {
    "accountId": "719532764",
    "clientSellCcy": "USD",
    "trade": [{
      "clientTradeId": "CBTID20200618120925899",
      "status": "ACCEPTED",                              // or REJECTED
      "jpmContractId": "T178C681EB1A458B802AE896671925", // ← THE CONTRACT ID (locked rate)
      "jpmQuoteId": "R3CC77CEAE64623BE9706A5A807207",
      ...
    }]
  }
}

jpmContractId format: Always 30 chars, pattern T[A-Za-z0-9]{29} per OAS.

Critical error to avoid: ERR_2551 — "Trade request received on an indicative quote." Only EXECUTABLE quotes can be traded; INDICATIVE quotes are informational only. UTA must always request quoteType: "EXECUTABLE" at the Quote step for production wires.


7.6.4 GP2 Wire Payment with locked Contract ID — Step 3

Identifier typePrefixSourceUsage
Rate IDR (30 chars)RFQ Quote response (jpmQuoteId) or FX Rate Sheet response (rateId)Acceptable but not recommended for production wires — represents an unbooked quote
Contract IDT (30 chars)RFQ Trade response (jpmContractId)Recommended for UTA — locked rate; GL variance zero

JSON example for the wire Payment body (verbatim per Jessica):

json
"instructionForDebtorAgent": "/FXA/T178C681EB1A458B802AE896671925"

UTA standard: Always use the Contract ID (T… prefix) in instructionForDebtorAgent, sourced from a completed Step 2 RFQ Trade. Never use a Rate ID directly in production wires.

Note on GP2 OAS fxInformation field — alternative path, NOT canonical: The GP2 OAS v2.4.7 includes a Payment.fxInformation object with rateId / contractId fields. An earlier (2026-05-08) draft of this spec elevated fxInformation.contractId to canonical based on OAS schema inspection. Jessica Jin's authoritative March 3 response establishes that the production-canonical pattern is instructionForDebtorAgent: "/FXA/<id>", not fxInformation.contractId. The OAS fxInformation field may document an alternative or future path; treat it as informational. (Lesson: customer-specific Implementation Manager guidance trumps public OAS schema interpretation — see Bank/lessons-learned.md.)


7.6.5 RFQ Trade Cancellation — Step 4 (optional)

AttributeValue
EndpointPOST /tsapi/v1/trades/cancel (operationId cancel-trade)
Use caseUTA booked a trade but the downstream wire is no longer happening (e.g., payee bounced pre-flight validation)
Request body`{ data: { accountId, trade: [{ clientTradeId
Key errorERR_3129 — "Cancellation request received for a trade where the payment has already been submitted." Cancellation is only valid before the GP2 wire is initiated

7.6.6 FX Rate Sheet API — alternative rate source (CNB §5.6 indicative rate file replacement)

Authoritative spec: Playbook/FX Rate Sheet API 1.0.2.yaml

Purpose: Pull published indicative + executable FX rates for UTA's account on a periodic schedule, without running a per-transaction RFQ Quote. This is the JPM equivalent of CNB §5.6's Exchange Rate File — direct functional replacement.

AttributeValue
EndpointGET /tsapi/v1/accounts/{accountId}/ratesheets/current (operationId getCurrentRatesheet)
Base URLsProduction OAuth: https://openbanking.jpmorgan.com/tsapi/v1 · Production mTLS: https://apigateway.jpmorgan.com/tsapi/v1 · CAT OAuth: https://openbankinguat.jpmorgan.com/tsapi/v1
Auth modelmTLS or OAuth (both declared in OAS — unlike RFQ which is mTLS-only)
Path paramsaccountId (UTA's account; same value as RFQ accountId field)
Query paramscustomerDepartment[] — optional array of LOB names (e.g., ["E-commerce Dept", "Payments Dept"]); max 100 items, each 1-50 chars. Used when JPM has set up department-specific rate tiers for UTA (requires upfront TSFX Product configuration per OAS)

Response shape (key fields):

json
{
  "_metadata": {
    "sendingTime": "20180903-15:01:02Z",
    "clientRequestId": "51a190dc-940d-43d1-a0b9-5fabd5f2e640",
    "disclaimer": "..."                               // Treasury Services FX disclaimer
  },
  "data": {
    "accountId": "123456789",
    "ratesheetId": "d51176f6-...",
    "publicationId": "e51176f6-...",
    "publicationTime": "2018-09-03T15:01:02Z",
    "expiry": "2018-09-03T15:01:02Z",                  // ← rates expire after this
    "thresholdAmount": 1000000,                         // ← rates valid up to this amount
    "thresholdCcy": "USD",
    "customerDepartment": [{
      "name": "Example E-commerce Dept",
      "currencyPairs": [{
        "clientBuyCcy": "BRL",
        "clientSellCcy": "USD",
        "onshoreOffshore": "Onshore",                  // or Offshore
        "baseCcy": "USD",
        "fromBuyCcyToSellCcy": "Divide",                // or Multiply
        "rates": [{
          "rateId": "R1234567-8901-2345-6789-012345678901",   // ← R-prefix, same format as RFQ
          "clientRate": 3.31645,
          "rateType": "EXECUTABLE",                            // or INDICATIVE
          "paymentMethod": "ACH",                              // WIRE_DRAFT_BOOK | ACH | WALLET | CARD
          "beneficiaryType": "BUSINESS",
          "minTransactionSize": 100,
          "maxTransactionSize": 10000,
          "minMaxTransactionSizeCcy": "USD"
        }]
      }]
    }]
  }
}

Key concepts:

  • rateType: EXECUTABLE — UTA can use this rateId directly in a wire body (/FXA/<rateId>) without running RFQ Trade, provided the transaction amount falls within minTransactionSize / maxTransactionSize and the wire executes before expiry. Risk: less price-locked than a Contract ID since it's based on a pre-published rate, not a real-time confirmation
  • rateType: INDICATIVE — Informational only; cannot be used to execute a wire. Useful for UI display ("show payer estimated FX rate before they commit")
  • thresholdAmount — Hard cap above which the rate sheet's rates don't apply at all (UTA would need RFQ instead)

UTA design choice between RFQ and Rate Sheet:

Use caseRecommended path
Production cross-currency wires with GL assuranceRFQ Quote → RFQ Trade → use Contract ID (§7.6.2 → §7.6.3 → §7.6.4)
UI display of estimated rates pre-commitmentRate Sheet, rateType: INDICATIVE
Repetitive small-value FX flows within rate sheet boundsRate Sheet, rateType: EXECUTABLE — acceptable if UTA accepts the rate-sheet-bounded GL risk
Bulk pricing context for FX dashboardRate Sheet (pulled periodically; covers all currency pairs UTA has set up)

For UTA's Klutch use case (inbound AR cash-application + outbound settlement wires to athletes/loanouts): the RFQ flow (§7.6.2 + §7.6.3) is the right path for FX wires. The Rate Sheet API is documented here for completeness and future use.

Error codes (FX Rate Sheet, verbatim from OAS):

CodeMeaning
GCA-001/GCA-003Unauthorized Access
GCA-010Account not found
GCA-099System unavailable
ERR_1201Invalid Rate Sheet Request, invalid accountId
ERR_1203All rates expired, unable to find valid rates for request
ERR_1204Internal error, resend new Rate Sheet Request

7.6.7 Out-of-scope: Xpedite Remit FX Rate Sheet

JPM also publishes an Xpedite Remit FX Rate Sheet API v1.0.1 (Playbook/Xpedite Remit FX Rate Sheet API 1.0.1.yaml) — POST /tsapi/v1/xR/fxrates. This is a separate Xpedite Remit product (consumer cross-border remittance), not the corporate treasury FX flow UTA uses. NOT IN SCOPE for UTA's Klutch corporate wires. Retain the OAS for awareness; no spec coverage needed.


7.6.8 Updated open items for §7.6

ItemStatus
RFQ Quote / Trade endpoint URLsClosed — see §7.6.2, §7.6.3 (RFQ API v1.0.1 OAS)
Wire body field name (/FXA/)Closed — Jessica Jin 2026-03-03; see §7.6.4
Indicative-rate file equivalentClosed — FX Rate Sheet API v1.0.2 (see §7.6.6); replaces CNB §5.6
Sample US Wire FX Payment bodyStill Confirm-Blocked. The wire-body field is documented; the complete US wire request body (with full debtor/creditor shapes for a USD-denominated Fedwire) is not in any OAS we have. [ACTION — JPM Integration Manager / Jessica Jin] provide a verified US wire FX sample, or this resolves naturally in CAT
jpmContractId lifecycle / expiryOAS implies no expiry on a booked trade, but the documented expirationTimeUTC is on the Quote (not the Trade). [CONFIRM with JPM] whether a booked Contract ID has its own expiration window separate from the wire's requestedExecutionDate
Trading hours / currency cutoffsOAS error codes (ERR_1329, ERR_1330, ERR_1369) reference branch and currency trading hours but don't enumerate them. [CONFIRM with JPM] — likely a JPM Markets reference document

Status update (rolled forward):

  • v3.0 initial draft (2026-05-08): Confirm-Blocked — entire flow. Speculative path via JPM Wallet FX-Wire.
  • 2026-05-08 OAS-based correction: incorrectly elevated fxInformation.contractId as canonical.
  • 2026-05-11 first revert: restored Jessica's /FXA/ pattern as canonical (wire body); RFQ upstream still pending.
  • 2026-05-11 second update (this revision): RFQ API v1.0.1 OAS + FX Rate Sheet API v1.0.2 OAS downloaded. End-to-end flow now Cleared. All major architectural pieces in place. Remaining open items are implementation-level (US wire sample body, Contract ID lifecycle, trading hours catalog) — answerable in CAT.

Source basis: Request for Quote API v1.0.1 OAS — authoritative for upstream RFQ · FX Rate Sheet API v1.0.2 OAS — authoritative for published rates · [Jessica Jin, JPM Implementation Manager, 2026-03-03 response] — authoritative for wire-body /FXA/ pattern · GP2 OAS fxInformation documented as alternative/future path (see Playbook/Global Payments 2.4.7.yaml).

7.7 Check Issuance & Print

Status: Cleared (full OAS verified)  |  Channel: REST POST (sync /checks/issuances; async /checks/prints with GET /checks/prints/{id} poll)  |  Sequence: Wave 2

Purpose: Two flows — (a) Issuance registers a check that UTA prints in-house in the JPM Issuance/Positive Pay register; (b) Print submits a request to JPM to print and mail the check on UTA's behalf.

OAS verified against Checks API v2.1.1 OpenAPI 3.1.0 spec on 2026-05-12 — see Playbook/Checks API 2.1.1.yaml.

Base URLs (shared with §6.4 and §7.8):

  • Production: https://api.payments.jpmorgan.com/payable/v2
  • Mock: https://api-mock.payments.jpmorgan.com/payable/v2

7.7.1 Check Issuance — POST /checks/issuances

AttributeValue
EndpointPOST /checks/issuances (single check)
Required fieldsdebtor (with accountNumber 2–17 digits + financialInstitutionId.{id, idType}), checkAmount.{amount, currency}, checkNumber (1–10 digits), issueDate (ISO 8601)
Optional fieldscheckType enum, payees[] (1–3 items, each name 1–50 chars + priority 1–3), address (structured), additionalInformation[] (up to 10 items)
checkType enumCUSTOMER_CHECK (default for US/CA) | CERTIFIED_CUSTOMER_CHECK | BANK_CHECK | DRAFT | ELECTRONIC_DRAFT (NOT supported for Issuance or Cancellation)
additionalInformation valueType enumESCHEATMENT_PRODUCT_CODE (max 6 chars, Issuance only) | ADDITIONAL_DATA (max 35 chars, Issuance only)
clientReferenceNOT supported on Issuance (per OAS note). UTA's internal reference must be tracked outside this API
financialInstitution.idType enumUSABA | BIC | SORT_CODE | CLEARING_SYSTEM_ID
Multi-payeeUp to 3 payees with priority 1–3. Distinct from Print, which allows 2 payees max at 40-char names
Response (201)id (UUID), issueDate, requestInvocationId
Common errors (HTTP 400 with code 10001/10199)"checkAmount/issueDate is mandatory", "Issue already exists for check", "Stop on file for check", "Cancel exists for check"

Sample Issuance request — US, with escheatment data (verbatim shape from OAS):

json
{
  "debtor": {
    "accountNumber": "1234567890",
    "financialInstitutionId": { "id": "123456789", "idType": "USABA" }
  },
  "checkNumber": "123456790",
  "issueDate":   "2026-10-01",
  "checkAmount": { "currency": "USD", "amount": "500.00" },
  "payees": [
    { "name": "John Doe",   "priority": 1 },
    { "name": "ELITE CORP", "priority": 2 }
  ],
  "address": {
    "addressLines": ["123 Main St", "Suite 100"],
    "city": "Tampa", "postalCode": "33607",
    "countrySubDivision": "FL", "country": "US"
  },
  "additionalInformation": [
    { "valueType": "ESCHEATMENT_PRODUCT_CODE", "text": "123456" }
  ]
}

7.7.2 Check Print — POST /checks/prints (async)

JPM prints and mails the check on UTA's behalf. Two templates available via printType:

TemplateprintType valueUse case
US Cashier's Check / DraftCASHIERSHigh-trust draft drawn on bank funds. US-only. No bank holidays / weekends (EST). Bank assigns the checkNumber. clientReference is required and must be unique (1–10 chars)
US/CA Accounts Payable (6 column) (JPM template name; see note below)ACCOUNTS_PAYABLE_6_COLUMNStandard structured-remittance check template. issueDate ≤ 180 days future, no past dates. Defaults to current date if omitted

About the ACCOUNTS_PAYABLE_6_COLUMN template name: ACCOUNTS_PAYABLE_6_COLUMN is JPM's literal printType enum value — the name reflects the layout (6-column structured remittance with NET / DISCOUNT / GROSS triplets) that JPM originally built for AP use cases. UTA does not have a traditional Accounts-Payable function on the Klutch JPM accounts. UTA uses this template for athlete/loanout settlement-payout checks because the structured remittance layout fits Klutch's per-payment breakdown (e.g., gross deal amount, agency fee, net to athlete). The enum value must be sent verbatim to JPM regardless of UTA's internal label for the use case.

Shared required fields: debtor, checkAmount, payees (1–2 items, each name 1–40 chars + priority 1–2), address (structured), delivery.courier

Print-only delivery block:

FieldNotes
couriere.g., USPS, FEDEX, UPS (1–5 chars per OAS)
courierBillingAccountNumberRead-only; assigned by JPM
contactPhoneRequired for non-USPS couriers
specialHandling.deliveryAddressThird-party delivery target (e.g., mailing service)
specialHandling.companyNameRequired if specialHandling present
specialHandling.attention"ATTN" line — person/department

Cashier-specific required: clientReference (unique), remittance.{documents[], remitter}. Cashier amounts are constrained to type: NET_AMOUNT only.

ACCOUNTS_PAYABLE_6_COLUMN-specific required (JPM template name; UTA uses this template for settlement-payout checks, not AP): checkNumber, formCode (UTA-defined template code, 1–8 chars), remittance.documents[] structured with the NET_AMOUNT / DISCOUNT_AMOUNT / GROSS_AMOUNT triplet (all 3 required per document; NET = GROSS − DISCOUNT; up to 1000 documents per request). Optional memoLines[] (1 line max, 50 chars).

Response (202 async): id (print job UUID), issueDate, requestInvocationId. The export process is asynchronous — UTA must poll GET /checks/prints/{id} for status.

Polling — GET /checks/prints/{id} (results cached 5 min):

Response is CheckPrintDetailsResponse containing:

  • checkApprovalStatus enum: SUCCESS | REJECTED | ERROR | PENDING_CONFIRMATION | PENDING_APPROVAL
  • checkPrintValidationStatus enum: SUCCESS | ERROR | PENDING_INVESTIGATION | PENDING_FUNDING
  • checkPrintValidationErrors[] (when validationStatus = ERROR)
  • exportStatus (boolean) — true once printed and exported

Sub-ledger gate: UTA's GL post-action on a Print request is gated on exportStatus: true AND checkApprovalStatus: SUCCESS AND checkPrintValidationStatus: SUCCESS. Any other combination is held for ops review.

Sample Print request — Cashier's with FedEx delivery:

json
{
  "printType": "CASHIERS",
  "clientReference": "UTA-CC-001",
  "debtor": { "accountNumber": "987654321" },
  "checkAmount": { "amount": "500.00", "currency": "USD" },
  "payees": [{ "name": "John Doe", "priority": 1 }],
  "address": {
    "addressLines": ["456 Corporate Ave", "Floor 10"],
    "city": "Chicago", "postalCode": "60642",
    "countrySubDivision": "IL", "country": "US"
  },
  "delivery": { "courier": "FEDEX", "contactPhone": "312-555-6789" },
  "remittance": {
    "documents": [{
      "description":  ["Reimbursement"],
      "documentDate": "2026-04-01",
      "amounts": [{ "value": { "amount": "500.00", "currency": "USD" }, "type": "NET_AMOUNT" }]
    }],
    "remitter": "UTA Klutch"
  }
}

Source basis: Checks API v2.1.1 OAS — authoritative · Checks API overview · Checks Getting Started · Check Issuance & Cancellation overview · Issuance parameters · Issuance how-to · Check Print overview · Check Print parameters · Manage Check Print how-to · Checks API error codes.

Ops: JPM exposes GET /checks/health (unauthenticated, 30-sec server-side cached, returns {status: UP|DOWN, isReady, version, applicationName, statusUpdatedAt}) — useful for CAT smoke tests, pre-batch readiness checks, and ops monitoring (Datadog-style probes). Not part of UTA's per-transaction request flow.

7.8 Cancellation, Stop Payment & Revoke

Status: Cleared (full OAS verified) — all three verbs OAS-confirmed  |  Channel: REST POST  |  Sequence: Wave 2

Purpose: Three distinct lifecycle interventions on issued checks, each addressing a different stage:

VerbEndpointWhenEffect
CancellationPOST /checks/cancellationsPre-clearance void — before the check has been presented/clearedRemoves the check from the issuance/Positive Pay register; reconciles outstanding record
StopPOST /checks/stopsPost-issuance halt — after the check is in circulation but before it clearsPlaces a hold; if presented, JPM returns it. Time-bound — see expiration fields below
RevokePOST /checks/stops/revokeLifts a prior StopRemoves the stop; the check can be processed normally again

OAS verified against Checks API v2.1.1 OpenAPI 3.1.0 spec on 2026-05-12 — closes §12 #6 with OAS-anchored paths and schemas.

7.8.1 Check Cancellation — POST /checks/cancellations

AttributeValue
Required fieldsdebtor, checkAmount, checkNumber, issueDate (same shape as Issuance)
Optional fieldscheckType, payees[] (1–2 items only — third priority not used for Cancel), additionalInformation (without ESCHEATMENT_PRODUCT_CODE — Issuance-only)
clientReferenceNOT supported (same as Issuance)
Response (200)id, issueDate, requestInvocationId
Common error scenarios (HTTP 400 with code 10199)"Cancel already exists", "Stop exists for check", "Check Has Already Cleared", "Cancel amount mismatch"

Sample Cancellation request:

json
{
  "debtor": {
    "accountNumber": "1234567",
    "financialInstitutionId": { "id": "123456789", "idType": "USABA" }
  },
  "checkNumber": "123456790",
  "issueDate":   "2026-10-01",
  "checkAmount": { "currency": "USD", "amount": "500.00" },
  "payees":      [{ "name": "John Doe", "priority": 1 }]
}

Operational rule: UTA's UI must call Cancel synchronously when a check is voided in the sub-ledger before mailing — the void action gates on a successful Cancel response. Once a check has been mailed, the equivalent action is Stop (§7.8.2), not Cancel.

7.8.2 Stop Payment — POST /checks/stops

AttributeValue
Required fieldsdebtor, type (SINGLE | RANGE), check (with checkNumber for SINGLE, or checkRange.{start, end} for RANGE), stopReason enum
Optional fieldscheckAmount, payees[] (1–3 items). Not applicable to RANGE stopscheckAmount + payees are SINGLE-only
Range limitUp to 1000 checks per range
stopReason enum (15 values)US: CHECKS_LOST, CHECKS_DAMAGED, WRONG_AMOUNT, WRONG_PAYEE, CHECKS_POST_DATED, CHECKS_ALTERED, CHECKS_FORGED, SIGNER_OR_MAKER, CHECKS_STOLEN, OTHER. CA: CLIENT_INSTRUCTION, CHEQUE_LOST, CHEQUE_EXPIRED, CHEQUE_DESTROYED, CHEQUE_STOLEN
Response (202)id (StopPaymentId UUID), createdAt, requestInvocationId
Stop expiration semanticsA Stop is time-bound. Inquiry-returned additionalStopInfo: remainingTime (days remaining as ISO 8601 duration, decrements daily), originalTime (initial duration), expirationTime (years until full expiry), isRenewed (boolean — auto-renews on remainingTime: P0D reset). When both remainingTime and expirationTime reach 0, the Stop is no longer in effect

Sample Stop — Single check, US:

json
{
  "debtor": {
    "accountNumber": "1234567890",
    "financialInstitutionId": { "id": "123456789", "idType": "USABA" }
  },
  "type": "SINGLE",
  "check": { "checkNumber": "123456666" },
  "stopReason": "CHECKS_LOST"
}

Sample Stop — Range, US:

json
{
  "debtor": { "accountNumber": "1234567890", "financialInstitutionId": { "id": "123456789", "idType": "USABA" } },
  "type": "RANGE",
  "check": { "checkRange": { "start": "10020", "end": "10030" } },
  "stopReason": "CHECKS_LOST"
}

7.8.3 Revoke a Stop — POST /checks/stops/revoke

Two operation modes via the operationType discriminator:

operationTypeRequired fieldsUse when
IDstopId (from the prior Stop response)You have the stop's identifier — preferred path
DETAILdebtor, type, check — plus optional checkAmount, payeesThe original stopId is unavailable (e.g., re-keyed from a paper record)

Response (202): id, createdAt, requestInvocationId.

Sample Revoke by ID:

json
{ "operationType": "ID", "stopId": "n8a40v3r-3769-4o79-9z0l-ale1edc90389" }

Sample Revoke by detail:

json
{
  "operationType": "DETAIL",
  "debtor": { "accountNumber": "1234567890", "financialInstitutionId": { "id": "123456789", "idType": "USABA" } },
  "type": "SINGLE",
  "check": { "checkNumber": "123456666" }
}

7.8.4 Cross-cutting Checks API error codes (HTTP 400 schema, shared with §6.4 and §7.7)

CodeUsage
10001Mandatory field missing
10002 / 10003Min/max length violation
10100 / 10101 / 10102Min/max/range value violation
10103 / 10104 / 10105 / 10199Bad format / bad value / unexpected field / other
12000System error
13000Uncategorized error
14000Security failure (also drives HTTP 401)

HTTP 503 returns ServiceUnavailable with same Error schema. HTTP 404 on revoke = stop-id not found. Health check available at GET /checks/health for connectivity testing (results cached 30 seconds).

Source basis: Checks API v2.1.1 OAS — authoritative · Stop & Revoke overview · Stop & Revoke parameters · Manage Check Stop how-to · Manage Check Revoke how-to · Checks API error codes.

7.9 Positive Pay Decisioning (Deferred — programmatic surface only)

Status: Phase 1 protection ACTIVE via §7.7 Issuance  |  Programmatic decisioning Deferred — JPM REST API not yet GA  |  Channel: TBD  |  Sequence: Phase 2

Critical framing — what is and isn't deferred: Positive Pay has two halves. UTA gets the protective half from day 1 — only the automation of decisioning is deferred.

HalfMechanismPhase 1 status
Protection (Issuance register)UTA registers every check via POST /checks/issuances (§7.7). JPM validates inbound presentments against this register. Any presentment that doesn't match an Issuance record is flagged as an exception.ACTIVE in Phase 1. Wired up via §7.7. UTA gets fraud-protection benefit from the moment §7.7 goes live, regardless of how exceptions are decisioned.
Exception decisioningWhen JPM flags an exception, UTA decides PAY or RETURN.Manual in Phase 1; programmatic deferred to Phase 2 pending JPM REST API GA.

Purpose of §7.9 specifically: documents the programmatic exception decisioning surface that lets UTA's system pull the exception queue from JPM and post Pay/Return decisions automatically — the automation layer on top of the Phase-1-functional manual flow.

State (2026-05-08): No REST decisioning endpoint or Positive Pay reference appears anywhere in the JPM developer portal Checks markdown. Jessica Jin reconfirmed 2026-03-03: "Check Exception Management will be launching tentatively in Q2. Can incrementally add this capability when this is live via the API." See §12 #7.

Phase 1 decisioning paths (until JPM REST GA):

PathMechanismUTA operational costTradeoff
Manual JPM Access UIDesignated UTA operator(s) log into JPM Access during a daily cutoff window, review exception queue, click PAY or RETURN per itemDaily login + per-item review during JPM's cutoff window (typically morning to early afternoon ET)Operational overhead; matches existing CNB pattern; preserves full decision flexibility
Default decisioning rules (configured at JPM onboarding, not programmatic)UTA tells JPM at onboarding: "auto-return all exceptions" (safest), or "auto-pay below $X / auto-return above," or similarZero ongoing operational costRigid policy; legitimate-but-mismatched checks may bounce; safest variant (auto-return-all) may cause friction for legitimate payees

UTA decision needed at JPM onboarding (see §5 kickoff agenda item #6): which Phase 1 path, who owns the operational workflow if Manual UI, and what the default-rule policy is if Default Rules.

Architectural impact when REST GA lands: the §7.7 Issuance flow does not change. UTA wires in a pull-exception + post-decision flow as an additive Wave 3 capability without disrupting Phase 1 plumbing.

7.10 Out-of-Scope GP2 Rails

The following GP2 rails are reachable via the same POST /payment/v2/payments endpoint by setting paymentType accordingly. None are in scope for UTA Phase 1 but they are documented here so the dev team knows not to wire them in:

paymentTypeRailNotes
PUSH_TO_CARD (or per-OAS value)Push to Card — disburses to debit/prepaid cardsOut — UTA does not disburse to cards
PUSH_TO_WALLETPush to PayPal / VenmoOut — not a UTA payee channel
ZELLEZelle DisbursementsOut — UTA uses Zelle through retail rails, not corporate disbursement
JPM_COIN (Kinexys)Cross-border via JPM Blockchain Deposit AccountOut — no BDA at UTA
INTERACCanadian RTP schemeOut of geography (CAD 25,000 limit; UTA's Canadian volume is too low to justify)

7.11 Inbound Credit Refunds & Reversals

Status: Per-rail (see table)  |  Use case: Refunding a credit UTA received (overpayment, duplicate payment, wrong-account, client request, fraud reversal)

Distinction: This subsection covers refunding an inbound credit UTA already receivednot returning an outbound payment UTA sent (which is §7.2 Return endpoint for RTP and paymentStatus = RETURNED callbacks for ACH per §7.3). The operational ask is: "client deposited $X to UTA in error / overpayment / wants it back — how do we send it back via JPM?"

Per-rail refund mechanisms:

Inbound railProgrammatic refund surface?Refund mechanismUTA requirement
RTP (TCH RTP / FedNow)Partial — needs JPM confirmation. GP2 POST /payment/v2/payments/returns with paymentType: RTP accepts a return citing the bankReferenceNumber received via the original §6.5 Payment Receipts notification. OAS confirms the endpoint and schema, but only ships a Brazil PIX (RealTimeBRPIXPaymentReturn) example — no US TCH/FedNow example. UTA must [CONFIRM with JPM] whether the same shape applies to US RTP (§12 #43).If confirmed for US: capture bankReferenceNumber from every Payment Receipts webhook, store in Client Processing; refund flow POSTs to /payments/returns with the captured ref + endToEndId for the return. If unconfirmed at Phase 1 cutoff: fall back to "new outbound payment" pattern below.
ACH creditNo. No client-initiated refund/return endpoint exists for inbound ACH credits in GP2 OAS. (NACHA R-code returns are RDFI-side automated rejections for system reasons like NSF / no-account — not voluntary refunds.)UTA initiates a new outbound ACH credit (§7.3) back to the originator's account. Use originator's bank info captured in §6.1 Transaction Details (achBatchItems[].items[].dfiAccountId / dfiBankId) + originator name from the same record. Reference the original payment in remittanceInformation for audit.
Wire (inbound)No. Wires are technically irrevocable once received. "Wire recall" exists as a bilateral bank-to-bank SOP but is not a programmatic API — JPM ops engages on behalf of UTA via a manual process if the case justifies (e.g., demonstrable fraud, large-dollar error).UTA initiates a new outbound wire (§7.5) back to the originator. Use originator details captured in §6.1 Transaction Details (originatingBank.name, originatingCust.name, originatingCust.partyIds, etc.). Reference the original UETR / bankReferenceSearchable.standardValue in the outbound wire's remittanceInformation.unstructuredInformation[].text for audit.
Check depositNo. Check refunds are not a programmatic surface — once a deposited check has cleared, the funds are settled. (Pre-clearance reject is the drawee bank's mechanism, not UTA's.)UTA initiates a new outbound payment back to the depositor — typically ACH (§7.3) if UTA has the depositor's ABA/account, or check (§7.7 Print) otherwise. Reference the original deposit's checkNumber + customerReferenceSearchable.standardValue in the outbound payment's remittance.

Requirements UTA owns (per the §16 scope split — engineering design implements):

  1. What triggers a refund — defined upstream of this spec in Client Processing business rules. Likely: AR-team flag + manager approval; client-service ticket on overpayment; fraud-ops disposition.
  2. Originator-data persistence — Client Processing must retain enough of the inbound credit's data (from §6.1 Transaction Details + §6.5 Payment Receipts) to populate a return request. Minimum: original endToEndId, bankReferenceNumber/clearingSystemReference, originator name + account + bank, original amount + value date. These need to be queryable months after the original receipt (statutory dispute windows).
  3. Refund-as-new-outbound-payment dedup — when refund is implemented by initiating a new outbound payment (ACH / Wire / Check), UTA's idempotency key must NOT be the same as any prior outbound payment to that same beneficiary. Use a refund-specific key prefix (e.g., RFND-<original-bankRef>).
  4. Audit linkage — every refund (whether RTP-return-endpoint or new-outbound-payment) must carry a reference to the original inbound credit in remittance fields so JPM-side reconciliation (and UTA's audit) can pair them.
  5. Rail-selection policy for the "new outbound payment" fallback — when refunding an ACH credit or wire credit via a new outbound, does UTA refund on the same rail received? On the fastest available rail? Cheapest? Caller's preference? This is a Cliff decision before engineering hand-off.

Status: Phase 1 covers refund-via-new-outbound-payment for ACH, Wire, and Checks (uses already-in-scope §7.3 / §7.5 / §7.7 rails). RTP programmatic return is conditionally Phase 1 pending §12 #43 confirmation; if not confirmed before CAT-ready, RTP refunds also fall back to new-outbound-payment until JPM confirms US shape support.


8. Status Inquiry Strategy

JPM is a mixed push/poll model. The default path for every outbound payment is the GP2 Callback (§6.1). Polling GET /payment/v2/payments/{paymentId} is a fallback used only when a callback has not arrived within rail SLA, or when UTA needs a confirmation snapshot before a GL post.

8.1 Per-rail polling cadence (fallback, only when callback hasn't arrived)

RailCallback SLAFallback poll cadence (after SLA breach)Final-status criteria
RTP"typically within 30 seconds" of network responseEvery 30 sec for 5 min, then every 5 min for 30 min, then alertpaymentStatus ∈ {COMPLETED, REJECTED, RETURNED, CANCELED}
ACHWithin minutes for ACCEPTED/PROCESSING; T+2 for terminal COMPLETED/RETURNEDEvery 5 min until ACCEPTED, then every hour during business hours until terminalpaymentStatus ∈ {COMPLETED, REJECTED, RETURNED}
Wire (same-currency)Within minutes for ACCEPTED; same-day for terminalEvery 5 min until terminalpaymentStatus ∈ {COMPLETED, REJECTED, RETURNED}

Stop polling on terminal. UTA's polling loop must respect terminal status — never re-poll a payment that has reached COMPLETED, REJECTED, RETURNED, or CANCELED. This is the same discipline as CNB v5 §7 (where 0 and 10 were the terminal IFX status codes).

8.2 Status visibility scope

Status inquiry works only for transactions UTA submitted through GP2. Payments initiated via J.P. Morgan Access UI, Wire Center, or other channels are not queryable by paymentId from the GP2 endpoint.

8.3 Idempotency on retries

When a poll or a re-submission is needed:

  • Idempotency-Key header reused with same payload → returns the prior response (safe)
  • Idempotency-Key reused with different payload → error 10106 (HTTP 422) — generate a new key
  • Concurrent same key → error 10107 (HTTP 409) — wait + poll, do not retry immediately

9. Reconciliation Logic — The Three-Way Match

For JPM, the Three-Way Match assurance strategy uses GP2's webhook architecture as the engine and the Account Balances API + Transaction Details API as the brake.

Three sources:

  1. Bank Source ("The Brakes"): Account Balances API (§6.2) for balance snapshot + Transaction Details API (§6.1) for activity, queried at ~10:00 PM local for EOD close.
  2. Sub-ledger Source ("The Engine"): UTA's cumulative record of GP2 callback events (§6.6), Payment Receipts events (§6.5), and successful 201 responses from POST /payment/v2/payments (§7.2–§7.5).
  3. ERP Source (NetSuite): Total Journal Entries posted in the matching period, retrieved via the NetSuite REST API.

Assurance rule: any discrepancy between the bank's settled balance (Brakes) and the sub-ledger's recorded activity (Engine) must be flagged as a variance and routed to the GL manager for audit before next business day open.

Reconciliation timing:

StepTimeAction
IntradayContinuousGP2 Callbacks + Payment Receipts update sub-ledger in real time
EOD Balance Lock~10:00 PM localPull Account Balances API (§6.2) balances; freeze sub-ledger totals
EOD Match~10:05 PM localCompare Engine totals against Brakes; flag variances
Prior-Day Confirm~7:30 AM localPull Transaction Details API (§6.1) ?relativeDateType=PRIOR_DAY for prior day; reconcile any missing events

10. PACMan — Platform Availability Communication Management

Status: Deferred — Phase 2 reliability uplift (not required for Phase 1)  |  Channel: N/A in Phase 1  |  Sequence: Phase 2

Purpose: Optional pre-flight participant availability check for US RTP — confirms the receiving bank is currently online before UTA submits an RTP credit, avoiding 11026/11027/11703/11704 agent-suspended errors and burned endToEndIds. Phase 1 does not integrate PACMan. JPM's RTP endpoint returns agent-suspended errors directly, and §7.2's error path handles them. Reconsider for Phase 2 if RTP volume or operational posture changes the value calculus.

OAS: Playbook/Platform Availability API 1.1.0.yaml. Two REST endpoints (GET /participants, GET /participants/{id}) plus a declared webhook callback (POST /client-domain) — full deep-scan deferred to Phase 2.

Source basis: PACMan overview · Platform Availability API v1.1.0 OAS.


11. Rollout Sequencing

Three waves, ordered by dependency on JPM-side onboarding (Pre-Flight gates everything; webhooks gate Wave 1; FX gates Wave 3 pending JPM clarification).

Wave 1 — Inbound + base outbound (target: Test 2026-07, Prod 2026-09)

  • §4 Authentication (all 5 cert types)
  • §6.1 Transaction Details API — Intraday + Prior-Day Activity
  • §6.2 Account Balances API — EOD Balance Anchor
  • §6.5 Payment Receipts receiver (UTA-side endpoint stood up; RTP coverage)
  • §6.6 GP2 Callbacks receiver (UTA-side endpoint stood up)
  • §7.1 Validation Services (Pre-Flight)
  • §7.2 RTP — Real-Time Payments (with optional §10 PACMan check)
  • §7.3 ACH — Credit Disbursements
  • §8 Status inquiry strategy
  • §9 Reconciliation logic

Wave 2 — Wire + Checks + ACH Debit (target: Test 2026-08, Prod 2026-10)

  • §6.4 Check Image retrieval
  • §7.4 ACH — Authorized Debit Pulls
  • §7.5 Wire — Same-Currency
  • §7.7 Check Issuance & Print
  • §7.8 Cancellation, Stop Payment & Revoke

Wave 3 — FX + Positive Pay (target: dependent on JPM)

  • §7.6 Cross-Currency Wire / FX (blocked on JPM Integration Manager)
  • §7.9 Positive Pay Decisioning (blocked on JPM GA)

12. Open Items

Item numbers are stable across versions — never renumber. Closed items remain numbered with a (closed) suffix.

  1. GP2 pilot enrollment confirmation(path forward documented 2026-05-12). Jessica Jin 2026-05-12 provided the onboarding sequence: UTA submits formal implementation request to Sam Bomes + Joey at JPM, which triggers implementation-team assignment and UAT environment setup. UTA prerequisites (accounts in scope, payment types in scope, certificates, POC list registered in PDP) are now documented in §5. Reconfirmed Jessica's 2026-03-03 framing: "Our team is actively seeking clients to be in the pilot phase and believe the team would be a great candidate to be in GPV2." [ACTION — UTA: confirm §5 prerequisites, then send formal implementation request to Sam Bomes + Joey]

  2. Inbound webhook signature scheme (GP2 Callbacks + Payment Receipts) — JPM Integration Manager owes the canonical authentication contract on inbound webhooks. Public OAS shows x-jpmc-security: {} (empty placeholder). [CONFIRM with JPM]

  3. Complete CloudEvent type enum per rail — public portal documents only Payment.Completed and Payment.Rejected; OAS implies many more. JPM Integration Manager owes the full list. [CONFIRM with JPM]

  4. Cross-currency wire / FX flow product mapping(closed — end-to-end flow documented 2026-05-11). Wire-body field: instructionForDebtorAgent: "/FXA/<id>" per Jessica Jin (2026-03-03). Upstream RFQ flow: Request for Quote API v1.0.1 OAS downloaded (Playbook/Request for Quote API 1.0.1.yaml) — endpoints POST /tsapi/v1/quotes, /trades, /trades/cancel. Returns Rate ID (R… 30 chars) at Quote step, Contract ID (T… 30 chars) at Trade step. UTA standard: use Contract ID (T…) for production wires (locked rate). Full end-to-end flow now documented in §7.6.1-§7.6.5. Remaining sub-items (US Wire FX sample body, Contract ID lifecycle, currency trading hours) split into new items #33-#35.

  5. Checks API canonical base URL(closed) — Confirmed 2026-03-03 by Jessica Jin and re-verified by Checks API v2.1.1 OAS on 2026-05-12. Base URL is https://api-mock.payments.jpmorgan.com/payable/v2 (mock); production analog https://api.payments.jpmorgan.com/payable/v2. PDP reference for checkCancellation: https://developer.payments.jpmorgan.com/api/treasury/checks/checks#/operations/checkCancellation . HTTP conventions: https://developer.payments.jpmorgan.com/api/response-codes . v2.2 spec was correct on the /payable/v2 base Q5.

  6. Check Cancel verb/path(closed 2026-05-11; full §6.4 / §7.7 / §7.8 deep-scan completed 2026-05-12). All three verbs OAS-confirmed at OAS-canonical paths: Cancellation POST /checks/cancellations, Stop POST /checks/stops, Revoke POST /checks/stops/revoke. Full schemas, error codes, multi-payee limits, escheatment fields, stop-expiration semantics, and async polling for Print (GET /checks/prints/{id}) now documented in §7.7 and §7.8. See Playbook/Checks API 2.1.1.yaml.

  7. Positive Pay decisioning REST API GA timingReconfirmed 2026-03-03 by Jessica Jin: "Check Exception Management will be launching tentatively in Q2. Can incrementally add this capability when this is live via the API." UTA's spec treats this as Phase 2 deferred. Watch for Q2 2026 launch announcement.

  8. Payment Receipts webhook payload schema(closed — schema self-answered via OAS 2026-05-11). Payment Receipts API v1.2.0 OAS downloaded to Playbook/Payment Receipts 1.2.0.yaml. The full webhook envelope (creditConfirmation with transactionDetails, relatedParties.debtor/creditor with full postal addresses, relatedAgents, structured + unstructured remittanceInformation, and taxInformation.debtorTaxInformation for Mexico) is now documented in §6.5. Webhook path /webhook/credit-confirmation; receiver {YOUR-SERVER-DOMAIN}/creditConfirmation. OAS examples cover Singapore IRCT and UK FPS Agency Banking (no US RTP example, but schema is rail-agnostic). Remaining sub-item: rail-coverage roadmap — public docs originally implied RTP-only, but the OAS schema is rail-agnostic; whether JPM fires creditConfirmation events for inbound US Wire and inbound ACH credits is still unconfirmed. Polling fallback via Transaction Details API (§6.1) and Account Balances API EOD (§6.2) covers any gap. Sub-item split to new #36.

  9. Business Direct Connect — BAI code field name(closed — BDC out of scope for UTA per Jessica Jin 2026-05-12). UTA is corporate-segment on JPM's Access platform; BDC is the commercial-segment product. Original BDC OAS analysis (field commercialCode, shape {type: BAI \| BTRS \| ISO \| SWIFT, code: <string>}) is retained for historical context only. UTA's path is the Transaction Details API permanently (baiType.typeCode + baiType.description + baiType.btrsTypeCode). Not a future-state migration target.

  10. Business Direct Connect — date format and required-ness(closed — BDC out of scope for UTA per Jessica Jin 2026-05-12). Same as #9: BDC is commercial-segment-only; UTA is corporate-segment and permanently on Transaction Details API (which uses startDate/endDate or relativeDateType=CURRENT_DAY|PRIOR_DAY, YYYY-MM-DD).

  11. Business Direct Connect — rate limits(closed — BDC out of scope for UTA per Jessica Jin 2026-05-12). Not applicable; UTA is corporate-segment and cannot migrate to BDC (commercial-segment-only product).

  12. Validation Services mock base URL + complete verification-vs-authentication code tables. (closed — full §7.1 OAS deep-scan completed 2026-05-12). Validation Services API v2.2.3 OAS deep-scanned and §7.1 rewritten with full OAS-anchored schema (Playbook/Validation Services API 2.2.3.yaml). Servers confirmed: production apigateway.jpmorgan.com/tsapi/v2, CAT apigatewaycat.jpmorgan.com/tsapi/v2, mock api-mock.payments.jpmorgan.com/tsapi/v2. Two endpoints: POST /validations/entities and POST /validations/accounts. Required headers: x-client-id and x-program-id. Sample x-program-id values per profile (VERIAUTH, VERIAUTHMULTI, VERIAUTHNONUS, VERIAUTHUS, SUREPAYVOP) and async callback support ({client-url}/status) now documented in §7.1. Result-code first-digit dictionary and provider taxonomy fully captured. Auth confirmed as mTLS-only (no Digital Signature requirement). Per-customer onboarding values carry over to #38.

  13. GP2 Payment Cancellation endpoint exact path — referenced verbally but not surfaced. [CONFIRM with JPM]

  14. Cert-installation calendar — significance of double-asterisked dates (2026-07-16, 2026-07-30, 2026-11-19, 2026-12-17). [CONFIRM with JPM]

  15. apigateway.jpmorgan.com mTLS expiry 2026-05-28 / 2026-10-22 — UTA must re-pin before expiry. [ACTION — UTA]

  16. UTA decision: same-day wire credit treatment for AR auto-match. (closed) — Conservative (Pending) selected 2026-05-08. See §6.1. Current-day wire credits are treated as unposted until the ~7:30 AM prior-day confirm.

  17. UTA callback receiver standup — UTA hosts an HTTPS endpoint that JPM pushes to (GP2 Callbacks + Payment Receipts). Architecture TBD pending Amir's review — candidate approach floated in early discussions: AWS API Gateway + Lambda fronted by mTLS-terminating ALB. Implementation not started. [ACTION — Amir, UTA Engineering: confirm or propose alternative architecture, then scope the build]

  18. UTA account list for CAT entitlement(closed 2026-05-12). Two Klutch accounts confirmed by Cliff in 2026-05-12 followup to Jessica Jin: 900867182 (KSG Operating USD) and 900867232 (KSG Client Trust USD). JPM serves Klutch only; touring, endorsements, and voiceovers are at CNB and out of scope. These accounts go in the formal implementation request to Sam Bomes + Joey.

  19. PoC against JPM — none executed yet. [ACTION — UTA Engineering]

  20. JPM Wallet onboarding decision(closed 2026-05-12). §7.6 FX wire flow resolved via RFQ + GP2 Wire with /FXA/<contractId> (§12 #4 closed 2026-05-11). JPM Wallet is not required for UTA's FX wire path. Decision: do not onboard JPM Wallet.

  21. PACMan schema and endpoint paths(closed 2026-05-11; PACMan deferred to Phase 2 on 2026-05-12). Platform Availability API v1.1.0 OAS downloaded (Playbook/Platform Availability API 1.1.0.yaml). Three endpoints surfaced: GET /participants (optional status=ONLINE\|OFFLINE filter), GET /participants/{id}, and POST /client-domain (webhook callback — corrected from prior framing of "polling-only"). Production hosts: openbanking.jpmorgan.com/tsapi/v1 (OAuth) and apigateway.jpmorgan.com/tsapi/v1 (mTLS); CAT analogs openbankinguat, apigatewayqaf. Scope decision 2026-05-12: PACMan is an optional reliability uplift for RTP, not a Phase 1 necessity — JPM's RTP endpoint returns agent-suspended errors that §7.2 already handles. Full integration deferred to Phase 2 if RTP volume or operational posture changes the value calculus. See §10.

  22. Indicative FX rate file(closed 2026-05-11). Resolved by the FX Rate Sheet API v1.0.2 (Playbook/FX Rate Sheet API 1.0.2.yaml). Endpoint GET /tsapi/v1/accounts/{accountId}/ratesheets/current returns both EXECUTABLE and INDICATIVE rate types per currency pair, per customer department. Direct functional replacement for CNB §5.6 Exchange Rate File. Documented in §7.6.6.

  23. US Wire — sample request body(closed 2026-05-12). Jessica Jin provided verbatim curl + JSON sample (same-currency USD Fedwire). Documented in §7.5. Key shape confirmations: debtorAgent.financialInstitutionIds[] accepts multiple entries (USABA + BIC); paymentTypeInformation.paymentContext: "CUSTOMER"; paymentPurpose.purpose.code uses ISO 20022 codes; outbound remittanceInformation.unstructuredInformation is [{text: "..."}] (array of objects — distinct from §6.5 inbound array of strings).

  24. Per-rail endToEndId length — GP2 OAS v2.4.7 base schema is max 128 chars globally; my earlier per-rail limits (RTP 1-35, ACH 1-15, Wire 35) were from developer-portal narrative pages, not the OAS. Rail-specific validators may enforce stricter limits in CAT/Production. [CONFIRM with JPM] the per-rail validator length for RTP, ACH, and Wire before locking UTA's endToEndId generator format. See §7.2, §7.3, §7.4, §7.5.

  25. GP2 CloudEvent type enum — confirmed via OAS deep-scan (2026-05-08) that the spec lists 6 named callback examples (Push To Card Status, Push To Card - TP3 Status, Push To Card - TP3 Rejected Status, Kinexys DDA-to-BDA Completed Status, ACH Batch, RTP - BR PIX Payment Return) but does NOT enumerate the exact type strings. [CONFIRM with JPM] the complete Event.type enum so UTA's callback dispatcher can route on it. Same root issue as item #3.

  26. BDC product fit — clarification of right inbound product(closed; reaffirmed 2026-05-12 by Jessica Jin) Transaction Details API + Account Balances API is UTA's permanent path. Jessica's 2026-05-12 reply made the segment-eligibility framing explicit: "Business Direct Connect platform is for our commercial clients – UTA is considered a corporate client on our Access platform and will not be able to utilize FDX." BDC is not a future-state migration target — it is a different product line UTA cannot access. v3.0 spec §6.1 is the permanent path. Methodology lesson logged at Bank/lessons-learned.md.

  27. Transaction Details API — Mock server availability — OAS v3.1.8 declares Production + multiple CAT/UAT servers but NO dedicated mock. [CONFIRM with JPM Integration Manager] whether sandbox testing happens via CAT (with sandbox credentials) or via a separate mock URL not yet declared in the OAS. Blocks Postman validation of §6.1 until resolved. [ACTION — UTA Engineering]

  28. Transaction Details API — tier: LEGACY EOL timeline(closed / de-prioritized 2026-05-12). Per Jessica Jin: UTA is corporate-segment on the Access platform and cannot use BDC regardless of EOL timing. Whatever the EOL timeline for Transaction Details is, UTA's only path is to stay on it (or whatever Access-platform successor JPM ships for corporate clients). No BDC-migration parser-abstraction investment needed. Re-open only if Jessica or JPM announces an Access-platform replacement for corporate-segment clients.

  29. Account Balances API — OAS file(closed) Resolved 2026-05-11. OAS downloaded to Playbook/Account Balances API 1.0.5.yaml. §6.2 deep-scan proceeding.

  30. Transaction Details API — lockbox information parameter encoding — OAS literally names the parameter lockbox information (with a space). HTTP clients vary on whether they accept a literal space in query strings or require URL-encoding (%20). [CONFIRM in Postman/CAT] which form JPM's validator accepts. Affects UTA's parser library choice.

  31. Transaction Details API — BAI Type Code dictionary parity with CNB — UTA's existing CNB BAI2 parser handles a specific set of BAI Type Codes (115, 165, 195, 475, 935 RETURN WIRE, etc.). The Transaction Details API OAS doesn't enumerate which BAI codes JPM returns. [CONFIRM with JPM] that JPM uses the standard BAI2 code dictionary so the existing parser logic can be reused. If JPM uses any non-standard codes, the parser needs an extension table.

  32. GP2 Payments Playbook(closed) Resolved 2026-05-11. The GP2 Client Integration Guide v2 (2026_GP2_Client_Integration_Guide_Version_2.pdf) IS the GP2 Payments companion to the Reporting Playbook — symmetric pairing: Reporting Playbook covers reporting APIs (Transaction Details, Account Balances); GP2 Integration Guide covers outbound payments (ACH, Wire, RTP). The GP2 guide is screenshot-heavy and PDF text extraction is lossy — for implementation specifics, the GP2 OAS v2.4.7 is the authoritative reference; the guide is supplementary.

  33. US Wire FX — sample request body with instructionForDebtorAgent populated(closed 2026-05-12). Jessica's 2026-05-12 base US Wire sample (see #23 and §7.5) provides the same-currency shape; the FX variant adds instructionForDebtorAgent: "/FXA/<jpmContractId>" per §7.6.4 (Jessica 2026-03-03). UTA combines base-wire shape + the /FXA/ field for FX wires — the two confirmations are composable; no additional Jessica sample needed.

  34. RFQ Contract ID lifecycle / expiry window — RFQ OAS v1.0.1 shows expirationTimeUTC on the Quote response but does NOT document an explicit expiry on a booked Trade Contract ID. [CONFIRM with JPM] whether a booked jpmContractId has its own expiration window separate from the wire's requestedExecutionDate, and what happens if UTA's wire is submitted after that window. See §7.6.8.

  35. FX trading hours catalog — RFQ OAS v1.0.1 error codes reference branch and currency trading hour windows (ERR_1329 outside branch trading hours, ERR_1330 outside currency trading hours, ERR_1369 outside onshore CNY trading hours) but doesn't enumerate the windows. [CONFIRM with JPM] — likely a JPM Markets reference document; needed for UTA's submission timing logic to avoid wasted RFQ Quote calls.

  36. Payment Receipts — rail coverage for inbound US Wire and inbound ACH credits — split from item #8. The Payment Receipts v1.2.0 OAS schema is rail-agnostic (no rail enum constrains the creditConfirmation event), but the public dev-portal narrative originally framed Payment Receipts as RTP-only. UTA needs to know whether JPM actually fires creditConfirmation webhooks for inbound US Wire credits and inbound ACH credits, or only for RTP. If wire/ACH are not covered, UTA falls back to Transaction Details polling (§6.1) — already adequate. [CONFIRM with JPM Integration Manager] the rail enum for creditConfirmation events as actually delivered in production.

  37. Wire Payments 2 API confirmed out-of-scope(closed 2026-05-11). Wire Payments 2 API v2.0.5 OAS downloaded to Playbook/Wire Payments 2 API 2.0.5.yaml. OAS confirms this is the FI-to-FI (correspondent banking) wire product: initiatingParty.id.organizationId.other.id is required to equal "BANK", and all 3 OAS examples are labeled "US FI to FI." UTA is a corporate (talent agency), not a financial institution, so UTA's wires belong in GP2 (§7.5), not Wire Payments 2. See §7.5 distinction paragraph and JPM_API_Catalog.md. This resolves the earlier-session uncertainty over whether a separate Wire OAS existed — one does exist, but it is for a different customer segment.

  38. Validation Services — customer-specific x-client-id / x-program-id values issued to UTA at onboarding — split from item #12. Limited to the per-customer onboarding values; the first-digit message-class dictionary, the result-slot taxonomy (verification, authentication, individualID, businessID, individualScreening, businessScreening, accountScore, etc.), and the provider list are now documented in §7.1 from OAS v2.2.3. UTA still needs the actual x-client-id UTA is assigned plus the x-program-id values for each profile UTA enables (Standard, Multi, Non-US, ACS, Microdeposit, SurePay). [CONFIRM with JPM at onboarding]

  39. Platform Availability — outage push notification surface(deferred to Phase 2 on 2026-05-12). Re-scan of PACMan OAS v1.1.0 identified a webhook endpoint POST /client-domain ("Participant Outage reporting Webhook") that the prior pass missed — push surface IS supported on this product (no separate Notifications product required for outage push). However, PACMan as a whole is deferred from Phase 1 — see §10 and #21. Two outstanding sub-items to revisit if Phase 2 elects to subscribe: (a) the subscription mechanism (how UTA registers its callback URL with JPM) is not in the OAS; (b) the webhook body schema in the OAS path is the simple partnerBank shape, but components.schemas also defines a richer outageEventDetails shape (event types outage.created / outage.modified / outage.cancelled with impactedProducts[]) that is not linked to any path — confirm which is actually delivered.

  40. DigiCert certificate renewal-timeline changes (industry-wide) — Jessica Jin flagged 2026-05-12: "There are certificate management changes in the industry from DigiCert in regard to certificate renewal timelines." Affects how UTA's 5 cert types (§4.1) are generated and rotated, and how UTA coordinates with JPM's 2026 cert-installation calendar (#14). [ACTION — Amir, UTA Engineering] research current DigiCert timelines before generating UTA's certs.

  41. Statement PDF retrieval — Access-platform alternative to BDC — Surfaced 2026-05-12 by the BDC ineligibility cascade. The BDC product (§14.3, marked OUT OF SCOPE) was the only documented JPM Statements PDF API. UTA still needs monthly PDF statement archival for compliance and retention. Phase 1 workaround documented in §6.3: manual download from JPM Access UI (same as today's pre-integration workflow). [CONFIRM with JPM Integration Manager at kickoff] whether an Access-platform statement-retrieval API exists (analogous to BDC's /accounts/{accountId}/statements/{statementId} but on the corporate-segment side). If yes, scope into Phase 2; if no, manual JPM Access download remains UTA's only path indefinitely.

  42. Validation Services — Account Confidence Score (ACS) numeric-score field location — Surfaced 2026-05-13 during §7.1 sample-response audit. OAS-confirmed AccountScore schema is {code: integer, message: string} only (e.g., 1109 "Information Found", 1209 "No Information Found"). JPM's dev-portal narrative documents a numeric 0–1000 RAG-banded score, but no numeric score field exists in the OAS AccountScore shape. Three possibilities to resolve: (a) the numeric score is returned inside the details block for VERIAUTHUS-profile responses but not schema-documented; (b) the dev-portal narrative is out of step with the current schema and the only consumable signal is the accountScore.code value; (c) the numeric score is on a future-OAS roadmap and not yet surfaced. [CONFIRM with Jessica Jin] which slot/field carries the 0–1000 score, or that the coded accountScore.code is the only signal. Until resolved, UTA's Pre-Flight ACS logic keys off accountScore.code first-digit (1 Information Found / 2 No Information Found), not the un-located numeric score. See §7.1 ACS sample response and "OAS vs dev-portal mismatch" note.

  43. RTP client-initiated returns — US TCH / FedNow shape confirmation — Surfaced 2026-05-13 during §7.11 Inbound Credit Refunds audit. GP2 OAS exposes POST /payment/v2/payments/returns with paymentType: RTP and the PaymentReturn schema is rail-agnostic on its face — but the only ships example is Brazil PIX (RealTimeBRPIXPaymentReturn). No US TCH/FedNow return example exists in the OAS. [CONFIRM with Jessica Jin] whether (a) the same /payments/returns shape works for inbound US RTP credits citing the bankReferenceNumber UTA receives from §6.5 Payment Receipts, (b) US RTP returns require a different shape JPM has not yet published in the OAS, or (c) US RTP credits are simply not eligible for client-initiated programmatic return and UTA must refund via a new outbound payment. Drives §7.11 Phase 1 scope decision: if (a) confirmed, RTP refunds use the programmatic return endpoint; if (b) or (c), RTP refunds fall back to the new-outbound-payment pattern same as ACH/Wire/Check refunds.


13. Next Actions

  1. Jessica Jin reply received 2026-05-12 closing (a) BDC ineligibility for UTA — corporate-segment client cannot use commercial-segment BDC (closes §12 #9 / #10 / #11 / #26 / #28); (b) US Wire sample request body provided verbatim (closes §12 #23 / #33; §7.5 Status flipped to Cleared); (c) onboarding path: formal implementation request to Sam Bomes + Joey at JPM kicks off implementation-team assignment + UAT environment setup. Next: UTA-side, send the formal implementation request once §5 UTA prerequisites are confirmed (accounts in scope, payment types in scope, certificates obtained, POC list registered in PDP).
  2. Stand up UTA's callback receiver (§4.5 + §6.5 + §6.6) — Amir to confirm the receiver architecture (candidate: AWS API Gateway + Lambda + mTLS-terminating ALB; not yet locked) and then scope the build. This is on the critical path; cannot be parallelized with cert exchange.
  3. Cliff: deliver UTA's Klutch account number(s) for CAT entitlement (#18). JPM serves Klutch only — touring, endorsements, and voiceovers are at CNB.
  4. Generate UTA-side certificates — all 5 types per §4.1, in coordination with UTA security. Plan the 2026 cert-installation calendar windows backwards from the desired CAT-ready date.
  5. Engineering PoC against the GP2 sandboxPOST /payment/v2/payments with a synthetic RTP body, validate the response shape, then validate that a sandbox Payment Receipts callback fires when a counterpart simulates an inbound credit. Goal: prove the end-to-end happy path before CAT.
  6. Engineering design document — Amir's team owns drafting (separate from this spec; see §16 three-document set for context). Covers HOW the integration-boundary requirements in §6 / §7 / §8 / §9 plus the Client Processing behavior in document (B) are implemented: class decomposition, queue architecture, retry semantics, error-handling matrices for callbacks vs. polling, callback-receiver structure. Cliff's role here is requirements clarification when Amir's team flags an implementation question that exposes a gap at the integration boundary (when to call X, what to do with payload Y, how to handle exception Z) — those answers land in this spec. Gaps inside Client Processing (business rules, triggers, payload consumption) land in document (B). Engineering hand-off depends on BOTH (A) this spec AND (B) Client Processing behavior spec being ready — Amir's design needs both inputs. (A)-only hand-off would leave (C) without the business-rules layer it implements against.
  7. Schedule JPM Integration Manager call to walk through still-open JPM-side items in §12 — particularly #2 (webhook signature), #3/#25 (CloudEvents type enum), #13 (GP2 Payment Cancellation path), #23/#33 (US Wire sample), #28 (Transaction Details EOL), #36 (Payment Receipts rail coverage), #38 (Validation Services per-customer values), #39 (PACMan push surface), #42 (Validation Services ACS numeric-score field location), #43 (RTP client-initiated returns US shape confirmation). Many of these are unlikely to be resolved by email.

13.1 Requirements gaps to close before engineering hand-off

The following are Cliff-owned requirements decisions (per the §16 scope split) that Amir's engineering team will likely flag during the engineering-design phase. Flagged here so they don't surface as last-minute blockers. Each is a "what does UTA want to do" decision, not a "how does it work technically" question — answers land in this spec, not in the engineering design doc.

  1. Webhook receiver behavior on retransmits (§6.5 Payment Receipts, §6.6 GP2 Callbacks). The receiver dedup-by-endToEndId rule is documented, but the response-to-JPM policy on partial failures is not. Decisions needed: (a) does UTA's receiver always return 200 OK to JPM regardless of downstream handler outcome, deferring to a local retry queue? (b) or does the receiver propagate downstream failures back to JPM as 5xx and let JPM retry? (c) what's the local retry policy if (a)? Tradeoff: option (a) puts retry burden on UTA; option (b) gives JPM control but couples receiver liveness to downstream system health.

  2. Per-error-code handling matrix for outbound payments (§7.2 – §7.5). GP2 returns granular error codes (e.g., 9001 Data Provider Error, 9005 Bad Request / Rate Limit, plus rail-specific rejection codes on paymentStatus: REJECTED callbacks). UTA needs a per-code disposition matrix: which codes auto-retry, which queue for manual review, which auto-bounce back to AR with notification, which page on-call. Currently the spec covers terminal-state criteria but not the per-code branching policy.

  3. Microdeposit Challenge operational workflow (§7.1 Validation Services). When Pre-Flight returns MICRODEPOSIT REQUIRED, JPM sends two small deposits to the candidate account, then asks the customer to confirm the amounts. Decisions needed: who at UTA handles the customer-confirmation step? Is there a Client Processing UI for it, or is this a manual operator workflow? What's the timeout / escalation policy if the customer doesn't confirm within JPM's window?

  4. Three-Way Match failure handling (§9 Brakes). When the EOD Three-Way Match fails (bank vs sub-ledger vs GL), what's the operational workflow? Manual review queue assigned to which team? Auto-retry the match after a settle period? Page on-call after how many consecutive failures? What's the escalation tree?

  5. Inbound credit refund — rail-selection policy (§7.11). When refunding an inbound credit via the new-outbound-payment pattern (ACH, Wire, Check), what rail does UTA choose? Same rail as received? Fastest available (RTP if eligible)? Cheapest (ACH)? Caller's preference? Different policies per refund-reason category (overpayment vs fraud vs client request)?

  6. Refund authorization workflow (§7.11, upstream from this spec). Who authorizes a refund inside UTA — AR-team flag + manager approval; client-service ticket; fraud-ops disposition? This is upstream of the integration but shapes what Client Processing must capture and what state-transitions Amir's team designs around.

Resolution path: Cliff drafts answers (or asks Andrew / cash-mgmt / client-accounting for input where the policy is operationally owned elsewhere). Answers land in the relevant §6 / §7 / §9 section as new requirements rows. Once landed, items in this subsection get a (closed) suffix the same way §12 items do. Do not delete closed items — the historical record matters for engineering-design traceability.


14. References

Every endpoint, field, schema, and behavior cited in this document traces back to one of the sources below. Pages on the developer portal are stable HTTPS URLs and load without authentication; pages requiring sign-in (the Developer Portal Security tab where certificates are uploaded) are flagged inline. The GP2 Integration Guide PDF lives in UTA's JPM/ folder and is referenced by page number where applicable.

14.1 J.P. Morgan Payments Developer Portal — Reference Pages (cross-cutting)

TopicURL
API reference roothttps://developer.payments.jpmorgan.com/api/home
Authentication overviewhttps://developer.payments.jpmorgan.com/api/authentication
mTLS + Digital Signature mechanicshttps://developer.payments.jpmorgan.com/api/mtls-with-digital-signature
OAuth flow (sandbox + signed JWT)https://developer.payments.jpmorgan.com/api/oauth
J.P. Morgan public certificates (download + thumbprints)https://developer.payments.jpmorgan.com/api/certificates
2026 callback / encryption cert installation calendarhttps://developer.payments.jpmorgan.com/api/environments
API versioning / deprecation policyhttps://developer.payments.jpmorgan.com/api/versioning
Cross-API HTTP response code patternshttps://developer.payments.jpmorgan.com/api/response-codes

14.2 Global Payments 2 (GP2) — Payment Initiation, Status, Returns

TopicURL
GP2 overviewhttps://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/index
GP2 Callbacks (CloudEvents webhooks)https://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/callbacks
GP2 OpenAPI spec (OAS)https://developer.payments.jpmorgan.com/api/treasury/global-payments/global-payments-2/global-payments-2-oas
GP2 status responses & error codeshttps://developer.payments.jpmorgan.com/api/treasury/global-payments/global-payments-2/error-codes
GP2 changeloghttps://developer.payments.jpmorgan.com/api/treasury/global-payments/global-payments-2/changelog
Treasury Global Payments getting started (CAT access gating)https://developer.payments.jpmorgan.com/docs/treasury/global-payments/getting-started

Real-Time Payments (RTP) — §7.2:

TopicURL
RTP overviewhttps://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/real-time-payments/index
RTP payment & return parametershttps://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/real-time-payments/payment-parameters
RTP resources (rails, limits, response types)https://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/real-time-payments/resources
Initiate a Real-Time Payment requesthttps://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/real-time-payments/how-to/initiate-a-real-time-payments-request
Get RTP statushttps://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/real-time-payments/how-to/retrieve-transaction-status
Initiate an RTP returnhttps://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/real-time-payments/how-to/initiate-a-real-time-payments-return-request
Get return statushttps://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/real-time-payments/how-to/get-the-status-of-a-return-request

ACH (NACHA, both directions) — §7.3 & §7.4:

TopicURL
ACH overviewhttps://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/ach/index
ACH payment parameters (credit)https://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/ach/payment-parameters-credit
ACH payment parameters (debit)https://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/ach/payment-parameters-debit
ACH resources (cutoffs, limits)https://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/ach/resources
Initiate an ACH paymenthttps://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/ach/how-to/initiate-a-low-value-ach-payment
Get ACH statushttps://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/ach/how-to/get-the-status-of-a-low-value-ach-request

Wire (same-currency) — §7.5:

TopicURL
Same-Currency Wire overviewhttps://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/wire/same-currency-wires/index
Wire payment parametershttps://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/wire/same-currency-wires/payment-parameters
Wire resources (cutoffs, limits)https://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/wire/same-currency-wires/resources
Initiate a wire paymenthttps://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/wire/how-to/initiate-a-high-value-wire-payment
Get wire statushttps://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/wire/how-to/get-the-status-of-a-high-value-wire-request

Cross-Currency / FX — §7.6 (Cleared via RFQ API — see §14.9 for authoritative OAS):

UTA's FX wire path is the Request for Quote API v1.0.1 (§14.9) combined with GP2 Wire carrying instructionForDebtorAgent: "/FXA/<contractId>" — see §7.6. JPM Wallet was evaluated and is not required for UTA (§12 #20 closed 2026-05-12). No standalone JPM developer-portal documentation page exists for this composite RFQ+GP2 flow — the OAS files and JPM's RFQ-flow guidance in the §7.6 sub-sections of this spec are authoritative. Previously-listed JPM Wallet FX-Wire/FX-ACH dev-portal URLs returned 404 and were removed 2026-05-13.

14.3 Business Direct Connect (FDX v6) — OUT OF SCOPE for UTA

BDC is JPM's commercial-segment product. UTA is corporate-segment on the Access platform and cannot use BDC (per Jessica Jin 2026-05-12; closes §12 #9 / #10 / #11 / #26 / #28). Retained here for historical reference only — none of these URLs are part of UTA's permanent integration path. UTA's inbound reporting product is the Transaction Details API + Account Balances API combination (see §6.1, §6.2). The original BDC v6.2.16 OAS file remains in JPM/Playbook/Future-State/ marked as a historical artifact.

14.4 Payment Receipts API (Inbound RTP credits)

TopicURL
Payment Receipts overviewhttps://developer.payments.jpmorgan.com/docs/treasury/payment-receipts/doc
Payment Receipts OpenAPI spec (/webhook/credit-confirmation schema)https://developer.payments.jpmorgan.com/api/treasury/payment-receipts/payment-receipts-oas

14.5 Validation Services (Pre-Flight)

TopicURL
Validation Services overviewhttps://developer.payments.jpmorgan.com/docs/fraud-solutions/validation-services/index
Validation Services getting startedhttps://developer.payments.jpmorgan.com/docs/fraud-solutions/validation-services/getting-started
Account Validation overviewhttps://developer.payments.jpmorgan.com/docs/fraud-solutions/validation-services/capabilities/account-validation/index
Account Validation parametershttps://developer.payments.jpmorgan.com/docs/fraud-solutions/validation-services/capabilities/account-validation/account-validation-parameters
Verify a US bank account & ownership how-tohttps://developer.payments.jpmorgan.com/docs/fraud-solutions/validation-services/capabilities/account-validation/how-to/Verify-bank-account-status
Account Confidence Score (ACS) how-tohttps://developer.payments.jpmorgan.com/docs/fraud-solutions/validation-services/capabilities/account-validation/how-to/request-an-account-confidence-score
Global Account Validation how-tohttps://developer.payments.jpmorgan.com/docs/fraud-solutions/validation-services/capabilities/account-validation/how-to/global-account-validation
Account Validation global coverage (countries)https://developer.payments.jpmorgan.com/docs/fraud-solutions/validation-services/capabilities/account-validation/account-validation-global-coverage
Entity Validation overviewhttps://developer.payments.jpmorgan.com/docs/fraud-solutions/validation-services/capabilities/entity-validation/index
Entity Validation parametershttps://developer.payments.jpmorgan.com/docs/fraud-solutions/validation-services/capabilities/entity-validation/entity-validation-parameters
Validation Services API spec (OAS)https://developer.payments.jpmorgan.com/api/fraud-solutions/validation-services/validation-services-oas
Validation Services error codeshttps://developer.payments.jpmorgan.com/api/fraud-solutions/validation-services/error-codes

14.6 Checks API (Issuance, Print, Stop & Revoke, Image, Inquiry)

TopicURL
Checks API overviewhttps://developer.payments.jpmorgan.com/docs/treasury/checks/index
Checks getting startedhttps://developer.payments.jpmorgan.com/docs/treasury/checks/getting-started
Checks core conceptshttps://developer.payments.jpmorgan.com/docs/treasury/checks/core-concepts
Check Issuance & Cancellation overviewhttps://developer.payments.jpmorgan.com/docs/treasury/checks/capabilities/check-issuance-and-cancellation/overview
Issuance parametershttps://developer.payments.jpmorgan.com/docs/treasury/checks/capabilities/check-issuance-and-cancellation/payment-parameters
Issuance how-tohttps://developer.payments.jpmorgan.com/docs/treasury/checks/capabilities/check-issuance-and-cancellation/how-to/how-to
Stop & Revoke overviewhttps://developer.payments.jpmorgan.com/docs/treasury/checks/capabilities/stop-and-revoke/overview
Stop & Revoke parametershttps://developer.payments.jpmorgan.com/docs/treasury/checks/capabilities/stop-and-revoke/parameters
Manage Check Stop how-tohttps://developer.payments.jpmorgan.com/docs/treasury/checks/capabilities/stop-and-revoke/how-to/check-stop-and-revoke
Manage Check Revoke how-tohttps://developer.payments.jpmorgan.com/docs/treasury/checks/capabilities/stop-and-revoke/how-to/stop-and-revoke
Check Image overviewhttps://developer.payments.jpmorgan.com/docs/treasury/checks/capabilities/check-image/overview
Check Image parametershttps://developer.payments.jpmorgan.com/docs/treasury/checks/capabilities/check-image/payment-parameters
Check Inquiry overviewhttps://developer.payments.jpmorgan.com/docs/treasury/checks/capabilities/check-inquiry/overview
Check Inquiry parametershttps://developer.payments.jpmorgan.com/docs/treasury/checks/capabilities/check-inquiry/payment-parameters
Check Print overviewhttps://developer.payments.jpmorgan.com/docs/treasury/checks/capabilities/check-print/overview
Check Print parametershttps://developer.payments.jpmorgan.com/docs/treasury/checks/capabilities/check-print/parameters
Manage Check Print how-tohttps://developer.payments.jpmorgan.com/docs/treasury/checks/capabilities/check-print/how-to/manage-check-print
Get Check Print Details how-tohttps://developer.payments.jpmorgan.com/docs/treasury/checks/capabilities/check-print/how-to/get-check-print-details
Checks API spec (OAS)https://developer.payments.jpmorgan.com/api/treasury/checks/checks-oas
Checks API error codeshttps://developer.payments.jpmorgan.com/api/treasury/checks/error-codes
Checks API changeloghttps://developer.payments.jpmorgan.com/api/treasury/checks/changelog

14.7 PACMan (Platform Availability Communication Management)

TopicURL
PACMan overviewhttps://developer.payments.jpmorgan.com/docs/treasury/pacman/doc

14.8 Out-of-Scope GP2 Rails (referenced in §7.10 only)

RailURL
Push to Card overviewhttps://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/push-to-card/index
Push to Wallet overviewhttps://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/push-to-wallet/index
Zelle Disbursements overviewhttps://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/zelle-disbursements/index
Kinexys Digital Payments overviewhttps://developer.payments.jpmorgan.com/docs/treasury/global-payments/capabilities/global-payments-2/jpm-coin-system/index

14.9 Local Documents

JPM-issued playbooks (authoritative for product selection and onboarding sequence):

TopicPath
US JPM API Playbook — Reporting v1 (prescribes Transaction Details + Account Balances)US J.P. Morgan API Playbook_Reporting_v1.pdf
GP2 Client Integration Guide v2 (outbound payments companion to Reporting Playbook)2026 GP2 Client Integration Guide v2.pdf

OAS YAML files (authoritative for schemas, field names, error codes):

APISpec section(s)Path
Transaction Details API v3.1.8§6.1 intraday + prior-dayPlaybook/Transaction Details API 3.1.8.yaml
Account Balances API v1.0.5§6.2 EOD balance lockPlaybook/Account Balances API 1.0.5.yaml
Global Payments 2 v2.4.7§6.6 callbacks + §7.2 RTP + §7.3 ACH Credit + §7.4 ACH Debit + §7.5 WirePlaybook/Global Payments 2.4.7.yaml
Request for Quote API v1.0.1§7.6.2 Quote + §7.6.3 Trade + §7.6.5 CancelPlaybook/Request for Quote API 1.0.1.yaml
FX Rate Sheet API v1.0.2§7.6.6 (CNB §5.6 indicative-rate-file equivalent)Playbook/FX Rate Sheet API 1.0.2.yaml
Payment Receipts v1.2.0§6.5 inbound creditConfirmation webhookPlaybook/Payment Receipts 1.2.0.yaml
Validation Services API v2.2.3§7.1 Pre-Flight (entity + account validation)Playbook/Validation Services API 2.2.3.yaml
Checks API v2.1.1§6.4 + §7.7 + §7.8 (inquiry, image, issuance, cancellation, stop, revoke, print)Playbook/Checks API 2.1.1.yaml
Platform Availability API v1.1.0§10 (PACMan — deferred to Phase 2; not in Phase 1 build)Playbook/Platform Availability API 1.1.0.yaml
Onboarded Accounts API v1.0.1§5 (one-time post-CAT and Prod go-live entitlement verification)Playbook/Onboarded Accounts 1.0.1.yaml
Wire Payments 2 API v2.0.5 (OUT OF SCOPE — FI-to-FI correspondent banking; UTA wires use GP2 per §7.5)§7.5 distinction note onlyPlaybook/Wire Payments 2 API 2.0.5.yaml
Xpedite Remit FX Rate Sheet API v1.0.1 (OUT OF SCOPE — consumer remittance, not corporate treasury)§7.6.7 (mentioned only)Playbook/Xpedite Remit FX Rate Sheet API 1.0.1.yaml
Global Payments API v1.2.0 (DEPRECATED — superseded by GP2 v2.4.7; per Jessica Jin 2026-03-03: "GPV1 will be deprecated eventually, I would not recommend building to GPV1 as a fallback." Do not build against this)(no scope section — deprecated)Playbook/Global Payments API 1.2.0.yaml
BDC v6.2.16 (OUT OF SCOPE — UTA ineligible. BDC is JPM's commercial-segment product; UTA is corporate-segment on the Access platform per Jessica Jin 2026-05-12: "Business Direct Connect platform is for our commercial clients – UTA is considered a corporate client on our Access platform and will not be able to utilize FDX." Not a future-state target either)(no migration path; UTA stays on Transaction Details + Account Balances permanently)Playbook/Future-State/J.P. Morgan Business Direct Connect 6.2.16.yaml
JPM API Catalog (master checklist of all 46 JPM products + scoping decisions)catalog-level referencePlaybook/JPM_API_Catalog.md

Predecessor specs and other materials:

TopicPath
Predecessor spec (do not edit)JPM/UTA JPM GP2 Integration Specification v2.2.md
Predecessor spec (do not edit)JPM/UTA JPM GP2 Integration Specification v1.3.md
JPM Integration Manager response — 7 questions answeredJPM/correspondence/2026-03-03_jessica-jin-questions-response.md

14.10 Conversations & Direction

SourceWhenWhat it covered
JPM Integration Manager response2026-03RFQ Quote → Trade → Contract ID flow shape; Account Balances API rate-limit guidance; ~10:00 PM EOD lock + ~7:30 AM prior-day lock; Payment Receipts PDP path; Transaction Details same-day wire credit availability; Checks API mock base; Positive Pay Q2 launch tentative
Cliff directionpost-2026-03Expand ACH scope to include authorized debit pulls (§7.4)
Amir architecture (candidate, not yet confirmed)2026-04+Candidate approach floated for UTA callback receiver: AWS API Gateway + Lambda fronted by mTLS-terminating ALB. Architecture not yet confirmed by UTA Engineering as of 2026-05-12 — awaiting Amir's formal review and decision (§12 #17).
Cliff/Andrew alignment2026-05October 2026 production target; 2–3 month test-readiness window

End of Document — UTA ↔ JPM Global Payments 2 Integration Specification v3.0 (Draft)

Confidential. For internal use only.

Loading...