---
title: "Connectors"
description: "`connectors.listApps`, `listAllApps`, `iterateApps`, `getApp` and `listCategories` for the apps that can be connected, `list`, `get`, `connect`, `update`, `disconnect` and `reconnect` for the connectors, `listActions`, `getAction` and `runAction` for what they can do, and `listCalls`, `listAllCalls` and `iterateCalls` for what was done."
url: "https://openemail.uk/docs/sdk/connectors"
area: "TypeScript"
category: "Mailbox"
---

# Connectors

`connectors.listApps`, `listAllApps`, `iterateApps`, `getApp` and `listCategories` for the apps that can be connected, `list`, `get`, `connect`, `update`, `disconnect` and `reconnect` for the connectors, `listActions`, `getAction` and `runAction` for what they can do, and `listCalls`, `listAllCalls` and `iterateCalls` for what was done.

## Every method

**connectors.ts**

```
const { items: apps } = await openemail.connectors.listApps({ search: 'slack' })
console.log(apps[0]?.slug, apps[0]?.auth, apps[0]?.connectable)

const started = await openemail.connectors.connect({
  app: 'slack',
  scope: 'workspace',
  label: 'Sales Slack',
  access: 'read',
})
console.log(started.connectUrl, started.connectExpiresAt)

let connector = await openemail.connectors.get(started.id)
while (connector.status === 'pending') {
  await new Promise((resolve) => setTimeout(resolve, 5000))
  connector = await openemail.connectors.get(connector.id)
}

const actions = await openemail.connectors.listActions(connector.id, { search: 'search messages' })
const action = await openemail.connectors.getAction(connector.id, 'SLACK_SEARCH_MESSAGES')
console.log(actions.map((entry) => entry.action), action.kind, action.input)

const found = await openemail.connectors.runAction(connector.id, 'SLACK_SEARCH_MESSAGES', {
  input: { query: 'renewal' },
})
console.log(found.ok, found.data, found.truncated)

await openemail.connectors.update(connector.id, { access: 'full' })
const sent = await openemail.connectors.runAction(connector.id, 'SLACK_SEND_MESSAGE', {
  input: { channel: 'sales', text: 'The renewal is signed.' },
})
if (!sent.ok) console.log(sent.error)

for await (const call of openemail.connectors.iterateCalls({ connectorId: connector.id })) {
  console.log(call.at, call.action, call.kind, call.status, call.source)
}

for (const shared of await openemail.connectors.list({ scope: 'workspace', status: 'expired' })) {
  const fresh = await openemail.connectors.reconnect(shared.id)
  console.log(shared.appName, shared.failure, fresh.connectUrl)
}

await openemail.connectors.update(connector.id, { paused: true })
await openemail.connectors.disconnect(connector.id)
```

A connector is an outside app that a person connected so the assistant can look things up in it and act there. `connect` only starts the connection: it resolves the connector, still `pending`, with a `connectUrl`, and a person opens that link to sign in to the app or to enter its key, on a page outside the API. `get` reads the connector fresh, and it is `active` once they have finished. `reconnect` resolves a new link for a connector that is `expired`, and the connector keeps its id.

`listActions` finds what the app can do by a few words, `getAction` resolves the input one action takes as a JSON Schema, and `runAction` runs it. An action that changes something runs at once: over the API nobody is asked first, so your code decides. A connector whose `access` is `read` refuses it with 403 `connector_read_only`. `listCalls` reads what was done through the connectors in the last 90 days, without inputs or results.

Reading needs `connectors:read`. `listActions`, `getAction` and `runAction` need `connectors:use`, and `connect`, `update`, `disconnect` and `reconnect` need `connectors:write`. An API key reaches workspace connectors only. A connector that belongs to one person is reached only by an app that person connected, which also needs `account:read`, or `account:write` to change it, and a key or a token limited to some addresses or domains reaches no workspace connector.
