# Call other applications

> Authorise another application by its id, call its actions from your code and your pages, show its settings on your home page, and expose your own.

An application can call the actions of another application instead of writing them again.

The examples use `$TOKEN`, `$API_KEY` and `$APP_ID` as [Build an
application](/docs/build-an-application/#the-credentials-in-the-examples) defines them.

## Dependencies: reuse a brick

Published applications are listed at `GET /v1/catalog`, and one of them, with the OpenAPI document
of the version it has in production, at `GET /v1/catalog/{app}`, `{app}` being its slug. Both are
public: an assistant that has to sign in before it can see what exists cannot compare two of them. Each
entry names its team's slug in `group`, `null` when the team has none; the older
`GET /v1/groups/{group}/apps/{app}` still answers for links already written.

Your own group's applications, private ones included, are bricks too: `catalog_search` and `catalog_read`
list those with a version in production, `app_list` lists them all, and your applications call them
without review.

Authorise the one you want, **by its `app_id`** — a name can be renamed, an id cannot:

```sh
curl -s -X PUT "https://api.eu.apigami.com/v1/apps/$APP_ID/dependencies/$OTHER_APP_ID" \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"uses_production_version":true}'
```

Nothing is deployed to authorise one, and the very next call is allowed. Removing one takes effect at
once, including on a run already in flight. Then call its action from your own code the way you call
your own, with the run token you were handed:

```ts
await fetch(`${API}/v1/apps/${OTHER_APP_ID}/actions/listMessages`, {
  method: 'POST',
  headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ since: '2026-09-01' }),
})
```

The user who approved *your* application does not connect to the one you use underneath: what it
needs is part of the sites your application declares, and that is what they saw when they connected to
your application. When it has settings for each person, your home page shows them
([Show the settings of the bricks you call](#show-the-settings-of-the-bricks-you-call)): the link people keep
is yours, not the brick's. The brick's own link is for its trials, where its author has the person connect
it and tries its actions on real data before you build on them. Your pages call its actions with `apigami.call(action, input, { app })`, under the same
authorisation. An application you call never learns which browser it is talking
to — it is given a stable reference that says two invocations came from the same one, and nothing
more.

A brick knows a person by the `user_ref` of its own group. It sees the same one whichever application
calls it, and the same as when the person uses it directly; it differs from the one your application
sees only when the brick belongs to another group. What they already set up in the brick, such as
tokens it keeps on that `user_ref`, works when your application calls it: nothing is asked again
unless the brick answers that a setting is missing (`X-Apigami-Settings`).

**When a brick fails, you get its own answer**: its status, its body and its headers, minus every
`X-Apigami-*` header it set, plus `X-Apigami-Run-Id` and `X-Apigami-Served-By`. An answer without
`X-Apigami-Run-Id` is Apigami refusing, `{ "error": "…" }`: the brick not among your dependencies or the
person not connected (`403`), a value missing from its environment (`409`). Past thirty seconds you get
`202 { run_id, state: "running" }` instead. Its `X-Apigami-Settings` never reaches you: Apigami records
the need for the person, `GET /v1/me` under your token lists it in `settings_needed`, and `apigami.js`
shows the banner on your pages. Pass the brick's status and message on; to send the person to repair it,
give your own connect link, `/connect?app_id={your app_id}`, whose home shows the brick's settings.

A brick called by Apigami, from your actions or your pages, gets its run token in `X-Apigami-Run` and no
`x-apigami-user-ref`: it reads the person with `GET /v1/me`, as any action does.

## Show the settings of the bricks you call

When your application calls a brick ([Dependencies: reuse a brick](#dependencies-reuse-a-brick)) that keeps
something for each person, a connection to a service or a default project, your home page shows its
settings, drawn by you from the brick's own actions. The person keeps one link, yours, and sets everything
up there. What they connected in the brick before, from its own link while its author tried it for
instance, is already connected here.

`catalog_read` lists a brick's settings actions, tagged `settings` in its manifest. Call them with
`apigami.call(action, input, { app })`. A brick that connects a service answers `settingsStatus` and
`signOut` ([Expose your settings](#expose-your-settings-to-the-applications-that-call-yours)), and its
connection opens with `apigami.open(brick, '/oauth/start')`:

```html title="your home page, the section of one brick"
<section id="mail"></section>
<script src="https://api.eu.apigami.com/apigami.js"></script>
<script type="module">
  const BRICK = 'THE_BRICK_APP_ID'
  const section = document.querySelector('#mail')
  const draw = async () => {
    const status = await apigami.call('settingsStatus', {}, { app: BRICK })
    const button = document.createElement('button')
    button.textContent = status.state === 'ok' ? 'Disconnect' : status.state === 'reconnect' ? 'Reconnect' : 'Connect'
    button.onclick = async () => {
      // apigami.open() is called before any await: the browser allows a window on a click only.
      if (status.state === 'ok') await apigami.call('signOut', {}, { app: BRICK })
      else await apigami.open(BRICK, '/oauth/start')
      draw()
    }
    section.replaceChildren(status.state === 'ok' ? `Connected: ${status.account} ` : 'Not connected ', button)
  }
  await apigami.ready()
  draw()
</script>
```

- `apigami.open` opens a window at once, then sends it to the brick's own address, where the brick gets
  its session for this person without a click, since approving your application covers the bricks it calls.
  The brick's `/oauth/start` then leads to the service.
- It resolves on the brick's `apigami:settings-changed` message, or when your page gets the focus back,
  since a service may cut the window off from your page: read the status again then.
- One connection serves every application that uses the brick. The brick knows the person by the same
  `user_ref` under each, so someone who connected it from another application finds it connected here.
- Your page calls only the applications yours may call directly. Before your page shows the settings of a
  brick that your brick calls, authorise that one for your application too.
- When a brick needs the person, a refused refresh token for instance, `apigami.js` shows a banner on your
  other pages, leading to your connect link, which opens your home: its section says what to do.

## Expose your settings to the applications that call yours

A brick is an application that others call ([Dependencies: reuse a brick](#dependencies-reuse-a-brick)).
When yours keeps something for each person, a connection to a service or a default, it exposes its
settings as actions, and each application that calls it shows them on its own home page
([Show the settings of the bricks you call](#show-the-settings-of-the-bricks-you-call)). In the manifest,
its OpenAPI and one small `settings` page in `x-apigami.pages`:

- Tag each settings action `"tags": ["settings"]`: a `post` that serves one person, `401` without a
  `user_ref`, with a `summary` written for that person. `catalog_read` lists them for the agent of each
  application that considers calling yours.
- A brick that connects a service answers two fixed names: `settingsStatus`, which answers
  `{ state: 'ok' | 'setup' | 'reconnect', account, settings? }` and always sets `X-Apigami-Settings` to
  that state, and `signOut`, which deletes the tokens and answers `{ state: 'setup' }`.
- Any other setting is a tagged action with a `requestBody`, such as `setDefaultProject`.
- The connection is not an action: the calling page opens your `/oauth/start` with `apigami.open()`, and
  your `/oauth/start` and `/oauth/callback` read the person in `x-apigami-user-ref`, as [Sign in to other services](/docs/app-sign-in/#sign-in-to-a-third-party-service-from-your-app-oauth-pkce-callback) shows. Your last page
  posts `{ type: 'apigami:settings-changed' }` to its `opener`, to the target `'*'` and carrying nothing
  else, then closes.
- Never answer a link from an action. Your own link is for your trials, and for someone who uses your
  application on its own: while you build it, give it to the person, so that they connect the service and
  you try your actions on their real data before an application builds on them. Once an application calls
  yours, people keep that application's link, whose home shows your settings, and approving it covers
  yours. A connection made from your link stays: you know the person by the same `user_ref` under every
  application that uses yours.
- Keep a minimal `settings` page for your own link to open: Connect, a link to your `/oauth/start` in the
  same tab, the account connected, from `settingsStatus`, and Disconnect, through `signOut`. Without one,
  your link ends on "Connected" and nothing lets the person sign in to the service.
- Your settings actions are an API: renaming one, or changing what it answers, breaks the section of every
  application that calls yours.