Skip to navigation

Use Remote Deposit Capture (API)

Learn how to use remote deposit capture (RDC) to convert paper checks received in-person into electronic payments via the API

View as MarkdownOpen in Claude
Applies to:Developers

Remote Deposit Capture (RDC) is a service that allows you to convert paper checks received in-person into electronic payments without physically depositing them at a bank. This guide explains how to implement RDC via the API.

Remote Deposit Capture requires configuration by the Payabli team. Contact us to get started.

RDC uses Back Office Conversion (BOC), which only supports consumer checks received in-person at a point-of-sale or staffed payment location. Some checks aren’t eligible, including mailed, drop box, business, cashier’s, government, and insurance checks. See Capturing in-person checks for full eligibility details.

The implementation process consists of two main API calls:

  1. Check image capture and OCR extraction
  2. Payment processing using the extracted check information

Before you begin, make sure you read Capturing in-person checks to understand the key concepts and requirements for Remote Deposit Capture (RDC).

Step 1: Process check images

First, send the check images to Payabli for processing using the /CheckCapture/CheckProcessing endpoint. You need to send the front and back images of the check in JPEG or PNG format, base64 encoded.

POST
/api/CheckCapture/CheckProcessing
curl -X POST https://api-sandbox.payabli.com/api/CheckCapture/CheckProcessing \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"entryPoint": "8cfec329267",
"frontImage": "/9j/4AAQSkZJRgABAQEASABIAAD...",
"rearImage": "/9j/4AAQSkZJRgABAQEASABIAAD...",
"checkAmount": 12550
}'

A successful response includes the extracted check information, including the OCR account and routing numbers, as well as the check amount.

Response
{
"success": true,
"processDate": "2025-04-10T04:17:09.875Z",
"amountDiscrepancyDetected": false,
"endorsementDetected": true,
"checkType": 1,
"id": "txn_abc123def456",
"ocrMicr": "⑆123456789⑆ ⑈123456⑈ 0123",
"ocrMicrStatus": "SUCCESS",
"ocrMicrConfidence": "95",
"ocrAccountNumber": "123456",
"ocrRoutingNumber": "123456789",
"ocrCheckNumber": "0123",
"ocrCheckTranCode": "",
"ocrAmount": "125.50",
"ocrAmountStatus": "SUCCESS",
"ocrAmountConfidence": "98",
"errors": [],
"messages": [
"Check processed successfully"
],
"carLarMatchConfidence": "97",
"carLarMatchStatus": "MATCH",
"referenceNumber": "REF_XYZ789",
"pageIdentifier": null
}

If the check processing fails, the response includes error information to help you troubleshoot the issue. Some errors appear in the errors array of 200 response, and validation errors are returned as a 400 response.

{
"id": "",
"success": false,
"processDate": "0001-01-01T00:00:00",
"ocrMicr": null,
"ocrMicrStatus": "",
"ocrMicrConfidence": null,
"ocrAccountNumber": null,
"ocrRoutingNumber": null,
"ocrCheckNumber": null,
"ocrCheckTranCode": null,
"ocrAmount": "107",
"ocrAmountStatus": "",
"ocrAmountConfidence": null,
"amountDiscrepancyDetected": false,
"endorsementDetected": false,
"errors": [
"It appears you submitted 2 images of front of check. Please retake both front and rear photos."
],
"messages": [],
"carLarMatchConfidence": null,
"carLarMatchStatus": null,
"frontImage": null,
"rearImage": null,
"checkType": 0,
"referenceNumber": "0"
}

Amount mismatches

The checkAmount you send must match the amount that OCR reads from the check. By default, the scan fails when the two amounts don’t match. The response has success set to false, amountDiscrepancyDetected set to true, and this error in the errors array: The amount on the check does not match the amount provided.

Your organization or paypoint can choose to accept these scans instead. When this setting is on, a scan with mismatched amounts succeeds. The response still has amountDiscrepancyDetected set to true, and the messages array includes a warning. The array can also include other warnings, such as a missing endorsement.

