ACH
Originate a payment
14min
in this tutorial, you'll learn how to ✅ originate a push payment ✅ monitor status of the payment ✅ handle notifications of change to the outbound payment (rejected, returned, noc) if you are new to ach we recommend you read the ach before starting this tutorial if you are new to apis and how they work we recommend you read the api basics docid\ hjr4y6ml96zuyj6trytom page before starting this tutorial the tutorial uses these api endpoints api description ach docid\ hzerkoy6y5wxhne2gna71 originate the payment do not poll the apis for status updates and reconciliation purposes incorporate webhooks into the payment reconciliation process before you begin make sure you have bank rails docid\ kbym9o05dwmdjsf8k7lzi partner id account number banking and payments docid\ dgnysfx9f7pnesmuxnwsp the following webhook events originate the ach payment there are two types of ach payments push payment when you transfer money to an account in another bank pull payment when you request funds from an account in another bank use an ach docid\ f jev5sqf7wkohvl3qgh (prenote) to verify and validate account details a prenote simply means originating a payment of $0 00 if you don't receive an error response, the details are correct this tutorial covers push payments a push payment can result in the recipient receives the payment cr or ach rejects the payment the recipient fi returns the payment the recipient receives the payment but ach sends a notification of change let's send $100 to bob smith who has an account at another bank since we are transferring the money to bob's account the transactiontype attribute must be push to originate an ach payment call post /ach/v1/payments the details of the push payment are defined by the call attributes, which can be seen here important we strongly recommend that you include an idempotency key in your request header to provide duplicate protection should the payment fail read more about idempotency keys idempotency docid\ jiv0q1 cymjqqger3ijmp money amounts in api calls and responses are written without a decimal point between the dollars and the cents post /ach/v1/payments { "accountnumber" "2714035231", "receiver" { "routingnumber" "021000021", "accountnumber" "456789000", "accounttype" "checking", "name" "bob smith", "identification" "xyz123", }, "seccode" "web", "description" "payment", "transactiontype" "push", "amount" 10000, "servicetype" "sameday", "clientidentifier" "21fe77da e2f8 4475 9397 81a293d63b8x" } a successful api call returns a json response with the details of your originated payment { "id" "b96b935a 4713 4aae 973b aeee00f1a749", "accountnumber" "2714035231", "referenceid" "a2236s8s20fh", "paymenttype" "origination", "direction" "outbound", "status" "created", "source" "api", "postingtype" "individual", "postingcode" "ok", "posting" "pending", "originator" { "routingnumber" "021214891", "accountnumber" "2714035231", "accounttype" "checking", "name" "cross river bank", "identification" "021214891" }, "receiver" { "routingnumber" "021000021", "accountnumber" "456789000", "accounttype" "checking", "name" "bob smith", "identification" "xyz123" }, "seccode" "web", "description" "payment", "transactiontype" "push", "amount" 10000, "servicetype" "sameday", "effectivedate" "220811", "tracenumber" "021214898943562", "wasreturned" false, "wascorrected" false, "holddays" 0, "original" { "paymentid" "b96b935a 4713 4aae 973b aeee00f1a749" }, "createdat" "2022 08 11t10 39 49 9996701 04 00", "partnerid" "1e5d3f04 ae24 4af6 9e30 aecf012b99dd", "productid" "cc62e17f 5912 483e 9e42 aed30112fbb6", "lastmodifiedat" "2022 08 11t10 39 49 9996701 04 00", "clientidentifier" "21fe77da e2f8 4475 9397 81a293d63b8x" } the status attribute in the response indicates that your payment was created it does not indicate that your payment was successful payment confirmation after originating the payment, its status changes to pending or hold for up to several hours a pending status lets you know that the payment request is created but has not been batched for release to the federal reserve the batching process occurs several times a day a hold status indicates that the payment request is in review and has not yet been approved for release to the federal reserve next, the payment moves to batched status if the payment is originated close to a weekend or bank holiday it may take a few days for the status to transition to batched when the federal reserve accepts the payment the status changes to processing , which triggers the ach payment sent event the payment id provided in the response body of the payment origination request ( id ) appears in the details object of the ach payment sent event in this case b96b935a 4713 4aae 973b aeee00f1a749 { "id" "7c135bfa 234f 48d2 9d70 adc70135d15f", "eventname" "ach payment sent", "status" "pending", "partnerid" "30dee145 b6a2 4058 8dc3 ac4000dee91f", "createdat" "2021 10 20t14 48 01 12 04 00", "resources" \[ "ach/v1/payments/b96b935a 4713 4aae 973b aeee00f1a749" ], "details" \[ { "paymentid" "b96b935a 4713 4aae 973b aeee00f1a749", "coretransactionid" null, "memopostid" "85b509f9 61f0 4af3 b64c b04900de43da", "clientbatchid" null, "clientbatchsequence" null, "accountnumber" "2714035231", "postingcode" null, "clientidentifier" null, "purpose" "entered by #60c3c9c8fd17ba0070a7fb4f#" } ] } payment status webhook events rejected payment there may be situations where a payment request is rejected a payment request rejected after initially receiving a success response from post /ach/v1/payments could be due to technical rejection the transaction was unable to post from the account being used for your request, and is covered in this tutorial example you originate a push payment for an amount greater than the balance of the originator account you originate a payment from an account with an active restriction manual rejection the payment was rejected by the cross river operations or bsa/aml teams contact cross river directly for information on why the payment was rejected to simulate a technical rejection, originate a push payment for an amount that exceeds the originating account balance information on ach simulation is found here again, let's send $100 to bob smith who has an account at another bank this time, the amount you are sending exceeds the amount in the originator account call post /ach/v1/payments define the call attributes as above in to originate an ach payment { "accountnumber" "2674958042", "receiver" { "routingnumber" "021000021", "accountnumber" "456789000", "accounttype" "checking", "name" "bob smith", "identification" "xyz123", }, "seccode" "web", "description" "payment", "transactiontype" "push", "amount" 10000, "servicetype" "sameday", "clientidentifier" "bd3e0315 5f29 4b1c a004 1fcdd0b8bee1" } the following json response is returned { "id" "f868a125 22b8 4c7e a8dd aeee00f76ce7", "accountnumber" "2674958042", "referenceid" "a223o84jdv79", "paymenttype" "origination", "direction" "outbound", "status" "created", "source" "api", "postingtype" "individual", "postingcode" "ok", "posting" "pending", "originator" { "routingnumber" "021214891", "accountnumber" "2674958042", "accounttype" "checking", "name" "cross river bank", "identification" "021214891" }, "receiver" { "routingnumber" "021000021", "accountnumber" "456789000", "accounttype" "checking", "name" "bob smith", "identification" "xyz123" }, "seccode" "web", "description" "payment", "transactiontype" "push", "amount" 10000, "servicetype" "sameday", "effectivedate" "220811", "tracenumber" "021214896697194", "wasreturned" false, "wascorrected" false, "holddays" 0, "original" { "paymentid" "f868a125 22b8 4c7e a8dd aeee00f76ce7" }, "createdat" "2022 08 11t11 00 50 8991331 04 00", "partnerid" "1e5d3f04 ae24 4af6 9e30 aecf012b99dd", "productid" "d5f3ce06 8550 413e a2e1 aed1016d6eea", "lastmodifiedat" "2022 08 11t11 00 50 8991331 04 00", "clientidentifier" "bd3e0315 5f29 4b1c a004 1fcdd0b8bee1" } the ach payment rejected event is triggered the details object in the ach payment rejected event contains the payment id from the response body ( id ) in this case f868a125 22b8 4c7e a8dd aeee00f76ce7 in the details object of the event, the postingcode tells you the request and response codes docid 8i6yat2jnqfg8cc8e1tls , in this case res (account restriction) if the payment needs to be reviewed manually, the rejectionreason gives you more information about the rejection sample ach payment rejected event { "id" "496659ff 6034 480a 84af aeee00f78ade", "eventname" "ach payment rejected", "status" "pending", "partnerid" "1e5d3f04 ae24 4af6 9e30 aecf012b99dd", "createdat" "2022 08 11t11 01 16 483 04 00", "resources" \[ "ach/v1/payments/f868a125 22b8 4c7e a8dd aeee00f76ce7" ], "details" \[ { "paymentid" "f868a125 22b8 4c7e a8dd aeee00f76ce7", "coretransactionid" null, "memopostid" "517f24c5 3cf1 4168 b721 b04900e36f00", "clientbatchid" null, "clientbatchsequence" null, "accountnumber" "2674958042", "postingcode" "res", "clientidentifier" null, "purpose" "entered by #60c3c9c8fd17ba0070a7fb4f#", "rejectionreason" "other" } ] } returned payment sometimes an ach payment is returned by the receiving bank see request and response codes docid 8i6yat2jnqfg8cc8e1tls for a complete list of why a payment might be returned example the receiving bank can't find the specified receiver account number most returns occur within 2 business days, but may take longer a payment return creates a new payment record with the paymenttype set as return the new payment record is connected to the original payment record with the previous paymentid field important once payment status transitions to complete , the payment record is no longer updated, even if the payment is returned a payment returned from a receiving bank triggers the ach return received webhook event here's an example of an ach return webhook event sample ach return received event { "id" "d3ad6473 6690 44f1 a4a6 b04900d95419", "eventname" "ach return received", "status" "pending", "partnerid" "1e5d3f04 ae24 4af6 9e30 aecf012b99dd", "createdat" "2023 07 24t09 11 16 133 04 00", "resources" \[ "ach/v1/payments/fb05013b eaba 439e 8c6b b04900d8f805" ], "details" \[ { "paymentid" "fb05013b eaba 439e 8c6b b04900d8f805", "coretransactionid" "28633d37 f441 496a ab07 b04900d93e75", "originalpaymentid" "1a1a9919 33b5 4933 9b9f b034011462df", "accountnumber" "2151546989", "tracenumber" "021000021754553", "reasoncode" "r01", "reasondata" "" } ] } the event shows reasoncode r01 (insufficient funds) the originalpaymentid field shows the id of the original outbound payment notification of change (noc) there are times when cross river receives an ach notification of change (noc) related to an outbound payment when you create an api call, a noc is referred to as a correction in the paymenttype attribute unlike an ach return, a noc indicates that the payment you previously originated posted to the receiver account contained an error (such as an incorrect routing number) see request and response codes docid 8i6yat2jnqfg8cc8e1tls for a complete list register for the ach noc received webhook event to be notified of an inbound noc here's an example of a noc webhook event sample ach noc received event { "id" "43d767a8 6b3a 4b5e 9fe6 b05401215333", "eventname" "ach noc received", "status" "pending", "partnerid" "1e5d3f04 ae24 4af6 9e30 aecf012b99dd", "createdat" "2023 08 04t13 33 24 01 04 00", "resources" \[ "ach/v1/payments/197021dd 4b47 47b3 a75e b0540120f5f2" ], "details" \[ { "paymentid" "197021dd 4b47 47b3 a75e b0540120f5f2", "coretransactionid" "578f36cd f8e8 47ba afa8 b05401213c5f", "originalpaymentid" "2cc0a0dd 6d7e 4ad9 9d3e b0540105ba19", "accountnumber" "2696592019", "tracenumber" "021200333650075", "reasoncode" "c02", "reasondata" "026009593" } ] } the reasoncode attribute in the response is c02 this indicates an incorrect routing number the reasondata attribute is the correct receiver routing number if you receive a noc notification, update your internal records with the information you receive in the reasondata attribute