> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lead.bank/llms.txt
> Use this file to discover all available pages before exploring further.

# Originate and Service an On-Sheet Loan

> Originate a term loan on the v2 APIs, disburse the principal, and report servicing activity as it happens. For programs where Lead holds the receivable.

<Note>
  The v2 APIs in this guide are in preview, with a planned beta release in December 2026. Preview APIs are not yet available in sandbox or production and can change before beta. Use this guide to plan an integration, not to build one. Your Technical Account Manager will confirm sandbox timing for your program. See [Versioning and backwards compatibility](/core-concepts/platform/versioning-and-backwards-compatibility).
</Note>

This guide walks through originating a term loan on Lead's v2 APIs, disbursing the principal, and reporting the loan's servicing activity. It is for programs where **Lead holds the receivable on its balance sheet** until the loan reaches a terminal status, rather than selling it to you.

## How it works

Once you've onboarded a borrower, create **Entity** objects for the borrower and the people behind it. Once you've made an underwriting decision, create an **Application** object. Then open a **User Account** object for the borrower, which carries the features it's opened with and the `balance_sheet_model` that marks the loan as held on Lead's balance sheet. Any files that need to be provided to Lead (e.g., identification documents, loan agreements) are created as **File** objects, then linked to the Entity, Application, and/or User Account objects. Record the loan's terms on a **User Credit Balance** object created under the user account. To disburse the principal, create a **Funding** object, which moves money from Lead's general ledger to an account number your program controls. From there, you send the external disbursement from that account number to the borrower.

