Pay
Alternative Payments
Check Payments

Check Payments

Accept payments from paper checks using Check21 or check conversion


Check payments enable you to accept traditional paper checks through digital channels. Payload supports two methods for check processing: Check21 for remote deposit with check images, and check conversion for recording in-person check payments. Both methods convert physical checks into electronic transactions while maintaining the audit trail and compliance requirements of traditional check processing.

Prerequisites

Before accepting check payments, understand how bank account payment methods work.


Check Payment Methods


Payload supports two distinct check payment methods depending on your use case.

Check21 - Remote Deposit Capture

Check21 enables customers to submit check payments remotely by uploading images of the front and back of their check. The images are processed using OCR (Optical Character Recognition) to extract routing number, account number, check number, and amount. This is ideal for remote payments where the customer physically possesses the check but cannot deposit it in person.

Use cases:

  • Remote bill payment by mail
  • Online check submission portals
  • Mobile check deposit alternatives

Requirements:

  • Clear images of check front and back
  • Check must be payable to your business
  • Physical possession of the check
  • Images in JPG, PNG, or PDF format

Check Conversion - In-Person and Mail Payments

Check conversion allows you to record check payments received in-person at manned locations (retail, bill pay counters) or by mail by capturing the check details without uploading images. This is ideal when you receive physical checks at retail locations, lockbox locations, or through mail, and need to record the transaction in Payload for tracking and reconciliation purposes.

Use cases:

  • Bill pay counter transactions
  • Lockbox location payments
  • Mail-received check recording
  • Retail location check payments

Requirements:

  • Check received in-person at manned location or by U.S. mail
  • Check number for reference
  • Provide advance written notice to customers that checks will be converted to electronic transactions
  • Retain check images or copies for 2 years from settlement date
  • Destroy physical checks within 14 days of settlement
  • Provide opt-out procedures for customers who do not authorize conversion
  • Include check serial number in transaction records

Limitations:

  • Maximum payment amount: $25,000
  • Not available for certified checks

When to Use Check Payments


Check payments are ideal for specific business scenarios where electronic payments are not yet universal and they are still accepting checks. Using Payload you can unifiy capture of all forms of payment.

Common use cases

  • Rent and Lease Payments: Property management accepting monthly rent
  • Earnest Money Deposit: Good-faith deposit after a home purchase agreement is signed
  • Insurance Premiums: Policy payments and claim disbursements
  • Utility Bills: Water, electric, gas, and other service payments
  • Professional Services: Legal, accounting, consulting invoices

Check21 Implementation


Accept Check21 remote deposit payments using Payment Form or direct API integration.

Check21 with Payment Form

Use Check21 with the Payment Form SDK to accept remote check deposits via image upload.

import payload
 
pl = payload.Session("secret_key_3bW9...", api_version="v2")
 
# Create payment form intent for Check21 image upload
intent = pl.Intent.create(
    type="payment_form",
    payment_form={
        "payment_template": {
            "amount": 250.00,
            "source": "check",  # Enable check image upload fields
            "description": "Invoice #INV-2024-001",
        }
    },
)
 
print(f"Intent Token: {intent.token}")
print("Use this token to initialize Payload.js on the frontend")
print("Form will include check_front[file] and check_back[file] upload fields")
<!DOCTYPE html>
<html>
<head>
  <script src="https://payload.com/Payload.js"></script>
</head>
<body>
  <form id="check-payment-form">
    <h2>Submit Check Payment</h2>
 
    <!-- Check front image upload -->
    <label>
      Check Front Image
      <input type="file" pl-input name="check_front[file]" accept="image/*,.pdf" required />
    </label>
 
    <!-- Check back image upload -->
    <label>
      Check Back Image
      <input type="file" pl-input name="check_back[file]" accept="image/*,.pdf" required />
    </label>
 
    <button type="submit">Submit Payment</button>
  </form>
 
  <script src="form.js"></script>
</body>
</html>
// Fetch client token from your server
fetch('/payment-form-intent', { method: 'POST' })
  .then(res => res.json())
  .then(data => {
    // Initialize Payload with the client token
    Payload(data.token)
 
    // Initialize the payment form
    const form = new Payload.Form(document.getElementById('check-payment-form'))
 
    // Handle successful payment processing
    form.on('processed', (evt) => {
      console.log('Check payment processed:', evt.transaction_id)
      alert('Check payment submitted successfully!')
      window.location.href = '/success'
    })
 
    // Handle payment errors
    form.on('error', (evt) => {
      console.error('Check payment error:', evt.message)
      alert('Error processing check: ' + evt.message)
    })
  })

This example shows:

Backend:

  • Create payment form intent with type: 'payment_form'
  • Set payment_form.source: 'check' to enable check image upload fields
  • Specify expected payment amount
  • Return client token for form initialization

Frontend:

  • HTML form with two file inputs for check front and back images
  • pl-input attribute with name="check_front[file]" and name="check_back[file]"
  • Accept image formats: JPG, PNG, PDF
  • Initialize form with client token from backend
  • Handle processed event for successful check submission
  • Handle error event for processing failures

Check21 with API

Submit check payments directly via API by providing base64-encoded check images.

import base64
 
import payload
 
pl = payload.Session('secret_key_3bW9...', api_version='v2')
 
 
# Helper function to convert image file to base64 data URI
def image_to_data_uri(file_path):
    with open(file_path, 'rb') as image_file:
        base64_image = base64.b64encode(image_file.read()).decode('utf-8')
        mime_type = 'image/png' if file_path.endswith('.png') else 'image/jpeg'
        return f"data:{mime_type};base64,{base64_image}"
 
 
# Convert check images to data URIs
check_front_uri = image_to_data_uri('./check_front.jpg')
check_back_uri = image_to_data_uri('./check_back.jpg')
 
# Submit Check21 payment via API
transaction = pl.Transaction.create(
    type='payment',
    source='check',
    amount=250.00,
    description='Invoice #INV-2024-001',
    receiver={'account_id': 'acct_processing123'},
    check_images={
        'front': {'file': {'data_uri': check_front_uri}},
        'back': {'file': {'data_uri': check_back_uri}},
    },
    attrs={'invoice_id': 'INV-2024-001', 'customer_ref': 'CUST-789'},
)
 
print(f"Transaction ID: {transaction.id}")
print(f"Status: {transaction.status.value}")
print(f"Check Number: {transaction.order_number}")
print("OCR processing will extract check details automatically")

This example shows API-based check processing:

  1. Encode Images: Convert check images to base64 data URIs
  2. Transaction Data: Set type: 'payment' and source: 'check'
  3. Amount Validation: Optionally provide amount for OCR comparison
  4. Receiver Account: Specify receiver.account_id for processing account receiving funds
  5. Check Images: Include check images in check_images object with front and back properties as base64 data URIs

Image Format:

Data URI format
front_image = "data:image/jpeg;base64,/9j/4AAQSkZJRg..."
back_image = "data:image/png;base64,iVBORw0KGgoAAAANS..."

OCR Processing

When you submit check images, Payload's OCR engine extracts:

  • Routing Number: Bank routing/ABA number from MICR line
  • Account Number: Customer account number from MICR line
  • Check Number: Check sequence number from MICR line
  • Amount: Written and numeric amount (if provided, used for validation)
  • Date: Check date for verification
  • Payee: To whom the check is made out

Amount Validation: If you provide an amount in the transaction request, it's compared against the OCR-extracted amount. If they don't match within a reasonable tolerance, the transaction is flagged for review.

Image Requirements

Check images must meet these requirements for successful OCR processing:

Format:

  • Supported: JPG, PNG, PDF
  • File size: Under 10MB per image
  • Resolution: Minimum 300 DPI recommended
  • Color or grayscale (color preferred)

Quality:

  • Clear, in-focus images
  • All four corners visible
  • No glare or shadows
  • Check must be flat (not folded)
  • Text must be readable

Content:

  • MICR line clearly visible on front
  • Signature visible on front
  • All endorsements visible on back
  • Date and amount legible

Check Conversion


Record check payments received in-person or by mail without uploading images.

import payload
 
pl = payload.Session('secret_key_3bW9...', api_version='v2')
 
# Record in-person check payment without uploading images
transaction = pl.Transaction.create(
    type='payment',
    source='check',
    amount=1500.00,
    description='Rent payment - March 2024',
    order_number='1234',  # Physical check number for tracking
    sender={
        'method': {
            'type': 'bank_account',
            'bank_account': {
                'routing_number': '110000000',
                'account_number': '1234567890',
                'account_type': 'checking',
            },
            'account_holder': 'John Smith',
        }
    },
    receiver={'account_id': 'acct_processing123'},
)
 
print(f"Transaction ID: {transaction.id}")
print(f"Status: {transaction.status}")
print(f"Check Number: {transaction.order_number}")
print("Physical check should be deposited at your bank separately")

Check conversion is simpler than Check21:

  1. Set Source: Use source: 'check' to indicate check payment
  2. Bank Account Details: Manually enter routing number and account number from the check in sender.method.bank_account
  3. Account Holder: Include the account holder name from the check in sender.method.account_holder
  4. Check Number: Set order_number to the physical check number for tracking
  5. Amount: Provide the check amount (maximum $25,000)
  6. No Images: Check images are not required or uploaded
  7. Manual Processing: You handle physical check deposit separately

