Payrix ACH Integration
Process ACH transactions with Payrix including GIACT risk verification
Process ACH (bank account) transactions through Preczn with Payrix as your processor, including optional GIACT risk verification for enhanced fraud prevention.
PrerequisitesBefore integrating Payrix ACH, ensure you have:
- A Payrix processor connection configured on your platform
- Merchant accounts with Payrix credentials
- Webhooks configured to receive transaction events
For general ACH concepts and requirements, see ACH Transactions.
Setup
Enable GIACT Verification
GIACT verification provides additional risk assessment for ACH transactions. When enabled, Preczn fetches GIACT decision results from Payrix for transactions that return a generic_error status.
To enable GIACT verification:
- Contact Payrix to enable GIACT on your Payrix account. If you want to test GIACT in sandbox, request enablement for both your live and sandbox Payrix accounts.
- Enable in Preczn Dashboard:
- Navigate to Connections → Payrix
- Toggle GIACT Enabled to on
- Click Save
GIACT Must Be Enabled on Both SidesGIACT verification requires enablement at both Payrix and Preczn. If GIACT is not enabled on your Payrix account, transactions will not trigger GIACT verification even if the toggle is enabled in Preczn.
Platform-Level ConfigurationGIACT verification is enabled at the platform level, not per-merchant. Once enabled, all ACH verify transactions through your Payrix connection will use GIACT verification when applicable.
Configure Webhooks
To receive GIACT verification results, you must configure webhooks to listen for these events:
| Event | Description | When Sent |
|---|---|---|
transaction.pending | Transaction is awaiting GIACT verification | Immediately after initial API response |
transaction.errored | Transaction failed with GIACT results | After GIACT verification completes |
See Webhooks for configuration instructions.
How ACH Works with Payrix + GIACT
When GIACT is enabled, Payrix ACH verify transactions follow an asynchronous verification flow:
sequenceDiagram
participant Client
participant Preczn
participant Payrix
participant GIACT
Client->>Preczn: POST /v1/transactions (verify)
Preczn->>Payrix: Submit ACH verify
Payrix-->>Preczn: generic_error (GIACT pending)
Preczn-->>Client: 200 OK (status: P)
Preczn->>Client: Webhook: transaction.pending
Note over Preczn,GIACT: Async GIACT fetch
Preczn->>Payrix: GET /risk/v2/decision/policy-run-summary
Payrix->>GIACT: Request decision
GIACT-->>Payrix: BLOCK/PASS/SKIP
Payrix-->>Preczn: GIACT results
Preczn->>Client: Webhook: transaction.errored
Async Flow Means Two WebhooksUnlike synchronous processors, Payrix ACH with GIACT may send two webhooks for a single transaction:
transaction.pending- Sent immediately when the transaction enters pending statetransaction.errored- Sent after GIACT verification completes with the final decisionYour integration must handle this asynchronous pattern.
Integration Guide
Required Fields
For Payrix ACH verify transactions, include these fields:
| Field | Type | Required | Description |
|---|---|---|---|
merchantId | string | Yes | Preczn merchant ID (mid_*) |
type | string | Yes | Must be verify |
payment.bankAccount.account | string | Yes | Bank account number |
payment.bankAccount.routing | string | Yes | Bank routing number |
payment.bankAccount.type | string | Yes | Account type (see below) |
payment.bankAccount.bankCountry | string | No | ISO 3166-1 alpha-3 country code (default: USA) |
firstName | string | Yes | Account holder's first name |
lastName | string | Yes | Account holder's last name |
Account Types
| Value | Description |
|---|---|
personalChecking | Personal checking account |
personalSavings | Personal savings account |
corporateChecking | Business checking account |
corporateSavings | Business savings account |
Corporate AccountsFor corporate account types (
corporateChecking,corporateSavings), you can optionally includeaccountBusinessNameto specify the business name associated with the account.
Step 1: Submit ACH Verify Transaction
Submit a verify transaction to validate the bank account:
POST /v1/transactions
{
"merchantId": "mid_8np2rx4qk6m3wy9jzaht5v7dc",
"type": "verify",
"payment": {
"bankAccount": {
"account": "1234567890",
"routing": "011000015",
"type": "personalChecking",
"bankCountry": "USA"
}
},
"firstName": "Jane",
"lastName": "Smith",
"email": "[email protected]",
"billingAddress": {
"address": "123 Main Street",
"city": "New York",
"region": "NY",
"postal": "10001",
"country": "USA"
}
}Step 2: Handle Pending Response
When GIACT is enabled and Payrix returns a generic_error, Preczn returns a Pending status:
{
"id": "txn_5kx9mw2nq8r7hp4jvbct6y3fa",
"type": "verify",
"merchantId": "mid_8np2rx4qk6m3wy9jzaht5v7dc",
"platformId": "pfm_3dv7ky9m5r2wp8xjqnbt4c6hf",
"currency": "USD",
"firstName": "Jane",
"lastName": "Smith",
"isGiactEligible": true,
"authorization": {
"status": "P",
"processorCode": "generic_error",
"processorTransactionId": "t1_txn_8a4bc9d21ef753b6c7902e1",
"errors": [
"Transaction processing failed"
]
},
"payment": {
"type": "personalChecking",
"bankCountry": "USA",
"bin": "011000015",
"last4": "7890",
"token": "tkn_4hn8mq2rv6x9kp3jwyct5b7da"
},
"processor": {
"id": "pfmCon_7mx4rk9np2w6hy3jqvbt8c5da",
"name": "Payrix",
"routingSource": "direct"
},
"createdOn": "2024-01-15T14:30:00Z"
}
Status "P" Means GIACT Verification in ProgressWhen you receive
status: "P"(Pending) withprocessorCode: "generic_error"andisGiactEligible: true, this indicates Preczn is fetching GIACT verification results. Do not treat this as a failure. Wait for the webhook to receive the final result.
Step 3: Receive Webhook with GIACT Results
After GIACT verification completes, you receive a transaction.errored webhook with the GIACT decision in the errors array:
{
"id": "what_7c5mm92aes8tkbchfzgf6d3x28",
"webhookId": "wh_1hatb29w5z8ayb885kc0jj180k",
"eventType": "transaction.errored",
"data": {
"id": "txn_5kx9mw2nq8r7hp4jvbct6y3fa",
"type": "verify",
"merchantId": "mid_8np2rx4qk6m3wy9jzaht5v7dc",
"platformId": "pfm_3dv7ky9m5r2wp8xjqnbt4c6hf",
"currency": "USD",
"firstName": "Jane",
"lastName": "Smith",
"authorization": {
"status": "E",
"processorCode": "generic_error",
"processorTransactionId": "t1_txn_8a4bc9d21ef753b6c7902e1",
"errors": [
"GiactTxnInquiry: BLOCK",
"Transaction processing failed"
]
},
"payment": {
"type": "PERSONAL_CHECKING",
"bin": "011000015",
"last4": "7890"
},
"processor": {
"id": "pfmCon_7mx4rk9np2w6hy3jqvbt8c5da",
"name": "Payrix",
"routingSource": "direct"
},
"createdOn": "2024-01-15T14:30:07Z"
}
}GIACT Results
GIACT Decision Codes
The GIACT verification returns one of three decision results:
| Decision | Meaning | Recommended Action |
|---|---|---|
BLOCK | The transaction data was reviewed with GIACT and has been declined with an assessed fee | Reject the transaction; display adverse action notice; request a different payment method |
PASS | The transaction data was reviewed with GIACT and approved with an assessed fee | Proceed with the transaction |
SKIP | The data submitted did not meet the initial requirements to begin a GIACT review | Review manually or proceed based on your risk tolerance |
Adverse Action Notice Required for BLOCKWhen GIACT returns
BLOCK, Payrix requires that you display an adverse action notice to the customer. This notice informs the customer that their transaction was declined based on information obtained from a consumer reporting agency.For the required notice text and compliance details, see Payrix Adverse Action Notice Requirements.
For more details on GIACT verification, see the Payrix GIACT documentation.
Error Array Format
GIACT results appear in the authorization.errors array with the format:
{decisionType}: {result}
For example:
GiactTxnInquiry: BLOCKGiactTxnInquiry: PASSGiactTxnInquiry: SKIP
GIACT Errors Are PrependedGIACT decision results are prepended to the beginning of the
errorsarray. If there were existing errors from the processor, they appear after the GIACT results.
Example: GIACT BLOCK Response
{
"authorization": {
"status": "E",
"processorCode": "generic_error",
"processorTransactionId": "t1_txn_8a4bc9d21ef753b6c7902e1",
"errors": [
"GiactTxnInquiry: BLOCK",
"Transaction processing failed"
]
}
}Example: GIACT PASS Response
{
"authorization": {
"status": "E",
"processorCode": "generic_error",
"processorTransactionId": "t1_txn_8a4bc9d21ef753b6c7902e1",
"errors": [
"GiactTxnInquiry: PASS",
"Transaction processing failed"
]
}
}
GIACT PASS Still Results in Error StatusEven when GIACT returns
PASS(approved with an assessed fee), the transaction status remainsE(Error) because the original Payrix transaction triggered GIACT review. The GIACT result indicates whether the account passed verification, but you should retry the transaction to complete the payment.
Webhook Events
Event Timeline
| Phase | Event | Status | Description |
|---|---|---|---|
| 1 | API Response | P (Pending) | Immediate response when GIACT verification is triggered |
| 2 | transaction.pending | P (Pending) | Webhook confirming pending state |
| 3 | transaction.errored | E (Error) | Final webhook with GIACT results |
transaction.pending Payload
{
"id": "what_9m2kx7rn4q8hp5jvbct6y3faw",
"webhookId": "wh_2jbtc39x6z9byc996ld1kk291l",
"eventType": "transaction.pending",
"data": {
"id": "txn_5kx9mw2nq8r7hp4jvbct6y3fa",
"type": "verify",
"merchantId": "mid_8np2rx4qk6m3wy9jzaht5v7dc",
"platformId": "pfm_3dv7ky9m5r2wp8xjqnbt4c6hf",
"authorization": {
"status": "P",
"processorCode": "generic_error",
"processorTransactionId": "t1_txn_8a4bc9d21ef753b6c7902e1",
"errors": [
"Transaction processing failed"
]
}
}
}transaction.errored Payload
{
"id": "what_7c5mm92aes8tkbchfzgf6d3x28",
"webhookId": "wh_1hatb29w5z8ayb885kc0jj180k",
"eventType": "transaction.errored",
"data": {
"id": "txn_5kx9mw2nq8r7hp4jvbct6y3fa",
"type": "verify",
"merchantId": "mid_8np2rx4qk6m3wy9jzaht5v7dc",
"platformId": "pfm_3dv7ky9m5r2wp8xjqnbt4c6hf",
"authorization": {
"status": "E",
"processorCode": "generic_error",
"processorTransactionId": "t1_txn_8a4bc9d21ef753b6c7902e1",
"errors": [
"GiactTxnInquiry: BLOCK",
"Transaction processing failed"
]
}
}
}Best Practices for Async Flow
- Store transaction ID on initial response - Track the
idreturned in the API response - Listen for both webhook events - Configure handlers for
transaction.pendingandtransaction.errored - Use transaction ID for correlation - Match webhooks to original requests using the transaction ID
- Implement webhook retry handling - Ensure idempotent processing in case of duplicate deliveries
- Set appropriate timeouts - GIACT verification typically completes within seconds, but allow for delays
Testing GIACT in Sandbox
To test the GIACT verification flow in sandbox, use the following bank account details to trigger a BLOCK response:
{
"payment": {
"bankAccount": {
"type": "personalChecking",
"account": "0000000004",
"routing": "122105278",
"bankCountry": "USA"
}
}
}This will:
- Return an initial
P(Pending) status withisGiactEligible: true - Trigger the async GIACT verification flow
- Send a
transaction.pendingwebhook - Send a
transaction.erroredwebhook withGiactTxnInquiry: BLOCKin the errors array
Sandbox GIACT Enablement RequiredRemember that GIACT must be enabled on your Payrix sandbox account to test this flow. Contact Payrix to enable GIACT for your sandbox environment.
Troubleshooting
Common Scenarios
Transaction Stuck in Pending
Symptom: Transaction remains in P status without receiving transaction.errored webhook.
Possible causes:
- Webhook endpoint is unreachable
- Webhook URL is misconfigured
- GIACT API is experiencing delays
Solution: Check your webhook configuration and logs. Contact support if the issue persists beyond 5 minutes.
No GIACT Results in Errors Array
Symptom: transaction.errored webhook received but errors array is empty or missing GIACT data.
Possible causes:
- GIACT is not enabled for your platform
- Transaction was not a verify type
- Payment method was not ACH
Solution: Verify GIACT is enabled for your Payrix connection and that you're submitting ACH verify transactions.
Immediate Error Response (No Pending State)
Symptom: Transaction returns E status immediately without going through P state.
Possible causes:
- GIACT is not enabled for your platform
- Payrix returned an error other than
generic_error - Transaction validation failed before reaching Payrix
Solution: Check the processorCode value. Only generic_error triggers GIACT verification.
Error Reference
| Error | Meaning | Solution |
|---|---|---|
generic_error | Payrix flagged transaction for GIACT verification | Wait for webhook with GIACT results |
GiactTxnInquiry: BLOCK | GIACT reviewed and declined the transaction (fee assessed) | Reject transaction; request different payment method |
GiactTxnInquiry: PASS | GIACT reviewed and approved the transaction (fee assessed) | Proceed with the transaction |
GiactTxnInquiry: SKIP | Data did not meet requirements for GIACT review | Review manually based on risk tolerance |
Status Transitions
Normal ACH (no GIACT):
Submit → Approved/Declined/Error
Payrix ACH with GIACT:
Submit → Pending → Error (with GIACT results)
Related Resources
- ACH Transactions - General ACH concepts
- Create Transaction - API reference
- Webhooks - Webhook configuration
- Object ID Prefixes - ID format reference
Updated 4 days ago