From then on, everything that happens to the loan on your ledger is reported to Lead as a **user credit transaction**: each repayment, fee, interest accrual, and charge-off, posted as it happens. You are the ledger of record for the loan. If you report something incorrectly, reverse it and post the correct user credit transaction. See [Step 8](#step-8-report-servicing-activity-as-it-happens).

Origination is a per-loan flow. Servicing reporting is continuous, and it runs until the user credit balance reaches a terminal status.

## Example scenario

Harbor Point Capital offers working-capital term loans to restaurants inside its point-of-sale platform. Rosa's Cantina, owned and run by Rosa Alvarez, borrows \$40,000 over 24 months. Harbor Point underwrites the business in its own systems, reports the approval to Lead, opens the loan, draws the principal, and sends it to the restaurant's operating account. Because Harbor Point's program is on-sheet, Lead funds and holds the loan rather than selling it to Harbor Point, and Harbor Point reports Rosa's repayments to Lead as they post over the following two years.

## Objects involved

| Object | Role in this flow | Endpoint | Reference |
| - | - | - | - |
| Entity | Rosa Alvarez, and Rosa's Cantina with your KYB and OFAC results attested | `POST /v2/entities` | [Entity](/v2/products/entity/overview) |
| Application | The terminal underwriting decision | `POST /v2/applications` | [Applications](/v2/products/applications/overview) |
| User account | The borrower's credit relationship with Lead, and where `balance_sheet_model` lives | `POST /v2/user_accounts` | [User Accounts](/v2/products/user-accounts/overview) |
| File | The loan agreement and other documents, uploaded once and linked by ID | `POST /v2/files` | [Files](/v2/products/files/overview) |
| User credit balance | The loan's terms and running position | `POST /v2/user_accounts/{user_account_id}/user_credit_balances` | [User Credit Balance](/v2/products/user-credit-balance/overview) |
| Funding | Moves the principal from Lead's general ledger to your account number | `POST /v2/fundings` | [Fundings](/v2/products/fundings/overview) |
| Payment | The external disbursement to the borrower | `POST /v1/ach`, `POST /v1/instant_payments` | [ACH](/products/ach/overview), [Instant Payments](/products/instant-payments/overview) |
| User credit transaction | Your servicing report: repayments, interest, fees, charge-offs | `POST /v2/user_credit_balances/{user_credit_balance_id}/user_credit_transactions` | [User Credit Transaction](/v2/products/user-credit-transaction/overview) |

## Before you start

* **Scopes.** You need `file/read_write`, `entity/read_write`, `application/read_write`, `user_account/read_write`, `user_credit_balance/read_write`, `user_credit_transaction/read_write`, `funding/read_write`, and the scope for each payment rail you disburse on. See [Authentication](/api-reference/using-the-api/authentication).
* **A destination account number for fundings.** Every funding posts to an `account_number_id` that you specify. It must be `active`, belong to your program, and sit on a core balance that Lead has enabled to receive fundings. A core balance is the balance position within one of your program's bank accounts at Lead. See [Core Balance](/products/core-balance/overview). This is a one-time setup, not a per-loan step. Your Technical Account Manager can tell you which of your account numbers qualify.
* **Your `product_config_id`.** Required on every user account you create. Your Lead team provides it. There is no endpoint to look it up, so store it alongside your credentials.
* **Idempotency.** Every `POST` and `PATCH` in this flow requires an `Idempotency-Key` header. On the user credit transaction endpoint this matters most: a retried request without a key posts a second user credit transaction and double-counts the amount. See [Idempotency](/api-reference/using-the-api/idempotency-v2).

## Integration steps

### Step 1: Create the entities

A business borrower needs an entity for each person behind it. Create Rosa as an individual entity first, then create the business and link her as its control person and beneficial owner.

```text theme={null}
POST /v2/entities
{
  "type": "individual",
  "intended_eligibility": ["authorized_signer"],
  "individual_details": {
    "first_name": "Rosa",
    "last_name": "Alvarez",
    "date_of_birth": "1984-03-12",
    "identification_details": {
      "type": "us_entity",
      "tax_identification": { "type": "ssn", "value": "987654321" }
    }
  },
  "kyc_details": { "result": "passed", "screened_at": "2026-09-30T14:20:00Z" },
  "ofac_details": { "result": "passed", "screened_at": "2026-09-30T14:20:00Z" }
}
```

```text theme={null}
POST /v2/entities
{
  "type": "business",
  "intended_eligibility": ["account_holder"],
  "risk_score": "low",
  "business_details": {
    "type": "llc",
    "name": "Rosa's Cantina LLC",
    "doing_business_as": "Rosa's Cantina",
    "address_details": {
      "physical_address": { "line_1": "214 Market St", "city": "Denver", "state": "CO", "postal_code": "80202", "country": "US" }
    },
    "identification_details": {
      "type": "us_entity",
      "tax_identification": { "type": "ein", "value": "123456789" }
    }
  },
  "control_persons": [ { "entity_id": "entity_rosa_alvarez_001", "title": "Owner" } ],
  "beneficial_owners": [ { "entity_id": "entity_rosa_alvarez_001", "ownership_percentage": 100 } ],
  "kyc_details": { "result": "passed", "screened_at": "2026-09-30T14:25:00Z" },
  "ofac_details": { "result": "passed", "screened_at": "2026-09-30T14:25:00Z" }
}
```

* **Send `intended_eligibility`** for the roles each entity will hold. Lead then checks in real time that the entity has the data those roles need, and rejects the request rather than letting you discover the gap at account opening. Read `eligibility` on the response to confirm.
* **Every linked person must meet the data requirements for `authorized_signer`**, even if they will never sign. If one doesn't, the business is ineligible for `account_holder`, and its `failed_checks` point at that person's `entity_id`.

See [Eligibility](/v2/products/entity/eligibility) for every check and how to fix it.

### Step 2: Report the underwriting decision as an application

Applications are reported in a terminal status: `approved`, `declined`, or `canceled`. Lead does not require you to report applications that are still in progress. A `declined` application requires `details.adverse_action_notice`.

```text theme={null}
POST /v2/applications
{
  "status": "approved",
  "product_name": "Working Capital Term Loan",
  "entities": {
    "account_holders": ["entity_rosas_cantina_001"],
    "authorized_signers": ["entity_rosa_alvarez_001"]
  },
  "details": {
    "underwriting": {
      "is_secured": false,
      "is_mla": false,
      "currency_code": "USD",
      "underwriting_grade": "A",
      "limit": 4000000,
      "max_limit": 4000000
    }
  },
  "decision": { "decided_at": "2026-09-30T15:00:00Z", "reason": "Meets program underwriting criteria" },
  "documents": []
}
```

`documents` is required, and an empty array is valid. On an `approved` application, each account holder must be eligible for `account_holder`. See [The Application Object](/v2/products/applications/application-object).

### Step 3: Open the user account

The user account is where two facts about the loan are declared: what the user account is for, and how Lead treats the receivable it generates. You link the loan documents to it in the next step.

```text theme={null}
POST /v2/user_accounts
{
  "application_id": "application_rosas_cantina_001",
  "requested_features": ["credit_with_underwriting"],
  "balance_sheet_model": "held_for_investment",
  "product_config_id": "product_config_harbor_point_001",
  "product_name": "Working Capital Term Loan",
  "entities": {
    "account_holders": ["entity_rosas_cantina_001"],
    "authorized_signers": ["entity_rosa_alvarez_001"]
  },
  "details": {
    "underwriting": {
      "is_secured": false,
      "is_mla": false,
      "underwriting_grade": "A",
      "currency_code": "USD",
      "available_credit": 4000000,
      "limit": 4000000,
      "max_limit": 4000000
    }
  },
  "documents": []
}
```

Five things to know:

* **`requested_features` declares what the user account is for.** The two credit features stay distinct: `credit_with_underwriting` and `credit_without_underwriting`. The feature you request decides which data Lead requires, so requesting it is the declaration. The response returns what was granted as `features`.
* **`balance_sheet_model` is required on any user account with a credit feature.** `held_for_investment` means Lead holds the receivable, which is this flow. `held_for_sale` means the receivable is sold to you after your program's hold period. You cannot change it after creation. Lead can move it to `held_for_sale` when a loan is sold to you (see [Selling an on-sheet loan back to you](#selling-an-on-sheet-loan-back-to-you)).
* **`application_id` is required** with `credit_with_underwriting`, so step 2 always comes first.
* **A commercial user account needs at least one `authorized_signer`.** Here that is Rosa.
* **`documents` is required on create, and an empty array is valid.** Send `[]` here and link the loan documents in step 4.

See [The User Account Object](/v2/products/user-accounts/user-account-object).

### Step 4: Upload the loan documents and link them to the user account

Upload each document with the Files API, then link the returned `file_id` values to the user account.

This example assumes that only loan agreement documents need to be provided to Lead. The final set of documents required will be determined by your Legal point of contact.

```bash theme={null}
curl --request POST \
     --url https://api.sandbox.lead.bank/v2/files \
     --header 'Authorization: Bearer <token>' \
     --header 'Idempotency-Key: 4f9b1c2e-8a7d-4e3f-9b6a-1d2c3e4f5a6b' \
     --form 'type=loan_agreement' \
     --form 'file=@rosas_cantina_loan_agreement.pdf;type=application/pdf'
```

```text theme={null}
PATCH /v2/user_accounts/{user_account_id}
{
  "documents": [
    { "file_id": "file_rosas_cantina_loan_agreement", "timestamp": "2026-09-30T15:20:00Z", "version": "v1" }
  ]
}
```

* **The `type` you declare on upload decides where the file can be linked.** A `loan_agreement` can be linked to an application or a user account. A `formation_document` can only be linked to a business entity. See [The type enum](/v2/products/files/file-object#the-type-enum).
* **Each document entry needs a `file_id` and a `timestamp`.** `timestamp` is when your customer saw or agreed to the document, not when you uploaded the file.
* **A `PATCH` replaces the whole `documents` array.** To add a document later, send every existing entry plus the new one.
* **One file, one type.** If one PDF holds two documents, upload it once for each type. Files can't be changed or deleted, so if you upload the wrong file or type, upload a new one and link the new `file_id`.

See [Files](/v2/products/files/overview) and [Documents](/v2/products/user-accounts/user-account-object#documents) on the user account.

### Step 5: Define the loan as a user credit balance

The user credit balance holds the loan's terms and, over its life, its running position. You create it under the user account from step 3.

```text theme={null}
POST /v2/user_accounts/{user_account_id}/user_credit_balances
{
  "name": "Working Capital Loan - Rosa's Cantina",
  "currency_code": "USD",
  "interest": { "rate": "9.990000", "effective_rate": "9.500000", "effective_apr": "10.250" },
  "autopay_method": "ach",
  "details": {
    "structure": "non_revolving",
    "expected_maturity_date": "2028-10-01",
    "max_funding_amount": 4000000,
    "term": { "length": 24, "unit": "months" },
    "expected_finance_charge_amount": 428000,
    "repayment_details": {
      "expected_payment_frequency": "monthly",
      "expected_number_of_payments": 24,
      "expected_payment_amount": 184500,
      "expected_first_payment_date": "2026-11-01"
    }
  }
}
```

**Decision point:** `details.structure` decides which terms are required. A `non_revolving` user credit balance requires `expected_maturity_date`, `max_funding_amount`, `term`, `expected_finance_charge_amount`, and `repayment_details` up front. A `revolving` one rejects them, because available credit rather than a fixed schedule is the live constraint. A `non_revolving` user credit balance usually has one funding. A `revolving` one takes one funding per draw.

The user credit balance starts `active`, with every amount at zero. Until you fund it, it represents your intention to lend on the stated terms. The user account must be `active` and have a credit feature, or the request is rejected.

### Step 6: Draw the principal with a funding

```text theme={null}
POST /v2/fundings
{
  "user_credit_balance_id": "user_credit_balance_rosas_001",
  "account_number_id": "account_number_harbor_point_funding",
  "currency_code": "USD",
  "amount": 4000000
}
```

The response returns the funding with `status: processing`. When the money reaches your account number, the funding moves to `posted`, `core_transaction_id` is set, and you receive a `funding.posted` webhook.

* **`amount` is the whole principal**, in minor units. On a `non_revolving` user credit balance, it plus every `processing` and `posted` funding already on it cannot exceed `max_funding_amount`.
* **Lead records the disbursement for you.** Within seconds of `posted`, Lead posts a `funding` user credit transaction on the user credit balance, with `funding_id` set. Do not post your own user credit transaction for the same disbursement.
* **Report the borrower origination fee separately.** Post a `fee` user credit transaction with `details.fee_type: borrower_origination` and the funding's ID in `funding_id`, which is required for that fee type.

See [The Funding Object](/v2/products/fundings/funding-object).

### Step 7: Send the external disbursement to the borrower

The principal is in your account and the funds are yours to move. Pay the borrower from that account number on any rail Lead supports.

```text theme={null}
POST /v1/ach
{ "amount": 4000000, "account_number_id": "account_number_harbor_point_funding", "...": "..." }
```

For an instant external disbursement, check reach before you promise it in your product, and fall back to ACH from the same account rather than failing the loan. See [Instant Payments](/products/instant-payments/overview).

### Step 8: Report servicing activity as it happens

Post each event against the user credit balance as it posts on your ledger.

```text theme={null}
POST /v2/user_credit_balances/{user_credit_balance_id}/user_credit_transactions
{
  "type": "payment",
  "description": "Scheduled payment",
  "currency_code": "USD",
  "amount": -184500,
  "amount_breakdown": { "principal": -151200, "interest": -33300, "fees": 0 },
  "effective_at": "2026-11-01T08:30:00Z"
}
```

The types you use most on a term loan are `interest_accrued`, `fee`, and `payment`. See [Types](/v2/products/user-credit-transaction/user-credit-transaction-object#types) for every type and the sign each one requires.

Rules worth building around:

* **`amount` must have the sign the type requires**, and must equal `principal + interest + fees`. A `payment` reduces what the borrower owes, so it is negative. `interest_accrued` and `fee` are positive.
* **All three `amount_breakdown` fields are required**, even when a component is zero.
* **`effective_at` is when the balance moved on your ledger**, not when you called the API. It must fall in the current calendar quarter in UTC, or in the previous quarter during the first seven days of a quarter. Plan backfill and catch-up logic around that window.
* **`details.fee_type` is required when `type` is `fee`.**
* **The user credit balance must be `active`.** Nothing posts to `inactive`, `closed`, or `reporting_stopped` user credit balances, except `card_network` user credit transactions.
* **Report the whole life of the loan**, including the outcomes you would rather avoid. `cancellation`, `charge_off`, and `charge_off_recovery` exist for them.

**Corrections.** To correct a user credit transaction, reverse it and post the right one. The original is never changed.

```text theme={null}
POST /v2/user_credit_transactions/{id}/reverse
```

Lead creates a new user credit transaction that negates the original. You can reverse a user credit transaction once. A second reversal returns `409`, and you cannot reverse one Lead posted, such as `funding`. `PATCH /v2/user_credit_transactions/{id}` changes only `description` and `metadata`. It is not a way to correct an amount. See [Reversals](/v2/products/user-credit-transaction/user-credit-transaction-object#reversals).

### Step 9: Keep the user credit balance current, and close it out

Update the fields that can change, like `past_due` or `repayment_details`, with `PATCH /v2/user_credit_balances/{id}`. Move the status with the explicit endpoints:

```text theme={null}
POST /v2/user_credit_balances/{id}/activate
POST /v2/user_credit_balances/{id}/deactivate
POST /v2/user_credit_balances/{id}/close
POST /v2/user_credit_balances/{id}/stop_reporting
```

**Your reporting obligation runs until the user credit balance reaches a terminal status**, `closed` or `reporting_stopped`. For a loan that runs to term, call `close` with `status_reason: paid_off`. For one written off as a loss, report the `charge_off` user credit transaction, then `close` with `status_reason: charged_off`.

Terminal means Lead stops expecting reporting on the user credit balance. It does not mean Lead's view can never be corrected. If you close a user credit balance in error, see [Correcting a mistaken status change](/v2/products/user-credit-balance/statuses#correcting-a-mistaken-status-change).

## Selling an on-sheet loan back to you

<Note>
  **Planned.** How you signal a purchase is still being designed. The shape below is what to design around.
</Note>

Because Lead holds the receivable, your recourse when a loan starts to deteriorate is to **buy it back** rather than leave it on Lead's books as it becomes non-performing. This is **offloading**, and it is the intended path for a loan heading toward non-accrual.

Offloading reuses the receivables and receivable sales that originate-to-sell programs run every business day. The difference is when the sale date arrives: an originate-to-sell receivable has one from the moment it is created, while an on-sheet receivable has none until you give it one.

1. **A receivable exists from the start.** When you create an on-sheet user credit balance, Lead creates a receivable for it with `held_for: investment`. Its amount tracks the live position, growing with fundings and reducing with the payments you report.
2. **You signal the purchase, with a date.** You tell Lead which loan to sell you and the date you intend to buy it.
3. **Lead marks the receivable for sale.** It moves to `held_for: sale`, takes your date as its `request_date`, and the user account's `balance_sheet_model` moves to `held_for_sale`.
4. **The receivable joins that day's receivable sale**, and its amount is fixed.
5. **Lead settles the receivable sale** by debiting `purchase_amount` from your operating account. Receivable sale webhooks tell you when the sale is created, whether it settled, and whether it failed.

Three things to design around now:

* **The receivable sale is Lead-generated.** There is no call to create or accept one. Build reconciliation around the [receivable sale webhooks](/v2/products/receivable-sales/overview#what-you-can-do).
* **Settlement is all or nothing.** Your operating account must hold the full `purchase_amount` by 4:00pm CT on the sale's business day, or the **whole** sale fails, not just the loan that caused it.
* **On-sheet receivables are not returned by the Receivables API yet.** You can read a receivable once it is held for sale. Until then, the user credit balance is your view of the live position. See [Which receivables you can see](/v2/products/receivables/overview#which-receivables-you-can-see).

## Handling exceptions

| What happens | Signal | What to do |
| - | - | - |
| An entity isn't eligible for the role you need | `422 parameters_invalid` when you send `intended_eligibility`, or `failed_checks` on the response | Fix the data each failed check names, then `PATCH` the entity. See [Eligibility](/v2/products/entity/eligibility). |
| The balance-sheet model isn't permitted for your program | `422` on user account creation | This is a program configuration question, not a payload bug. Raise it with your Lead team. |
| The user account can't hold a user credit balance | `422` on user credit balance creation | The user account must be `active` and have a credit feature. Features are declared at creation, so open the user account with `credit_with_underwriting`. |
| A user credit transaction is missing a breakdown field or has the wrong sign | `422 parameters_invalid` | Send all three `amount_breakdown` fields, with the sign the type requires. |
| The user credit balance isn't active | `422` on posting a user credit transaction | Check the user credit balance's status before posting. |
| A retried request has a changed body | `422 idempotency_request_inconsistent` | An `Idempotency-Key` is bound to one body. Use a new key for a corrected request. |
| A repayment was reported wrongly | Your own reconciliation | Reverse it and post the correct user credit transaction. |
| The loan is charged off | Your own decision | Post a `charge_off` user credit transaction, then `close` with `status_reason: charged_off`. |

Every v2 error follows the shape on [Errors](/api-reference/using-the-api/errors-v2).

## Testing this flow in sandbox

<Note>
  **Sandbox availability.** The v2 endpoints in this guide are in preview and not yet in sandbox. Your Lead team will confirm when they reach sandbox for your program, ahead of production.
</Note>

Once the v2 endpoints are available in sandbox, you can run this flow end to end there. A funding stays `processing` until you call `POST /v2/fundings/{id}/advance`, which moves it to `posted` and creates the `funding` user credit transaction. Reconcile a run with the IDs returned along the way: the funding's `core_transaction_id` ties the draw to its core transaction, and `GET /v2/user_credit_transactions?funding_id={id}` returns the user credit transaction Lead posted for it.

See [Environments and testing](/core-concepts/platform/environments-and-testing).

## Related

[Fundings](/v2/products/fundings/overview) · [User Credit Balance](/v2/products/user-credit-balance/overview) · [User Credit Transaction](/v2/products/user-credit-transaction/overview) · [Receivables](/v2/products/receivables/overview) · [Files](/v2/products/files/overview) · [Platform Evolution](/core-concepts/platform/platform-evolution) · [Executing vs. reporting](/core-concepts/platform/executing-vs-reporting)

*This guide describes APIs in preview. If something here does not match what you see, contact your Lead team.*


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.