Depositing Checks

📘

Checks API Reference

In this tutorial we explore depositing a check into a master account. We will also register relevant webhooks to receive status updates on our payment. Before starting the tutorial, please make sure you have the following:

• API credentials
• Partner ID
• Master Account Number

This tutorial also assumes you have already opened a master account. If not, please complete the Opening an Account tutorial prior to completing this tutorial.

Get an Access Token

Before calling the COS API you must first request an access token. Once the access token has been obtained it is recommended that it is cached for the lifetime of the token. If the API starts to return a 401 response code, it is likely that your token has expired and you need to obtain a new one. More details can be found here.

Register Webhooks

Webhooks allow us to receive notifications when certain events occur within COS. After your check is deposited, you will want to stay informed in order to track the payment through its lifecycle. For that you will need to call the webhook registration endpoint and indicate you wish to receive certain events.

Check.Payment.Sent will notify you in the event the check deposit has been sent to the Federal Reserve for clearing.

POST /webhooks/v1/registrations
{
  "partnerId": "00000000-0000-0000-0000-000000000000",
  "eventName": "Check.Payment.Sent",
  "callbackUrl": "https://cos.yourcompanysite.com/check-events",
  "type": "Push",
  "format": "Basic"
}

Check.Payment.Rejected will notify you in the event an outbound check was rejected due to compliance reasons or was rejected by the Federal Reserve.

POST /webhooks/v1/registrations
{
  "partnerId": "00000000-0000-0000-0000-000000000000",
  "eventName": "Check.Payment.Rejected",
  "callbackUrl": "https://cos.yourcompanysite.com/check-events",
  "type": "Push",
  "format": "Basic"
}

Check.Payment.Returned will notify you in the event the drawee bank returns the check.

POST /webhooks/v1/registrations
{
  "partnerId": "00000000-0000-0000-0000-000000000000",
  "eventName": "Check.Payment.Returned",
  "callbackUrl": "https://cos.yourcompanysite.com/check-events",
  "type": "Push",
  "format": "Basic"
}

To learn more about webhook registrations click here. For a full listing of available check webhook events click here.

Before We Begin...

Checks are considered as a type of payment in COS. There are two directions - inbound and outbound, as well as two payment types - forward and return. This means:

  • A check that is deposited into a COS account is considered an outbound forward item because the check needs to be sent to the Federal Reserve and presented to the drawee bank (paying bank) for payment.
  • A check that is drawn from a COS account is considered an inbound forward item because the Federal Reserve is presenting it to Cross River for payment.
  • A returned check that is being presented by the Federal Reserve is considered an inbound return.
  • A check that is returned by Cross River is considered an outbound return.

Depositing A Check

In this scenario, you're a Banking-as-a-Service (BaaS) partner that offers a deposit account product to consumers. Your app allows your customers to perform mobile deposits. One of your customers just made a $1 check deposit into their account using your app, which is calling COS to pass the deposit details.

POST /v1/payments
{
  "accountNumber": "2193590144",
  "amount": 100,
  "frontImage": "image/jpg;base64,/9j/4REyRXhpZgAATU0AKgA...",
  "backImage": "image/jpg;base64,/9j/4QuqRXhpZgAATU0AKg..."
}

The check images are required, and you'll need to submit the front and back of the check separately as Base64 encoded values. A successful request will produce the following response:

{
  "id": "9a44fdbf-89e2-4300-8f05-ad9501439bb1",
  "accountNumber": "2193590144",
  "referenceId": "C2436F698K0D",
  "paymentType": "Forward",
  "checkType": "Standard",
  "direction": "Outbound",
  "status": "Created",
  "source": "OpsPortal",
  "posting": "Pending",
  "postingCode": "OK",
  "coreTransactionId": "21ba5fb0-e609-4560-a36f-ad9501439bb1",
  "memoPostId": "dc20e619-c5f7-4890-b3c8-ad9501439bb1",
  "originalPaymentId": "9a44fdbf-89e2-4300-8f05-ad9501439bb1",
  "customerId": "700f0d35-9940-4132-8608-ad89013927a9",
  "payerRoutingNumber": "",
  "payerAccountNumber": "",
  "payeeName": "",
  "checkNumber": "",
  "bofdRoutingNumber": "021214891",
  "sequenceNumber": "1353885824",
  "amount": 100,
  "currency": "usd",
  "recognizedAmount": 0,
  "iqaPassed": false,
  "hasFrontImage": true,
  "hasBackImage": true,
  "isRedeposit": false,
  "policy": "NewAccount",
  "schedule": [
    0,
    0,
    100
  ],
  "createdAt": "2021-08-31T15:38:13.2795042-04:00",
  "wasReturned": false,
  "purpose": "ENTERED BY #60C367E26DD36A0068580230#",
  "depositBusinessDate": "210831",
  "productId": "d5dc52bb-df80-4a5d-a5a8-ad89013844bd",
  "partnerId": "ede1a60d-3d51-47e8-9a9b-ad8901381f9e",
  "lastModifiedAt": "2021-08-31T15:38:13.2951299-04:00"

COS will execute its OCR process to convert the check images into a format which complies with Federal Reserve Standards. Once the check is added to a distribution and released to the Fed, you will receive a webhook event as confirmation:

{
  "id": "160e52d2-4355-4fa3-a421-ad8800f886a2",
  "eventName": "Check.Payment.Sent",
  "status": "Pending",
  "partnerId": "4c5b488d-711d-428a-bdae-ad800131970d",
  "createdAt": "2021-08-31T15:39:51.3-04:00",
  "resources": [
    "checks/v1/payments/9a44fdbf-89e2-4300-8f05-ad9501439bb1"
  ],
  "details": []
}

You can verify the status of the check by querying the GET /v1/payments/{id} endpoint using the payment ID.

GET /v1/payments/{id}

{
  "id": "9a44fdbf-89e2-4300-8f05-ad9501439bb1",
  "accountNumber": "2193590144",
  "referenceId": "C2436F698K0D",
  "paymentType": "Forward",
  "checkType": "Standard",
  "direction": "Outbound",
  "status": "Completed",
  "source": "Api",
  "posting": "Posted",
  "postingCode": "OK",
  "coreTransactionId": "21ba5fb0-e609-4560-a36f-ad9501439bb1",
  "memoPostId": "dc20e619-c5f7-4890-b3c8-ad9501439bb1",
  "originalPaymentId": "9a44fdbf-89e2-4300-8f05-ad9501439bb1",
  "customerId": "700f0d35-9940-4132-8608-ad89013927a9",
  "payerRoutingNumber": "021200339",
  "payerAccountNumber": "123456789",
  "payeeName": "",
  "checkNumber": "1237",
  "bofdRoutingNumber": "021214891",
  "sequenceNumber": "1353885824",
  "amount": 100,
  "currency": "usd",
  "micr": "d021200339dc12345678c1237",
  "recognizedAmount": 100,
  "iqaPassed": true,
  "hasFrontImage": true,
  "hasBackImage": true,
  "isRedeposit": false,
  "policy": "NewAccount",
  "schedule": [
    0,
    0,
    100
  ],
  "createdAt": "2021-08-31T15:38:13.28-04:00",
  "rejectedAt": "2021-08-31T15:38:17.527-04:00",
  "wasReturned": false,
  "purpose": "ENTERED BY #60C367E26DD36A0068580230#",
  "depositBusinessDate": "210831",
  "productId": "d5dc52bb-df80-4a5d-a5a8-ad89013844bd",
  "partnerId": "ede1a60d-3d51-47e8-9a9b-ad8901381f9e",
  "lastModifiedAt": "2021-08-31T15:38:17.5280148-04:00"
}

In the example above, the check was assigned the NewAccount availability policy along with the schedule. The schedule defines the days when funds from the check deposit will be available in the customer's COS account, where the first day (Day 1) is always equal to the value in the depositBusinessDate field. In the COS Explorer Portal, the same schedule would appear as:

Check Validation

Check deposits are systemically validated for compliance purposes. Results of this validation will appear in the response body. The example below illustrates details of a deposit made where the amount in the deposit request was $5,600.00 but the amount written on the check itself was $1.00.

Since the recognized amount was different than the deposit amount, the deposit was automatically rejected.

GET /v1/payments/{id}

{
  "id": "d94c5c62-f0c1-4e50-8b68-ad8f00fbcc6c",
  "accountNumber": "2150856074",
  "referenceId": "C2371LM3D88Q",
  "paymentType": "Forward",
  "checkType": "Standard",
  "direction": "Outbound",
  "status": "Rejected",
  "source": "OpsPortal",
  "posting": "Pending",
  "rejectionReason": "AmountMismatch",
  "postingCode": "OK",
  "coreTransactionId": "b5215fda-f720-4530-abe7-ad8f00fbcc6c",
  "memoPostId": "88509b68-ea34-407c-b934-ad8f00fbcc6c",
  "originalPaymentId": "d94c5c62-f0c1-4e50-8b68-ad8f00fbcc6c",
  "customerId": "7aa966b5-bbff-438a-b20d-ad870144dc85",
  "payerRoutingNumber": "021200339",
  "payerAccountNumber": "123456789",
  "payeeName": "",
  "checkNumber": "1237",
  "bofdRoutingNumber": "021214891",
  "sequenceNumber": "1767120148",
  "amount": 560000,
  "currency": "usd",
  "micr": "d021200339dc12345678c1237",
  "recognizedAmount": 100,
  "iqaPassed": true,
  "hasFrontImage": true,
  "hasBackImage": true,
  "isRedeposit": false,
  "policy": "NewAccount",
  "schedule": [
    0,
    0,
    552500,
    0,
    0,
    0,
    0,
    0,
    0,
    7500
  ],
  "createdAt": "2021-08-25T11:16:46.22-04:00",
  "rejectedAt": "2021-08-25T11:16:49.467-04:00",
  "wasReturned": false,
  "purpose": "ENTERED BY #60C367E26DD36A0068580230#",
  "depositBusinessDate": "210825",
  "productId": "2f885dc0-850f-4e1f-b5f2-ad870144660e",
  "partnerId": "560ba513-848c-49ae-8edc-ad8701446094",
  "lastModifiedAt": "2021-08-25T11:16:49.4725995-04:00"
}

Handling Rejected Checks

Let's assume the amount passed to COS was different than what was written on the check. When the request is submitted and subsequently rejected, you would receive the rejection webhook event.

{
  "id": "96595e06-508f-4d5f-ba80-ad8800f1e69d",
  "eventName": "Check.Payment.Rejected",
  "status": "Pending",
  "partnerId": "4c5b488d-711d-428a-bdae-ad800131970d",
  "createdAt": "2021-08-18T10:40:44.033-04:00",
  "resources": [
    "checks/v1/payments/b9e53e1c-683e-469c-8f79-ad8800f1ccc3"
  ],
  "details": []
}

Now, use the GET /v1/payments/{id} endpoint along with the payment ID from the resources section of the check payment rejected event to determine the reason for rejection:

GET /v1/payments/{b9e53e1c-683e-469c-8f79-ad8800f1ccc3}
{
  "id": "b9e53e1c-683e-469c-8f79-ad8800f1ccc3",
  "accountNumber": "2645256591",
  "referenceId": "C230H9EP0LSX",
  "paymentType": "Forward",
  "checkType": "Standard",
  "direction": "Outbound",
  "status": "Rejected",
  "source": "Api",
  "posting": "Pending",
  "rejectionReason": "AmountMismatch",
  "postingCode": "OK",
  "coreTransactionId": "e00cc24b-94b0-4078-b804-ad8800f1ccc3",
  "memoPostId": "ccc821b3-a3a0-4632-9b18-ad8800f1ccc3",
  "originalPaymentId": "b9e53e1c-683e-469c-8f79-ad8800f1ccc3",
  "customerId": "56b2a592-014d-4b03-9c61-ad8100fb9da6",
  "payerRoutingNumber": "021200339",
  "payerAccountNumber": "123456789",
  "payeeName": "",
  "checkNumber": "1237",
  "bofdRoutingNumber": "021214891",
  "sequenceNumber": "3897987018",
  "amount": 50000,
  "currency": "usd",
  "micr": "d021200339dc123456789c1237",
  "recognizedAmount": 100,
  "iqaPassed": true,
  "hasFrontImage": true,
  "hasBackImage": true,
  "isRedeposit": true,
  "policy": "Standard",
  "schedule": [
    0,
    27500,
    22500
  ],
  "createdAt": "2021-08-18T10:40:21.98-04:00",
  "rejectedAt": "2021-08-18T10:40:25.163-04:00",
  "wasReturned": false,
  "depositBusinessDate": "210818",
  "productId": "d3e6c8ce-3277-4cdd-bfa4-ad800131bd92",
  "partnerId": "4c5b488d-711d-428a-bdae-ad800131970d",
  "lastModifiedAt": "2021-08-18T10:40:25.1640462-04:00"
}

The rejectReason shows a reason of AmountMismatch, which occurred because the amount from the deposit request was submitted as $500 but COS recognized an amount of $1 from the check image. You should address any check issues with the customer prior to resubmitting the check deposit to avoid subsequent rejections.

Changing Availability Policies

Partners have the ability to change the deposit schedule, allowing them to either provide a better customer experience (i.e. making funds available sooner for a high value customer) or minimize losses (i.e. delaying availability for a check that may likely be returned).

❗️

Availability policies can only be updated prior to the check being batched and released to the Fed.

Let's say a deposit we made to a recently opened account was assigned an availability policy of NewAccount but we want to change it to a Standard policy. To do this, you'll need to call the PUT /v1/payments/{id}/policy endpoint using the ID from the original deposit.

PUT /v1/payments/61fcc3e6-00d6-45aa-ab8c-ad8f0101330d/policy

{
  "policy": "Standard"
}

A successful response to this request will include the updated policy:

{
  "id": "61fcc3e6-00d6-45aa-ab8c-ad8f0101330d",
  "accountNumber": "2150856074",
  "referenceId": "C2375L9FAC48",
  "paymentType": "Forward",
  "checkType": "Standard",
  "direction": "Outbound",
  "status": "Pending",
  "source": "OpsPortal",
  "posting": "Authorized",
  "postingCode": "OK",
  "coreTransactionId": "d933cf7c-6273-4e2d-9721-ad8f0101330d",
  "memoPostId": "139690e1-f86e-4c8e-9491-ad8f0101330d",
  "originalPaymentId": "61fcc3e6-00d6-45aa-ab8c-ad8f0101330d",
  "customerId": "7aa966b5-bbff-438a-b20d-ad870144dc85",
  "payerRoutingNumber": "021200339",
  "payerAccountNumber": "123456789",
  "payeeName": "",
  "checkNumber": "1237",
  "bofdRoutingNumber": "021214891",
  "sequenceNumber": "3524300619",
  "amount": 100,
  "currency": "usd",
  "micr": "d021200339dc123456789c1237",
  "recognizedAmount": 100,
  "iqaPassed": true,
  "hasFrontImage": true,
  "hasBackImage": true,
  "isRedeposit": false,
  "policy": "Standard",
  "schedule": [
    0,
    100,
    0
  ],
  "createdAt": "2021-08-25T11:36:26.067-04:00",
  "wasReturned": false,
  "purpose": "ENTERED BY #60C367E26DD36A0068580230#",
  "depositBusinessDate": "210825",
  "productId": "2f885dc0-850f-4e1f-b5f2-ad870144660e",
  "partnerId": "560ba513-848c-49ae-8edc-ad8701446094",
  "lastModifiedAt": "2021-08-25T11:38:03.5749934-04:00"
}

Did this page help you?