Skip to content

Call other applications

Markdown

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 defines them.

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:

Terminal window
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:

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): 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.

When your application calls 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), and its connection opens with apigami.open(brick, '/oauth/start'):

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

Section titled “Expose your settings to the applications that call yours”

A brick is an application that others call (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). 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 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.