> ## 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 Your First Loan

> Create a borrower entity, submit an application, open a credit account, define loan terms on a subledger balance, and originate a funding.

### Before You Start

You will need:

* **Sandbox API credentials:** A `client_id` and `client_secret` provided by your Lead Technical Account Manager during kickoff.
* **curl:** Installed on macOS by default; `curl --version` should print something. Any HTTP client works.
* **A Funding FBO provisioned for your program:** Lead opens this during onboarding. The Funding API moves money into your Funding FBO when the Funding object posts.
* **Optional:** jq— for cleaner JSON output. Pipe responses through `| jq .` if you have it installed.

<Note>
  **Sandbox Only**

  Every example uses [api.sandbox.lead.bank](http://api.sandbox.lead.bank). The same calls work against [api.lead.bank](http://api.lead.bank) in production once your program is approved for go-live, but you should never run this guide against production credentials.
</Note>

<Tip>
  If you have not already done [Make Your First Payment API Call](/get-started/quickstart/make-your-first-payment-api-call), start there — it covers authentication, idempotency, and the Entity API in more depth.
</Tip>

## Steps

<Badge color="blue" size="lg" shape="pill" icon="watch">25 minutes</Badge>

We'll walk through originating a simple \$5,000 personal term loan to an individual borrower, repaid monthly over 24 months.

<AccordionGroup>
  <Accordion title="1: Get an Access Token">
    Same OAuth2 client credentials flow as the Payment Quickstart. Exchange your `client_id` and `client_secret` for a short-lived access token and pass it as a Bearer header on every subsequent request.

    ```text theme={null}
    curl -X POST https://api.sandbox.lead.bank/v1/oauth/token \
      -H 'Content-Type: application/json' \
      -d '{
        "grant_type": "client_credentials",
        "client_id": "YOUR_CLIENT_ID",
        "client_secret": "YOUR_CLIENT_SECRET",
        "scope": "entity/read_write application/read_write account/read_write subledger_balance/read_write funding/read_write"
      }'
    ```

    Save the access\_token value as a shell variable:

    ```text theme={null}
    export LEAD_TOKEN="eyJhbGciOiJSUzI1NiIs..."
    ```

    <Note>
      **Scopes**

      Lending workflows need broader scopes than payments. The scope list above covers everything in this guide.
    </Note>
  </Accordion>

  <Accordion title="2: Create the Borrower Entity">
    Every loan starts with an Entity for the borrower. We'll create an Individual with placeholder KYC and OFAC results so the sandbox accepts it.

    ```text theme={null}
    curl -X POST https://api.sandbox.lead.bank/v0/entities \
      -H "Authorization: Bearer $LEAD_TOKEN" \
      -H 'Content-Type: application/json' \
      -H 'Idempotency-Key: quickstart-loan-entity-001' \
      -d '{
        "type": "individual",
        "client_customer_id": "qs-borrower-001",
        "intended_roles": ["account_holder"],
        "risk_score": "low",
        "individual_details": {
          "first_name": "Ada",
          "last_name": "Lovelace",
          "date_of_birth": "1990-12-10",
          "identification_details": {
            "type": "us_entity",
            "tax_identification": { "type": "ssn", "value": "123456789" }
          },
          "contact_methods": [
            { "type": "email", "email": "ada@example.com" }
          ],
          "address_details": {
            "physical_address": {
              "line_1": "123 Analytical Engine Way",
              "city": "Brooklyn",
              "state": "NY",
              "postal_code": "11201",
              "country": "US"
            }
          }
        },
        "kyc_details": { "result": "passed", "screened_at": "2026-01-15T10:00:00Z" },
        "ofac_details": { "result": "passed", "screened_at": "2026-01-15T10:00:00Z" }
      }'
    ```

    Save the returned `id` (starts with `entity_`):

    ```text theme={null}
    export LEAD_ENTITY_ID="entity_abc123..."
    ```
  </Accordion>

  <Accordion title="3: Create the Application">
    The Application is your record of the underwriting decision. Lead relies on this data to fulfill critical compliance requirements — including Fair Lending audits and adverse action tracking under **Regulation B (ECOA)** and **Regulation V (FCRA)**, **Military Lending Act (MLA)** status verification, and **BSA/AML** recordkeeping. Applications are always created in a terminal status (`approved`, `declined`, or `canceled`). Lead does not track in-flight applications; you finalize the underwriting decision on your side, then create the API object when you have a definitive result.

    For our approved \$5,000 loan:

    ```text theme={null}
    curl -X POST https://api.sandbox.lead.bank/v0/applications \
      -H "Authorization: Bearer $LEAD_TOKEN" \
      -H 'Content-Type: application/json' \
      -H 'Idempotency-Key: quickstart-loan-app-001' \
      -d '{
        "client_application_id": "QS-LOAN-001",
        "status": "approved",
        "entities": {
          "account_holders": ["'$LEAD_ENTITY_ID'"]
        },
        "details": {
          "product_name": "Personal Term Loan",
          "credit": {
            "is_secured": false,
            "is_mla": false,
            "currency": "USD",
            "underwriting_grade": "A",
            "limit": 500000,
            "max_limit": 500000,
            "report": {
              "score": 760,
              "pulled_at": "2026-04-01T09:30:00Z",
              "source": "experian"
            }
          }
        },
        "decision": {
          "decided_at": "2026-04-01T10:00:00Z",
          "reason": "Approved based on credit profile and debt-to-income ratio."
        },
        "documents": [
          {
            "document_id": "credit-pull-consent-ada-20260401",
            "type": "credit_pull_consent",
            "consented_at": "2026-04-01T09:25:00Z"
          }
        ]
      }'
    ```

    Save the returned `id` (starts with `application_`):

    ```text theme={null}
    export LEAD_APPLICATION_ID="application_xyz789..."
    ```

    <Note>
      **Documents**

      Document IDs reference filenames in your `/documents` SFTP directory. For this quickstart you can use any string — sandbox does not verify the file exists. In production, the file must be delivered to SFTP before referencing it.
    </Note>
  </Accordion>

  <Accordion title="4: Create the Credit-Enabled Account">
    The Account is the legal account the borrower holds with Lead. For credit products, the Account is required and must reference an `application_id`. Capabilities tell Lead what type(s) of Balances the Account will hold — `credit_with_underwriting` for products requiring a credit Balance with an underwriting component (e.g., a loan with an application) and `credit_without_underwriting` for products requiring a credit Balance but do not have an underwriting component (e.g., courtesy overdraft).

    ```text theme={null}
    curl -X POST https://api.sandbox.lead.bank/v0/accounts \
      -H "Authorization: Bearer $LEAD_TOKEN" \
      -H 'Content-Type: application/json' \
      -H 'Idempotency-Key: quickstart-loan-account-001' \
      -d '{
        "application_id": "'$LEAD_APPLICATION_ID'",
        "capabilities": ["credit_with_underwriting"],
        "entities": {
          "account_holders": ["'$LEAD_ENTITY_ID'"]
        },
        "details": {
          "product_name": "Personal Term Loan",
          "credit": {
            "is_secured": false,
            "is_mla": false,
            "underwriting_grade": "A",
            "currency": "USD",
            "available_credit": 500000,
            "limit": 500000,
            "max_limit": 500000
          }
        },
        "documents": [
          {
            "document_id": "loan-agreement-ada-20260401",
            "type": "loan_agreement",
            "displayed_at": "2026-04-01T10:05:00Z"
          }
        ]
      }'
    ```

    Save the returned `id` (starts with `account_`):

    ```text theme={null}
    export LEAD_ACCOUNT_ID="account_def456..."
    ```
  </Accordion>

  <Accordion title="5: Create the Subledger Balance">
    This is where the loan actually comes into existence. The Subledger Balance defines all the terms — amount, maturity, repayment schedule, interest — and is what Lead's ledger tracks throughout the life of the loan. When you create it, every outstanding amount (principal, interest, fees) is zero because no draw has happened yet.

    For a term loan, use `structure: non_revolving` — there's a fixed loan amount and repayments do not restore available credit. Use `structure: revolving` instead if you're opening a line of credit or credit card where the borrower can re-draw after repayment.

    ```text theme={null}
    curl -X POST https://api.sandbox.lead.bank/v0/subledger_balances \
      -H "Authorization: Bearer $LEAD_TOKEN" \
      -H 'Content-Type: application/json' \
      -H 'Idempotency-Key: quickstart-loan-balance-001' \
      -d '{
        "account_id": "'$LEAD_ACCOUNT_ID'",
        "client_subledger_balance_name": "Personal Term Loan - Ada Lovelace",
        "currency_code": "USD",
        "type": "credit",
        "details": {
          "structure": "non_revolving",
          "is_interest_based": true,
          "interest_rate": "9.990000",
          "effective_apr": "10.250",
          "autopay_method": "ach",
          "expected_maturity_date": "2028-04-01",
          "max_funding_amount": 500000,
          "expected_finance_charge_amount": 53400,
          "term": { "value": 24, "unit": "months" },
          "repayment_details": [
            {
              "expected_payment_frequency": "monthly",
              "expected_number_of_payments": 24,
              "expected_first_payment_date": "2026-05-01",
              "expected_first_payment_amount": 23058,
              "expected_last_payment_date": "2028-04-01",
              "expected_last_payment_amount": 23058,
              "expected_payment_amount": 23058
            }
          ]
        }
      }'
    ```

    Save the returned `id` (starts with `subledger_balance_`):

    ```text theme={null}
    export LEAD_BALANCE_ID="subledger_balance_ghi789..."
    ```

    <Note>
      **Why Balance and Funding are Decoupled**

      You define loan terms once (Balance) but can draw funds against them many times (Funding). For a term loan this usually means one draw at origination, but for a line of credit you'll create multiple Funding objects against the same Balance throughout its life.
    </Note>
  </Accordion>

  <Accordion title="6: Create the Funding">
    The Funding object instructs Lead to move principal from a Lead GL into your Funding FBO. Once posted, you can disburse those funds externally via ACH, wire, or instant payment — but that's a separate step on a payment rail.

    For this term loan, the borrower is taking the full \$5,000 as a single draw. There is no merchant origination fee (this isn't a BNPL product) and nothing is withheld for later disbursement.

    ```text theme={null}
    curl -X POST https://api.sandbox.lead.bank/v0/fundings \
      -H "Authorization: Bearer $LEAD_TOKEN" \
      -H 'Content-Type: application/json' \
      -H 'Idempotency-Key: quickstart-loan-funding-001' \
      -d '{
        "subledger_balance_id": "'$LEAD_BALANCE_ID'",
        "currency_code": "USD",
        "principal": {
          "external_disbursement_amount": 500000,
          "withheld_amount": 0,
          "merchant_origination_fee_amount": 0
        },
        "metadata": {
          "client_draw_id": "QS-DRAW-001"
        }
      }'
    ```

    The response returns an id that starts with `funding_` and an initial `status` of `processing`. Save it:

    ```text theme={null}
    export LEAD_FUNDING_ID="funding_jkl012..."
    ```

    <Note>
      **Principal Components**

      For a simple personal term loan, the entire principal goes to `external_disbursement_amount`. The other two fields cover other use cases: `withheld_amount` is for funds you'll disburse later and `merchant_origination_fee_amount` is for merchant fees (typically in BNPL loans).
    </Note>
  </Accordion>

  <Accordion title="7: Retrieve the Funding">
    Funding objects move asynchronously from `processing` to `posted` (or `rejected`). Poll the Funding endpoint — or listen for the `funding.posted` webhook event — to confirm.

    ```text theme={null}
    curl https://api.sandbox.lead.bank/v0/fundings/$LEAD_FUNDING_ID \
      -H "Authorization: Bearer $LEAD_TOKEN"
    ```

    When status flips to posted, the \$5,000 is sitting in your Funding FBO and ready to be disbursed externally.

    <Note>
      **Sandbox**

      Funding does not auto-advance in sandbox. Use `POST /v0/fundings/{id}/advance` to move the Funding from processing → posted (or processing → rejected) so you can test your webhook handlers and downstream disbursement logic.
    </Note>
  </Accordion>
</AccordionGroup>

## What's Next

* **Disburse Funds Externally**
  Now that \$5,000 is in your Funding FBO, send it to the borrower via ACH, wire, or instant payment.
* **Webhooks**
  Listen for `funding.posted` and `funding.rejected` instead of polling. Configure your endpoint per [Webhooks & Events.](/api-integrations/webhooks)
* **Service the Loan**
  Report ongoing activity — interest accrual, principal repayments, fees — against the Subledger Balance via the Balance and Transaction files. See [Balance Reconciliation](/file-integrations/balances-and-transactions/balance-reconciliation).
* **Multi-Draw Use Cases**
  For multi-draw term loans or lines of credit, create additional Funding objects against the same Subledger Balance over its life. The sum of all `principal.*` amounts across posted and processing Fundings cannot exceed the Balance's `max_funding_amount` (for `non_revolving`) or the available credit (for `revolving`).
* **Closing the Loan**
  Once the balance is paid off and the loan is in a terminal status, update the Subledger Balance to `closed` via the Balance file. Closure requires all outstanding amounts to be zero.

## Troubleshooting

| <h4>Error</h4>                                           | <h4>Potential Fix</h4>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| :------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **401 Unauthorized**                                     | <ul><li>Token expired (24h default). Run Step 1 again.</li><li>Authorization header malformed. Should be exactly `Authorization: Bearer <token>` — note the space and capitalization.</li></ul>                                                                                                                                                                                                                                                                                                                                                                             |
| **422 Unprocessable Entity on Create Application**       | <ul><li>`details.decision.adverse_action_notice` missing for a declined status. Required when the decision is declined.</li><li>`credit.limit` exceeds `credit.max_limit`. The assigned limit cannot be higher than what underwriting approved.</li><li>`client_application_id` starts with the reserved prefix `application_`. Pick a different prefix on your side.</li></ul>                                                                                                                                                                                             |
| **422 Unprocessable Entity on Create Entity**            | <ul><li>`application_id` missing. Required for credit accounts. The Account must reference the Application that authorized the credit.</li><li>`details.credit.available_credit` greater than `details.credit.limit`. Available credit cannot exceed the current limit.</li><li>Missing `authorized_signers` when account holders are commercial. Required for business or sole prop account holders.</li></ul>                                                                                                                                                             |
| **422 Unprocessable Entity on Create Subledger Balance** | <ul><li>`type` is anything other than credit. Lending workflows require `credit`-type balances; deposit is not valid here.</li><li>`details.structure` missing or invalid. Must be non\_revolving for term loans or revolving for lines of credit and credit cards.</li><li>`details.expected_maturity_date`, `details.max_funding_amount`, `details.term`, or `details.expected_finance_charge_amount` missing for a `non_revolving` structure. All four are required.</li><li>`details.is_interest_based` missing. Required for credit-type Subledger Balances.</li></ul> |
| **422 Unprocessable Entity on Create Funding**           | <ul><li>Sum of `external_disbursement_amount` + `withheld_amount` is 0. At least one of the two must be greater than 0.</li><li>`merchant_origination_fee_amount` is greater than or equal to `external_disbursement_amount` + `withheld_amount`. The merchant fee must be less than total principal.</li><li>Total funding across all posted and processing Fundings against this Subledger Balance exceeds `max_funding_amount`. Only relevant for `non_revolving` structures.</li></ul>                                                                                  |
| **409 Conflict**                                         | <ul><li>You reused an Idempotency-Key with a different request body.</li><li>Either send the same body (and you'll get the original response back), or pick a new key.</li></ul>                                                                                                                                                                                                                                                                                                                                                                                            |
