Skip to content
Last updated

Onboard a line of credit

This guide walks you from credentials-in-hand to an activated, revolving line of credit in the sandbox, then opens a draw and records a purchase against it, using the same public API you call in production. Run every call against the sandbox host. By the end you have an active line of credit with a credit limit, an active draw, and a purchase recorded against that draw.

This is the line-of-credit sibling of Onboard an installment loan. The borrower step is identical and is not re-explained here; everything from the loan-create step onward diverges, because a line of credit is a different schema (NewLineOfCredit, not NewInstallment) with a different money model — a revolving credit limit drawn against over time, not a fixed amount disbursed once. Where this guide overlaps the installment recipe it links to it rather than restating.

Do this in the sandbox. For how the sandbox is provisioned, the environment model, and the payment failure path, see Sandbox and test data — this guide does not restate them. The purchase decline path is different from the payment decline path, and this guide documents it below.

Prerequisites

  • An API key. Sent in the X-API-KEY header on every request. See Credentials and access.
  • The sandbox base URL. https://sandboxapi.peach.finance/api. See Portals and environments for the host model.
  • A line-of-credit loanTypeId. Configured by Peach and handed to you during onboarding — you cannot create or list loan types through the public API, and a line-of-credit loan type is a distinct product template from an installment one. See Credentials and access. This guide uses the placeholder LT-AAAA-BBBB.
  • The borrower, loan, and loan-type concepts. See Core concepts.

Your loan type must be configured before any of these calls succeed, and it must be a line-of-credit type: loan creation rejects a request whose type does not match the loan type's configured type. Creation also 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 same gate the installment recipe describes.

The onboarding sequence

Six calls take a borrower to a line of credit with a purchase recorded against it. The borrower, line, and activation are the origination; the draw and purchase exercise the revolving surface an installment loan does not have.

Peach APIYour applicationPeach APIYour applicationPOST /people (create borrower)personIdPOST /people/{personId}/loans (type lineOfCredit, status originated)loanId (status originated)POST /people/{personId}/loans/{loanId}/activateline status active, credit limit establishedPOST /people/{personId}/loans/{loanId}/draws (status originated)drawId (status originated)POST /people/{personId}/loans/{loanId}/draws/{drawId}/activatedraw status activePOST /people/{personId}/loans/{loanId}/draws/{drawId}/purchasespurchase recorded against the draw
Peach APIYour applicationPeach APIYour applicationPOST /people (create borrower)personIdPOST /people/{personId}/loans (type lineOfCredit, status originated)loanId (status originated)POST /people/{personId}/loans/{loanId}/activateline status active, credit limit establishedPOST /people/{personId}/loans/{loanId}/draws (status originated)drawId (status originated)POST /people/{personId}/loans/{loanId}/draws/{drawId}/activatedraw status activePOST /people/{personId}/loans/{loanId}/draws/{drawId}/purchasespurchase recorded against the draw

Step 1: Create the borrower

Create the person the line of credit will belong to. This step is identical to the installment recipe — same endpoint, same required fields (a person borrower needs a name; identity is required unless your company disables it). See Onboard an installment loan → Create the borrower for the request body and field table; it is not repeated here.

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" }
}

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.

Step 2: Create the line of credit

Create the line against your line-of-credit loanTypeId. Set type to lineOfCredit and create it in originated status: the line is originated but does not start until you activate it in Step 3.

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

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

Required fields

FieldRequiredNotes
typeYesMust be lineOfCredit. Must match your loan type's configured type, or the request is rejected.
loanTypeIdYesYour Peach-configured line-of-credit loan type.
servicedByYesWho services the line. Use creditor for a line serviced on the Peach platform. Values: creditor, thirdPartyServicer, debtCollectionAgency.
statusYesNew loans accept only pending, originated, or declined. Use originated to originate now and activate next.
newDrawsAllowedYesLine-of-credit only. Whether the borrower can open additional draws on the line. Required on the line schema and read unconditionally by the create handler.
atOrigination.creditLimitAmountYesLine-of-credit only. The revolving credit limit — the maximum the borrower can utilize across draws. There is no amountFinanced and no duration on a line; those installment fields do not apply.
atOrigination.paymentFrequencyYesweekly, everyTwoWeeks, twiceMonthly, or monthly. Note singleTerm is not valid for a line of credit (it is for installment).
atOrigination.originationLicenseYesnationalBank, stateLicense, bankSubsidiary, or stateBank.
atOrigination.originatingCreditorNameYesName shown to the borrower in communications.
atOrigination.interestRatesYesArray of rate periods; the final entry must have days: null.
atOrigination.personAddress or atOrigination.personAddressIdYesAn address is required to create the loan. See below.

