# Client-side vaulting

Footprint's unified onboarding and vaulting platform makes it simple to vault sensitive user data directly from client-side contexts like a mobile app or a web app.

## Prequisites

Please read our [Server-side API Authentication guide](/articles/integrate/api-authentication).

## Step 1: Use an existing vault or create a new one (server-side)

For each user in your system you should create a single Footprint user vault (server side). If your user doesn't have an `fp_id` yet, create a new user using the `POST /users` API.

### Example request

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

### Example response

```json
{
  "id": "fp_id_K0q6Eh6Rr3WOOfFBLPiHsr"
}
```

If you're migrating other sensitive data, [read our guide here](/articles/integrate/migrate-existing-data)
Make sure to store the `fp_id` on your user record to access and vault data.

## Step 2: Create a client token (server-side)

In order to vault data directly from client code, you need to generate a short-lived client token.

Footprint's vault supports several types of structured data like identity data, card-holder data, and custom data for arbitrary key-value records. For structured data Footprint can validate that data is in the right format to ensure that you can reliably use this data in various applications and reporting/compliance needs. For unstructured data, you can store any other sensitive user data that may not fit the mold.

[Learn more about how to namespace and vault identity, card, and custom data](/articles/vault/apis#payment-cards). Note that card objects can be named, i.e. `card.primary` or `card.secondary`. This lets you store arbitrarily many cards in a user vault and control the naming scheme for each card.

### Example request

```bash
curl https://api.onefootprint.com/users/fp_id_K0q6Eh6Rr3WOOfFBLPiHsr/client_token \
	-X POST \
    -u sk_test_CXUsbCR8j2kH6e5GeEl8eSBnQTIPCUaKpv: \
    -d '{
          "fields": [
            "card.primary.number",
            "card.primary.cvc",
            "card.primary.expiration",
            "card.primary.name"
          ],
          "scope": "vault",
          "ttl": 180
      }'
```

Be sure to specify the exact list of fields that you plan to vault.

### Example response

```json
{
  "expires_at": "2023-05-24T14:15:22Z",
  "token": "ctok_vJK5Ze2N5fQ1GtE5V770BH8CZtQwXHF1hxowB9Nowh0"
}
```

Now that you have this client token, you can transmit it to your client code and use it to vault data directly from the client.

## Step 3: Use the client token store data in the vault (client-side)

From your client-side app, vault the data directly to footprint:

### Example request

```bash
curl https://api.onefootprint.com/users/vault \
	-X PATCH \
    -H 'x-fp-authorization: ctok_vJK5Ze2N5fQ1GtE5V770BH8CZtQwXHF1hxowB9Nowh0' \
    -d '{
            "card.primary.number": "4242424242424242",
            "card.primary.cvc": "424",
            "card.primary.expiration": "10/25",
            "card.primary.name": "Whitfield Diffie"
      }'
```

You will only have permissions to vault the exact fields specifically requested in Step 2.

### Example response

A successful response will return status 200 and an empty object.

## Step 4 (optional): Use a client token to decrypt data

Footprint's client side vaulting APIs support two ways of decrypting data: structured decryption and downloads.

### Structured Decrypt Example

Structured decryption is useful when you need to decrypt several smaller fields like `ssn` or `card.*.number` at once. This API is similar to its backend counter-part.

On your backend, create a client side token with a single field and the `decrypt` scope. This token is safe to pass to your frontend because it has a short expiration time and limited scope.

```bash
curl https://api.onefootprint.com/users/fp_id_K0q6Eh6Rr3WOOfFBLPiHsr/client_token \
    -X POST \
    -u sk_test_CXUsbCR8j2kH6e5GeEl8eSBnQTIPCUaKpv: \
    -d '{
          "fields": [
            "id.ssn9",
            "card.primary.number"
          ],
          "scope": "decrypt",
          "ttl": 180,
          "decrypt_reason": "test structured"
      }'
```

```json
{
  "expires_at": "2023-07-31T14:15:22Z",
  "token": "ctok_vJK5Ze2N5fQ1GtE5V770BH8CZtQwXHF1hxowB9Nowh0"
}
```

On your client, you can make a request to the decrypt endpoint using the token generated above. You will be able to decrypt any field specified when creating the token.

```bash
curl https://api.onefootprint.com/users/vault/decrypt \
    -X POST \
    -H 'x-fp-authorization: ctok_vJK5Ze2N5fQ1GtE5V770BH8CZtQwXHF1hxowB9Nowh0' \
    -d '{
        "fields": ["id.ssn9", "card.primary.number"]
      }'
```

```json
{
  "id.ssn9": "1212121212",
  "card.primary.number": "424242424242424"
}
```

### Download Decrypt

Download decryption is most useful for decrypting larger objects like files. This is especially useful when you'd like to have a user download this file directly instead of decrypting it.

On your backend, create a client side token with a single field and the `decrypt_download` scope.

```bash
curl https://api.onefootprint.com/users/fp_id_K0q6Eh6Rr3WOOfFBLPiHsr/client_token \
    -X POST \
    -u sk_test_CXUsbCR8j2kH6e5GeEl8eSBnQTIPCUaKpv: \
    -d '{
        "fields": [
          "custom.paystub_w2"
        ],
        "scope": "decrypt_download",
        "ttl": 180,
        "decrypt_reason": "download w2 test"
      }'
```

```json
{
  "expires_at": "2023-07-31T14:15:22Z",
  "token": "ctok_vJK5Ze2N5fQ1GtE5V770BH8CZtQwXHF1hxowB9Nowh0"
}
```

Now, the client can decrypt and download this object with a simple GET request. The response body will entirely comprise the contents of the object specified in `fields` above. This can easily be used by your frontend to download the contents directly to the user's device.

```bash
curl https://api.onefootprint.com/users/vault/decrypt/ctok_vJK5Ze2N5fQ1GtE5V770BH8CZtQwXHF1hxowB9Nowh0
```