# Onboard an installment loan

This guide walks you from credentials-in-hand to an originated, activated, funded installment loan, using the same public API you call in production. Run every call in this guide against the sandbox host. By the end you have an `active` installment loan that has disbursed principal and, optionally, taken its first payment.

Do this in the sandbox. For how the sandbox is provisioned, the environment model, and the payment failure path, see [Sandbox and test data](/getting-started/sandbox-and-test-data) — this guide does not restate them. It covers line-of-credit onboarding nowhere; for a line of credit and its draws, see [Onboard a line of credit](/getting-started/use-cases/onboard-loc).

## Prerequisites

- **An API key.** Sent in the `X-API-KEY` header on every request. See [Credentials and access](/getting-started/credentials-and-access).
- **The sandbox base URL.** `https://sandboxapi.peach.finance/api`. See [Portals and environments](/getting-started/portals-and-environments) for the host model.
- **An installment `loanTypeId`.** Configured by Peach and handed to you during onboarding — you cannot create or list loan types through the public API. See [Credentials and access](/getting-started/credentials-and-access). This guide uses the placeholder `LT-AAAA-BBBB`.
- **The borrower, loan, and loan-type concepts.** See [Core concepts](/getting-started/core-concepts).


Your loan type must be configured before any of these calls succeed. Loan creation resolves the loan type's asset type and the company's default investor; a missing asset type or a company with no default investor (and no `investors` passed in the request) is rejected.

## The onboarding sequence

Four calls take a borrower to a funded loan. The first three are required; the payment is optional.


```mermaid
sequenceDiagram
    participant You as Your application
    participant Peach as Peach API
    You->>Peach: POST /people (create borrower)
    Peach-->>You: personId
    You->>Peach: POST /people/{personId}/loans (status: originated)
    Peach-->>You: loanId (status originated)
    You->>Peach: POST /people/{personId}/loans/{loanId}/activate
    Peach-->>You: loan status active, principal disbursed
    You->>Peach: POST /people/{personId}/loans/{loanId}/transactions (optional)
    Peach-->>You: transaction against the active loan
```

## Step 1: Create the borrower

Create the person the loan will belong to.


```http
POST https://sandboxapi.peach.finance/api/people
X-API-KEY: <YOUR-API-KEY>
Content-Type: application/json

{
  "name": {
    "firstName": "Ada",
    "lastName": "Lovelace"
  },
  "identity": {
    "identityType": "SSN",
    "value": "000000000"
  }
}
```

### Required fields

| Field | Required | Notes |
|  --- | --- | --- |
| `name.firstName`, `name.lastName` | Yes | A person borrower must have a name. Omitting `name` returns a 400. |
| `identity` | By default | Required unless your company sets `requireBorrowerIdentity` to `false`. When required, `identityType` and `value` are both required. |
| `borrowerType` | No | Defaults to `person`. Set to `business` for a business borrower (which requires `businessDetails` instead of `name`). |
| `status` | No | Defaults to `active`. |
| `dateOfBirth`, `externalId` | No | Optional. |


### Verify

The response returns a person `id` (for example, `BO-AAAA-BBBB`) with `status: active`. Save the `id` — it is the `personId` in every subsequent call.

This is also your first authenticated call, so treat a successful response as a smoke test: it confirms your API key, the sandbox host, and the `X-API-KEY` header are all correct.

## Step 2: Create the loan

Create an installment loan against your `loanTypeId`. Create it in `originated` status: the loan is signed and originated but does not accrue interest until you activate it in Step 3.


```http
POST https://sandboxapi.peach.finance/api/people/{personId}/loans
X-API-KEY: <YOUR-API-KEY>
Content-Type: application/json

{
  "loanTypeId": "LT-AAAA-BBBB",
  "servicedBy": "creditor",
  "status": "originated",
  "atOrigination": {
    "amountFinanced": 5000,
    "duration": 12,
    "paymentFrequency": "monthly",
    "originationLicense": "nationalBank",
    "originatingCreditorName": "Example Bank",
    "interestRates": [
      { "interestType": "absolute", "days": null, "rate": 0.0899 }
    ],
    "personAddress": {
      "addressLine1": "1 Main St",
      "city": "Houston",
      "state": "TX",
      "postalCode": "77002",
      "country": "US"
    }
  }
}
```

### Required fields

| Field | Required | Notes |
|  --- | --- | --- |
| `loanTypeId` | Yes | Your Peach-configured installment loan type. |
| `servicedBy` | Yes | Who services the loan. Use `creditor` for a loan serviced on the Peach platform. Values: `creditor`, `thirdPartyServicer`, `debtCollectionAgency`. |
| `status` | Yes | New loans accept only `pending`, `originated`, or `declined`. Use `originated` to originate now and activate next. |
| `atOrigination.amountFinanced` | Yes | Amount the borrower receives, minus upfront fees. |
| `atOrigination.duration` | Yes | Number of `paymentFrequency` periods (for example, `12` monthly periods). |
| `atOrigination.paymentFrequency` | Yes | `weekly`, `everyTwoWeeks`, `twiceMonthly`, `monthly`, or `singleTerm`. |
| `atOrigination.originationLicense` | Yes | `nationalBank`, `stateLicense`, `bankSubsidiary`, or `stateBank`. |
| `atOrigination.originatingCreditorName` | Yes | Name shown to the borrower in communications. |
| `atOrigination.interestRates` | Yes | Array of rate periods; the final entry must have `days: null`. |
| `atOrigination.personAddress` **or** `atOrigination.personAddressId` | Yes | An address is required to create the loan. See below. |