For the complete field contract — every optional origination parameter, fee, grace-period, and promo structure — see the Create loan endpoint in the API Reference.

An address is required to originate

An address requirement applies to the line of credit exactly as it does to an installment loan, and for the same reason: the create-loan handler calls extract_address_fields_for_create_loan unconditionally for every loan create, regardless of type, and that function rejects a request that carries neither atOrigination.personAddress nor atOrigination.personAddressId. This was re-verified independently against the line-of-credit path — it is the same code gate, not an assumption carried over from the installment recipe.

Address is a create-loan requirement, not an activation gate

As with installment loans, the address requirement is enforced at line creation, not at activation, and it is enforced in code rather than declared in the OpenAPI spec (both address fields are optional on the LineOfCredit schema). You do not need to create a separate address contact first — inlining personAddress in the origination request satisfies the requirement. Supplying both personAddress and personAddressId is rejected.

Verify

The response returns a loan id (for example, LN-AAAA-BBBB) with type: lineOfCredit and status: originated. Save the id — it is the loanId for activation and for every draw and purchase call.

Step 3: Activate the line of credit

Activate the originated line to start it. The request body is optional. The line must be in originated status to activate; calling activate on a line in any other status returns a 400. This is the same activation handler and the same status guard the installment recipe uses — the endpoint is shared.

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

{}
Activating a line does not disburse money

This is the central divergence from installment. When you activate an installment loan, Peach disburses principal — it moves the amount financed from cash to accounts receivable. When you activate a line of credit, no principal is disbursed: the disbursement ledger entry is guarded to installment loans only. Line activation establishes the revolving credit line and its credit limit and starts the line; money is utilized later, through draws and purchases (Steps 4–6). A line has a credit limit, not an amount financed.

As with installment, activating a line assesses fees only when your loan type configures them — an origination or draw fee, and any service or membership fee marked to charge at activation. Activation does not open a draw (you create draws explicitly, in Step 4), 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.

Verify

Re-fetch the line with GET /people/{personId}/loans/{loanId} and confirm status is now active. The line carries a credit limit (current.creditLimitAmount) but no outstanding principal balance yet — nothing has been drawn.

Step 4: Open a draw

A draw is the container credit is utilized through. Create it against the active line. The draw's status is required; create it in originated to activate it next.

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

{
  "status": "originated",
  "drawType": "regularPurchase",
  "atOrigination": {
    "interestRates": [
      { "interestType": "absolute", "days": null, "rate": 0.1899 }
    ]
  }
}

Required fields

FieldRequiredNotes
statusYesDraws accept only pending or originated (plus active when the loan type is not managed by Peach, and declined for a non-migrating line). Use originated, then activate.
drawTypeNobalanceTransfer, cashAdvance, or regularPurchase. Drives how the system auto-associates card transactions with the draw.
atOriginationConditionalOptional as a whole, but if supplied for an amortized draw it carries its own rate and min-payment fields. The full draw origination contract (amortization method, minPaymentCalculation) is a larger surface — see the API Reference and the note below.

The line must be active, not closed, and newDrawsAllowed must be true for a draw to be created. A draw created against an inactive line, a closed line, or a line with newDrawsAllowed: false returns a 400.

atOrigination is optional on a draw. The draw schema requires only status (see above), and the create handler reads atOrigination with an empty-object default, so a bare {"status": "originated"} draw is accepted; minPaymentCalculation is required only when you do supply atOrigination. When you omit the amortization inputs, the draw inherits its expected-periodic-payment method from the loan type. A card-style, non-amortized draw does not need an atOrigination block.

Draw amortization and schedule computation are out of scope here, the same as the installment schedule is; see the amortization utility documentation.

Verify

The response returns a draw id (for example, DR-AAAA-BBBB) with status: originated. Save the id — it is the drawId for activation and for the purchase call.

Step 5: Activate the draw

Activate the draw to start it. The draw-activate endpoint resolves to the same handler as loan activation, so the same guard applies: the draw must be in originated status.

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

{}

Verify

Re-fetch the draw with GET /people/{personId}/loans/{loanId}/draws/{drawId} and confirm status is active. An active draw can now have purchases recorded against it.

Step 6: Record a purchase against the draw

Utilization happens through purchases. Record a purchase against the active draw. A regular purchase requires only an amount and at least one of purchaseDetails.description or purchaseDetails.merchantName; the draw must be active (for a regular purchase without a prior authorization). By default a purchase is created in settled status, which increases the draw balance and posts to the ledger.

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

