## What is this?

After users & processor tokens have been registered via `POST /v2/invite-tokens`, you might need to add more processor tokens to _unclaimed_ emails or email + invite code pairs using [Append processor tokens to an existing invite](https://developers.bloomcredit.io/reference/appendprocessortokens).

For example:

- You created an invite token for `alice@example.com` with one Plaid processor token representing her checking account.
- Later, Alice links her savings account too. You now have a second processor token for her. Alice has not registered for Bloom+ yet.
- Instead of deleting and recreating the invite token, you use this endpoint to append the new processor token to Alice's existing invite.

This can be done for multiple emails at once — up to 100 emails in a single request.

> **Note:** This endpoint only works for organizations that have processor tokens enabled. If your organization only uses invite codes (no processor tokens), this endpoint will return an error.

---

## Quick start

### Append one token to one email

Bash

```shell
curl -X PATCH https://<your-bloom-api-host>/v2/invite-tokens/processor-tokens \
  -H "Content-Type: application/json" \
  -H "x-partner: a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
  -d '{\n    "items": [\
      {\
        "email": "alice@example.com",\
        "processor_tokens": ["processor-sandbox-new-token"]\
      }\
    ]\
  }'
```

### Append multiple tokens to multiple emails

Bash

```shell
curl -X PATCH https://<your-bloom-api-host>/v2/invite-tokens/processor-tokens \
  -H "Content-Type: application/json" \
  -H "x-partner: a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
  -d '{\n    "items": [\
      {\
        "email": "alice@example.com",\
        "processor_tokens": [\
          "processor-sandbox-alice-savings",\
          "processor-sandbox-alice-investment"\
        ]\
      },\
      {\
        "email": "bob@example.com",\
        "processor_tokens": [\
          "processor-sandbox-bob-savings"\
        ]\
      }\
    ]\
  }'
```

> Replace `<your-bloom-api-host>` with the base URL provided by your Bloom representative.
>
> Replace the `x-partner` UUID with your actual organization ID.

---

## Before you begin

### 1. You need existing invite tokens

This endpoint **adds** processor tokens to existing invite tokens. It does not create new invite tokens. If the email doesn't already have an invite token, the request will fail for that email.

To create invite tokens in the first place, use the batch create endpoint:

```undefined
POST /v2/invite-tokens
```

### 2. The invite token must be unused and not expired

You can only append processor tokens to invite tokens that:

- Have **not been used** yet (the user hasn't enrolled)
- Have **not expired** (the expiration date hasn't passed)

If the invite token has already been used or has expired, the request will fail for that email.

### 3. Your organization ID (`x-partner`)

This is a UUID that identifies your organization, in UUID format. For example:

```undefined
a1b2c3d4-e5f6-7890-abcd-ef1234567890
```

If you don't have your organization ID, reach out to your Bloom representative.

### What's the difference between this endpoint and `POST /v2/invite-tokens`?

|  | `POST /v2/invite-tokens` | `PATCH /v2/invite-tokens/processor-tokens` |
| --- | --- | --- |
| **Purpose** | Create new invite tokens | Add processor tokens to existing invite tokens |
| **Creates invite tokens?** | Yes | No |
| **Generates invite codes?** | Yes (if enabled) | No |
| **Requires existing invite token?** | No | Yes |
| **Sets expiration?** | Yes | No (uses the existing expiration) |

---

## Bloom API call

```undefined
PATCH /v2/invite-tokens/processor-tokens
```

Appends processor tokens to multiple existing invite tokens at once. Requires authentication via the `x-partner` header.

API reference: [Append processor tokens to an existing invite](https://developers.bloomcredit.io/reference/appendprocessortokens)

### Headers

| Header | Value | Description |
| --- | --- | --- |
| `x-partner` | Your organization UUID | Identifies your organization. Required. |
| `Content-Type` | `application/json` | Always `application/json`. Required. |

If `x-partner` is missing, invalid, or doesn't match a known organization, you will get a `401 Unauthorized` error.

### Request body

JSON

```json
{
  "items": [\
    {\
      "email": "alice@example.com",\
      "processor_tokens": ["processor-sandbox-new-token-1"]\
    },\
    {\
      "email": "bob@example.com",\
      "processor_tokens": ["processor-sandbox-new-token-2", "processor-sandbox-new-token-3"]\
    }\
  ]
}
```

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | array | Yes | List of emails with processor tokens to append. Min: 1, Max: 100 per request. |

Each item in the `items` array:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `email` | string | Yes | The email address of the existing invite token. Max 254 characters. |
| `processor_tokens` | string[] | Yes | New processor tokens to add. Min: 1, Max: 25 per email, each max 255 characters |

### Example

Suppose Alice already has an invite token with one processor token (`existing-checking-token`), and you want to add a second one for her savings account.

**Request:**

JSON

```json
{
  "items": [\
    {\
      "email": "alice@example.com",\
      "processor_tokens": ["new-savings-token"]\
    }\
  ]
}
```

**Response:**

JSON

```json
{
  "success_count": 1,
  "succeeded": [\
    {\
      "email": "alice@example.com",
      "processor_tokens": ["existing-checking-token", "new-savings-token"]\
    }\
  ],
  "failed": []
}
```

> Notice that `processor_tokens` in the response includes **all** tokens — both the one Alice already had (`existing-checking-token`) and the one you just added (`new-savings-token`). You always get the full picture back.

That's it. You send the email and the new tokens, and you get back the complete list of everything that's now associated with that invite.

### Response

Every response has the same shape, regardless of how many items succeeded or failed:

JSON

```json
{
  "success_count": 1,
  "succeeded": [ ... ],
  "failed": [ ... ]
}
```

| Field | Type | Description |
| --- | --- | --- |
| `success_count` | integer | How many emails were successfully updated. |
| `succeeded` | array | List of emails that were updated, with their full processor token list. |
| `failed` | array | List of emails that were NOT updated, with reasons. |

> **Note:** `succeeded` and `failed` are always JSON arrays, never `null`. If all items succeed, `failed` will be `[]`. If all fail, `succeeded` will be `[]`.
>
> The response preserves the order of the input. If you sent `[alice, bob, charlie]`, the response items will be in the same order across both `succeeded` and `failed`.

Each item in `succeeded`:

| Field | Type | Description |
| --- | --- | --- |
| `email` | string | The email address. |
| `processor_tokens` | string[] | The **full** list of all processor tokens now associated with this invite, including both old and new tokens. |

Each item in `failed`:

| Field | Type | Description |
| --- | --- | --- |
| `email` | string | The email address that failed. |
| `error` | string | A human-readable reason why it failed. |

### After the request

Compare `success_count` against the number of items you sent — did they all go through?

Check the `processor_tokens` array in each `succeeded` item — it shows the **full** list of tokens after the append, so you can confirm the new ones were added.

Check `failed` for any items that didn't go through. Read the `error` field to understand why and fix accordingly.

**Do not assume everything succeeded just because the HTTP status is 200.** Always check both `succeeded` and `failed`.

---

### Example: All succeed

You already created invite tokens for Alice and Bob with one processor token each. Now you're adding a second token to each.

**Request:**

JSON

```json
{
  "items": [\
    {\
      "email": "alice@example.com",\
      "processor_tokens": ["processor-sandbox-alice-savings"]\
    },\
    {\
      "email": "bob@example.com",\
      "processor_tokens": ["processor-sandbox-bob-savings"]\
    }\
  ]
}
```

**Response:**

JSON

```json
{
  "success_count": 2,
  "succeeded": [\
    {\
      "email": "alice@example.com",
      "processor_tokens": ["processor-sandbox-alice-checking", "processor-sandbox-alice-savings"]\
    },\
    {\
      "email": "bob@example.com",
      "processor_tokens": ["processor-sandbox-bob-checking", "processor-sandbox-bob-savings"]\
    }\
  ],
  "failed": []
}
```

Notice that `processor_tokens` in the response includes **all** tokens — both the original ones (`*-checking`) and the newly appended ones (`*-savings`).

---

### Example: Partial success

Alice's append works, but Bob's fails because he doesn't have an invite token yet.

**Response:**

JSON

```json
{
  "success_count": 1,
  "succeeded": [\
    {\
      "email": "alice@example.com",
      "processor_tokens": ["processor-sandbox-alice-checking", "processor-sandbox-alice-savings"]\
    }\
  ],
  "failed": [\
    {\
      "email": "bob@example.com",
      "error": "no unused, non-expired invite token found for email"\
    }\
  ]
}
```

---

### Example: Tokens already associated

You try to append `
