> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bijection.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Connecting and Syncing

> Provide credentials, verify the account, install sources and follow syncs

An integration definition says how to talk to a provider. A connection says
which provider, as which account, with which credential, in one deployment.
Credentials never appear in your code: they are stored privately in the
deployment and only the host uses them, for the requests the definition
declares.

You set up a connection with the
[`bijection integration`](/integrations/cli) commands, or from the Sources page
of the console.

<Steps>
  <Step title="Deploy the integration and schema">
    Push the integration definition and the schema that binds its collections,
    for example with `bijection dev`. Synced tables exist from this point on,
    empty.
  </Step>

  <Step title="Store the credential">
    Create a private credential from a file or from piped stdin:

    ```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
    bijection integration credential-create CRM_CREDENTIAL --from-file crm-credential.json
    ```
  </Step>

  <Step title="Configure the connection">
    Name the connection, point it at the integration's address and the
    provider's base URL, and reference the credential:

    ```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
    bijection integration configure crm \
      --module crm.js --export crm \
      --base-url https://crm.example.com/api \
      --credential-ref CRM_CREDENTIAL
    ```
  </Step>

  <Step title="Verify the account">
    Admit an identity check under a request ID of your choice, then run it:

    ```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
    bijection integration identify crm verify-1
    bijection integration run verify-1
    ```
  </Step>

  <Step title="Install the source">
    Install the synced table's source on the verified connection:

    ```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
    bijection integration install crm customers
    ```

    The command prints the new source's ID. From now on the collection is read
    on its `sync.every` schedule and the `customers` table fills in.
  </Step>
</Steps>

## Store the credential

`credential-create` reads the value from `--from-file` or from piped stdin,
never from an argument, and never prints it. The value must be valid UTF-8 and
at most 8 KiB, and every byte is kept, including a trailing newline. Use
`credential-rotate` with the same name to replace it later, and
`credential-status` to inspect its metadata.

For an HTTP integration, the credential is a JSON envelope that names its kind
and the origins it may be sent to:

```json crm-credential.json theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
{
  "kind": "bearer",
  "token": "…",
  "allowed_resource_origins": ["https://crm.example.com"]
}
```

`allowed_resource_origins` lists one to eight origins, and one of them must be
the origin of the connection's base URL. The credential is never sent anywhere
else. A bare secret is refused with `IntegrationCredentialEnvelope`.

| `kind` | Fields |
| - | - |
| `bearer` | `token` |
| `keyword` | `scheme`, `token`, optional `parameter`: an `Authorization` scheme other than `Bearer` |
| `basic` | `username`, `password` |
| `api_key` | `name`, `value`, `placement` (`header`, `query` or `body`) |
| `oauth_refresh` | `token_endpoint`, `client_id`, `client_secret`, `refresh_token`, optional `scope` |
| `oauth_client_credentials` | `token_endpoint`, `client_id`, `client_secret`, optional `scope` and `resource_headers` |
| `sigv4` | `access_key_id`, `secret_access_key`, `region`, `service`, optional `session_token` |
| `goog4` | `access_key_id`, `secret_access_key` |

Every kind also takes `allowed_resource_origins`.

[PostgreSQL](/integrations/postgres#connecting) and [mail](/integrations/mail)
integrations use their own private configuration instead of an envelope.

## Configure the connection

`configure` creates or updates a named connection. The name, `crm` above, is
how the other commands refer to it.

* `--module` and `--export` name the integration's address: the module path
  inside `bijection/`, with `.js`, and the export name.
* `--base-url` is the provider's API address. It must use `https` (plain
  `http` only for a loopback address) and carry no query, fragment or user
  info. The contracts' routes are appended to it. Omit it for PostgreSQL and
  mail integrations.
