Integrate with the LoanVault API in one afternoon
Send us a client's estimated settlement details, get a pre-approval decision, then send the final settled amounts so the client can complete their loan. Everything is a simple JSON REST API with OAuth 2.0 sign-in and webhook notifications.
What you will build
This guide is for debt settlement companies connecting their system to the LoanVault API, provided by NewLine.ai, on behalf of our client, Credologi. Your system makes three kinds of calls and listens for one kind of event:
The basics
| Topic | Detail |
|---|---|
| Environments | Sandbox: https://stage-backend.newline.ai · Production: https://backend.newline.ai. The URL you call decides whether the request is test or live. Sandbox never touches live data. |
| Format | JSON in, JSON out, including errors. HTTPS only. |
| Status codes | 200 on success, including an application that is created but comes back Ineligible. 4xx on failures. The status field in the body (created, modified, ok, failed) tells you the outcome. |
| Getting updates | Use webhooks to learn when an application changes stage. Use Get application details only for occasional, on-demand lookups. Do not poll it for status. |
| Dates | ISO 8601: YYYY-MM-DD or YYYY-MM-DDTHH:MM. |
| Credentials | Email Jason Marone to request a client ID and secret. |
| Estimates | Estimated settlement and fee amounts follow formulas established by the client (Credologi). |
Go-live checklist
Work top to bottom. Your progress is saved in this browser.
Authentication
We use OAuth 2.0 machine-to-machine (client credentials). Exchange your client ID and secret for a bearer token, then send that token in the Authorization header of every API call.
expires_in: 3600). Store it and reuse it until it expires. Do not request a new token on every API call.refresh_token, but you do not need it. When your access token is close to expiring, request a new one with your client ID and secret.Response
Use the token
| Environment | Token URL | API base URL |
|---|---|---|
| Sandbox | https://stage-backend.newline.ai/oauth/token | https://stage-backend.newline.ai |
| Production | https://auth.newline.ai/oauth/token | https://backend.newline.ai |
How the 2-stage flow works
Debt settlement loans are pre-approved on estimated amounts, before the final settled amounts are known. Once you have the final numbers, you update the same application so the client can finish.
1. POST pre-approval
Send borrower info plus estimated settlement balance and fees.
2. Underwriting
Application is approved or declined. Approved applications move to PreApproved and are locked.
3. Wait for webhook
ApplicationStageUpdated with data.stage = "PreApproved".
4. PATCH final values
Send final settled amounts and fees. The application unlocks.
5. Client completes
The borrower re-enters the loan, re-verifies info, submits. Re-underwritten, final decision. LoanVault emails the client the link for their current stage.
Submit a loan application for pre-approval
Create the application using estimated settlement amounts and estimated remaining settlement fees.
settlement.paymentsMade on every POST and PATCH. We ask for more than we need to cover differences in draft dates. To be eligible, the client must have made at least 6 payments in the last 6 months. Otherwise the application is created, but its stage is Ineligible (see the response below).Fields marked * are required. See the full field reference, or paste your own body into the payload validator before sending.
Request body
Responses
loanNumber. You need it for the PATCH call. Your externalId is echoed back so you can match records.Update the application with final settlement amounts
After you receive a PreApproved webhook, send the final settled amounts and final remaining fees. The request has the same shape as the pre-approval submission.
Replace {loanNumber} with the loan number returned from the POST.
PreApproved. Wait for the PreApproved webhook before you send it. At any other stage the API returns the error shown below.Error: application is not PreApproved
What typically changes between POST and PATCH
| Field | Pre-approval (estimate) | Final |
|---|---|---|
settlement.balance | Estimated remaining settled balance | Final remaining settled balance |
settlement.fee | Estimated remaining fees | Final remaining fees |
settlement.accounts[].settledBalance | Estimated settled amount | Actual settled amount |
customData.escrowAccountBalance | Balance at submission | Current balance |
Responses
After the PATCH, the borrower can re-enter the loan, re-verify demographics and employment/income, and submit. The loan is re-underwritten and a final decision is rendered.
Get application details and status
Fetch applications created with your API key. Filter by loanNumber or your externalId. Always send one of them: without a filter the endpoint returns every application for your account. The current status is in the stage field; see the full list of stages.
Response
Returns status: "ok" and a data array. Each item includes the stage, key dates, offers, funding info, and borrower details.
Webhooks
Webhooks push real-time notifications to your system. Register a URL for an event, and we send you a request whenever it happens.
- Implement an endpoint in your system that accepts
POSTJSON (for examplehttps://www.myportal.com/api/application-updates). - Register that URL with us using the call below.
- We send each subscribed event to your URL as it happens.
| Event | When it fires |
|---|---|
ApplicationStageUpdated | The stage of a loan application changes. |
Receive events
Each delivery contains the entire loan application object every time. Read data.stage. When it is PreApproved, you can send the final settlement values.
Incomplete, before any underwriting decision. Expect one webhook per stage change after that.Example: stage Incomplete
Example: stage PreApproved
This is the webhook that carries what the client was pre-approved for. The amount is in amount and customData.initialAmount, and the offers are in offers.list once they have been generated. You do not need to call Get application details to find it. If offers is an empty array here, the offers could not be generated (for example, no credit report was found for the borrower). The stage is still PreApproved, so check the type of offers before you read it.
Example: stage Declined
A declined application cannot move to the final stage. borrower.denialReasons always lists at least one reason when an application is declined. This application was declined before any offers were generated, so offers is an empty array.
Payload notes
These apply to the examples above. The samples use made-up data in the same shape the API sends.
| Field | What to expect |
|---|---|
offers | An empty array ([]) until offers are generated. That includes applications that are declined or found ineligible before pre-approval. Once offers have been generated they stay in the payload for every later stage, including Declined, Withdrawn and WithdrawnApplicant. At PreApproved it is normally an object, and offers.list is an array of up to five offers, one per loan term (for example 72, 60, 48, 36 and 24 months). It can still be an empty array at PreApproved when offers could not be generated, for example when no credit report was found for the borrower. The offers in list can change between stages, so always read the latest webhook. Once the client accepts an offer (OfferAccepted and later), offers.selected holds the chosen offer, with extra fields such as amortization, paymentsPerYear, financeCharges, directAmount and payoffAmount, and list still holds all the offers. Handle both shapes and read offers.list as an array, even when it has one item. |
loanNumber | Sent as a number in webhooks (for example 12002100003). Some other examples show a string. Accept either and store it as text. |
externalId | Your ID, returned as a string. |
customData | Your settlement details come back here: accounts, paymentsMade, originalFico, programStartDate, lastNsfDate, company, paymentProcessing, escrowAccountBalance, gcsAccountNumber (can be null), totalCreditors, initialAmount once pre-approved, and maximumRequestedAmount once approved. The settlement.fee, payment, balance and programPaymentFrequency you send are not included. |
| Numbers | Account balances and income gross are numbers, even where the request examples use strings. |
| Empty values | fundingDate, loanDate, closingDate and maturityDate are empty strings until they have a value. loanDate and maturityDate are filled in at OfferAccepted. |
fundingInfo | Starts with recurringPaymentEnable and withdrawalSameAsDeposit set to false. Once the client enters their bank details, a withdrawal object (name, account, routing) appears, and recurringPaymentEnable can become true. If you send dscPaymentProcessing when you submit, withdrawal can already be filled in from it at Incomplete, with recurringPaymentEnable set to true. |
purpose | Why the loan is being taken out. For debt settlement it is other. |
amount | The loan amount for the application. It is not present at Incomplete. It appears at PreApproved as the pre-approved amount, and it can change after you send the final settlement values, so use the latest value. |
customData.initialAmount | The amount the client was first pre-approved for. It is set at PreApproved, and it does not change when you send the final values. |
flags | A list of internal markers LoanVault adds as the application moves along, for example submitted_report. They are informational. Do not build logic on specific values, because the list can grow. |
| Other fields | Top-level source, state, language and term; county on addresses; business in financialSummary; denialReasons on the borrower (an empty array, and always at least one reason once Declined), and prescreenQuestions on the borrower at review stages. |
| After an offer is accepted | From OfferAccepted through Funded, the payloads we tested have the same shape, and only stage changes. Parse them the same way. |
| Fields by stage | Not every field is present at every stage. For example, borrower.creditBureau, rbpReasons and denialReasons appear in the PreApproved and Declined examples but not in Incomplete or ReviewDocuments payloads. Treat every field except the identifiers and stage as optional. |
Starter receiver (pick your language):
loanNumber or externalId to match your records.Register, list, and delete
Fields: event* (event name) and callbackUrl* (your receiving URL). The response returns a webhook id you can use to unregister.
Field reference
Applies to both the POST (pre-approval) and PATCH (final) request bodies. Fields marked * are required.
| Field | Type | Req. | Description |
|---|
Payload validator
Paste a request body to check it for missing required fields and bad formats before you call the API. Runs entirely in your browser; nothing is sent anywhere. Use test data only.
This checks structure and formats only. Eligibility is decided by the API and shows up as stage Ineligible. The validator only flags fewer than 6 payments in the last 6 months as a likely problem.
Application stages
The stage field uses the machine name below. For debt settlement integrations, the stages you will act on most are highlighted.
Machine name (stage) | Display name | Meaning |
|---|
Webhook payload tester
Paste a webhook body you received (or edit the sample) to see what your system should do next. Runs in your browser.
Troubleshooting & FAQ
Postman collection & OpenAPI
Test every endpoint without writing code, or generate a client library in your language.
- In Postman choose Import and select the collection.
- Open the collection's Variables and set
client_idandclient_secret. - Run Get access token first. It saves the token for the other requests.
Need help?
Send technical questions and credential requests to Jason Marone – jmarone@newline.ai. Include your externalId or loanNumber and the environment (sandbox or production) so we can look it up quickly.
NewLine.ai · 301 Government Center Drive, Suite 200, Wilmington, NC 28403 · T (910) 208-4612 · F (910) 660-0935