LendEasy/DocsLMS + Servicing·v1
Start integrating
Guides›Borrowers & Customers›Payment instruments

Payment instruments

The platform never receives an account number, only the provider can call an account verified, and switching one off stops future payments without touching history.

The safest place to keep a bank account number is somewhere else. An instrument is an owner-bound reference to an account or card held in a provider’s vault—the source of a payment, the destination of a funding or refund, the thing behind an autopay enrollment—and what LendEasy holds is a token and a masked display. A system that stores account numbers can eventually leak them; one that never receives them has nothing to leak.

A token in, a mask out

LendEasy accepts a providerTokenRef—a vault token—never a raw account or card value. The server resolves the token to derive the masked display, rail capabilities, and type. Ordinary reads return masked metadata only; raw numbers are never stored, so no route can leak them.

Accepted Rejected
providerTokenRef: "vault:ach:tok_sandbox_bank_44" Routing and account number
authorizationRef evidence reference Card PAN or security code
Owner fixed by the nested resource path Caller-asserted owner that disagrees with the path
Provider verification events Screenshots or secret values in notes

Two axes decide whether money moves

There is no public verify route. Verification arrives through provider events such as instant account verification; API callers cannot assert it.

status is ACTIVE or INACTIVE; verificationState is UNVERIFIED, VERIFIED, or FAILED. Payments, autopay, and funding all demand status: ACTIVE and verificationState: VERIFIED. Verification arrives from the provider because a state a caller could assert would prove nothing—the whole value of the word is that somebody outside the transaction checked the account and its owner.

A new token keeps the same type

Use the end-to-end Add & verify a payment instrument recipe. The routes are:

POST /v1/customers/{customerId}/payment-instruments
GET  /v1/customers/{customerId}/payment-instruments
GET  /v1/customers/{customerId}/payment-instruments/{instrumentId}
PUT  /v1/customers/{customerId}/payment-instruments/{instrumentId}
POST /v1/customers/{customerId}/payment-instruments/{instrumentId}/deactivate
GET  /v1/customers/{customerId}/payment-instruments/{instrumentId}/sensitive

Create takes instrumentType (ACH_BANK or CARD), the providerTokenRef, and an optional authorizationRef (CREATE_LMS_PAYMENT_INSTRUMENT):

curl -X POST "$BASE/v1/customers/412/payment-instruments" \
  -H "Authorization: Bearer $TOKEN" \
  -H "LendEasy-Tenant: demo-lender" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: maya-checking-token-v1" \
  -d '{
    "instrumentType": "ACH_BANK",
    "providerTokenRef": "vault:ach:tok_sandbox_bank_44",
    "authorizationRef": "evd_BANK_AUTH_11"
  }'
{ "resourceId": 704 }

A representative masked read is:

{
  "instrumentId": 704,
  "instrumentType": "ACH_BANK",
  "maskedDisplay": "••6789",
  "railCapabilities": ["ACH"],
  "verificationState": "VERIFIED",
  "accountValidationStatus": "VALIDATED",
  "status": "ACTIVE",
  "createdAt": "2026-08-11T16:10:00Z",
  "lastModifiedAt": "2026-08-11T16:12:00Z"
}

Lists filter by status, instrumentType, and verificationState. PUT replaces the vault token or authorization reference; a new token must resolve to the same immutable instrumentType and refreshes the masked display and rail capabilities. A card token swapped in under a bank instrument would leave every autopay enrollment and scheduled draw pointing at a rail the borrower never authorized.

GET …/sensitive adds providerTokenRef and authorizationRef to the masked fields. It needs the instrument sensitive-read permission on top of the ordinary one, under the same audited, no-store treatment as any sensitive read.

Verification is not authorization

Verification answers whether the provider confirmed the instrument and owner. Authorization answers whether the customer permitted this debit or recurring series. A one-time payment carries one-time evidence; autopay carries its Reg E authorizationRef and enrollment terms. Both still require an eligible instrument at execution.

Six checks before money moves

None of them is re-derived from a decision made earlier; all six are evaluated at execution:

  1. the owner in the resource path matches the payer or permitted recipient;
  2. status is ACTIVE and verificationState is VERIFIED;
  3. the requested rail is in railCapabilities;
  4. required one-time or recurring authorization evidence exists;
  5. no PAYMENT_HOLD or DISBURSEMENT_HOLD restriction blocks the movement;
  6. an optional Idempotency-Key guards the create against duplicate submission.

Deactivation stops future use, not history

Return-code policy distinguishes temporary funds conditions from structural account failures. Per-rail autopay failure policies decide, code by code, whether the instrument is kept or invalidated and whether autopay continues, enters review, or is cancelled; unknown codes fail closed to review. LendEasy never rewrites the state of historical payments that used the instrument.

POST …/deactivate takes a reasonCode and optional comment, stops future use, and cascades dependent autopay enrollments into review so operations can replace or cancel them. Without the cascade, the next cycle would draw on a closed account and return, adding a fee to a borrower whose only act was changing banks. It is idempotent—deactivating an inactive instrument is a no-op. In-flight payments continue under their rail state, because money already in the network cannot be recalled by a database update.

External parties such as merchants own instruments under /v1/external-parties/{partyId}/payment-instruments. The routes, permissions, and rules mirror the customer family exactly; a customer instrument cannot be used to fund an unrelated merchant.
Unified search across guides, recipes & the API referenceEsc