Amount mismatch warning (excerpt)
{
"success": true,
"amountDiscrepancyDetected": true,
"errors": [],
"messages": [
"Warning: The entered amount doesn't match the check amount. Verify the amount before you submit. An incorrect amount can cause a return or adjustment."
]
}

Payabli stores the check with the amount that you sent in checkAmount, so use that amount for totalAmount in step 2. Convert it from cents to dollars first. For example, a checkAmount of 120000 becomes a totalAmount of 1200.00. The merchant accepts liability for an incorrect amount, such as a return or adjustment. Show the warning to the merchant so they can verify the amount before they submit the payment. A scan where OCR can’t read the account or routing number still fails, even with this setting on.

Accepting checks with mismatched amounts requires configuration by the Payabli team. Contact us to get started.

Step 2: Process payment

After successfully processing the check images, use the extracted information to complete the payment transaction.

Send a POST request to /v2/MoneyIn/getpaid:

{
"entryPoint": "8cfec329267",
"paymentMethod": {
"method": "ach",
"achAccount": "123456", // Use ocrAccountNumber from step 1
"achRouting": "123456789", // Use ocrRoutingNumber from step 1
"achCode": "BOC", // Must be "BOC" for check conversion
"achHolder": "John Doe", // Account holder name
"achAccountType": "Checking" // Must be "Checking"
},
"paymentDetails": {
"checkUniqueId": "abc123def456", // Use id from step 1 response
"totalAmount": 125.50 // Use dot (.) as decimal separator
},
}

This request has some differences from the standard transaction, pay attention to the following fields:

FieldValueDescription
methodachPayment method must be ACH
achCodeBOCACH SEC code must be BOC for check conversion
achAccountType”Checking”Account type must be Checking
totalAmount125.50Amount in dollars, using a dot (.) as the decimal separator
checkUniqueIdabc123def456ID from the check processing response

A successful request returns a 201 response.

