# Onboarding sessions

An onboarding session starts an onboarding from your backend. You create a session token with your secret API key, passing what the session needs, such as an existing user's `fp_id`, bootstrap data, or external IDs, and hand the token to the Footprint SDK. It is an alternative to passing every argument to the SDK directly, and because your secret API key creates it, it can do things the SDK alone cannot:

* Control when a user may reonboard onto a playbook.
* Set the `external_id` of the user (or business) the onboarding session creates.
* Bootstrap data from your backend into the onboarding.

## Create a session token

From your backend, call POST /onboarding/session with your secret API key. The simplest request carries only the playbook key:

```bash
curl -X POST https://api.onefootprint.com/onboarding/session \
  -u sk_test_CXUsbCR8j2kH6e5GeEl8eSBnQTIPCUaKpv: \
  -d '{"kind": "onboard", "key": "pb_live_qBV2iO3nQI5moqo5GJlFhI"}'
```

The response carries the token, a hosted link, and the token's expiry:

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

Pass the token to the Footprint SDK as `authToken`. For a KYC (Know Your Customer) onboarding, pass it as a prop:

```javascript
import "@onefootprint/footprint-js/dist/footprint-js.css";
import footprint from "@onefootprint/footprint-js";

const handleClick = () => {
  const component = footprint.init({
    kind: "verify",
    authToken: "obtok_UxM6Vbvk2Rcy1gzcSuXgk3sj3L9I0pAnNH", // token from above
    onComplete: (validationToken) => {
      // TODO
    },
  });
  component.render();
};
```

## Example use cases

### Guarantee resolution to a specific user

Aim for one Footprint user, one `fp_id`, per user in your application. When you launch the Footprint flow from a logged-in context, pass your own database identifier for the user as `user_external_id`. The onboarding session resolves to the existing Footprint user with that `external_id`, or creates a new Footprint user with it.

```bash
curl -X POST https://api.onefootprint.com/onboarding/session \
  -u sk_test_CXUsbCR8j2kH6e5GeEl8eSBnQTIPCUaKpv: \
  -d '{
    "kind": "onboard",
    "key": "pb_live_qBV2iO3nQI5moqo5GJlFhI",
    "user_external_id": "8c992273-987d-4830-84f7-01324ab66899"
  }'
```

External IDs may only include alphanumeric characters, `_`, `-`, or `.` and must be between 10 and 256 characters.

If you already know the user's `fp_id`, pass it directly:

```bash
curl -X POST https://api.onefootprint.com/onboarding/session \
  -u sk_test_CXUsbCR8j2kH6e5GeEl8eSBnQTIPCUaKpv: \
  -d '{
    "kind": "onboard",
    "key": "pb_live_qBV2iO3nQI5moqo5GJlFhI",
    "fp_id": "fp_id_K0q6Eh6Rr3WOOfFBLPiHsr"
  }'
```

### Guarantee resolution to a specific business

For a KYB (Know Your Business) onboarding, pass a `business_external_id` alongside the user's, to log into the existing business with that `external_id` or create a new business with it. The located user must be recorded as an owner of the located business; otherwise the onboarding session returns an error.

```bash
curl -X POST https://api.onefootprint.com/onboarding/session \
  -u sk_test_CXUsbCR8j2kH6e5GeEl8eSBnQTIPCUaKpv: \
  -d '{
    "kind": "onboard",
    "key": "pb_live_qBV2iO3nQI5moqo5GJlFhI",
    "user_external_id": "8c992273-987d-4830-84f7-01324ab66899",
    "business_external_id": "2f55b318-5dec-4634-880f-38c4968d3b71"
  }'
```

The same character and length rules apply to `business_external_id`.

If you already know the business's `fp_bid`, pass it directly:

```bash
curl -X POST https://api.onefootprint.com/onboarding/session \
  -u sk_test_CXUsbCR8j2kH6e5GeEl8eSBnQTIPCUaKpv: \
  -d '{
    "kind": "onboard",
    "key": "pb_live_qBV2iO3nQI5moqo5GJlFhI",
    "fp_id": "fp_id_K0q6Eh6Rr3WOOfFBLPiHsr",
    "fp_bid": "fp_bid_fr7JHcV3hIzC7KbqTAsD3n"
  }'
```

### Bootstrap data

If your backend already holds data for the user, pass it as `bootstrap_data` and the flow prefills it for the user the session creates:

```bash
curl -X POST https://api.onefootprint.com/onboarding/session \
  -u sk_test_CXUsbCR8j2kH6e5GeEl8eSBnQTIPCUaKpv: \
  -d '{
    "kind": "onboard",
    "key": "pb_live_qBV2iO3nQI5moqo5GJlFhI",
    "bootstrap_data": {
      "id.first_name": "Jane",
      "id.last_name": "Doe"
    }
  }'
```

