# The Integration Guide

Footprint makes it easy to onboard your users, whether that means KYC, KYB,
Identity document verification, or collecting documents — all with security,
compliance, and risk/fraud prevention bundled together. This is the definitive
guide outlining all the ways you can integrate Footprint into your product,
including some advanced options and features to fully customize and own your
flow.

# Core concepts

### Vault

Each entity in Footprint is backed by a secure data **Vault** that stores
identity, financial, documents, and custom data attributes. When a user onboards
via a Footprint flow all data collected is automatically stored in the user’s
vault. Vaults store both structured and unstructured data, and keep track of
each change to every attribute with a versioned history. Footprint's vaulting
aims to be flexible while providing base-level validation logic for structured
vault data such as Identity or PCI data. All attribute values are referenced by
specific **data identifiers** (such as `id.ssn9` references the full SSN of a
user). Vault data fields are a core part of the Footprint platform: they support
granular role-based access controls (RBACs) for data access and can be used to
transmit data securely (via the Vault Proxy) to third-party destinations. Read
more about all the
[vault data fields here](/articles/vault/fields#vault-fields).

### The "fp\_id"

Also known as the “Footprint ID”. This is the unique, per-user identifier for an
entity inside of Footprint. It appears in API request, responses, and on the
dashboard to uniquely identify an entity. Similar to `fp_id`, an `fp_bid` is the
unique identifier for a business entity.

### The "external\_id"

This is an identifier that **you provide** for a user or business. This provides
a mechanism which you can map entities in your system to Footprint without
storing/knowing the Footprint ID for that entity.

We strongly recommend maintaining a one-to-one
mapping from users in your own database to users in Footprint. One easy way to
guarantee this is to provide an external ID when creating users.

### Playbook

A Playbook defines the end-to-end onboarding flow powered by Footprint: (a) what
information needs to be collected, (b) what verification checks need to run, and
(c) the rules that define decisioning based on the verification checks. A
`playbook_key` is the unique, publishable identifier for a playbook and appears
in API requests, responses, and in the dashboard.

### Onboarding

An onboarding represents a user/business onboarding onto a Playbook. Each time a
user/business goes through a playbook, it creates a new onboarding.

# The 2 options for launching Footprint

There are two types of ways Footprint integrates into your product.

1. **Hosted:** this is a web page hosted by Footprint that includes the full
   end-to-end onboarding flow. With one API call you can generate a URL and send
   it to your user.
2. **Embedded:** use one of our many SDKs across web, iOS, and Android to embed
   Footprint inside your product.

### Customization

Each option supports customization to varying degrees:

1. **Hosted:** Coming soon, use our appearance editor in the dashboard to
   control every element just liked in the embedded flow.
2. **Embedded:** use our SDK to fully customize the look and feel of each
   element including fonts, colors, borders, and much more. We support over 100
   attributes of customization. See here for full details:
   [https://docs.onefootprint.com/articles/integrate/customization](/articles/integrate/customization).

### Identity documents & document collection

One important caveat: Footprint handles the complexity of document collection
and verification. Document collection is considered a singular component which
includes everything from: device handoff (leveraging a mobile device when
starting the flow on desktop), automatic capture and liveness, document
classification, and selfie capture. The customization options extend to the full
document collection and scanning experience.

# The end-to-end integration

This guide covers all the most common steps to getting Footprint fully up in
running in just a few minutes.

## Step 1: Get your secret API key

Go to [the Footprint dashboard](https://dashboard.onefootprint.com/api-keys) and
**create a secret key**. Store this key somewhere safe.

## Step 2: Create a playbook and grab the Playbook publishable key

Go to [the Footprint dashboard](https://dashboard.onefootprint.com/playbooks)
and create a Playbook. Playbooks define the onboarding: (a) what information
needs to be collected, (b) what verification checks need to run, and (c) the
rules that define decisioning based on the verification checks.

## Step 3: Create an onboarding session token

To launch a Footprint onboarding flow, you’ll need to generate an onboarding
session token. Use the
POST
/onboarding/session endpoint:

```bash
curl -X POST https://api.onefootprint.com/onboarding/session \
  -H 'X-Footprint-Secret-Key: <SECRET_API_KEY>'\
  -d \
  '{
		"kind": "onboard", 
		"key": "<PLAYBOOK_KEY>"
    }'
```

### Step 3a: Advanced optional configuration for an onboarding session token

The
POST
/onboarding/session endpoint contains several advanced options
that can be passed in while creating the token. These are all optional. Read the
API reference for the full specification.

| Attribute                | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `fp_id`                  | Use this parameter to pass in the identifier of an existing footprint user. This is useful if you are creating an onboarding session for an existing user, if the user has previously onboarded onto a playbook, or if the user was simply created via API and has some data in their vault. The Footprint flow is smart enough to bootstrap an onboarding session with the data already present in the user vault. (Cannot be provided alongside `external_id`). Note see [here](/articles/integrate/migrate-existing-data) on using the `POST /users` to create a user vi API.                                                                                                                                                                                                                                                                                                            |
| `user_external_id`       | Similar to `fp_id` except an identifier that you know the user by in your own system. If a user with this external ID already exists within the Footprint ecosystem, we will select it. If not, the user created by this onboarding session will have this as its external id. (Cannot be provided alongside `fp_id`)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `bootstrap_data`         | Use this to provide any data that you would like to pass into the onboarding flow — this is useful if you already have some information on the user/business but have not created a user inside of Footprint with that data. Only use `bootstrap_data` if the vault does not exist. See [available user bootstrap fields](/articles/integrate/bootstrap-data#boostraping-kyc-data) and [business bootstrap fields](/articles/integrate/bootstrap-data#boostraping-kyc-data).                                                                                                                                                                                                                                                                                                                                                                                                                |
| `onboarding_external_id` | Use `onboarding_external_id` to control onboarding idempotency and associate an onboarding with an event in your application. For more information, see [here](/articles/integrate/onboarding-sessions#example-use-cases-onboarding-idempotency). When a user onboards using this token, Footprint will look up previous onboardings onto this playbook. If there is a matching onboarding with the provided `onboarding_external_id` (or if no `onboarding_external_id`is provided), the matching onboarding's results will be reused and returned without allowing the user to edit their data, run any verification checks, or re-evalute rules. The flow will close once the user logs in.  If there is no matching onboarding, a new onboarding will be created and the user will be allowed to onboard as normal.  Can only be provided if `fp_id` or `user_external_id` is provided. |

By default, if no `onboarding_external_id` is provided, a user will only be allowed to onboard onto a playbook one time. When a user starts an onboarding session onto a playbook onto which they've already onboarded, Footprint will reuse the result of the user's last onboarding to prevent you from incurring accidental charges for repeat onboardings.

**Additional options if onboarding a business (KYB)**

| Attribute              | Description                                                                                                                                                                                                                                                                                                                            |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `fp_bid`               | Like `fp_id` but for a business. The existing business to be linked to this user's onboarding session. Only takes effect when onboarding onto a KYB playbook. Cannot be provided along side `business_external_id`                                                                                                                     |
| `business_external_id` | When using a KYB playbook, optionally this business's identifier in your own database. If a business with this external ID owned by the identified user already exists within the Footprint ecosystem, we will select it. If not, we will create a new business with this as its `external_id`. Cannot be provided alongside `fp_bid`. |

**Warning**: the identified user must already own the business with this external ID or they will receive an error during onboarding.

**Note**: If no `fp_bid` or `business_external_id` is provided here when onboarding onto a KYB playbook, the user will be asked to enter their business information and create a new business.

## Step 4: Launch the Footprint flow

In step 3, the onboarding session creation endpoint will produce a response like
the following:

```json
{
  "expires_at": "2025-05-08T12:00-07:00",
  "link": "https://verify.onefootprint.com/?type=user#obtok_UxM6Vbvk2Rcy1gzcSuXgk3sj3L9I0pAnNH",
  "token": "obtok_UxM6Vbvk2Rcy1gzcSuXgk3sj3L9I0pAnNH"
}
```

### Step 4a: Hosted

If using the **Hosted launch option**, extract the `link` in the response and
deliver this to your end user via email, sms, or through a button in your app.

### Step 4b: Embedded

If using one of our embedded SDKs, extract the `token` and use that to launch
Footprint. Below find some examples of different SDKs.

**Web (JS/TS/React/Vue/Angular)**

```bash
npm install @onefootprint/footprint-js
```

```tsx
import "@onefootprint/footprint-js/dist/footprint-js.css";
import { onboarding } from "@onefootprint/footprint-js";

const App = () => {
  const launch = () => {
    onboarding.initialize({
      // replace with the `token` from the api response
      onboardingSessionToken: "obtok_UxM6Vbvk2Rcy1gzcSuXgk3sj3L9I0pAnNH",
      onComplete: (validationToken) => {
        console.log("completed", validationToken);
        // use the validationToken in next step
      },
    });
  };

  return <button onClick={launch}>Verify Identity</button>;
};
```

**iOS (Swift UI)**

Installation instructions available through
[Swift Package Manager](https://www.notion.so/The-definitive-Footprint-integration-guide-1edeb271246680b4b235d8d4de599a84?pvs=21)
and [Cocoa Pods](/articles/sdks/swift-introduction#installation-cocoa-pods).

```swift
import SwiftUI
import Footprint

struct ContentView: View {
    var body: some View {
        VStack {
            Button("Verify Identity") {
                Task {
                    do {
		                    // replace with the `token` from the api response
                        try await Footprint.shared.initializeWithAuthToken(authToken: "obtok_UxM6Vbvk2Rcy1gzcSuXgk3sj3L9I0pAnNH")                       
                        
                        try await FootprintHosted.shared.launchHosted(
                            onComplete: { validationToken in
                                print("Handoff completed successfully with token: \(validationToken)")
                            },
                            onCancel: {
                                print("Handoff was canceled by the user")
                            },
                            onError: { error in
                                print("Error occurred during handoff: \(error)")
                            }                            
                        )
                    } catch {
                        print("Error: \(error)")
                    }
                }
            }
        }
    }
}
```

**Android**

Installation instructions found here:
[https://docs.onefootprint.com/articles/sdks/android-introduction#installation](/articles/sdks/android-introduction#installation)

```swift
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            Column {
                val coroutineScope = rememberCoroutineScope()
                Button(onClick = {
                    coroutineScope.launch {
                        try {
                            Footprint.initializeWithAuthToken(
		                            // replace with the `token` from the api response
                                authToken = "obtok_UxM6Vbvk2Rcy1gzcSuXgk3sj3L9I0pAnNH",
                                context = this@MainActivity
                            )

                            FootprintHosted.launchHosted(
                                context = this@MainActivity,
                                onComplete = { token: String ->
                                    println("VerificationResult: the flow has completed. The validation token is $token")
                                },
                                onCancel = {
                                    println("VerificationResult: the flow was canceled")
                                },
                                onError = { error ->
                                    println("Footprint error occurred: ${error}")
                                }
                            )
                        } catch (e: FootprintException) {
                            println("Error initializing Footprint SDK: ${e.message}")
                        }
                    }
                }) {
                    Text("Verify identity")
                }
            }
        }
    }
}
```

### Silent mode support

Silent Integration allows Footprint to run completely invisible from end-users, vaulting data and collecting device insights without user interaction. This is ideal when you want to:

* **OTP Integration**: Users already complete OTP verification in your system
* **Custom UI Control**: Collect all data using your own system UI
* **Background Verification**: Verify user identity without disrupting their experience
* **Device Signals Collection**: Silently gather device signals for risk assessment

#### How it works

1. **Create an authless playbook** that doesn't collect passkeys or documents
2. **Collect all required data** (name, address, SSN, etc.) in your own system
3. **Supply all data required by that playbook via bootstrap\_data** when creating the onboarding session:
4. **Launch the SDK** with the onboarding session token - the flow will run silently in the background

When these requirements are met and no step-up is needed, the integration runs invisibly. If additional verification is required, Footprint will display a modal only for the specific data collection needed.

## Step 5: Process the validation\_token

Note: only applies if you are using the **Embedded** SDK. If
using **Hosted**, skip to step 6.

You’re almost done! At the end of the onboarding flow, the SDK invokes an
`onComplete` completion handler that passes a `validation_token` to your code.
Send the `validation_token` to your backend and then validate it using the
[`POST /onboarding/session/validate` API.](/api-reference#post-onboarding-session-validate)

```bash
curl -X POST https://api.onefootprint.com/onboarding/session/validate \
   -u <SECRET_API_KEY>: \
   -d '{"validation_token": "<VALIDATION_TOKEN>"}'
```

Note: This is a short-live token that represents a completed
onboarding, and can be used to exchange for the result of the onboarding
(decision in the case of KYC/KYB) along with the `fp_id`/ `fp_bid` of the
corresponding entity that was created or reused.

The response will look like:

```json
{
  "user": {
    "fp_id": "fp_id_GSxJr68GAf5jUT3pdL9ndjf7TLkA3GCX",
    "onboarding_id": "ob_SRFT2a1mN7DAWJ0VPXkiqK",
    "playbook_key": "pb_test_VMooXd04EUlnu3AvMYKjMW",
    "requires_manual_review": false,
    "status": "pass"
  },
  ...
}
```

We recommend storing the `fp_id` on your users table in your database (if you
have not already) to ensure a one-to-one mapping between your users and users in
Footprint.

### The verification result

Your playbook will define a set of rules used to evaluate the user's status and
to decide whether the user should be flagged for manual review. Use
the `status` and `requires_manual_review` fields to decide whether or not to
onboard this user to your product.

| **STATUS**   | **WHAT DOES THIS MEAN?**                                                                                                                                                                                                                                   |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pass`       | The rules defined on your playbook to verify the user evaluated to an outcome of `pass`.                                                                                                                                                                   |
| `fail`       | The rules defined on your playbook evaluated to an outcome of `fail`.                                                                                                                                                                                      |
| `none`       | Your playbook has no rules defined.                                                                                                                                                                                                                        |
| `pending`    | Verifying this user's identity is taking longer than expected. This happens in rare cases where asynchronous actions are required to make a decision. A final decision will be delivered via [webhooks](/articles/integrate/webhooks) to your application. |
| `incomplete` | This indicates a user has dropped off and not finished the onboarding flow.                                                                                                                                                                                |

| **REVIEW** | **WHAT DOES THIS MEAN?**                                                                                                                                                      |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| False      | Your playbook's rules have made a decision automatically.                                                                                                                     |
| True       | Your playbook's rules have requested that this user is reviewed manually before onboarding OR the user’s previous onboarding status caused the review flag to remain enabled. |

## Step 6: Listen to webhooks

When integrating with Footprint's frontend SDKs for collecting and verifying
user information, you most commonly may want to subscribe to events related to a
user's status.

### Step 6a: Subscribe a webhook endpoint

To enable webhook events, you need to register webhook endpoints in
the [Footprint dashboard](https://dashboard.onefootprint.com/webhooks). After
you register them, Footprint can push real-time event data to your application's
webhook endpoint when events happen in Footprint.

To get started, see
the [guide to consuming webhooks](https://docs.svix.com/receiving/introduction).

> We recommend that you secure your integration by always verifying that all
> webhook requests are generated by Footprint. Please see our guide on
> [securely verifying webhook signature](https://docs.svix.com/receiving/verifying-payloads/how)s.

### Step 6b: Recommended events to listen for

For the core Footprint integration, we recommend listening to the following
three event types.

* **Onboarding completed**

  We recommend subscribing to the
  footprint.onboarding.completed
  event, which will fire when a user's onboarding has reached a terminal status.

  In most cases,
  the [status received synchronously](#the-end-to-end-integration-step-5-process-the-validation-token-the-verification-result) at
  the end of Footprint's onboarding flow will be a terminal `pass`, `fail`,
  or `none`. In some cases where identity verifications vendors take longer to
  verify a user, you will synchronously receive a `pending` status in your
  integration with the frontend SDK. In these cases, you will receive the final
  decision for an onboarding through the `footprint.onboarding.completed` event.

* **Manual review**

  Employees at your company may change a user's status while manually reviewing
  a user in the Footprint dashboard. This will fire the
  footprint.user.manual\_review
  event. Upon receiving this webhook, we recommend consulting the
  GET
  /users/{fp_id} API for information on the user's new manual
  status.

* **Watchlist checks**

  If your playbook has continuous monitoring enabled, Footprint will regularly
  check if any of your users are found on AML watchlists. Updates on watchlist
  checks are sent using the
  footprint.watchlist\_check.completed
  event.

# Appendix

## Advanced integration options

Below we’ve high-lighted some additional, more advanced options available to you
as you integrate Footprint into your product. All of these are optional and
using these methods typically indicate you are using Footprint in less common
ways. Note some of these APIs may be gated, so please reach out to us if an API
you need is not enabled on your account.

## Use the API to fetching Onboardings, PII, Decisions, Risk signals, Documents, and more

In more advanced integration cases, you may want to process more detailed
verification data and results from Footprint (instead of only viewing it in the
dashboard). This can be useful if you are embedding results from Footprint in
your application (i.e. a seller marketplace app who needs to pass risk signals
to the seller who will verify a buyer for large transactions).

### The Onboarding object

Everytime a user or business onboards onto a playbook — an “onboarding” is
generated — and each onboarding has a unique ID often referenced as
`onboarding_id`. These IDs can be used to fetch risk signals, decisions,
documents and data collected, and more at a specific “onboarding”. An onboarding
ID lets you track the user as they update and modify data over time.

The two main places where onboarding IDs will be provided to you are:

1. When you validate an onboarding session (the
   POST
   /onboarding/session/validate) API
2. A Webhook when an onboarding is completed.

You can list onboardings for a user/business by using the
GET
/users/{fp_id}/onboardings and
GET
/businesses/{fp_bid}/onboardings APIs.

### Fetch risk signals, and list collected data and documents by onboarding ID

Once you have a particular `onboarding_id` you can use the
GET
/users/{fp_id}/onboardings/{onboarding_id}/risk\_signals and
GET
GET /users/{fp_id}/documents?onboarding\_id=ob\_xyz.. APIs to
fetch onboarding specific risk signals and captured documents.

### Fetch decisions

Given a user or a business, you can fetch all the decisions (including manual
review decisions that occurred with a human in the loop). Use the
[list all decisions](/api-reference#get-users-fp-id-decisions) API (for
users/businesses). The response will look like following:

```json
{
  "data": [
    {
      "kind": "playbook_run",
      "playbook_key": "pb_live_fZvYlX3JpanlQ3MAwE45g0",
      "status": "fail",
      "timestamp": "2022-01-04T12:00-07:00"
    },
    {
      "kind": "manual",
      "status": "pass",
      "timestamp": "2022-01-04T12:00-07:00"
    }
  ],
  "meta": {
    "next_page": 2
  }
}
```

### Decrypt PII/documents from the vault at a specific onboarding

Footprint’s information systems are built around highly-secured vaulting
infrastructure with granular access controls. Use the
[decrypt API](/api-reference#post-users-fp-id-vault-decrypt) to access plaintext
sensitive user/business data.

```bash
curl -X POST https://api.onefootprint.com/users/{fp_id}/vault/decrypt \
  -u <API_KEY>: \
  -d '{
    "fields": [
      "id.ssn9",
      "id.last_name",
      "document.passport.front.image",
      "document.passport.dob"
    ],
    "reason": "compliance",
    "at_onboarding_id": "ob_id_xyz..."
  }'
```

You may specify the `at_onboarding_id` field to decrypt a user's historical
information at the time of the provided onboarding.

## Auth-less Playbooks: disabling the OTP requirement

When creating a Playbook you can disable (toggle off) both the email and phone
OTP requirements. In this case, the only way to begin a Footprint verification
session is to use the
[onboarding session token](/api-reference#post-onboarding-session) — as
described in the main integration path above.

## Requesting more information via API

The Footprint dashboard has a handy button to request more information from the
end user — useful in a manual review situation. While this method automatically
can send the user a link, sometimes you’ll want to have more control over
prompting the user to satisfy this new request.

We recommend the following approach:

1. Send user an email/message (optional) Note: you can actually hook up the
   footprint.user.info\_requested
   \`\` to automate notifications triggered from the Footprint dashboard.
2. When the user opens your app/website, your app checks that the user has
   outstanding information requested via the `GET users/{fp_id}`
3. Use the API to generate
   an [onboarding session token](/api-reference#post-onboarding-session) to `inherit` any
   pending document/info requests requested for that user in the Footprint
   dashboard

## Linking users to businesses via API

If you are using KYB playbooks but not verifying beneficial owners (i.e. you are
not using Footprint’s feature of verifying business owners together with the
business), you can still take advantage of linking users to their businesses
(and vice-versa) so that you can connect entities in the API and see the
connections in the Footprint dashboard. Use the
[link a business owner](/api-reference#post-businesses-fp-bid-owners) API after
onboarding both a business and the user(s).