Response
{
"code": "A0000",
"reason": "Approved",
"explanation": "Transaction approved",
"action": "No action required",
"data": {
"parentOrgName": "Mountain View Services",
"paypointDbaname": "Mountain View Auto",
"paypointLegalname": "Mountain View Automotive Services LLC",
"paypointEntryname": "8cfec329267",
"paymentTransId": "2145-7b8fa3c9d5e64f73b2ee5a6b14bd39cd",
"connectorName": "checkcommerce",
"externalProcessorInformation": "",
"gatewayTransId": "ACH_TRN_8K92D7VZexp8PFR3RGYbu2zRTMG3oC",
"orderId": null,
"method": "ach",
"batchNumber": "checkcommerce_2145_ach_12-01-2025",
"batchAmount": 525,
"payorId": 4440,
"paymentData": {
"maskedAccount": "XXXXX3456",
"accountType": "Checking",
"accountExp": null,
"holderName": "John Doe",
"storedId": null,
"initiator": null,
"storedMethodUsageType": null,
"sequence": null,
"orderDescription": "",
"accountId": null,
"signatureData": null,
"binData": null,
"paymentDetails": {
"totalAmount": 125.5,
"serviceFee": 0,
"checkNumber": null,
"checkUniqueId": "abc123def456",
"currency": "USD",
"orderDescription": null,
"orderId": null,
"orderIdAlternative": null,
"paymentDescription": null,
"groupNumber": null,
"source": null,
"payabliTransId": null,
"categories": [],
"splitFunding": [],
"checkImage": null,
"unbundled": null
}
},
"transStatus": 1,
"paypointId": 3040,
"totalAmount": 125.5,
"netAmount": 125.5,
"feeAmount": 0,
"settlementStatus": 0,
"operation": "Sale",
"responseData": {
"resultCode": "A0000",
"resultCodeText": "Approved",
"response": null,
"responsetext": "CAPTURED",
"authcode": "AXS425",
"transactionid": "ACH_TRN_8K92D7VZexp8PFR3RGYbu2zRTMG3oC",
"avsresponse": null,
"avsresponse_text": null,
"cvvresponse": null,
"cvvresponse_text": null,
"orderid": null,
"response_code": "100",
"response_code_text": "Operation successful",
"customer_vault_id": null,
"emv_auth_response_data": null,
"type": null
},
"source": "api",
"scheduleReference": 0,
"orgId": 123,
"refundId": 0,
"returnedId": 0,
"chargebackId": 0,
"retrievalId": 0,
"invoiceData": {
"invoiceNumber": null,
"invoiceDate": null,
"invoiceDueDate": null,
"invoiceEndDate": null,
"invoiceStatus": null,
"invoiceType": null,
"frequency": null,
"paymentTerms": null,
"termsConditions": null,
"notes": null,
"tax": null,
"discount": null,
"invoiceAmount": null,
"freightAmount": null,
"dutyAmount": null,
"purchaseOrder": null,
"firstName": null,
"lastName": null,
"company": null,
"shippingAddress1": null,
"shippingAddress2": null,
"shippingCity": null,
"shippingState": null,
"shippingZip": null,
"shippingCountry": null,
"shippingEmail": null,
"shippingPhone": null,
"shippingFromZip": null,
"summaryCommodityCode": null,
"items": null,
"attachments": null,
"additionalData": null
},
"entrypageId": 0,
"externalPaypointID": "",
"isValidatedACH": false,
"transactionTime": "2025-12-01T10:15:28.742",
"customer": {
"identifiers": null,
"firstName": "John",
"lastName": "Doe",
"companyName": null,
"billingAddress1": "456 Oak Avenue",
"billingAddress2": "",
"billingCity": "Portland",
"billingState": "OR",
"billingZip": "97201",
"billingCountry": "US",
"billingPhone": "+15035551234",
"billingEmail": "example@payabli.com",
"customerNumber": "C-90010",
"shippingAddress1": "456 Oak Avenue",
"shippingAddress2": "",
"shippingCity": "Portland",
"shippingState": "OR",
"shippingZip": "97201",
"shippingCountry": "US",
"customerId": 4440,
"customerStatus": 0,
"additionalData": null
},
"splitFundingInstructions": null,
"cfeeTransactions": [],
"transactionEvents": [
{
"transEvent": "Created",
"eventData": "0HNHD69JBVWXP:00000001",
"eventTime": "2025-12-01T10:15:27.682442"
},
{
"transEvent": "Approved",
"eventData": "0HNHD69JBVWXP:00000001",
"eventTime": "2025-12-01T10:15:28.751283"
}
],
"riskStatus": "PASSED",
"riskReason": "",
"riskAction": "",
"deviceId": "",
"achSecCode": "BOC",
"achHolderType": "personal",
"ipAddress": "255.255.255.255",
"isSameDayACH": false,
"walletType": null,
"pendingFeeAmount": 0,
"riskFlagged": false,
"riskFlaggedOn": "2025-12-01T10:15:27.6712346",
"riskActionCode": 0,
"transAdditionalData": null
},
"token": null
}

Implementation recommendations

When implementing RDC, consider the following recommendations, which can help create a smoother user experience and reduce errors.

Data validation

Before submitting to the API:

  • Ensure check images are correctly encoded and within size limits
  • Verify the check amount sent to /CheckCapture/CheckProcessing is in cents (integer value), and the amount sent to /MoneyIn/getpaid uses dot (.) decimal notation
  • Check that the required parameters are correctly formatted

Error handling strategies

When implementing error handling, consider the following scenarios and strategies:

Error scenarioHandling strategy
OCR confidence below thresholdImplement manual review for low confidence results
Image quality issuesGive the user feedback to retake images
Amount discrepanciesIf the scan fails, show the error from the errors array and ask the user to check the amount and scan again. If the scan succeeds with a warning, show the warning from the messages array and ask the user to confirm the amount. See Amount mismatches.
Connectivity problemsImplement retry logic with exponential backoff

Testing recommendations

When testing your RDC implementation, consider the following scenarios:

  1. Image quality testing: Test with varied image qualities and lighting conditions.
  2. Error handling: Test with intentionally poor images and various check types to verify error handling.
  3. End-to-end flow: Test the complete flow from image capture to payment processing.
  4. Integration testing: Verify proper integration with your existing systems.

See these related resources to help you get the most out of Payabli.