[Bootstrap data](/articles/integrate/bootstrap-data) lists the fields you can bootstrap and the format each one takes.

### Onboarding idempotency

By default, when a user starts an onboarding session for a playbook they have already onboarded onto, Footprint reuses the result of their last onboarding, so repeat onboardings do not incur accidental charges. `onboarding_external_id` gives you control over this: if the user already has an onboarding with that `onboarding_external_id`, its result is reused. If not, Footprint creates a new onboarding and the user reonboards.

For example, to let users reonboard onto the same playbook every time they fill out a new account application in your product, pass the application's identifier as `onboarding_external_id`:

```bash
curl -X POST https://api.onefootprint.com/onboarding/session \
  -u sk_test_CXUsbCR8j2kH6e5GeEl8eSBnQTIPCUaKpv: \
  -d '{
    "kind": "onboard",
    "key": "pb_live_qBV2iO3nQI5moqo5GJlFhI",
    "user_external_id": "8c992273-987d-4830-84f7-01324ab66899",
    "onboarding_external_id": "bc13ca5b-210f-49af-9aba-e98db366484a"
  }'
```

To let users reonboard onto the same playbook once a month, derive `onboarding_external_id` from the current month:

```bash
curl -X POST https://api.onefootprint.com/onboarding/session \
  -u sk_test_CXUsbCR8j2kH6e5GeEl8eSBnQTIPCUaKpv: \
  -d '{
    "kind": "onboard",
    "key": "pb_live_qBV2iO3nQI5moqo5GJlFhI",
    "user_external_id": "8c992273-987d-4830-84f7-01324ab66899",
    "onboarding_external_id": "onboarding-2025-01"
  }'
```

We recommend a value that implies some limit on how often a user can reonboard onto one playbook, since you are responsible for the charge each reonboard incurs.

`onboarding_external_id` follows the same character and length rules as other external IDs. Because it is scoped to an individual user, you must also pass either `fp_id` or `user_external_id` when you create the session.

### Collect outstanding data

When you have requested information from a user in the Footprint dashboard, an onboarding session for that user lets them provide whatever is still outstanding.

The dashboard can send the user a link itself. When you want more control over how you prompt the user, subscribe to the footprint.user.info\_requested webhook event and send your own notification when information is requested from the dashboard.

A common flow checks whether the user has an outstanding request with the GET /users/{fp_id} API:

```bash
curl https://api.onefootprint.com/users/fp_id_K0q6Eh6Rr3WOOfFBLPiHsr \
  -u sk_test_CXUsbCR8j2kH6e5GeEl8eSBnQTIPCUaKpv:
```

```json
{
  "id": "fp_id_K0q6Eh6Rr3WOOfFBLPiHsr",
  "requires_manual_review": false,
  "status": "pass",
  "requires_additional_info": {
    "timestamp": "2023-12-12T21:28:38.771377Z",
    "note": "Hi Christian, we can't wait for you to get started with your Acme Bank credit card! To finish verifying your identity, can you please submit a photo of your SSN card? Once received, we can approve your application and mail out your credit card."
  }
}
```

A non-null `requires_additional_info` means there is an outstanding request for this user. It also carries the human-readable note you wrote in the dashboard for the user, which you can render in your own app. Create an `inherit` onboarding session to collect the requested information:

```bash
curl -X POST https://api.onefootprint.com/onboarding/session \
  -u sk_test_CXUsbCR8j2kH6e5GeEl8eSBnQTIPCUaKpv: \
  -d '{
    "kind": "inherit",
    "fp_id": "fp_id_K0q6Eh6Rr3WOOfFBLPiHsr"
  }'
```

### Update login methods

An onboarding session can also let a user update any or all of their login methods (phone and email) through the Footprint Auth SDK. The user first logs in with an existing login method on their account, then can add a passkey or update their phone or email.

To limit which auth methods the user can update, pass the allowed methods in `limit_auth_methods` when you create the token. For example, to let the user update only their phone number:

```bash
curl -X POST https://api.onefootprint.com/onboarding/session \
  -u sk_test_CXUsbCR8j2kH6e5GeEl8eSBnQTIPCUaKpv: \
  -d '{
    "kind": "update_login_methods",
    "fp_id": "fp_id_K0q6Eh6Rr3WOOfFBLPiHsr",
    "limit_auth_methods": ["phone"]
  }'
```

Then pass the token to the SDK as `authToken`:

This flow needs `@onefootprint/footprint-js` 3.9.0 or later.

```javascript
import "@onefootprint/footprint-js/dist/footprint-js.css";
import footprint from "@onefootprint/footprint-js";

const handleClick = () => {
  const component = footprint.init({
    kind: "update_login_methods",
    authToken: "obtok_UxM6Vbvk2Rcy1gzcSuXgk3sj3L9I0pAnNH",
    onComplete: (validationToken) => {
      // TODO
    },
  });
  component.render();
};
```