Loading, please wait…
ISO codes, formats, and platform terms used by the CommerceHub Party Boarding and Funds APIs (/ch/v1/party/* and /ch/v1/funds/*). Field descriptions in the API reference link straight to the matching entry on this page.
Each entry starts with a one-line definition, followed by a quick-reference table:
| Row | What it tells you |
|---|---|
| Fields | The request and response fields that use the term, written as JSON paths, for example payee.owners[].address.country. |
| Format | The JSON type and the exact rule the API validates, including the regular expression where one applies. |
| Example | A value that passes validation. |
| Watch out | Mistakes that commonly cause 400 Bad Request errors or mismatched data. |
All codes are case-sensitive: send them exactly as shown, for example USA not usa, and PaymentToken not PAYMENT_TOKEN.
A country identified by its three-letter ISO 3166-1 alpha-3 code.
| Fields | country (party and funds payee), address.country (owners, business registeredAddress), phone.countryCode, identityDetails[].issuingCountry, taxProfile.issuingCountry |
| Format | String, exactly 3 uppercase letters: ^[A-Z]{3}$ |
| Example | USA, CAN, GBR, AUS, IND |
| Look up | POST /ch/v1/party/configuration-inquiry with configurationType=COUNTRIES lists supported countries. |
Watch out
US). Party and payee fields reject it.phone.countryCode is the country of the phone (USA), not the dialing prefix (1 or +1). For a business phone it must equal party.country; an owner's phone can be any country.country filters on /ch/v1/party/configuration-inquiry and /ch/v1/party/agreements are shown with US in examples.country accepts 2 or 3 letters (^[A-Z]{2,3}$). Prefer address.country (alpha-3) for new integrations.GatewayPhone.countryCode carries a dialing code such as 91.address.countryCode is a legacy alias. Use address.country.A currency identified by its three-letter ISO 4217 code.
| Fields | amount.currency, paymentReceipt.approvedAmount.currency, paymentReceipt.balances[].currency, tender currency, the source and target currencies on /ch/v1/funds/currency-exchange-rates |
| Format | String, 3 uppercase letters: ^[A-Z]{3}$ |
| Example | USD, EUR, GBP, CAD |
| Look up | configurationType=COUNTRIES returns each country's default currency; configurationType=CURRENCY_TENDER filters tender types by currency. |
Watch out: Use the alphabetic code, not the numeric one (USD, not 840). See Amount for how to send the value.
Two related codes:
| Field | Standard | Format | Example |
|---|---|---|---|
party.locale | IETF BCP 47 language tag: language[-script][-region] | ^[a-zA-Z]{2,3}(-[a-zA-Z]{4})?(-([a-zA-Z]{2}|[0-9]{3}))?$, 2 to 12 characters | en-US, zh-Hant-TW, es-419 |
language filter on /ch/v1/party/agreements (agreementType=DISCLOSURE) | ISO 639-1 | 2 lowercase letters | en, fr |
Watch out: Use a hyphen, not an underscore (en-US, not en_US). The region part of a locale is alpha-2 (US), unlike country codes elsewhere in the API.
A phone number in E.164 international format: +, the country dialing code, and the subscriber number.
| Fields | phone.phoneNumber (party, owners, business), phoneNumber on /ch/v1/party/user-authenticate |
| Format | phone.phoneNumber: ^\+[1-9][0-9]{6,14}$, 8 to 16 characters including the +. On /ch/v1/party/user-authenticate the + is optional: ^\+?[1-9]\d{1,14}$. |
| Example | +14155552671 (United States), +442071838750 (United Kingdom) |
| Related fields | phone.countryCode (alpha-3 country code), phone.type (HOME, MOBILE, DAY, WORK, OTHER), phone.preference (for example PRIMARY) |
Watch out: No spaces, dashes, or brackets: +1 (415) 555-2671 and 404-555-5678 are rejected. Don't put the dialing code in phone.countryCode.
Dates and timestamps in JSON bodies use ISO 8601 (RFC 3339 profile). Headers are different; see the last row.
| Kind | Format | Example | Fields |
|---|---|---|---|
| Date | YYYY-MM-DD (exactly 10 characters) | 1988-06-19 | individual.dateOfBirth, business.dateOfIncorporation, business.registrationDate, identityDetails[].expirationDate, compliance.effectiveDate |
| Date-time with zone (request) | YYYY-MM-DDThh:mm:ss[.fraction](Z|±hh:mm), 20 to 30 characters | 2026-08-12T17:46:05Z | compliance.consentTimestamp, status.openDate, status.closeDate |
| Date-time (response) | ISO 8601 in UTC, up to nanosecond precision | 2026-10-06T20:58:53.017320772Z | transactionProcessingDetails.transactionTimestamp, processorResponseDetails.localTimestamp, rate validFrom/validTo, balanceTimestamp |
| Notification time | YYYY-MM-DDThh:mm:ss in UTC, no zone suffix | 2026-10-06T20:59:21 | eventTimestamp in the notification envelope |
Timestamp header | Unix epoch milliseconds (not ISO 8601) | 1767225600000 | Timestamp request header; see HMAC authentication |
Watch out: Always include a zone (Z or an offset) on request date-times. When parsing responses, accept a variable number of fractional digits (0 to 9).
A four-digit merchant category code (MCC), defined by ISO 18245, that classifies a business by what it sells.
| Fields | business.mcc |
| Format | String of exactly 4 digits: ^[0-9]{4}$ |
| Example | 5411 (grocery stores and supermarkets), 5999 (miscellaneous retail) |
| Look up | configurationType=MCC lists supported codes. |
Watch out: Send it as a string with leading zeros kept ("0742", not 742).
The state, province, or region part of an address.
| Fields | address.stateOrProvince |
| Format | String, up to 256 characters |
| Example | GA (Georgia), ON (Ontario), NSW (New South Wales) |
| Look up | configurationType=COUNTRY_ADDRESS returns a country's address rules. |
Watch out: For the United States and Canada send the two-letter postal abbreviation (GA, not Georgia). It matches the subdivision part of ISO 3166-2 (US-GA → GA); don't include the country prefix.
A person or business on your platform: a buyer, seller, or merchant. A party has a party type, a party role, contact details, and owners. It goes through KYB and/or KYC, is provisioned, and can then hold a wallet.
| Endpoints | Create and change with POST /ch/v1/party/onboard; read with POST /ch/v1/party/inquire. A buyer can also be created inline by a CREDIT on /ch/v1/funds/transact (see Funds operation types). |
| Identified by | Party ID (assigned by CommerceHub) and merchant party ID (assigned by you) |
partyId: the identifier CommerceHub assigns to a party when it is created.
| Fields | partyId (party responses, /ch/v1/party/inquire, /ch/v1/party/tender, /ch/v1/party/user-authenticate, document APIs), payee.partyId (/ch/v1/funds/transact), party.partyId (/ch/v1/funds/balance-inquiry, notifications) |
| Format | String of exactly 15 digits: ^[0-9]{15}$ |
| Example | 101517000004623 |
| Who sets it | CommerceHub. It's read-only on the party. |
Watch out
partyId when creating a party, or when onboarding a buyer inline with a CREDIT. Send merchant party ID instead, then store the partyId from the response.platform.merchantPartyId: your identifier for the party.
| Fields | platform.merchantPartyId (party create, funds payee.platform.merchantPartyId) |
| Format | String you choose; unique within your platform |
| Example | 7fe287e5-e04b-4be1-a90f-564cfb67eab6, BUYER-71720684 |
| Who sets it | You. Required to create a party and to onboard a buyer inline. CommerceHub echoes it in responses and PARTY_STATUS_CHANGED notifications. |
Watch out: Never reuse a merchant party ID for a different person or business. Use it to map CommerceHub parties back to your own customer records.
platform.clientId: your CommerceHub (CLX) client identifier.
| Format | String, read-only |
| Example | acme |
| Who sets it | CommerceHub, from your authenticated credentials. Don't send it. |
type: whether the party is a person or a company.
| Value | Meaning | Checks |
|---|---|---|
INDIVIDUAL | A single person. | KYC on the person. |
BUSINESS | A company or other legal entity. Send the business object. | KYB on the business and KYC on its owners. |
Watch out: In a payout without onboarding, the recipient's payee.type is PERSONAL (see Funds operation types). PERSONAL isn't valid when creating a party.
partyRole: what the party does on your platform.
| Value | Meaning |
|---|---|
BUYER | Buys goods or services. Can receive refunds (CREDIT) into a wallet. |
SELLER | Sells goods or services. Receives payouts. |
MERCHANT | A business accepting payments. |
Watch out: RECIPIENT is used only for the payee of a payout without onboarding; it isn't valid when creating a party.
An entry in owners[]: a person associated with the party, such as an owner, officer, or beneficial owner of a business.
| Field | Format | Example |
|---|---|---|
owners[].individual | Name, dateOfBirth (date), email, phone (E.164), identityDetails[] | — |
owners[].address | Address with alpha-3 country | — |
owners[].relationship.authorityTypes | Array; one or both of BENEFICIAL_OWNER (owns part of the business) and AUTHORIZED_SIGNATORY (can sign for it) | ["AUTHORIZED_SIGNATORY", "BENEFICIAL_OWNER"] |
owners[].relationship.percentage | String holding a whole number 0 to 100: ^(100|[0-9]{1,2})$ | "100", "25" |
owners[].relationship.title | Free text | CEO |
owners[].individual.identityDetails[].type | DRIVERS_LICENSE, PASSPORT, NATIONAL_ID, STATE_ID, … (check configurationType=IDENTITY_TYPES per country) | PASSPORT |
Watch out: percentage is a string ("25", not 25 or "25.5"). Percentages across all owners must not exceed 100.
revisionId: the current revision of a party's onboarding application.
| Fields | revisionId (party responses; /ch/v1/party/tender requests and responses) |
| Format | String of exactly 21 digits: ^[0-9]{21}$ |
| Example | 378259295295259202020 |
| Who sets it | CommerceHub. Read it from the party and send it back on tender requests. |
Watch out: It changes when the party changes. Read the latest value from /ch/v1/party/inquire before calling /ch/v1/party/tender.
status.status: where the party is in its lifecycle.
| Value | Meaning | Can move funds? |
|---|---|---|
PENDING | Not fully onboarded yet. | No |
ACTIVE | Onboarded and provisioned. | Yes |
SUSPENDED | Temporarily restricted. | No |
DECLINED | Rejected under operating policy. | No |
CLOSED | Permanently closed. | No |
CLOSED_FRAUD | Closed because of fraud. | No |
status.openDate and status.closeDate are date-times. Status changes arrive as PARTY_STATUS_CHANGED webhook notifications.
transactionDetails.operationType on POST /ch/v1/party/onboard selects the action.
| Value | What it does | Identify the party with |
|---|---|---|
CREATE | Creates a party. Requires type, partyRole, country, email, platform.merchantPartyId. | — (a partyId is returned) |
VALIDATE | Checks party data against the rules without saving it. | — |
UPDATE | Changes some fields. | partyId |
REPLACE | Replaces all of the party's data. | partyId |
DELETE | Removes the party. | partyId |
KYB | Submits the business for KYB. | partyId |
KYC | Submits the person or owners for KYC. | partyId |
PROVISION | Provisions an approved party. | partyId |
For CREDIT, TOP_UP, and PAYOUT, see Funds operation types.
The last onboarding step (operationType=PROVISION): it activates an approved party so it can hold funds and receive payouts.
| Requires | country, compliance (compliance consent), taxProfile (tax profile), and each owner's name and date of birth |
| If data is missing | The response lists FIELD_REQUIRED entries in requiredFieldViolations. |
| After it succeeds | status.status becomes ACTIVE, and the party's ledger accounts appear in finxactData. See Wallet. |
Watch out: A CREDIT with inline onboarding provisions the buyer automatically; you don't call PROVISION yourself.
Know Your Business: verification of a business party's identity and registration.
| Start | POST /ch/v1/party/onboard with operationType=KYB |
| Result | Asynchronous: PARTY_KYB_CHANGED webhook with INITIATED, PENDING, DOCUMENT_REQUIRED, APPROVED, or DECLINED. You can also poll /ch/v1/party/inquire. |
| If documents are needed | See Boarding step and MRD document codes (MRD-KYB-*). |
Know Your Customer: identity verification of an individual party or of a business's owners.
| Start | POST /ch/v1/party/onboard with operationType=KYC |
| Result | Asynchronous: PARTY_KYC_CHANGED webhook with the same states as KYB. |
| If documents are needed | Identity documents (MRD-KYC-*) or a liveness check (MRD-KYC-000). See MRD document codes. |
A stage of onboarding, such as KYB or KYC, returned by /ch/v1/party/inquire with a status and, when you need to act, an actions[] list.
status | Meaning | Your next step |
|---|---|---|
INITIAL | Created, not started. | None yet. |
PENDING | Being evaluated. | Wait for a webhook. |
AWAITING_ACTION | Needs you. | Do each actions[].code, for example UPLOAD_DOCUMENT, VERIFY_PHONE, SUBMIT_KYB, SUBMIT_KYC. |
VERIFIED | Approved. | Continue onboarding. |
REJECTED | Declined; final. | Stop. |
ERROR | The last operation failed. | Retry. |
SKIPPED | Not required. | None. |
retryAttempt (integer 1 to 5) counts document submissions for the step.
Codes that name the document requested for KYB or KYC.
| Fields | documentType on /ch/v1/party/document-upload, /ch/v1/party/document-delete, and in actions[] / documentOptions[] from /ch/v1/party/inquire |
| Format | MRD-KYB-nnn (business documents) or MRD-KYC-nnn (identity documents), up to 126 characters |
| Example | MRD-KYC-001 (driver's license), MRD-KYC-000 (liveness check), MRD-KYB-007 |
| Slots | docContext: front, back, multipage, or live (liveness only). all is allowed on delete. |
Flow: upload each slot with /ch/v1/party/document-upload → optionally remove one with /ch/v1/party/document-delete → submit with /ch/v1/party/document-evaluate. Use the exact documentType from the boarding step's actions[].
POST /ch/v1/party/user-authenticate verifies the person using your platform. operationType selects the check:
| Value | What it does |
|---|---|
GENERATE | Sends a one-time passcode (OTP) by sms, voice, or email. The phone must be E.164. |
VALIDATE | Checks the passcode the user entered. |
BOTCHECK | Runs a LexisNexis bot check. |
Results also arrive as PARTY_OTP_BUSINESS and PARTY_OTP_SIGNER webhook notifications (PENDING, VALIDATED).
taxProfile: the party's tax registration. Required before provisioning.
| Field | Format | Example |
|---|---|---|
taxFilingName | Name on the tax registration | Jane Doe |
taxId | ^[A-Za-z0-9- ]{1,50}$ | 123-45-7890 |
taxIdType | One of SSN, ITIN, EIN, TIN (United States); VAT; BN, GST, HST (Canada); UTR (United Kingdom); ABN, TFN (Australia); PAN, TAN (India); CRN; RFC (Mexico) | SSN |
issuingCountry | Alpha-3 country code | USA |
compliance: proof that the party accepted your terms. Required before provisioning.
| Field | Format | Example |
|---|---|---|
termsAndConditionsVersion | 1 to 12 characters; must match the current agreement version | 1.2 |
consentBy | Name of the person who consented | Jane Doe |
consentTimestamp | ISO 8601 date-time with zone | 2026-08-12T17:46:05Z |
effectiveDate | ISO 8601 date | 2026-08-12 |
POST /ch/v1/party/agreements manages legal terms. agreementType selects the action:
agreementType | What it does | Other inputs |
|---|---|---|
DISCLOSURE | Returns the disclosures to show the user. | country (required), language (ISO 639-1, optional) |
TERMSOFSERVICE | Records acceptance of terms of service. | type: acquiring, payouts, or partyAgreement |
SIGNATURE | Signs a terms-of-service document. | type: acquiring, payouts, or partyAgreement |
configurationType on POST /ch/v1/party/configuration-inquiry selects which reference data to return. Read-only; use it to build dropdowns and validate input before you call other APIs.
| Value | Returns | Filter |
|---|---|---|
COUNTRIES | Supported countries with alpha-3 code and default currency. | — |
PARTY_TYPES | Supported party types. | — |
ORGANIZATION_TYPES | Business legal types, for example LLC or CORP. | country |
MCC | Supported merchant category codes. | — |
COUNTRY_ADDRESS | Address rules. | country |
COUNTRY_TENDER | Tender types available in a country. | country |
CURRENCY_TENDER | Tender types available for a currency. | currency |
IDENTITY_TYPES | Accepted identityDetails[].type values. | country |
DEFAULT_TENDERS | Your client's default tender set. | — |
A stored-value account that CommerceHub holds for a provisioned party.
| Funds in | CREDIT (refund) and TOP_UP (from a bank account) |
| Funds out | PAYOUT to a card or bank account |
| Read | POST /ch/v1/funds/balance-inquiry returns paymentReceipt.balances[], one entry per balanceType, each with beginningBalance, endingBalance, availableBalance, and currency. |
| Ledger | The underlying ledger (Finxact) accounts appear in the party's finxactData after provisioning. |
Watch out: A party must be ACTIVE before its wallet can be funded. A CREDIT with inline onboarding handles this for you.
A payment instrument linked to a party, also called a payout product: the bank account or card that funds are paid out to or pulled from.
| Endpoint | POST /ch/v1/party/tender with operationType CREATE, UPDATE, DELETE, or VERIFY (send partyId and the current revision ID) |
| Tender ID format | A UUID or a ppo_ identifier: ^(?:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ppo_[A-Za-z0-9]+)$ |
| Example | a1b2c3d4-e5f6-7890-abcd-ef1234567890 |
status | Meaning |
|---|---|
LINKED | Active; can receive payouts. |
PENDING_VERIFICATION | Waiting for verification, for example micro-deposits. See Bank account verification. |
SUSPENDED | Temporarily disabled. |
INACTIVE | Permanently deactivated. |
BAV: confirmation that the party owns a bank account tender.
verification.status | Meaning | Your next step |
|---|---|---|
BAV_IN_PROGRESS | Being verified. | Check /ch/v1/party/inquire with inquiryType=ERRORS for any documents you must provide. |
BAV_APPROVED | Verified. | The tender can be used. |
BAV_DECLINED | Not verified. | Ask the party for another account. |
transactionDetails.operationType on POST /ch/v1/funds/transact. Each use case accepts a different payload; send only the fields listed for it.
| Use case | operationType | payee | Instrument | Final result webhook |
|---|---|---|---|---|
| Refund to an existing buyer | CREDIT | partyId only | — | CREDIT_STATUS_CHANGED |
| Refund with inline onboarding | CREDIT | Buyer details: type, partyRole, country, email, platform.merchantPartyId (required), plus owners[]. No partyId. | — | PARTY_STATUS_CHANGED, then CREDIT_STATUS_CHANGED |
| Wallet top-up | TOP_UP | partyId only | source: payment token | — |
| Wallet payout | PAYOUT | partyId only | target: payment token; optional rate.referenceId for cross-border | PAYOUT_STATUS_CHANGED |
| Payout without onboarding | PAYOUT | Recipient details: type=PERSONAL, partyRole=RECIPIENT, platform.merchantPartyId, owners[], email. No partyId. | target: encrypted card | PAYOUT_STATUS_CHANGED |
All of them return 201 Created with transaction state PENDING. The final outcome arrives by webhook.
Watch out: A CREDIT is declined with responseCode 006 if it would take the party over the configured cumulative credit limit; the reason and limit are in hostResponseMessage.
| Object | Meaning |
|---|---|
payee | The party whose wallet is credited, topped up, or paid out from, or the recipient of a payout without onboarding. Use payee.partyId for an onboarded party; send details instead when onboarding inline or paying a recipient who isn't onboarded. |
payer | The party providing the funds, usually your platform or the merchant. Optional in most flows. |
| Object | Meaning | Used by |
|---|---|---|
source | Where funds are pulled from. | TOP_UP |
target | Where funds are paid to. | PAYOUT |
Both are payment instruments selected by sourceType (case-sensitive): PaymentToken, PaymentCard, BankAccount, Wallet, or PaymentCheck. Funds transact requests accept PaymentToken (see Payment token) and, for a payout without onboarding, PaymentCard (see Encrypted card data).
A token that stands in for card or bank account details stored in the Fiserv Secure Vault, so you never send raw account numbers.
| Field | Format | Example |
|---|---|---|
sourceType | PaymentToken | PaymentToken |
tokenData | The token, up to 2048 characters | 1155522326930029 |
tokenSource | The token service provider (TSP) | FISERV_SECURE_VAULT |
Watch out: A token isn't a card number, even if it looks like one. Store and send it exactly as issued.
For a payout to a card that isn't tokenized, send target.sourceType=PaymentCard with the card encrypted in target.encryptionData. Plain-text card numbers are rejected.
| Field (all required) | Meaning | Example |
|---|---|---|
keyId | ID of the encryption key you used. | 62136234-eab8-47d9-9cf3-6199c46e29d1 |
encryptionType | Algorithm. | RSA |
encryptionBlock | Base64 of the encrypted card fields, concatenated in the order given by encryptionBlockFields. | SVx2/zwe...Q9MA== |
encryptionBlockFields | Comma-separated field:length list describing the block. | card.cardData:16,card.expirationMonth:2,card.expirationYear:4,card.securityCode:3 |
encryptionTarget | How the card was captured. | MANUAL |
Watch out: The lengths in encryptionBlockFields must match the plain-text values before encryption: expirationMonth is 02, not 2, and expirationYear has 4 digits.
A currency-conversion quote for a cross-border PAYOUT.
| Get one | POST /ch/v1/funds/currency-exchange-rates |
| Fields | referenceId (up to 64 characters), exchangeRate, margin, price components, validFrom, validTo (date-times) |
| Use it | Send rate.referenceId on the PAYOUT before validTo. |
| Example | "rate": { "referenceId": "838916029301" } |
Watch out: Use the quote between validFrom and validTo. If validTo has passed, request a new quote.
amount: a money value.
| Field | Format | Example |
|---|---|---|
total | JSON number in the currency's major unit (dollars, not cents), with no more decimal places than the currency allows (2 for USD) | 55.00, 7500.00 |
currency | ISO 4217 currency code | USD |
Both fields are required. If you send amount components, they must add up to total.
Watch out: 5500 means 5,500.00, not 55.00. Send a number, not a string (55.00, not "55.00").
Which identifier to use for what:
| You want to… | Use |
|---|---|
| Find a transaction in your own system | Merchant transaction ID |
| Link a notification to the original request | API trace ID (returned as merchantTransactionId in funds notifications) |
| Give support a reference | API trace ID |
| Sign a request | Client request ID and the Timestamp header |
merchantDetails.merchantId and merchantDetails.terminalId: your merchant account and the point of entry for a funds transaction.
| Format | Strings, issued at merchant boarding. You can also use your own identifiers (BYOID, up to 30 characters). |
| Example | merchantId 106336000000035, terminalId 10000001 |
Watch out: Use the IDs for the environment you're calling; certification (CERT) and production IDs differ.
transactionDetails.merchantOrderId: your order or purchase-order reference, for example the order a refund relates to.
| Format | String, up to 128 characters. Optional. |
| Example | 732ae4f6-9920-4be1-809a-2930af17ad92 |
Several transactions can share one order ID (for example a partial refund and a later refund).
transactionDetails.merchantTransactionId: your unique reference for this transaction.
| Format | String, up to 128 characters |
| Example | 34ca203a-3bab-463e-beb8-6447fb361f7b |
Watch out
merchantTransactionId so it's recognised as the same transaction.CREDIT_STATUS_CHANGED and PAYOUT_STATUS_CHANGED notifications, transactionDetails.merchantTransactionId holds the API trace ID of your original request, not the value you sent.The Client-Request-Id request header: a unique value you generate for each API call.
| Format | String, up to 1024 characters; a UUID or a random number is typical |
| Example | 5933077, 30dd879c-ee2f-11db-8314-0800200c9a66 |
| Echoed as | gatewayResponse.transactionProcessingDetails.clientRequestId |
It's part of the HMAC signature. Generate a new value, with a new Timestamp, for each call, including retries. Use merchant transaction ID to identify a retried transaction.
apiTraceId: CommerceHub's identifier for a request.
| Fields | gatewayResponse.transactionProcessingDetails.apiTraceId; repeated as transactionDetails.merchantTransactionId in funds notifications |
| Format | 32 hexadecimal characters, or a UUID: ^(?:[a-fA-F0-9]{32}|[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[1-5][a-fA-F0-9]{3}-[89abAB][a-fA-F0-9]{3}-[a-fA-F0-9]{12})$ |
| Example | ee0c7848dd15470d8979b744fe6aef41 |
Store it with your transaction. You need it to match the later webhook, and support uses it to find request logs.
transactionProcessingDetails.transactionId: the gateway's unique identifier for a transaction.
| Format | String, up to 40 characters |
| Example | 0200ee0c7848dd15470d8979b744fe6aef41 |
Watch out: Treat it as opaque. It often looks like a prefix plus the API trace ID, but don't parse it.
Every request is signed with HMAC-SHA256. Send these headers:
| Header | Value | Example |
|---|---|---|
Api-Key | Your CommerceHub API key. | — |
Client-Request-Id | A new client request ID. | 5933077 |
Timestamp | Current Unix epoch time in milliseconds. | 1767225600000 |
Auth-Token-Type | Always HMAC. | HMAC |
Authorization | Base64(HMAC-SHA256(sharedSecret, apiKey + clientRequestId + timestamp + rawRequestBody)) | — |
Watch out
2.AUTHENTICATION.md.gatewayResponse.transactionState: the state of the operation.
| Where | States |
|---|---|
201 response from /ch/v1/funds/transact | PENDING: accepted; final result comes by webhook. |
CREDIT_STATUS_CHANGED webhook | APPROVED, DECLINED |
PAYOUT_STATUS_CHANGED webhook | IN_PROGRESS (not final), DISBURSED, DECLINED, CANCELLED, REVERSED |
The reason is in paymentReceipt.processorResponseDetails: responseCode and responseMessage, plus hostResponseCode and hostResponseMessage from the ledger. For example 000 / Pending on acceptance, and 006 / "Transaction exceeds cumulative credit limit of 5000.00" on a declined credit.
Watch out: Don't treat PENDING or IN_PROGRESS as final, and don't retry a PENDING request; wait for the webhook.
Asynchronous events that CommerceHub (Notification Hub) posts to the webhook URL configured for your merchant. gatewayResponse.transactionType is the event; gatewayResponse.transactionState is the new state.
Event (transactionType) | States (transactionState) | Match it with |
|---|---|---|
PARTY_STATUS_CHANGED | CREATED, ACTIVE, SUSPENDED, CLOSED, CLOSED_FRAUD | party.partyId, party.platform.merchantPartyId |
PARTY_KYB_CHANGED, PARTY_KYC_CHANGED | INITIATED, PENDING, DOCUMENT_REQUIRED, APPROVED, DECLINED | party.partyId |
PARTY_OTP_BUSINESS, PARTY_OTP_SIGNER | PENDING, VALIDATED | party.partyId |
CREDIT_STATUS_CHANGED | APPROVED, DECLINED | transactionDetails.merchantTransactionId (= original API trace ID), payee.partyId |
PAYOUT_STATUS_CHANGED | IN_PROGRESS, DISBURSED, DECLINED, CANCELLED, REVERSED | transactionDetails.merchantTransactionId, payee.partyId |
Watch out
2xx quickly and process the event afterwards.transactionTimestamp.transactionDetails.retrievalReferenceNumber in funds notifications identifies the ledger transaction that actually moved the money.Some funds notifications wrap the event in an envelope. Check for an event property before reading gatewayResponse.
| Field | Meaning | Example |
|---|---|---|
event | The notification itself: gatewayResponse, paymentReceipt, transactionDetails, payee. | — |
eventTimestamp | When the event was generated, UTC, YYYY-MM-DDThh:mm:ss (no zone suffix). | 2026-10-06T20:59:21 |
type | Payload type. | FundsTransactResponse |
{
"event": {
"gatewayResponse": { "transactionType": "CREDIT_STATUS_CHANGED", "transactionState": "DECLINED" },
"transactionDetails": { "merchantTransactionId": "ee0c7848dd15470d8979b744fe6aef41", "operationType": "CREDIT" },
"payee": { "partyId": "106336000011065" }
},
"eventTimestamp": "2026-10-06T20:59:21",
"type": "FundsTransactResponse"
}A handler that supports both shapes:
const notification = body.event ?? body;
const { transactionType, transactionState } = notification.gatewayResponse;