Workflow:

  1. Provide advance written notice to customers that checks will be converted to electronic transactions
  2. Receive physical check from customer in-person at manned location or by U.S. mail
  3. Create check conversion transaction in Payload for tracking
  4. Retain check image or copy for 2 years
  5. Deposit physical check at your bank
  6. Destroy physical check within 14 days of settlement
  7. Reconcile when check clears

This approach tracks check payments in Payload alongside other payment types while you handle physical check deposit through normal banking channels. Use for checks received at point-of-sale, bill pay counters, lockbox locations, or by mail.

Troubleshooting


Common issues and solutions when processing check payments.

Poor Image Quality

Symptoms: OCR extraction fails or produces incorrect data.

Solutions:

  • Provide guidance on taking quality photos
  • Require minimum resolution and file size
  • Reject blurry or partially visible checks
  • Offer re-upload option with improved guidance

Amount Mismatch

Symptoms: OCR-extracted amount differs from provided amount.

Solutions:

  • Review check image manually to verify correct amount
  • Check for unclear handwriting or printing
  • Verify numeric and written amounts match on check
  • Flag for manual review if discrepancy is significant
  • Update amount if OCR is clearly incorrect

Schema Reference


The following fields are available when creating check payment transactions. For complete API reference, see Transactions API Reference.

Check21 Transaction Configuration

type
enum[string]Immutable
The type of transaction being processed. This determines the direction and nature of funds movement, such as payment collection, refund issuance, credit disbursement, or account funding operations.
Values: payment, deposit, withdraw, refund, payout
source
enum[string]Immutable
The method by which this transaction was initiated or captured. This indicates whether the transaction was submitted via API, manually keyed, swiped through a card reader, processed via EMV chip, captured through NFC/contactless, initiated via digital wallets like Google Pay or Apple Pay, or processed as a check conversion.
Values: api, keyed, swipe, emv, emv_quickchip, nfc, googlepay, applepay, check
amount
number (double)
The monetary amount for this transaction in the currency of the processing account. This value is always positive and represents the total value being transferred, collected, or refunded. The amount is rounded to two decimal places for display.
receiver
object
Information about the receiver party in this transaction, including the account and payment method to which funds are being sent or credited. For payment transactions, this is the processing account receiving funds. For payout transactions, this is the account receiving funds.
accountAccount
object
The expanded account object for the receiver. When included, this provides the full details of the account receiving funds in this transaction.
Visibility: explicit
account_id ID of Account
stringImmutable
The unique identifier of the account receiving funds for this transaction. This is an optional field that references the account object that owns the receiver payment method. (ID prefix: acct)
Pattern: ^acct_[A-Za-z0-9]+$
object
The expanded payment method object used by the receiver. When included, this provides the full details of the payment method to which funds are being credited.
method_id ID of PaymentMethod
stringImmutable
The unique identifier of the payment method used by the receiver. This references the payment method object to which funds are being sent or credited for this transaction. If not provided the account default will be used. (ID prefix: pm)
Pattern: ^pm_[A-Za-z0-9]+$
check_images
object
Images of the physical check for check conversion transactions. Both front and back images are required and will be processed using OCR to extract payment details. The front image provides account information while the back image shows endorsements.
object
The back image of the check being processed. This image is required for check deposit transactions and is used for verification and record-keeping purposes. It must show any endorsements on the back of the check.
Visibility: explicit
object
The front image of the check being processed. This image is used for OCR processing to extract account numbers, routing numbers, check numbers, and amounts. The image must be clear and readable for successful processing.
Visibility: explicit
order_number
string
Custom order or transaction number for this payment. Use this to link the payment to an order in your system or to provide a customer-facing transaction reference. Providing this value ensures duplicate protection is applied per order; .otherwise, duplicate protection applies across payments without an order reference. For check transactions this field contains the check number.
Max length: 64
description
string
A human-readable description of what this transaction is for. This text provides context about the purchase, service, or payment purpose and may be displayed to customers on receipts and in transaction histories.
Max length: 128

Next Steps

Enhance your check payment processing implementation


Handle Check Returns

Monitor and handle returned checks to manage insufficient funds, stopped payments, and closed accounts that can occur weeks after initial deposit.

Monitor Transaction Status

Track transaction status to monitor check clearing timelines and identify issues early in the processing cycle.

Automate with Webhooks

Subscribe to webhook notifications to receive real-time updates for check processing events, returns, and status changes.


Related articles