For the complete field contract — every optional origination parameter, fee, and promo structure — see the [Create loan endpoint](/api-docs/api-public/) in the API Reference.

### An address is required to originate

An installment loan cannot be created without an address. In the create-loan request you must supply either `atOrigination.personAddress` (an inline address, as shown above) or `atOrigination.personAddressId` (the ID of an existing address contact on the borrower). Supplying neither returns a 400; supplying both is also rejected.

Address is a create-loan requirement, not an activation gate
The address requirement is enforced at loan creation, not at activation, and it is enforced in code rather than declared in the OpenAPI spec (both address fields are optional in the schema). You do not need to create a separate address contact first — inlining `personAddress` in the origination request satisfies the requirement. But an address value must be present to originate the loan.

To reference an existing address instead of inlining one, first create an address contact on the borrower — `POST /people/{personId}/contacts` with `contactType: address` — then pass the returned contact `id` as `atOrigination.personAddressId` in the create-loan request. The `personAddressId` must resolve to an address-type contact on that borrower.

### Verify

The response returns a loan `id` (for example, `LN-AAAA-BBBB`) with `status: originated`. Save the `id` — it is the `loanId` for activation.

## Step 3: Activate and disburse the loan

Activate the originated loan to start it. Activation is what disburses principal and begins interest accrual. The request body is optional.


```http
POST https://sandboxapi.peach.finance/api/people/{personId}/loans/{loanId}/activate
X-API-KEY: <YOUR-API-KEY>
Content-Type: application/json

{}
```

The loan must be in `originated` status to activate. Calling activate on a loan in any other status returns a 400. (Step 2 created the loan in `originated`, so it is ready.)

On activation, Peach creates the active loan schedule and periods, creates the expected payments, creates the obligation for the first period, sets the active address at origination, starts monitoring the borrower, writes the ledger entries for activation — including disbursing principal from cash to accounts receivable — and fires the loan-activated event.

Beyond disbursement, the activation call itself assesses fees only when your loan type configures them: an origination fee is booked unless the loan type charges it at origination, and any service fee is written at activation. Activation does not enrol autopay and does not itself deliver a borrower notice — it fires a `loan.activated` event, and any activation-notice delivery is a downstream, configuration-gated step handled by Peach's communications processing.

Activation amortizes the loan and builds its schedule. This guide does not document schedule computation or the standalone amortization-preview utility; see the [amortization utility](/loan-lifecycle/amortization-utility) documentation.

### Verify

Re-fetch the loan with `GET /people/{personId}/loans/{loanId}` and confirm `status` is now `active`. To confirm the disbursement moved money, check the loan balances — a disbursed loan carries an outstanding principal balance equal to the amount financed.

## Step 4 (optional): Take the first payment

A payment is not required to complete origination, but you will usually want to exercise one. Create a One Time Payment transaction against the loan. A payment transaction is valid only when the loan is `active` (also `accelerated` or `chargedOff` in specific cases), which is why activation must come first.


```http
POST https://sandboxapi.peach.finance/api/people/{personId}/loans/{loanId}/transactions
X-API-KEY: <YOUR-API-KEY>
Content-Type: application/json
```

To move money you attach a payment instrument — a card or bank account — to the borrower and reference it on the transaction. For the transaction contract, the test instruments and values, and how to drive a payment to a declined outcome, see [Sandbox and test data](/getting-started/sandbox-and-test-data). This guide does not restate them.

A One Time Payment requires a payment instrument. The create-transaction flow builds a one-time payment with a mandatory payment-instrument requirement and rejects the call when no instrument resolves from the `paymentInstrumentId` you send, so you cannot record a One Time Payment without one. (Which specific sandbox instrument values to use is a separate question — see [Sandbox and test data](/getting-started/sandbox-and-test-data).)

## Error handling

| Response | Cause | Resolution |
|  --- | --- | --- |
| `400` "Name is required when creating a person" | `POST /people` sent with no `name` for a person borrower. | Include `name.firstName` and `name.lastName`, or set `borrowerType` to `business`. |
| `400` "Identity required when creating a borrower for this company" | `identity` omitted while your company requires it. | Include `identity.identityType` and `identity.value`, or ask Peach to set `requireBorrowerIdentity` to `false`. |
| `400` "a personAddressId or personAddress is required to create a loan" | `POST /people/{personId}/loans` sent with no address. | Add `atOrigination.personAddress` or `atOrigination.personAddressId`. |
| `400` "New loans can only be created in status: ..." | `status` not one of `pending`, `originated`, `declined`. | Create the loan in `originated`, then activate. |
| `400` "... is in an incorrect status for activation" | Activate called on a loan not in `originated` status. | Confirm the loan is `originated` before activating; a loan already `active` is activated. |


## Testing

Run this whole sequence against the sandbox host and confirm each step's verify condition. For seeding wider test data, the test payment instruments, and exercising the payment failure path, see [Sandbox and test data](/getting-started/sandbox-and-test-data).

## Production considerations

The request and response contracts are identical between sandbox and production — the only difference is the host you call and the credentials you use. When you move to production, point the same calls at the production base URL with production credentials. See [Portals and environments](/getting-started/portals-and-environments) for the host model and [Credentials and access](/getting-started/credentials-and-access) for environment-scoped keys.

## Next steps

- [Onboard a line of credit](/getting-started/use-cases/onboard-loc) — The equivalent recipe for a revolving line of credit and its draws.
- [Sandbox and test data](/getting-started/sandbox-and-test-data) — Test instruments, magic values, and the payment failure path.
- [Core concepts](/getting-started/core-concepts) — The borrower, loan, and loan-type model behind these calls.