Debt Settlement
Accumulate a settlement balance by drafting recurring payments from a consumer, then disburse to the creditor when the negotiated amount is reached and refund any remainder.
POST /api/Auth/Token with your Main-Token and X-OTP to obtain a JWT, then send Authorization: Bearer <JWT> on every other call — only the token call needs a TOTP code. Your base URL and credentials are issued at onboarding.Create the consumer on your vendor account. consumer1 is the primary applicant and consumer2 is an optional co-applicant. Set consumerType to Business and supply businessInfo with its principals for a business consumer.
| Field | Type | Required | Description | Value |
|---|---|---|---|---|
| consumerType | enum | REQUIRED | Individual or Business. | |
| accountStatus | enum | REQUIRED | Active, Cancelled, Completed, OnHold or OnHoldRequest. | |
| affiliateId | int | REQUIRED | Your affiliate ID, issued at onboarding. | |
| feeSplitGroupId | int | REQUIRED | Fee split group the consumer is enrolled under. | |
| consumer1 | object | REQUIRED | Primary consumer on the account. | see fields below |
| consumer1.firstName | string | REQUIRED | Legal first name. | |
| consumer1.lastName | string | REQUIRED | Legal last name. | |
| consumer1.taxId | string | REQUIRED | SSN, 9 digits, no dashes. | |
| consumer1.dateOfBirth | date | REQUIRED | Date of birth, YYYY-MM-DD. | |
| consumer1.address | string | REQUIRED | Street address. | |
| consumer1.city | string | REQUIRED | City. | |
| consumer1.state | string | REQUIRED | Two-letter state abbreviation. | |
| consumer1.zip | string | REQUIRED | ZIP code. | |
| consumer1.phone | string | REQUIRED | Primary contact number. | |
| consumer1.email | string | REQUIRED | Contact email. Statement and notice delivery uses this address. | |
| additionalPhone | string | optional | Secondary contact number. |
curl --request POST \
--url 'https://FQDN/api/Consumer' \
--header 'Authorization: Bearer <JWT>' \
--header 'Content-Type: application/json' \
--data '[
{
"consumerType": "Individual",
"accountStatus": "Active",
"affiliateId": 20,
"feeSplitGroupId": 3,
"consumer1": {
"firstName": "John",
"lastName": "Doe",
"dateOfBirth": "1980-01-15",
"address": "123 Main St",
"city": "Anytown",
"state": "CA",
"zip": "90001",
"phone": "555-123-4567",
"email": "john.doe@example.com"
}
}
]'const options = {
method: 'POST',
headers: {
'Authorization': 'Bearer <JWT>',
'Content-Type': 'application/json'
},
body: JSON.stringify([
{
"consumerType": "Individual",
"accountStatus": "Active",
"affiliateId": 20,
"feeSplitGroupId": 3,
"consumer1": {
"firstName": "John",
"lastName": "Doe",
"dateOfBirth": "1980-01-15",
"address": "123 Main St",
"city": "Anytown",
"state": "CA",
"zip": "90001",
"phone": "555-123-4567",
"email": "john.doe@example.com"
}
}
])
};
fetch('https://FQDN/api/Consumer', options)
.then(r => r.json())
.then(console.log);import requests
url = "https://FQDN/api/Consumer"
headers = {
"Authorization": "Bearer <JWT>",
"Content-Type": "application/json"
}
payload = [
{
"consumerType": "Individual",
"accountStatus": "Active",
"affiliateId": 20,
"feeSplitGroupId": 3,
"consumer1": {
"firstName": "John",
"lastName": "Doe",
"dateOfBirth": "1980-01-15",
"address": "123 Main St",
"city": "Anytown",
"state": "CA",
"zip": "90001",
"phone": "555-123-4567",
"email": "john.doe@example.com"
}
}
]
resp = requests.post(url, headers=headers, json=payload)
print(resp.json()){
"isSuccess": true,
"results": [
{ "request": { ... }, "isSuccess": true, "errorMessage": [] }
]
}Individual or Business.GET /api/Lookup/FeeSplitGroup.consumerId — the account number used on every later call.Register the creditor addresses you will settle against. Each is validated and de-duplicated — if the address already exists the existing creditor UID is returned instead of a duplicate. Results come back per creditor, so partial failures are visible alongside successes.
| Field | Type | Required | Description | Value |
|---|---|---|---|---|
| name | string | REQUIRED | Creditor name. | |
| address | string | REQUIRED | Street address line 1. | |
| address2 | string | optional | Street address line 2 (suite, unit, etc.). | |
| city | string | REQUIRED | City. | |
| state | string | REQUIRED | Two-letter state abbreviation. | |
| zip | string | REQUIRED | ZIP code. |
curl --request POST \
--url 'https://FQDN/api/Creditor' \
--header 'Authorization: Bearer <JWT>' \
--header 'Content-Type: application/json' \
--data '[
{
"name": "Capital One",
"address": "1600 Capital One Drive",
"address2": "",
"city": "McLean",
"state": "VA",
"zip": "22102"
}
]'const options = {
method: 'POST',
headers: {
'Authorization': 'Bearer <JWT>',
'Content-Type': 'application/json'
},
body: JSON.stringify([
{
"name": "Capital One",
"address": "1600 Capital One Drive",
"address2": "",
"city": "McLean",
"state": "VA",
"zip": "22102"
}
])
};
fetch('https://FQDN/api/Creditor', options)
.then(r => r.json())
.then(console.log);import requests
url = "https://FQDN/api/Creditor"
headers = {
"Authorization": "Bearer <JWT>",
"Content-Type": "application/json"
}
payload = [
{
"name": "Capital One",
"address": "1600 Capital One Drive",
"address2": "",
"city": "McLean",
"state": "VA",
"zip": "22102"
}
]
resp = requests.post(url, headers=headers, json=payload)
print(resp.json()){
"isSuccess": true,
"results": [
{ "request": { ... }, "isSuccess": true, "errorMessage": [] }
]
}creditorAddressUid — required by Add Settlement.- 1YouSchedule payment draftsPOST /Drafts
- RAMFiExecute ACH draftRAMFi drafts the consumer bank
- BanksConsumer bank debitedclears ~2 business days
- 2YouMonitor returnsGET /Reporting/ConsumerReturns
- RAMFiFlag returns / holdRAMFi reports NSF, sets Hold
- 3YouSettle with the creditorPOST /Settlement
- RAMFiDisburse settlementRAMFi sends to creditor
- BanksCreditor creditedsettlement complete
- 4YouRefund remainderPOST /Consumer/Refunds
- RAMFiDisburse to consumerRAMFi refunds the balance
Show full interaction diagram
Settlement lifecycle. App-lane boxes are API calls; RAMFi runs KYC, executes drafts, flags returns, and disburses. The Banks lane shows where money settles.
POST /api/Consumer/ConsumerBankInfo, then post the payment schedule with POST /api/Drafts. Each draft accrues a savingsAmount that funds later settlements.Consumer account status transitions. A returned draft moves the consumer to OnHold; PUT /api/Consumer/ConsumerStatus restores Active and also ends the account as Completed or Cancelled.
Active, Cancelled, Completed, OnHold — sent and returned as names. Only an Active consumer is eligible to be drafted.
Post the consumer’s payment schedule. Each draft splits into fee buckets plus a savingsAmount that accrues toward settlements. Send the whole schedule in one array; each row is validated independently.
| Field | Type | Required | Description | Value |
|---|---|---|---|---|
| keepUnpaidPayments | boolean | REQUIRED | Keep drafts already scheduled but not yet paid. Send false to replace the schedule outright. |
| Field | Type | Required | Description | Value |
|---|---|---|---|---|
| consumerId | int | REQUIRED | Consumer the schedule belongs to. | |
| draftId | int | REQUIRED | Send 0 for a new draft; an existing ID updates that draft. | |
| paymentDate | datetime | REQUIRED | Date the draft is pulled from the consumer's bank account. | |
| totalPaymentAmount | number | REQUIRED | Total drafted on this date — fees plus savings. | |
| savingsAmount | number | REQUIRED | Portion held in the consumer's trust account toward settlements. | |
| fee1Amount | number | optional | First fee component. | |
| fee2Amount | number | optional | Second fee component. | |
| returned | boolean | optional | Leave false when scheduling; set by the platform if the draft is returned. | |
| extendedId | string | optional | Your own reference for this draft. Echoed back on returns and reporting. | |
| isAdHoc | boolean | optional | true for a one-off draft outside the recurring schedule. |
curl --request POST \
--url 'https://FQDN/api/Drafts' \
--header 'Authorization: Bearer <JWT>' \
--header 'Content-Type: application/json' \
--data '[
{
"consumerId": 1001,
"draftId": 0,
"paymentDate": "2026-08-15T00:00:00",
"fee1Amount": 75.00,
"fee2Amount": 25.00,
"savingsAmount": 150.00,
"totalPaymentAmount": 250.00,
"returned": false,
"extendedId": "DRAFT-2026-12345",
"isAdHoc": false
}
]'const options = {
method: 'POST',
headers: {
'Authorization': 'Bearer <JWT>',
'Content-Type': 'application/json'
},
body: JSON.stringify([
{
"consumerId": 1001,
"draftId": 0,
"paymentDate": "2026-08-15T00:00:00",
"fee1Amount": 75.00,
"fee2Amount": 25.00,
"savingsAmount": 150.00,
"totalPaymentAmount": 250.00,
"returned": false,
"extendedId": "DRAFT-2026-12345",
"isAdHoc": false
}
])
};
fetch('https://FQDN/api/Drafts', options)
.then(r => r.json())
.then(console.log);import requests
url = "https://FQDN/api/Drafts"
headers = {
"Authorization": "Bearer <JWT>",
"Content-Type": "application/json"
}
payload = [
{
"consumerId": 1001,
"draftId": 0,
"paymentDate": "2026-08-15T00:00:00",
"fee1Amount": 75.00,
"fee2Amount": 25.00,
"savingsAmount": 150.00,
"totalPaymentAmount": 250.00,
"returned": false,
"extendedId": "DRAFT-2026-12345",
"isAdHoc": false
}
]
resp = requests.post(url, headers=headers, json=payload)
print(resp.json()){
"isSuccess": true,
"results": [
{ "request": { ... }, "isSuccess": true, "errorMessage": [] }
]
}0 for a new draft.true for a one-off outside the schedule.Poll for drafts that failed after initiation (NSF, closed account). A return carries the reason in notes and any companyReturnFee assessed. Resolve the underlying issue before the next scheduled draft.
| Field | Type | Required | Description | Value |
|---|---|---|---|---|
| date | date | REQUIRED | Report date, YYYY-MM-DD. Returns are reported one day at a time. |
curl --request GET \
--url 'https://FQDN/api/Reporting/ConsumerReturns' \
--header 'Authorization: Bearer <JWT>' \
--header 'Content-Type: application/json'const options = {
method: 'GET',
headers: {
'Authorization': 'Bearer <JWT>',
'Content-Type': 'application/json'
}
};
fetch('https://FQDN/api/Reporting/ConsumerReturns', options)
.then(r => r.json())
.then(console.log);import requests
url = "https://FQDN/api/Reporting/ConsumerReturns"
headers = {
"Authorization": "Bearer <JWT>",
"Content-Type": "application/json"
}
resp = requests.get(url, headers=headers)
print(resp.json())[
{
"consumerId": "1001",
"name": "John Doe",
"amount": 250.00,
"debitDate": "06/14/2026",
"notes": "Insufficient funds",
"returnDate": "06/15/2026",
"companyReturnFee": 25.00,
"pmtNumber": 4,
"totalDraftFees": 75.00,
"paymentId": "PMT-12345"
}
]Pay the creditor from accrued savings. paymentType selects the rail — RamCheck (physical check, 3+ business days), EftAch (2+ business days), Wire (same-day, 12:00 PM Pacific cutoff) or PayByPhone. EftAch and Wire additionally require the payee bank fields.
| Field | Type | Required | Description | Value |
|---|---|---|---|---|
| settlementId | int | REQUIRED | Send 0 for a new settlement. | |
| accountNumber | int | REQUIRED | Consumer ID the settlement is paid from. | |
| paymentAmount | number | REQUIRED | Amount paid to the creditor on this leg. | |
| paymentDate | datetime | REQUIRED | Date the payment is due to the creditor. | |
| paymentType | enum | REQUIRED | RamCheck, WireTransfer, EftAch, MoneyOrder, PayByPhone or AchDebt. | |
| payeeName | string | REQUIRED | Who the payment is made out to — often a collection agency rather than the original creditor. | |
| creditorAddressUid | int | REQUIRED | Creditor address UID returned when the creditor was added. | |
| payeeConsumerAccountNumber | string | REQUIRED | The consumer's account number with the creditor. | |
| creditorName | string | REQUIRED | Original creditor name. | |
| referenceNumber | string | REQUIRED | Your reference for this settlement. | |
| debtAmount | number | optional | Original debt balance, for reporting. | |
| totalFeeAmount | number | optional | Total fees applied to this settlement. |
curl --request POST \
--url 'https://FQDN/api/Settlement' \
--header 'Authorization: Bearer <JWT>' \
--header 'Content-Type: application/json' \
--data '[
{
"settlementId": 0,
"accountNumber": 1001,
"paymentAmount": 550.00,
"paymentDate": "2026-08-15T00:00:00",
"paymentType": "RamCheck",
"payeeName": "ABC Collections",
"creditorAddressUid": 101,
"payeeConsumerAccountNumber": "CL-123456",
"creditorName": "Capital One",
"referenceNumber": "SET-2026-5001",
"debtAmount": 1200.00,
"totalFeeAmount": 150.00
}
]'const options = {
method: 'POST',
headers: {
'Authorization': 'Bearer <JWT>',
'Content-Type': 'application/json'
},
body: JSON.stringify([
{
"settlementId": 0,
"accountNumber": 1001,
"paymentAmount": 550.00,
"paymentDate": "2026-08-15T00:00:00",
"paymentType": "RamCheck",
"payeeName": "ABC Collections",
"creditorAddressUid": 101,
"payeeConsumerAccountNumber": "CL-123456",
"creditorName": "Capital One",
"referenceNumber": "SET-2026-5001",
"debtAmount": 1200.00,
"totalFeeAmount": 150.00
}
])
};
fetch('https://FQDN/api/Settlement', options)
.then(r => r.json())
.then(console.log);import requests
url = "https://FQDN/api/Settlement"
headers = {
"Authorization": "Bearer <JWT>",
"Content-Type": "application/json"
}
payload = [
{
"settlementId": 0,
"accountNumber": 1001,
"paymentAmount": 550.00,
"paymentDate": "2026-08-15T00:00:00",
"paymentType": "RamCheck",
"payeeName": "ABC Collections",
"creditorAddressUid": 101,
"payeeConsumerAccountNumber": "CL-123456",
"creditorName": "Capital One",
"referenceNumber": "SET-2026-5001",
"debtAmount": 1200.00,
"totalFeeAmount": 150.00
}
]
resp = requests.post(url, headers=headers, json=payload)
print(resp.json()){
"isSuccess": true,
"results": [
{ "request": { ... }, "isSuccess": true, "errorMessage": [] }
]
}0 for a new settlement.consumerId.RamCheck, EftAch, Wire, PayByPhone.EftAch and Wire only.Return any unused balance to the consumer once the program completes or is cancelled.
| Field | Type | Required | Description | Value |
|---|---|---|---|---|
| consumerId | int | REQUIRED | Consumer receiving the refund. | |
| fundingSourceId | int | REQUIRED | Funding source the refund is drawn from. | |
| amount | number | REQUIRED | Amount to refund. | |
| scheduleDate | datetime | REQUIRED | Date the refund is released. | |
| refundMethod | enum | REQUIRED | ACH, Check, OvernightCheck or ConsumerTrust. | |
| extendedId | string | REQUIRED | Your reference for this refund. | |
| tCode | string | optional | Transaction code, when your program uses one. | |
| tSubCode | int | optional | Transaction sub-code. |
curl --request POST \
--url 'https://FQDN/api/Consumer/Refunds' \
--header 'Authorization: Bearer <JWT>' \
--header 'Content-Type: application/json' \
--data '[
{
"consumerId": 1001,
"amount": 250.00,
"fundingSourceId": 1,
"refundMethod": "ACH",
"tCode": "R",
"tSubCode": 1,
"extendedId": "REFUND-2026-12345"
}
]'const options = {
method: 'POST',
headers: {
'Authorization': 'Bearer <JWT>',
'Content-Type': 'application/json'
},
body: JSON.stringify([
{
"consumerId": 1001,
"amount": 250.00,
"fundingSourceId": 1,
"refundMethod": "ACH",
"tCode": "R",
"tSubCode": 1,
"extendedId": "REFUND-2026-12345"
}
])
};
fetch('https://FQDN/api/Consumer/Refunds', options)
.then(r => r.json())
.then(console.log);import requests
url = "https://FQDN/api/Consumer/Refunds"
headers = {
"Authorization": "Bearer <JWT>",
"Content-Type": "application/json"
}
payload = [
{
"consumerId": 1001,
"amount": 250.00,
"fundingSourceId": 1,
"refundMethod": "ACH",
"tCode": "R",
"tSubCode": 1,
"extendedId": "REFUND-2026-12345"
}
]
resp = requests.post(url, headers=headers, json=payload)
print(resp.json()){
"isSuccess": true,
"results": [
{ "request": { ... }, "isSuccess": true, "errorMessage": [] }
]
}OnHold. Resolve the underlying issue, then PUT /api/Consumer/ConsumerStatus back to Active before the next scheduled draft.