{
  "amount": 100,
  "type": "regular",
  "status": "settled",
  "purchaseDetails": {
    "merchantName": "Example Merchant"
  }
}

Required fields

FieldRequiredNotes
amountYesThe purchase amount (minimum 0).
purchaseDetails.description or purchaseDetails.merchantNameYesAt least one must be present, or the request is rejected.
typeNoregular (default), refund, or cashBack. A regular purchase increases the draw balance.
statusNoDefaults to settled. Accepts a purchase status (see below). settled and pending post to the ledger and increase the draw balance; declined does not.
cardIdNoThe card used for the purchase. If it cannot be resolved, the purchase is still created and validation.cardIdMissing is set in the response.

A settled purchase posts to the ledger at creation, with no separate settlement or processor step. Peach is the system of record for line-of-credit purchases: for a regular purchase the create call writes the ledger entries directly and emits the balance-change event, rather than routing through a card processor the way a card payment does. A pending purchase posts the same way; a declined purchase is record-keeping only and never posts.

Verify

Fetch the purchases on the draw with GET /people/{personId}/loans/{loanId}/draws/{drawId}/purchases and confirm the purchase is present in settled status. Then check the draw balances — a settled purchase increases the draw's outstanding balance by the purchase amount, and the line's utilization rises correspondingly.

Purchase declines are not payment declines

A declined purchase and a declined payment are two different objects with two different mechanisms. Do not model them the same way.

A payment decline is a runtime outcome. A card payment (a transaction) is adjudicated by the processor; when it is declined, the transaction lands in TransactionStatus.Failed with the failure reason CardDeclined. There is no literal "declined" transaction status — a decline is a Failed transaction plus a reason code. That path, its CyberSource test-host routing, and how to drive it are documented in Sandbox and test data → Exercising the decline and failure path; this guide does not restate it.

A purchase decline is a status you set. PurchaseStatus has a literal Declined member. Peach is the system of record for line-of-credit purchases — your platform (or its card processor) has already adjudicated the authorization, and you record the outcome, including a decline, into Peach. You create or transition a purchase to declined directly through the API: pass "status": "declined" (with an optional declineReason) on the create call, or transition an existing pending/authorized purchase to declined. A declined purchase is record-keeping only — it never posts to the ledger and does not increase the draw balance when created that way.

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

{
  "amount": 100,
  "type": "regular",
  "status": "declined",
  "declineReason": "insufficientCredit",
  "purchaseDetails": { "merchantName": "Example Merchant" }
}
Payment declinePurchase decline
ObjectTransactionPurchase
StatusFailed (no literal "declined")Declined (literal enum member)
Extra fieldfailureReason: CardDeclineddeclineReason
Set byThe processor at runtimeYou, as system of record
Ledger effectNo successful money movementNone — record-keeping only
Where documentedSandbox and test dataThis page

Error handling

ResponseCauseResolution
400 "Cannot create loan of type ... with configuration for type ..."type in the request does not match the loan type's configured type.Use a line-of-credit loanTypeId and set type: lineOfCredit.
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 line in originated, then activate.
400 "... is in an incorrect status for activation"Activate called on a line (or draw) not in originated status.Confirm the object is originated before activating.
400 "Cannot create draws on inactive line of credit."Draw created before the line was activated.Activate the line (Step 3) first.
400 "New draws not allowed on this loan."Draw created while the line has newDrawsAllowed: false.Create the line with newDrawsAllowed: true, or update the line.
400 "Cannot create a purchase on an inactive line."Regular purchase recorded before the line/draw was active.Activate the line and the draw first; a declined purchase is exempt on a closed/terminal line.
400 "At least one of the attributes, 'description' or 'merchantName' must be passed."Purchase created with an empty purchaseDetails.Include purchaseDetails.description or purchaseDetails.merchantName.

Testing

Run this whole sequence against the sandbox host and confirm each step's verify condition. To exercise both decline paths: record a purchase with "status": "declined" (the Step 6 variant above) to confirm your integration reads PurchaseStatus.Declined, and separately drive a payment transaction to a declined outcome per Sandbox and test data. For seeding wider test data and the test payment instruments, see 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 for the host model and Credentials and access for environment-scoped keys.

Next steps

  • Onboard an installment loan — The fixed-amount sibling of this recipe; start there for the installment comparison and the shared borrower step.
  • Sandbox and test data — Test instruments, magic values, and the payment failure path (distinct from the purchase decline above).
  • Core concepts — The borrower, loan, draw, and purchase model behind these calls.