---
title: Encryption API
description: Encrypt JSON payloads via API without implementing JWE yourself
---

## Overview

If you are unable to implement JWE encryption in your own systems, Figure provides an API endpoint that encrypts a JSON payload on your behalf using Figure's public key. The encrypted output is a standard JWE compact serialization string that can be used anywhere Figure expects encrypted data — for example, as a query parameter when redirecting a borrower to Figure.

{% sequence %}
{% actor id="partner" label="Your system" kind="partner" /%}
{% actor id="api" label="Encryption API" kind="figure" /%}
{% actor id="app" label="Figure app" kind="figure" /%}
{% message from="partner" to="api" label="Send the JSON to encrypt" endpoint="POST /encryption/v1/encrypt" /%}
{% message from="api" to="partner" reply=true label="An encrypted JWE string" /%}
{% message from="partner" to="app" label="Redirect the borrower with ?inquiry={encrypted}" /%}
{% /sequence %}

{% callout type="info" title="Part of Data protection" %}
The Encryption API produces the same JWE you'd create yourself. To learn how Figure protects borrower data, or to encrypt payloads in your own systems instead, see [Data protection (JWE)](/jwe-data-protection/intro).
{% /callout %}

## Authentication

This endpoint uses the same authentication as all other Figure Partner API endpoints:

- **`apikey`** header — Your API key, provided during onboarding.

See [API basics](/getting-started) for more information on required headers.

## Request

```txt {% title="URL" %}
POST https://api.figure.com/encryption/v1/encrypt
```

### Headers

| Header         | Required | Description                          |
|----------------|----------|--------------------------------------|
| `apikey`       | Yes      | Your API key                         |
| `Content-Type` | Yes      | Must be `application/json`           |

### Body

The request body is any valid JSON object representing the data you want to encrypt. For example, if you are encrypting inquiry prefill data:

```json5 {% title="Example payload" %}
{
  "applicant": {
    "name": {
      "firstName": "Jane",
      "lastName": "Doe"
    },
    "email": "jane.doe@example.com",
    "phone": "555-123-4567"
  },
  "property": {
    "address": {
      "street1": "123 Main St",
      "city": "Anytown",
      "state": "CA",
      "zip": "90210"
    }
  }
}
```

### Example request

```bash {% title="cURL" %}
curl -X POST https://api.figure.com/encryption/v1/encrypt \
  -H "apikey: <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "applicant": {
      "name": { "firstName": "Jane", "lastName": "Doe" },
      "email": "jane.doe@example.com"
    }
  }'
```

## Response

```json5 {% title="Response payload" %}
{
  "encrypted": "<JWE compact serialization string>"
}
```

The `encrypted` field contains a JWE compact serialization string (five base64url-encoded segments separated by periods). See [JSON Web Encryption (JWE)](/jwe-data-protection/intro) for details on the JWE format.

## Store a payload request

Use the payload request endpoint when Figure should store the payload and return a **redirect URL** for a relevant user based on `payloadType` to open a Figure-hosted flow with pre-filled data.
Unlike `/encryption/v1/encrypt`, this endpoint does not return the encrypted payload in the response.

### Request

```txt {% title="URL" %}
POST https://api.figure.com/encryption/v1/payload-requests
```

### Top-level fields

| Field | Required | Description |
|-------|----------|-------------|
| `payloadType` | Yes | `HELOC_INQUIRY` or `HELOC_APPLICATION` (see matrix below). |
| `payload` | Yes | JSON object; schema depends on `payloadType`. Unknown properties are rejected for **`HELOC_INQUIRY`**. |
| `loanOriginatorUuid` | Conditional | UUID of the lead-portal **loan originator user record** (referrer), not a borrower identity UUID. **Always required for `HELOC_INQUIRY`.** Also required when your API key is authorized for **more than one organization**. Optional for `HELOC_APPLICATION` when the key maps to a single organization and the payload does not carry a conflicting loan originator reference. If both the request and payload carry a loan originator id, they must match. |

### `payloadType` matrix

| `payloadType` | Who opens `redirectUrl` | `payload` shape | `redirectUrl` path and query |
|---------------|-------------------------|-----------------|----------------------------|
| `HELOC_INQUIRY` | Loan originator | Canonical `applicant` + optional `property` (tab below) | `/leadportal/app/new-inquiry/heloc?payloadUuid={uuid}` |
| `HELOC_APPLICATION` | Borrower | Flat HELOC register prepop fields (tab below) | `/account/heloc/register?payloadUuid={uuid}` |

Figure builds `redirectUrl` from the path and `payloadUuid` in the matrix. **If** your organization has a configured branded HELOC host, that host is used for both payload types; the path still depends on `payloadType` (see matrix). A branded host is optional—not every partner uses one.

{% callout type="info" title="Payload shape depends on payloadType" %}
Select the tab that matches your `payloadType`. **`HELOC_INQUIRY`** always uses the canonical `applicant` / `property` contract. **`HELOC_APPLICATION`** uses the flat register prepop shape shown in the application tab.
{% /callout %}

{% tabs %}
{% tab label="HELOC inquiry" %}