* `--credential-ref` names the credential.
* `--component` selects a component; the default is the root.
* `--setup key=value` supplies a [setup field](/integrations/defining-integrations#setup-fields)
  the definition declares. `--show-setup` lists them without changing
  anything.

Changing a connection's configuration clears its verification and stops work
started under the old configuration. Verify it again before its sources sync.

## Verify the account

`identify` admits a run of the definition's
[`identify` handler](/integrations/defining-integrations#verifying-the-account),
and `run` executes it. The provider account it reads becomes the connection's
verified identity, and later syncs are checked against it.

The request ID is yours to choose and identifies the work. If a command's
response is lost, run it again with the same ID to recover the same request
instead of starting another. `bijection integration status <request-id>` shows
where a request stands.

## Install sources

`install <connection> <table>` installs the source that fills one synced table
from a verified connection. It prints the source ID, the same value synced
documents carry in `source_id`. Install each synced table of the integration
you want to fill.

`bijection integration sources` lists the installed sources with their
connection and sync health.

## Following syncs

`bijection integration source-status <source>` shows a source's schedule, its
state and any work it retains. The console's Sources page shows the same
information for every source, grouped by connection.

A source is in one of these states:

* **Scheduled**: it syncs on its interval.
* **Retrying**: a sync failed in a way that can succeed later, and a retry is
  scheduled.
* **Blocked**: a sync can't continue without you. Published data stays
  readable.

### Sync history

<Warning>Sync history is in beta.</Warning>

Each source keeps its open sync and its newest 50 finished syncs. For each run
you see when it started, what started it (the schedule, a manual request, a
provider notification, reconciliation or a repair), its state, and what it
admitted: pages, requests, response bytes and records received. Records
received count what the run admitted, not the rows that changed in the table:
a sync that found nothing new completes with records received and nothing
published.

The history appears under each source in the console, and in the `syncs`
field of `source-status`.

### Sync now

To sync a source before its next scheduled run:

```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
bijection integration refresh <source>
```

or click **Sync now** on the source in the console. If a sync is already
running, the request is served by the next one rather than starting a second
sync.

### Test connection

<Warning>Connection checks are in beta.</Warning>

**Test connection** on a source in the console runs the connection's
`identify` handler again and compares the answer with the verified account,
without changing the connection. The result is one of:

* **Confirmed**: the connection answers as the account it was verified as.
* **Identity differs**: the connection now answers as a different account.
  Syncs keep their verified connection; reconfigure or verify it again.
* **Unverified**: the connection answered, but was never verified.
* **Failed**, with the reason.

### From your application

<Warning>Sync history, Sync now and connection checks in applications are in beta.</Warning>

An application built with `applicationQueries` from `bijection/server` also
exposes three functions for its synced collections, for signed-in users only:

* `sourceSyncs({ collection, source? })` lists the collection's sources, each
  with its handle (the `source_id` its rows carry), status, open and latest
  sync and connection check. Name a `source` to also get its history, newest
  first, at most 50 syncs. Counts and times are exact `bigint`s. A user who
  may not read the collection's rows is refused.
* `requestSourceSync({ collection, source })` is **Sync now**. It answers
  `accepted`, or `coalesced` when a sync was already requested. It is
  refused for a source whose connection was reconfigured since it was
  installed; install it again first.
* `requestConnectionCheck({ collection, source })` records a check for the
  calling user and answers its `request` ID. The user then runs it with
  `runConnectionCheck` from `bijection/apps` and their own token. If the
  response is lost, running the same ID again finishes the check or returns
  its result.

Both requests spend provider budget, so nobody can make them until you decide
who may, with `sourceControl`. It runs after your `authorize` function, and
only `true` allows the request. The user also needs read access to the
source's rows.

```ts bijection/application.ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
import { applicationQueries } from "bijection/server";
import { requireMember, isAdmin } from "./membership";

export const { sourceSyncs, requestSourceSync, requestConnectionCheck } =
  applicationQueries({
    collections: { customers: { label: "Customers" } },
    operations: {},
    authorize: requireMember,
    // Admins may sync any source; everyone else may only read the history.
    sourceControl: async (ctx) => isAdmin(ctx),
  });
```

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
import { applicationApi, runConnectionCheck } from "bijection/apps";

const api = applicationApi();
const { request } = await client.mutation(api.requestConnectionCheck, {
  collection: "customers",
  source,
});
const result = await runConnectionCheck(deploymentUrl, token, {
  source,
  request,
});
```

## When a sync stops

When a source is blocked, `source-status` reports the reason and the ID of the
retained work. After fixing the cause, resume exactly that work:

```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
bijection integration resume <source> <request-id>
```

To give up on the current sync instead, cancel it; future syncs stay
scheduled:

```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
bijection integration cancel-source <source> <request-id>
```

Deploying a changed integration definition stops work that started under the
old code. If a source is blocked after a deploy, run `install` again for the
same connection and table to update its binding, then `resume` it. The
console does both with **Update binding and resume**.

## Connected accounts

<Warning>Connected accounts are in beta.</Warning>

A connection configured with `configure` uses one deployment credential. An
integration can instead be connected by an application user with their own
provider account, through the provider's authorization flow. The
`account-*` commands and the connected accounts panel on the Sources page drive
this flow:

1. `account-authorize` starts an authorization for an application user and
   returns the provider URL to visit.
2. `account-callback` completes it with the code the provider returns.
3. `account-resources` lists what the account offers to read, and
   `account-select` installs the chosen resources.

Four lifecycle operations have different effects:

| Operation | Syncing | Provider authority | Synced records |
| - | - | - | - |
| `account-pause` | Stopped | Kept | Kept |
| `account-resume` | Resumed | Kept | Kept |
| `account-disconnect` | Stopped | Revoked | Kept |
| `account-erase` | Stopped | Revoked | Removed |

Disconnecting is final for that authorization: reconnecting starts a new one.
Erasing requires a disconnected account and removes the records its sources
published, but not effects already delivered to the provider. See the
[CLI reference](/integrations/cli#connected-accounts) for every option.
