How to originate an instant payment
In this tutorial, you'll learn how to
Register the relevant webhooks
Originate a real-time payment credit transfer from your master account
Simulate a rejected credit transfer
If you are new to real-time payments we recommend you read the Instant payments overview before starting this tutorial.
The tutorial assumes you have a knowledge of APIs and how they work. Refer to the API overview page for more details.
Before you begin
Make sure you have:
-
Your partner ID
-
Your master account number
You should be familiar with these terms
Financial institution (FI) |
The bank involved in the transfer of the money between parties |
Debtor |
The account sending a payment via the instant payments network |
Creditor |
The account receiving a payment via the instant payments network |
The tutorial uses these API endpoints:
Transfer money between banks in real time via the instant payments network |
The tutorial uses these webhooks
|
Outbound payment has been successfully sent to the receiving institution and the funds are available in the receiver's bank account. |
|
Inbound payment has been received from another institution and has successfully posted to an account in COS. |
|
Payment has been rejected by the receiving institution or instant payments network |
Register the relevant webhook events
To receive the webhook events for this tutorial you need to register each specific webhook event type. Once you're registered, the event objects are sent to the registered URLs.
The event object contains a list of resource identifiers used to download details on each event.
Originate the credit transfer
Instant payment credit transfers send funds from your account to the recipient account in real time. Credit transfers can be sent from master accounts and associated subledgers.
The account sending the funds is the debtor and the account receiving the funds is the creditor.
CR offers you two different network platforms for Instant Payments: RTP via The Clearing House (TCH) and FedNow.
In this tutorial, you are the debtor. We are going to originate an outbound credit transfer from your master account to the creditor.
The outbound credit transfer can result in the creditor FI:
-
Accepting the transfer
Send an accepted status back to CR and posted the funds.
Status code: ACTC
-
Rejecting the transfer
Send a rejected status back to CR and no debit/credit occurs.
Status code: RJCT
-
Does not respond
CR receives a reject from the Clearinghouse and no debit/credit occurs.
Status code: RJCT
-
Accepting the transfer without posting.
The credit transfer was accepted but funds were not yet deposited into the creditor account. The creditor FI can subsequently send an accepted status and post the funds into the creditor's account, or send a rejected status, within 24 hours.
Status code: ACWP
Cross River cannot know how another financial institution displays to their customers the information transmitted with the Originate a payment message. Contact the receiving FI directly to learn more about fields in their banking portal or on their bank statements.
To originate the credit transfer
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 here.
Call POST /rtp/v1/payments
. For this call, some attributes are required. A full list of attributes is found here.
In our tutorial, you will send a gift of $175 to C Brown.
Money amounts in API calls and responses are written without a decimal point between the dollars and the cents.
Example request: originate a credit transfer
POST /Rtp/v1/payments
{
"accountNumber": "2553179843",
"amount": 17500,
"creditor": {
"routingNumber": "011000138",
"accountNumber": "456789000",
"name": "C Brown",
"addressStreetName": "Main St",
"addressBuildingNumber": "34",
"addressCity": "New York",
"addressState": "NY",
"addressPostalCode": "12345",
"addressCountry": "US"
},
"purpose": "gift money"
}
A successful API call returns a JSON response with the details of your originated credit transfer.
When the credit transfer (pacs.008) is sent to the instant payments network, the Rtp.Payment.Sent
webhook event fires. This event contains the payment ID within the details
section of the event body (in this case, 7b5f4bfb-8595-452b-914e-ad9400f7b8e3).
{
"id": "7af80bc3-4f1c-4842-b60e-ad9400fb59db",
"eventName": "Rtp.Payment.Sent",
"status": "Pending",
"partnerId": "bd7a716f-6349-43ef-89cd-aa2200f15977",
"createdAt": "2021-08-30T11:15:08.623-04:00",
"resources": [
"rtp/v1/payments/7b5f4bfb-8595-452b-914e-ad9400f7b8e3"
],
"details": [
{
"paymentId": "7b5f4bfb-8595-452b-914e-ad9400f7b8e3",
"paymentType": "CreditTransfer",
"resultCode": "OK",
"resultAdditionalInfo": null,
"coreTransactionId": "3e04e9b9-e80f-4f5f-9a0b-b04a011d23df",
"memoPostId": "4820a916-f062-49ad-9519-b04a011d2372",
"accountNumber": "2553179843",
"postingCode": "OK",
"rtpTransactionStatus": "ACTC",
"purpose": null,
"awaitingResponse": "False",
"referencedPaymentId": null
}
]
}
Rejected credit transfers
You can simulate receiving a reject response from a creditor.
Call POST /rtp/v1/payments
like you did in Originate the credit transfer.
Add the reject: prefix to the creditor name
like you see on line 9 in the request example below.
POST /v1/payments
{
"accountNumber": "2553179843",
"amount": 15000,
"creditor": {
"routingNumber": "011000138",
"accountNumber": "456789000",
"name": "reject:Cleveland Brown",
"addressStreetName": "Main St",
"addressBuildingNumber": "34",
"addressCity": "New York",
"addressState": "NY",
"addressPostalCode": "00093",
"addressCountry": "US"
},
"purpose": "gift money"
}
The response example returns a payment status
of Rejected on line 13.
GET /v1/payments/{id}
{
"id": "7b5f4bfb-8595-452b-914e-ad9400f7b8e3",
"originalPaymentId": "7b5f4bfb-8595-452b-914e-ad9400f7b8e3",
"referenceId": "R242O0354Y055",
"accountNumber": "2553179843",
"amount": 15000,
"operatorCoreTransactionId": "2da7c99c-5804-4757-98c1-ad9400fa6c2c",
"memoPostId": "7b5f4bfb-8595-452b-914e-ad9400f7b8e3",
"memoPostRemovedAt": "2021-08-30T11:14:44.973-04:00",
"direction": "Outbound",
"status": "Rejected",
"paymentType": "CreditTransfer",
"source": "Api",
"transactionAccountContext": "Rejected",
"rtpTransactionStatus": "RJCT",
"debtor": {
"routingNumber": "021214891",
"accountNumber": "2553179843",
"name": "P Griffin",
"addressStreetName": "Main Street",
"addressBuildingNumber": "31",
"addressCity": "New York",
"addressState": "NY",
"addressPostalCode": "00093",
"addressCountry": "US"
},
"creditor": {
"routingNumber": "011000138",
"accountNumber": "456789000",
"name": "C Brown",
"addressStreetName": "Main St",
"addressBuildingNumber": "34",
"addressCity": "New York",
"addressState": "NY",
"addressPostalCode": "00093",
"addressCountry": "US"
},
"network": {
"messageDefId": "pacs.008.001.08",
"businessMessageId": "B20210830021214273T1BQPZ97287285414",
"messageId": "M20210830021214273T1BEML46024873029",
"createdAt": "2021-08-30T11:01:55.74-04:00",
"numberOfTransactions": 1,
"interbankSettlementAmount": 15000,
"currency": "USD",
"interbankSettlementDate": "2021-08-30",
"settlementMethod": "CLRG",
"clearingSystemCode": "TCH",
"instructionId": "20210830021214273T1B4S0534677157734",
"endToEndId": "9a2638dc8cbe48f18d8cad9400f7b8e3",
"transactionId": "20210830021214273T1B4S0534677157734",
"clearingSystemRef": "001",
"fromParticipantId": "021214273T1",
"toParticipantId": "990000001S1",
"instructingRoutingNumber": "021214891",
"instructedRoutingNumber": "011000138",
"headerCreationDate": "2021-08-30T11:11:45.373-04:00",
"messageCreationDateTime": "2021-08-30T11:01:55.74-04:00"
},
"confirmedStatus": {
"messageStatusReportId": "2da7c99c-5804-4757-98c1-ad9400fa6c2c",
"acceptedDateTime": "2021-08-30T11:11:45.4-04:00",
"transactionStatus": "ACTC"
},
"serviceLevelCode": "SDVA",
"localInstrumentProprietary": "STANDARD",
"categoryPurpose": "CONSUMER",
"currency": "USD",
"chargeBearer": "SLEV",
"purpose": "gift money",
"wasRefunded": false,
"wasPaid": false,
"createdAt": "2021-08-30T11:01:55.74-04:00",
"completedAt": "2021-08-30T11:14:45.05-04:00",
"processingStartedAt": "2021-08-30T11:11:45.247-04:00",
"postingCode": "OK",
"productId": "13362d99-f04e-455b-9363-abc10151c27c",
"partnerId": "bd7a716f-6349-43ef-89cd-aa2200f15977",
"lastModifiedAt": "2021-08-30T11:14:45.0505825-04:00",
"sentAt": "2021-08-30T11:11:45.3733333-04:00",
"sendAttemptCount": 1,
"result": {
"code": "OK"
},
"discounts": [],
"awaitingResponse": false
}
The Rtp.Payment.Rejected
event is triggered.
The details
object in the Rtp.Payment.Rejected
event contains the payment ID from the response body (id
). In this case: 7b5f4bfb-8595-452b-914e-ad9400f7b8e3.
In the details
object of the event, the resultCode
gives you the reason code, in this case AC06 (Account is blocked).
Sample Rtp.Payment.Rejected event
{
"id": "06afb069-dc90-48ea-b642-b04a0126580f",
"eventName": "Rtp.Payment.Rejected",
"status": "Pending",
"partnerId": "1e5d3f04-ae24-4af6-9e30-aecf012b99dd",
"createdAt": "2023-07-25T13:51:40.417-04:00",
"resources": [
"rtp/v1/payments/7b5f4bfb-8595-452b-914e-ad9400f7b8e3"
],
"details": [
{
"paymentId": "7b5f4bfb-8595-452b-914e-ad9400f7b8e3",
"paymentType": "CreditTransfer",
"resultCode": "AC06",
"resultAdditionalInfo": null,
"postingCode": "RES",
"rtpTransactionStatus": null,
"purpose": null,
"referencedPaymentId": null
}
]
}