> This page is for Unified.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.merge.dev/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.merge.dev/_mcp/server.

# Bootstrap

> How to bootstrap a Linked Account by passing Merge the integration credentials you already have, so your end user does not have to authorize again.

---

Bootstrapping creates a Linked Account from credentials you already hold, so your end user never sees an authorization screen. You send Merge the credentials and the end user's details, Merge validates them against the third-party platform, and the account completes and starts syncing.

Use it when the authorization already happened somewhere else:

* **Migrating in-house integrations to Merge**, where you hold the credentials and don't want to ask every customer to reconnect
* **Moving off another integration provider**, where you can export credentials and hand them over in one pass
* **Onboarding an end user without Link**, where you control the connection experience in your own product

Bootstrapping is enabled per organization and per integration, and Merge sets up how credentials are held and refreshed with you at the same time. [Contact Merge](https://www.merge.dev/get-in-touch) to turn it on and to confirm the integrations you need.

---

## How it works

Your backend posts the credentials to `/integrations/bootstrap-linked-account` with your API key. Merge validates them with a live call to the third-party platform, then creates the Linked Account and starts the initial sync. There is no `link_token` and no `public_token` exchange, so the account token comes back in the response and the `linked_account.linked` webhook fires just as it does for an account created through Link.

Because validation is live, a call fails when the credentials are expired or missing a scope. Treat a failure as a signal to re-authorize that end user rather than to retry.

**`cURL`**

```bash cURL
curl --request POST \
  --url https://api.merge.dev/api/integrations/bootstrap-linked-account \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "integration": "jira",
    "category": "ticketing",
    "end_user_origin_id": "customer_abc",
    "end_user_email_address": "alice@acme.com",
    "end_user_organization_name": "Acme",
    "linked_account_credentials": {
      "oauth_access_token": "YOUR_END_USER_ACCESS_TOKEN"
    },
    "additional_auth_fields": {
      "base-url": "https://acme.atlassian.net"
    }
  }'
```

```python
import requests

response = requests.post(
    "https://api.merge.dev/api/integrations/bootstrap-linked-account",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "integration": "jira",
        "category": "ticketing",
        "end_user_origin_id": "customer_abc",
        "end_user_email_address": "alice@acme.com",
        "end_user_organization_name": "Acme",
        "linked_account_credentials": {
            "oauth_access_token": "YOUR_END_USER_ACCESS_TOKEN"
        },
        "additional_auth_fields": {"base-url": "https://acme.atlassian.net"},
    },
)

linked_account = response.json()
```

A successful call returns `201` with `linked_account_id` and `account_token`. Store the account token against your end user the same way you would after a Link session.

### Request parameters

| Parameter                                   | Type    | Description                                                                                                                                                              |
| ------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `integration`                               | String  | Slug of the third-party platform, for example `jira`                                                                                                                     |
| `category`                                  | String  | Required when the integration serves more than one category                                                                                                              |
| `end_user_origin_id`                        | String  | Your unique ID for the end user                                                                                                                                          |
| `end_user_email_address`                    | String  | Email address of the end user                                                                                                                                            |
| `end_user_organization_name`                | String  | Name of the end user's organization                                                                                                                                      |
| `linked_account_credentials`                | Object  | The credentials Merge should use for this Linked Account, such as OAuth tokens, an API key, or a client id and secret. OAuth 2.0 access tokens are what it accepts today |
| `additional_auth_fields` *(Optional)*       | Object  | Connection details the integration needs, such as a domain or base URL                                                                                                   |
| `category_common_model_scopes` *(Optional)* | Object  | Common Model and field permissions for this account. Anything you leave out inherits your organization's settings                                                        |
| `require_selective_sync` *(Optional)*       | Boolean | Leave the account incomplete so your end user can choose what to sync. Defaults to `false`                                                                               |

To find out what an integration expects in `additional_auth_fields`, post the same `integration` and `category` to `/integrations/bootstrap-linked-account/meta`. The response names each required field with its type and a description, and an empty response means the integration needs credentials only.

---

## Letting your end user choose what to sync

Some end users need to pick which files, channels, or mailboxes Merge can access even when you hold their credentials. Set `require_selective_sync` to `true` and the account is created but left incomplete, so nothing syncs until the selection is made.

To collect it, create a [link token](/merge-unified/filestorage/linked-account/link-token/create) with `completed_account_initial_screen` set to `SELECTIVE_SYNC` and open Merge Link as usual. Your end user lands on the picker instead of an authorization screen, and the account completes when they submit. This is available for File Storage, Chat, and Email.

---

## Failures

A call that fails validation returns `400` with the reason in `non_field_errors`, and the third-party platform's raw response in `raw_api_response` where it gave one. The usual causes are an expired token, a missing scope, or a missing entry in `additional_auth_fields`. A `400` reading `Integration and admin level not supported` means the integration is not enabled for your organization yet.

Calling bootstrap again for an `end_user_origin_id` that already has a Linked Account reuses that account rather than creating a second one.

---

## Next steps

#### [Linked Accounts →](/merge-unified/platform-and-account-metadata/linked-accounts)

How Linked Accounts, end users, and account tokens fit together

#### [Merge Link options →](/merge-unified/merge-link/overview)

The delivery methods for end users who do need to authorize