```json5 {% title="Request payload" %}
{
  "payloadType": "HELOC_INQUIRY",
  "loanOriginatorUuid": "00000000-0000-0000-0000-000000000001",
  "payload": {
    "applicant": {
      "name": {
        "prefix": "Ms",
        "firstName": "Jane",
        "middleName": "Q",
        "lastName": "Borrower",
        "suffix": "Jr"
      },
      "dob": "1985-04-12",
      "phone": "4155550100",
      "email": "jane.borrower@example.com",
      "homeAddress": {
        "street1": "123 Main St",
        "street2": "Apt 4",
        "city": "San Jose",
        "state": "CA",
        "zip": "95126"
      },
      "income": {
        "employmentType": "FULL_TIME",
        "grossAnnualIncome": 185000,
        "liquidAssets": 75000
      }
    },
    "property": {
      "address": {
        "street1": "123 Main St",
        "street2": "Apt 4",
        "city": "San Jose",
        "state": "CA",
        "zip": "95126"
      },
      "ownershipType": "SOLE",
      "occupancyType": "PRIMARY",
      "isListedForSale": false
    }
  }
}
```

Enum values for `employmentType`, `ownershipType`, and `occupancyType` match [HELOC enum types](/heloc-inquiries/enum-types) (`occupancyType` uses `PropertyType`: `PRIMARY`, `SECONDARY`, `INVESTMENT`).

{% /tab %}
{% tab label="HELOC application" %}

```json5 {% title="Request payload" %}
{
  "payloadType": "HELOC_APPLICATION",
  "payload": {
    "name": {
      "firstName": "Carlos",
      "lastName": "Johnson"
    },
    "dob": "1947-07-30",
    "propertyAddress": {
      "street1": "1066 Arbol Way",
      "city": "San Jose",
      "state": "CA",
      "zip": "95126",
      "occupancyType": "HOME",
      "ownership": "SOLE"
    },
    "homeAddress": {
      "street1": "1066 Arbol Way",
      "city": "San Jose",
      "state": "CA",
      "zip": "95126"
    },
    "isListedForSale": false,
    "income": {
      "employmentType": "FULL_TIME",
      "income": 120000.0
    },
    "email": "carlos.johnson@example.com",
    "phoneNumber": "4155551234"
  },
  "loanOriginatorUuid": "00000000-0000-0000-0000-000000000000"
}
```

{% /tab %}
{% /tabs %}

`payloadType` selects which `payload` schema applies (see the matrix and examples above).

`loanOriginatorUuid` is **required** for **`HELOC_INQUIRY`**. For **`HELOC_APPLICATION`**, supply it at the top level or inside the payload according to your onboarding contract when the payload identifies the loan originator. It is also **required** when your API key is authorized for more than one organization. If both the top-level request and the payload include a loan originator id, they must match.

An encrypted version of the above payload is also accepted:

```json5 {% title="Encrypted request payload" %}
{
  "encrypted": "<JWE compact serialization string>"
}
```

### Minimum required fields (`payload`)

Rules apply on create; all other documented fields are optional (partial pre-fill is allowed).

| Rule | `HELOC_INQUIRY` | `HELOC_APPLICATION` |
|------|-----------------|---------------------|
| `applicant.email` | **Required** | Use top-level `email` on the flat register payload (required for meaningful pre-fill). |
| Name **or** home address | **At least one:** both `applicant.name.firstName` and `applicant.name.lastName`, **or** `applicant.homeAddress.street1` | Follow register prepop requirements for the fields you send. |
| `property` object | Optional entirely | Optional |
| Inquiry-only `applicant.income.liquidAssets` | Allowed | **Rejected** when validated as inquiry-shaped JSON |
| Application-only income fields | **Rejected** (for example `otherAnnualIncome` under inquiry income) | Allowed per register prepop schema |
| `businessInfo` (SMB broker) | **Rejected** in MVP | N/A |

For **`HELOC_INQUIRY`**, do not send register-flat top-level fields (`email`, `propertyAddress`, `phoneNumber`, and similar), legacy `metadata` / offer blocks, `property.ownership` (use `ownershipType`), or `property.propertyType` (use `occupancyType`).

### Response

```json5 {% title="Response payload" %}
{
  "redirectUrl": "https://apply.figure.com/account/heloc/register?payloadUuid=00000000-0000-0000-0000-000000000002",
  "requestPayloadUuid": "00000000-0000-0000-0000-000000000002",
  "expiresAt": "2026-08-20T12:00:00Z"
}
```

The path in `redirectUrl` depends on `payloadType` (see matrix). The example above shows a register URL for **`HELOC_APPLICATION`**; inquiry responses use the inquiry path from the matrix.

| Field | Description |
|-------|-------------|
| `redirectUrl` | Full HTTPS URL. Send the relevant user (see matrix) to this URL. Figure combines the matrix path and `payloadUuid`; if a branded HELOC host is configured for your organization, that host is used for both payload types. |
| `requestPayloadUuid` | Stable id for the stored payload (also appears as `payloadUuid` in `redirectUrl`). |
| `expiresAt` | UTC timestamp after which the stored payload is no longer valid. |

### After create

- **`HELOC_INQUIRY`:** Route the **loan originator** to `redirectUrl`. They sign in to Lead Portal if needed, then open the HELOC create-inquiry experience with fields pre-filled from the stored payload.
- **`HELOC_APPLICATION`:** Route the **borrower** to `redirectUrl` to continue the HELOC application flow.

Send the relevant user to `redirectUrl` after create. Stored payloads are fetched by Figure frontends over authenticated APIs; partners only need to retain `requestPayloadUuid` for support correlation, not to call fetch themselves. Requests are matched by identity email (or similar value) to prevent erroneous decryption attempts. Users are authenticated before decryption is allowed.

## Error responses

| Scenario                  | HTTP Status | Description                                      |
|---------------------------|-------------|--------------------------------------------------|
| Missing or invalid API key | 401         | The `apikey` header is missing or invalid        |
| Invalid JSON body          | 400         | The request body is not valid JSON               |
| Server error               | 500         | An unexpected error occurred during encryption   |
