# Connect an app

Nothing can act until an account is connected. This page covers connecting one yourself, connecting one on behalf of somebody using your product, what happens when a connection goes stale, and how to bound what a connection is allowed to ask for.

## Connect one yourself

Open **Connect** in the console. It lists every app this project can reach and the accounts already connected to each. Pick one and follow the sign-in.

Most apps use a sign-in flow: atmon sends you to the app, the app asks whether you agree, and you come back with a connected account. Some use a long-lived key instead, in which case the screen asks for the key rather than sending you anywhere.

Every connection belongs to a person you name. In the console that defaults to you. When your own product connects accounts, you name the person yourself.

## Connect one for somebody else

This is what a product does inside its own settings screen. Two steps.

Start the connection, naming the person and the app:

```ts
const { connectedAccountId, authorizationUrl } =
  await atmon.connections.initiateConnection({
    entityId: "user-42",
    toolkitSlug: "github",
  });
```

Then send that person to `authorizationUrl`. They sign in at the app, the app returns them to atmon, and the account becomes active. Until that happens the account is pending, and a pending connection that nobody finishes expires on its own after ten minutes.

For an app that takes a key rather than a sign-in, submit the key instead. It is sealed the moment it arrives, and there is no call anywhere on any surface that reads a stored credential back out.

You never see a token either way. Your code holds an account id; atmon holds the credential and attaches it to outbound requests itself.

## What happens when you act

You never pick a credential. An action names a person and a tool, and atmon uses that person's active account for the app that tool belongs to.

If there is no active account, the call comes back refused with the code `not_connected`, before anything is sent. That is the signal to show a connect button rather than an error.

## When a connection goes stale

Connections are kept fresh in the background, ahead of expiry, so an action does not stall waiting for a refresh. When refreshing stops working, the account is marked expired and calls to it answer `auth_expired`.

That one is not something a retry fixes. The person has to sign in again. Treat `auth_expired` in your product the way you would treat a signed-out state: show a reconnect prompt, addressed to the person whose account it is.

Disconnecting is immediate on our side, and it also tells the app to forget the grant where the app supports being told.

## Bound what a connection may ask for

Sign-in screens ask for permissions, and by default a connection asks for what the app's connector declares it needs. You can narrow that per app in the policy document:

```ts
await approver.policy.setPolicy({
  policy: {
    scopeCaps: [{ toolkitSlug: "github", maxScopes: ["repo:status", "public_repo"] }],
  },
});
```

The cap is checked before the sign-in screen is built, not when a call is made. That timing is the reason it works: once a person has agreed to a permission, the grant is real whatever happens next, so the only place to stop it is before the screen exists.

An entry that permits nothing at all is how you stop new connections to an app without disconnecting the ones already there. With no caps written, nothing is capped. Writing them takes an approver key; see [Policies](./policies.md).

## What one tool needs

Each tool says which permissions it requires. `describe_tool` returns them, and each app's page in the [toolkit catalog](../reference/toolkits/index.md) lists them per tool. A call that the app refuses for want of a permission is a reconnection with a wider request, subject to whatever caps you set.

## From your own code

The connection calls are documented in the [ConnectionsService reference](../reference/api/connections.md): starting a flow, submitting a key, reading an account's state, and disconnecting.
