LendEasy/Docs
Get API keys
GuidesLoansAutopay

Autopay

Enroll a borrower-authorized instrument, initiate one payment per due obligation under explicit timing and amount policies, and govern failures with per-rail return-code policy.

Autopay is a policy-driven payment initiator. It reads the current due obligation and creates a normal payment intent with source: "AUTOPAY"; it never posts directly to the ledger or bypasses payment validation and restrictions. Each loan has at most one current enrollment at /v1/loans/{loanId}/autopay.

Enrollment lifecycle

Cancellation is final for that enrollment; a borrower re-enrolls with a new authorization. There is never a second active enrollment on the same loan.

Amount policies

amountPolicy.type Draw amount Typical use
FULL_DUE All currently due components at initiation. Statement-noticed variable amounts, like Harbor.
MIN_DUE The minimum due for the target installment after posted activity. Keeping an account current without sweeping extra charges.
FIXED The authorized fixedAmount (with currency), capped by current eligibility. Voluntary recurring overpayment or a payment plan.

FIXED does not silently rise to cover a larger amount due, and FULL_DUE is accepted only when the product’s statement lead leaves room for the ten-day advance notice described below.

Timing policy

timingPolicy states exactly when a draw is initiated relative to each due date:

  • initiateDaysBeforeDue—how many days ahead the payment intent is created;
  • businessDayConventionPRECEDING, FOLLOWING, or NONE when the computed date lands on a non-business day; and
  • onScheduleChangeFOLLOW_NEW_SCHEDULE to track a rescheduled due date automatically, or REVIEW_REQUIRED to hold draws for human review after a schedule change.

Enroll Harbor

HARBOR · FICTIONAL EXAMPLE

Harbor Personal Loan

Fixed-rate installment loan

Contract principal
$8,400.00
Nominal rate
13.25% fixed
Term
18 monthly payments
Prepaid origination fee
$252.00
Payment
$517.14
Disclosed APR
17.291%
curl -X POST "$BASE/v1/loans/7204/autopay" \
  -H "Authorization: Bearer $TOKEN" \
  -H "LendEasy-Tenant: demo-lender" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: harbor-autopay-enrollment-01" \
  -d '{
    "instrumentId": 704,
    "authorizationRef": "evd_JUN_AP_73",
    "timingPolicy": { "initiateDaysBeforeDue": 0, "businessDayConvention": "FOLLOWING" },
    "amountPolicy": { "type": "FULL_DUE" }
  }'

The command envelope ({ "resourceId": 31 }) confirms enrollment; GET /v1/loans/7204/autopay returns the canonical state:

{
  "loanRef": "7204",
  "status": "ACTIVE",
  "instrument": { "instrumentId": 704, "maskedDisplay": "••6789" },
  "timingPolicy": { "initiateDaysBeforeDue": 0, "businessDayConvention": "FOLLOWING", "onScheduleChange": "FOLLOW_NEW_SCHEDULE" },
  "amountPolicy": { "type": "FULL_DUE" },
  "authorizationRef": "evd_JUN_AP_73",
  "consecutiveFailureCount": 0,
  "effectiveDate": "2026-08-21"
}

The instrument must be ACTIVE and VERIFIED and belong to the borrower. Each cycle, autopay re-reads the due facts, instrument status, and restrictions, then creates one idempotently keyed payment intent per enrollment and due obligation—scheduler retries cannot create a duplicate draw. A manual payment that already covers the installment suppresses the draw; autopay does not send a $0 request or charge the original schedule amount anyway.

Regulation E authorization and notice

authorizationRef is required at enrollment: it references the borrower’s preauthorized-transfer authorization evidence, and no draw is initiated without it. For transfers that vary in amount, Regulation E § 1005.10(d) describes advance notice of the amount and date, generally at least 10 days before the scheduled transfer.

The due-date statement is the notice artifact for FULL_DUE enrollments, which is why enrollment is coupled to the product’s statementLeadDays: a lead shorter than the notice window rejects the enrollment rather than producing draws without compliant notice. Cancelling autopay is treated as a Regulation E revocation.

Pause, resume, and cancel

POST /v1/loans/{loanId}/autopay/pause, …/resume, and …/cancel each require a reasonCode from the closed catalog, with an optional comment:

BORROWER_REQUEST · STAFF_REQUEST · PAYMENT_RETURN_ACCOUNT_OWNERSHIP · RESTRICTION_CASCADE · FAILURE_POLICY · LOAN_CLOSED · REVIEW_RESOLVED · OTHER_DOCUMENTED

Pause stops initiation but keeps the enrollment and its authorization. Resume works from PAUSED or REVIEW_REQUIRED and clears the review reason and failure count; missed cycles are not automatically swept into catch-up draws. Cancel works from any state, cancels the enrollment’s pending unsubmitted payment intents, and is the revocation of record. A request that would repeat the current state is a successful no-op, and human calls carry the LendEasy-Case header when case management is enabled. Restrictions cascade too: an AUTOPAY_HOLD or COLLECTIONS_HOLD pauses the enrollment in the same transaction, and deactivating the instrument moves it into review.

Failure policies

How a returned draw is handled is tenant-level, per-rail policy—not product configuration. GET /v1/autopay/failure-policies returns the current policy for each rail, and PUT /v1/autopay/failure-policies/{rail} (rail ACH or CARD) replaces one rail’s policy in full:

{
  "automaticRetry": true,
  "retryAfterBusinessDays": 2,
  "maxRetryAttempts": 2,
  "maxConsecutiveFailedCycles": 3,
  "runNextScheduledCycle": true,
  "exhaustionAction": "REVIEW_REQUIRED",
  "returnCodes": [
    { "returnCode": "R01", "retryAllowed": true, "instrumentAction": "KEEP", "autopayAction": "CONTINUE", "caseAction": "NONE", "recommendedAction": "NONE", "treatAsUnauthorized": false },
    { "returnCode": "R10", "retryAllowed": false, "instrumentAction": "INVALIDATE", "autopayAction": "CANCELLED", "caseAction": "OPEN_PAYMENT_FAILURE", "recommendedAction": "CANCEL_AUTOPAY", "treatAsUnauthorized": true }
  ]
}

Each return-code row decides retry eligibility, the instrument’s fate (KEEP or INVALIDATE), the enrollment reaction (CONTINUE, REVIEW_REQUIRED, or CANCELLED), whether a payment-failure case opens, and whether the code is treated as an unauthorized-debit claim. The base fields govern retry pacing and exhaustion: the enrollment’s consecutiveFailureCount accumulates until maxConsecutiveFailedCycles triggers the exhaustionAction. An unknown return code always fails closed into review and blocks secondary automation.

What to monitor

  • draws initiated versus due obligations;
  • draws suppressed by prior manual payments;
  • statement lead versus the notice window on FULL_DUE enrollments;
  • settlement and return rates by rail and instrument;
  • consecutive failures and enrollments in REVIEW_REQUIRED; and
  • return codes falling through to the fail-closed review path.

An active enrollment that skips an eligible due date, or two intents for the same due obligation, is an invariant breach and raises a reconciliation incident.

Unified search across guides, recipes & the API referenceEsc