# Prefill Applications

The Prefill API allows you to start a loan application on behalf of an applicant by submitting partial data upfront. Rather than requiring the applicant to fill out the entire application from scratch, you prefill known information — such as the applicant's name, email, and business details — and provide them with a link to complete the rest.

## Table of Contents

- [How It Works](#how-it-works)
- [Creating a Prefilled Application](#creating-a-prefilled-application)
- [The Prefill URL](#the-prefill-url)
- [Token Expiration](#token-expiration)
- [Retrieving a New Prefill Token](#retrieving-a-new-prefill-token)
- [Webhook Events](#webhook-events)
- [Error Handling](#error-handling)
- [Best Practices](#best-practices)

---

## How It Works

The prefill flow has four main steps:

![Diagram showing the four-step prefill API flow](/images/prefill-flow-diagram.jpg)

{% details summary="Text version of the flow diagram" %}

```
1. YOU CALL THE PREFILL API
   └─→ POST /api/v3/applications/prefill
   └─→ Response includes prefill_url and prefill_token

2. APPLICANT RECEIVES LINK
   ├─→ You send the prefill_url to the applicant directly
   └─→ OR an email is automatically sent (if email communication is not suppressed)

3. APPLICANT COMPLETES APPLICATION
   └─→ Applicant opens the prefill_url
   └─→ Pre-populated fields are already filled in
   └─→ Applicant completes remaining fields and submits

4. IF TOKEN EXPIRES (applicant didn't complete in time)
   └─→ prefill_application.token_expired webhook fires
   └─→ GET /api/v3/applications/{app_id}/prefill to get a new token and deliver the new prefill_url to the applicant
   └─→ OR an email is automatically sent (if email communication is not suppressed)
```

{% /details %}

{% callout type="info" %}
Whether the applicant receives the link via an automatic email or directly from you depends on your affiliate configuration. If your affiliate is configured to suppress email communication, you are responsible for delivering the `prefill_url` to the applicant.
{% /callout %}

---

## Creating a Prefilled Application

{% endpoint method="POST" path="/api/v3/applications/prefill" /%}

Send a `POST` request with the applicant and (optionally) business and loan details. Only the owner's `first_name`, `last_name`, and `email` are required — everything else is optional.

### Request Body

**Owner Information (`owners`)** — Required, at least one owner.

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `first_name` | string | Yes | Owner's first name (max 100 chars) |
| `last_name` | string | Yes | Owner's last name (max 100 chars) |
| `email` | string | Yes | Owner's email address |
| `middle_name` | string | No | Owner's middle name |
| `name_suffix` | string | No | Name suffix (e.g., "III") |
| `job_title` | string | No | Owner's job title |
| `phone_number` | string | No | Phone number (format: `XXX-XXX-XXXX`) |
| `date_of_birth` | string | No | Date of birth (format: `YYYY-MM-DD`, must be in the past) |
| `is_applicant` | boolean | No | Whether this owner is the primary applicant |
| `ownership_percent` | integer | No | Ownership percentage (1–100) |
| `ssn` | string | No | Social Security Number (`XXXXXXXXX` or `XXX-XX-XXXX`) |
| `address` | object | No | Owner's home address |

**Business Information (`business`)** — Optional.

| Field | Type | Description |
|-------|------|-------------|
| `legal_name` | string | Legal business name (max 100 chars) |
| `doing_business_as` | string | DBA name (max 100 chars) |
| `entity_type` | string | Business structure (e.g., `limited_liability_company`, `sole_proprietor`, `partnership`, `s_corporation`, `c_corporation`, `other`) |
| `phone_number` | string | Business phone (format: `XXX-XXX-XXXX`) |
| `naics_code` | string | NAICS industry code (exactly 6 digits) |
| `start_date` | string | Business start date (format: `YYYY-MM-DD`) |
| `non_profit` | boolean | Whether the business is a non-profit |
| `tax_identification` | string | Business TIN/EIN |
| `address` | object | Business address |

**Loan Request (`loan_request`)** — Optional.

| Field | Type | Description |
|-------|------|-------------|
| `amount` | integer | Requested loan amount ($10,000–$500,000) |
| `purpose` | string | Loan purpose (e.g., `working_capital`, `equipment_purchase`, `business_expansion`, `debt_refinancing`, `inventory_purchase`) |
| `authorization` | boolean | Credit check authorization |

**Other Fields**

| Field | Type | Description |
|-------|------|-------------|
| `reference_id` | string | Your internal reference ID for this application (max 100 chars) |

### Example Request

```javascript
const response = await fetch('https://api.quantum.com/api/v3/applications/prefill', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_TOKEN',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    owners: [{
      first_name: "Jane",
      last_name: "Smith",
      email: "jane@smithenterprises.com",
      phone_number: "415-555-0198",
      date_of_birth: "1985-06-15",
      is_applicant: true,
      ownership_percent: 100
    }],
    business: {
      legal_name: "Smith Enterprises LLC",
      entity_type: "limited_liability_company",
      phone_number: "415-555-0100",
      naics_code: "541511",
      start_date: "2018-01-15"
    },
    loan_request: {
      amount: 75000,
      purpose: "working_capital"
    },
    reference_id: "PARTNER-REF-20250001"
  })
});

const prefillApp = await response.json();
console.log('Prefill URL:', prefillApp.prefill_url);
```

### Example Response (201 Created)

```json
{
  "id": "c9cefb5c-447b-433f-a4b7-16ce14a80eac",
  "prefill_url": "https://quantumlends.com/ui/apply/sp/c9cefb5c-447b-433f-a4b7-16ce14a80eac?token=nHzIm8OvrkAD6Lt9NLwHjcxn4jIfUFWFJ52bXKaEwB0",
  "prefill_token": "nHzIm8OvrkAD6Lt9NLwHjcxn4jIfUFWFJ52bXKaEwB0",
  "owners": [
    {
      "first_name": "Jane",
      "last_name": "Smith",
      "email": "jane@smithenterprises.com",
      "phone_number": "415-555-0198",
      "date_of_birth": "1985-06-15",
      "is_applicant": true,
      "ownership_percent": 100
    }
  ],
  "business": {
    "legal_name": "Smith Enterprises LLC",
    "entity_type": "limited_liability_company",
    "phone_number": "415-555-0100",
    "naics_code": "541511",
    "start_date": "2018-01-15"
  },
  "loan_request": {
    "amount": 75000,
    "purpose": "working_capital"
  },
  "created": "2025-06-15 14:30:00",
  "modified": "2025-06-15 14:30:01",
  "reference_id": "PARTNER-REF-20250001"
}
```

{% callout type="info" %}
Save the `prefill_url` from the response — this is the link the applicant will use to continue their application. If your affiliate suppresses email communication, you are responsible for delivering this URL to the applicant.
{% /callout %}

{% callout type="info" %}
The response only includes fields that have values. Null or empty fields are omitted.
{% /callout %}

### Minimal Request Example

Only the owner's name and email are strictly required:

```javascript
const response = await fetch('https://api.quantum.com/api/v3/applications/prefill', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_TOKEN',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    owners: [{
      first_name: "Jane",
      last_name: "Smith",
      email: "jane@smithenterprises.com"
    }]
  })
});
```

---

## The Prefill URL

The `prefill_url` returned in the response is a one-time-use link that takes the applicant directly to a pre-populated application form. The URL contains an authentication token so the applicant does not need to log in.

```
https://quantumlends.com/ui/apply/sp/{application_id}?token={prefill_token}
```

### How the Link Reaches the Applicant

The delivery method depends on your affiliate configuration:

| Configuration | Behavior |
|---------------|----------|
| **Emails not suppressed** (default) | An email is automatically sent to the applicant's email address with the prefill URL. |
| **Emails suppressed** | No email is sent. You are responsible for delivering the `prefill_url` to the applicant through your own channels (email, SMS, in-app notification, etc.). |

{% callout type="warning" %}
If your affiliate configuration suppresses emails, make sure your integration delivers the `prefill_url` to the applicant promptly. The token embedded in the URL will expire after a period of time.
{% /callout %}

---

## Token Expiration

The `prefill_token` embedded in the prefill URL has an expiration time. If the applicant attempts to open the link after the token has expired, they will not be able to access the prefilled application.

When an expired token is used, a `prefill_application.token_expired` webhook event is fired regardless of your email configuration. Additionally, the system handles link renewal based on your email settings:

| Configuration | What Happens on Expiration |
|---------------|---------------------------|
| **Emails not suppressed** | A new email is automatically sent to the applicant with a fresh link containing a new token. The `prefill_application.token_expired` webhook is also fired. |
| **Emails suppressed** | The `prefill_application.token_expired` webhook is fired. No email is sent — you must retrieve a new token and deliver the updated link to the applicant. |

{% callout type="info" %}
The `prefill_application.token_expired` webhook is particularly important if your affiliate suppresses emails, since it is the only way to know when the applicant needs a new link. However, you can subscribe to this event for visibility into token expirations.
{% /callout %}

---

## Retrieving a New Prefill Token

{% endpoint method="GET" path="/api/v3/applications/{app_id}/prefill" /%}

When you receive a `prefill_application.token_expired` webhook event, use this endpoint to retrieve a new `prefill_token` and `prefill_url` for the application. This is the recommended way to get a fresh link after token expiration, especially if your affiliate configuration suppresses emails.

### Path Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `app_id` | string (UUID) | Yes | The application ID from the original prefill response or the webhook event payload |

### Example Request

```javascript
const appId = 'c9cefb5c-447b-433f-a4b7-16ce14a80eac';

const response = await fetch(`https://api.quantum.com/api/v3/applications/${appId}/prefill`, {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_TOKEN'
  }
});

const prefillData = await response.json();
console.log('New Prefill URL:', prefillData.prefill_url);
```

### Example Response (200 OK)

```json
{
  "id": "c9cefb5c-447b-433f-a4b7-16ce14a80eac",
  "prefill_url": "https://quantumlends.com/ui/apply/sp/c9cefb5c-447b-433f-a4b7-16ce14a80eac?token=xR7kP2mQvL9wN3jYhT6sA1cBfD4eG8iK0oU5rW2xZ9q",
  "prefill_token": "xR7kP2mQvL9wN3jYhT6sA1cBfD4eG8iK0oU5rW2xZ9q"
}
```

{% callout type="info" %}
Each call to this endpoint generates a new token — any previously issued tokens for the application are invalidated. Make sure to deliver the latest `prefill_url` to the applicant.
{% /callout %}

### Handling Token Expiration Flow

Here's the recommended flow for handling token expiration:

```
1. WEBHOOK RECEIVED
   └─→ prefill_application.token_expired event fires

2. RETRIEVE NEW TOKEN
   └─→ GET /api/v3/applications/{app_id}/prefill
   └─→ Response includes new prefill_url and prefill_token

3. DELIVER NEW LINK
   └─→ Send the updated prefill_url to the applicant
```

---

## Webhook Events

The Prefill API introduces two webhook event types. Subscribe to these events to track prefilled application activity.

{% callout type="info" %}
To subscribe to these events, see the [Webhooks Integration Guide](/webhooks-guide.html). Add `prefill_application.created` and `prefill_application.token_expired` to your subscription's event list.
{% /callout %}

### `prefill_application.created`

Fired when a prefilled application is successfully created.

**Payload:**

| Field | Description |
|-------|-------------|
| `id` | The UUID of the created application |
| `affiliate_id` | The affiliate ID associated with your account |
| `partner_reference_id` | The `reference_id` provided in your prefill request (if any) |

### `prefill_application.token_expired`

Fired when an applicant attempts to access a prefill link with an expired token. This is especially useful if your affiliate suppresses emails, since you need to know when to resend the link.

**Payload:**

| Field | Description |
|-------|-------------|
| `id` | The UUID of the application |
| `affiliate_id` | The affiliate ID associated with your account |
| `partner_reference_id` | The `reference_id` provided in your prefill request (if any) |

{% callout type="info" %}
This webhook is deduplicated — you will receive at most one notification per token within a 24-hour window, even if the applicant clicks the expired link multiple times.
{% /callout %}


---

## Error Handling

### POST /api/v3/applications/prefill

| Status Code | Cause | Description |
|-------------|-------|-------------|
| **201** | Success | Application created. Response contains `prefill_url` and application data. |
| **400** | Not configured | Your account does not have an affiliate configured for prefill. Contact your Quantum representative. |
| **403** | Unauthorized | Your API credentials do not have permission for this operation. |
| **422** | Validation error | One or more fields are missing or invalid. Check the `error.details` array for specifics. |

### GET /api/v3/applications/{app_id}/prefill

| Status Code | Cause | Description |
|-------------|-------|-------------|
| **200** | Success | New token generated. Response contains `prefill_url` and `prefill_token`. |
| **403** | Unauthorized | Your API credentials do not have permission for this operation. |
| **404** | Not found | The application ID does not exist or does not belong to your account. |

### Example: Validation Error Response

```json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Some fields are missing or invalid",
    "details": [
      {
        "field": "body.owners.0.email",
        "message": "value is not a valid email address"
      }
    ]
  }
}
```

{% callout type="warning" %}
If you receive a `400` error indicating that prefill is not configured, contact your Quantum representative to enable it for your account.
{% /callout %}

---

## Best Practices

### Provide As Much Data As Possible

While only `first_name`, `last_name`, and `email` are required, prefilling additional fields reduces friction for the applicant and increases the likelihood of application completion. At minimum, consider including:

- Owner's phone number and date of birth
- Business legal name and entity type
- Loan request amount and purpose

### Use Reference IDs

Include a `reference_id` to correlate prefilled applications with records in your system. This ID is returned in webhook payloads and API responses, making it easy to track applications across systems.

```json
{
  "reference_id": "YOUR-INTERNAL-ID-12345"
}
```

### Handle Token Expiration

If your affiliate suppresses emails, implement a handler for the `prefill_application.token_expired` webhook event. When received, call `GET /api/v3/applications/{app_id}/prefill` to retrieve a fresh token and deliver the new prefill link to the applicant promptly to avoid drop-off.

### Monitor Webhook Events

Subscribe to both `prefill_application.created` and `prefill_application.token_expired` events to maintain visibility into the prefill pipeline.

---

## Next Steps

- Review the [API Reference](/api-reference.html) for the complete prefill endpoint schema
- Set up [Webhook Subscriptions](/webhooks-guide.html) for prefill events
- Contact your Quantum representative to enable prefill for your account
