Connected accounts
Connect an account at a provider such as Stripe, GitHub or Notion with an API key. It becomes a secret bound to that provider's API, never shown to you or to an agent.
The ten integrations that connect with an API key are available now. The integrations you sign in to (HubSpot, Slack and Google Calendar) are coming one at a time in later releases; this page already describes how signing in works.
A connected account is a secret connected for one integration and bound to that integration’s API hosts. There are two ways to connect, and each integration uses one:
- Sign in (coming: HubSpot, Slack, Google Calendar). You approve Anlyon’s access on the provider’s own consent page. The secret is of kind
connection: instead of a value, it holds the account. When an action that references it runs, Anlyon fetches the account’s current access token, puts it in the request header, sends the request, and forgets it. - API key. You create a key in the provider’s own settings and paste it (Stripe, GitHub, Intercom, Attio, Notion, Sentry, PagerDuty, Asana, Discord, Resend). Anlyon checks the key with the provider before storing it. The secret is of kind
static, withintegrationIdset.
Actions use either exactly like any secret:
"headers": { "Authorization": "Bearer {{secret:HUBSPOT}}" }
Where the credential lives, and who sees it
- A sign-in token is held by Anlyon’s connector service, a separate component Anlyon operates on its own infrastructure. It stores the token encrypted and refreshes it when it expires. It is fetched at dispatch, for that one request.
- An API key is held in Anlyon’s secret store, encrypted, like any secret you store. The connector service is not involved.
- Either is redacted from every response and error Anlyon records.
- No API returns it. Not to you, not to the console, and not to an agent. The secret’s metadata says which integration it is and, in
health, whether it still works, for a key and a sign-in alike. - It can only go where the provider’s API is. A connected account is bound to the integration’s API hosts, which Anlyon sets, and it may appear only in a header. An action that addresses any other host is refused. For an API key these are set from the integration and cannot be chosen when you connect.
GET /api/v2/secrets/{name} shows a connected account like this. Signed in:
{
"name": "HUBSPOT",
"kind": "connection",
"connection": { "integrationId": "hubspot", "status": "active" },
"integrationId": "hubspot",
"health": { "status": "active", "checkedAt": "2026-10-15T08:00:00.000Z", "reason": null },
"allowedHosts": ["api.hubapi.com"],
"allowedPlacements": ["header"]
}
Connected with an API key:
{
"name": "GITHUB",
"kind": "static",
"connection": null,
"integrationId": "github",
"health": { "status": "active", "checkedAt": "2026-10-15T08:00:00.000Z", "reason": null },
"allowedHosts": ["api.github.com"],
"allowedPlacements": ["header"]
}
`health` is the same record for both. `status` is `active`, or `needs_reauth` once the account stopped working; `checkedAt` is when Anlyon last asked the provider; `reason` says why it stopped. See [Does it still work?](#does-it-still-work) below.
Connect an account
In the console: Actions → Integrations. Choose the integration, press Connect, and give the secret a name.
- For a sign-in integration, Anlyon shows the access it will ask for and the hosts the token may reach, then opens the provider’s consent page in a window. When you approve, the account appears under the integration.
- For an API-key integration, Anlyon shows where in the provider’s settings to create the key and which permissions to give it, with a link to that page, and a field to paste it into. When the provider accepts the key, the account appears under the integration.
From the CLI:
anlyon connections integrations # what can be connected, and how
anlyon connections add hubspot --secret HUBSPOT # sign-in: opens the consent page, waits, prints the secret
anlyon connections add github --secret GITHUB # API key: shows the instructions, then asks for the key without echoing it
anlyon connections list
The same command works for both kinds. An API key is never a command-line argument, so it does not reach your shell history. In a script, pipe it:
printf %s "$GITHUB_TOKEN" | anlyon connections add github --secret GITHUB --api-key-stdin --yes
From an SDK or the API, sign-in: POST /api/v2/connections/sessions with { "integrationId": "hubspot", "secretName": "HUBSPOT" } returns a connectUrl to open in a browser. Then call POST /api/v2/connections/sessions/{sessionId}/complete until it answers status: "completed". A session expires after 15 minutes.
From an SDK or the API, API key: POST /api/v2/connections/keys with { "integrationId": "github", "secretName": "GITHUB", "apiKey": "..." } answers 201 with the secret’s metadata. In the SDKs this is connections.connectWithApiKey(...) (TypeScript) and connections.connect_with_api_key(...) (Python).
GET /api/v2/connections/integrations says which way each integration is connected, in auth.kind (oauth or api_key), and for an API key gives the provider’s instructions and link.
Connecting needs secrets:write. Listing needs secrets:read. A connected account counts as one secret toward your plan’s secret quota. At most 10 connections may be started per minute per workspace.
What happens to a key you paste
Before anything is stored, Anlyon sends the key to the provider once, in one read-only request to the integration’s own API host, to ask whether the provider accepts it.
- The provider accepts it: the key is stored and the account is connected.
- The provider refuses it (
CONNECTION_KEY_REJECTED): nothing is stored. Check that you copied the whole key and gave it the permissions listed. - The provider could not be reached (
CONNECTION_KEY_CHECK_FAILED): nothing is stored. Try again.
Create a key with the fewest permissions the operations need. Anlyon does not narrow a key: what the key allows at the provider is what an action using it can do, inside the limits and approvals you set. To replace a key, reconnect the account (below): the new key is checked the way the first one was, and the secret keeps its name and hosts. PUT /api/v2/secrets/{name} also replaces the value, without the check.
Choose what your agent may do
A connected account on its own does nothing. In the console, connecting continues to What may your agent do here?: the integration’s operations, one switch each, in two groups. The same screen opens later from the account’s row (Operations).
Each integration is a full toolset: the reads and writes an agent routinely needs on that product’s objects, so your agent needs no other tool for it and never holds the key. Account administration (members, billing, permissions, webhooks) is left out.
-
Reads return what the provider answers and change nothing: search, list and get. Each list returns one page, sized so the answer fits, and takes the provider’s cursor for the next. A read has no limit and no receipt. It is logged like any call, and an approval policy can still match it. Turn on all reads switches them on together.
-
Writes are governed. Each declares what one call changes, which counts against your limits, and can be held for an approval. Where the provider has a read that shows the change, Anlyon reads it back and the receipt is graded
confirmed. Where it has none, the write’s description says why, and its receipt is gradedacknowledged. -
Turning an operation on creates one declared action in your workspace, named
<integration>-<operation>(for examplehubspot-update-contact-stage), that sends this account’s credential. Its suggested approval policy is installed off. The switch shows on only once the action exists. An operation that needs settings first (the Stripe account and currency for refunds, the sending domain for email) asks for them, and they are fixed into the action. -
Turning it off disables the action. It is never deleted, so its receipts and pinned versions stay.
-
Approval policies suggested for the operations you turned on are listed with an Enable switch.
-
Limits are suggested with an amount you can change, and created only when you press Create limit. Creating a limit needs permission to manage impact limits; without it the screen says so and creates nothing.
Then Add to your agent lists the operations that are on by tool name and gives the setup for Claude Code, Cursor, Codex, the AI SDK, LangChain or curl. MCP clients sign in with a browser. The others need an agent key, which the screen can create with actions:invoke, actions:read and approvals:read only, shown once. A tool for the same provider already in your own code is not governed by Anlyon until you replace it with one of these.
| Integration | Reads | Writes |
|---|---|---|
| GitHub | Search and list issues; issue comments and labels; pull requests, their files, reviews and review comments; repository, branches, commits and file contents; code search | Open, update, close and reopen issues; comment, edit and delete comments; add and remove labels and assignees; create and delete labels; open a pull request, review it, request reviewers, merge it |
| Notion | Search pages and databases; get a page, a property, a block and its children; get and query a database; list comments | Create a page, a database and a database row; update page properties; append paragraphs and blocks; update and delete a block; archive and restore a page; add, reply to, update and delete comments |
| Intercom | Search and list contacts and conversations; get a contact, a conversation, a company, an admin; list tags, admins, teams and companies; search and get Help Center articles | Create, update and delete contacts; tag and untag a contact; attach and detach a company; start a conversation; reply, add a note, assign to an admin or a team, snooze, close, reopen, tag |
| Attio | Query people, companies and list entries; get a record, a note, an entry, a task; list attributes, notes, lists and tasks | Create people and companies; update a job title, a company, a description; delete a record; add and delete notes; add to a list, update an entry, remove it; create, reschedule, complete and delete tasks |
| Asana | Workspaces, projects, sections, tasks in a project or section, a task, its subtasks and stories, tags | Create, update, complete, reopen and delete tasks; create subtasks; comment; move to a section; add and remove followers and tags; create and delete sections |
| Discord | A server’s channels and active threads; a channel’s messages, pins and archived threads; a message; a thread’s messages | Post, reply, edit and delete messages; post in a thread; add and remove a reaction; pin and unpin; start, join and archive a thread (as your bot) |
| PagerDuty | Incidents, their notes, log entries and alerts; services; who is on call; escalation policies; schedules; users; maintenance windows | Open, acknowledge, resolve, reassign, snooze and merge incidents; change urgency; add a note; create and end a maintenance window |
| Sentry | Projects, teams, releases; issues with a search query; an issue, its events, one event | Resolve, resolve in the next release, reopen, archive (with or without a time), assign to a member or a team, unassign, set priority, bookmark, mark seen |
| Stripe | Customers (list, search, get); payment intents; charges; refunds; invoices; subscriptions; balance and balance transactions | Refund a payment (the stripe.refund adapter, counted in money); create, update and delete customers; cancel a subscription or end it at period end; finalize and void an invoice |
| Resend | Emails, domains, contacts, segments, a contact’s segments | Send an email (the resend.email_send adapter, counted per recipient); reschedule and cancel a scheduled email; create, rename, delete and (un)subscribe contacts; add and remove a contact from a segment |
More integrations are being added. To use an API that is not here, import its OpenAPI spec or declare the action yourself.
Each operation’s limitations are in its description, which a reviewer sees in the preview. The same operations install from the CLI with anlyon packs install ./packs/hubspot --action <operation>; see Install a pack.
What Anlyon asks for
For a sign-in integration, Anlyon requests the smallest set of scopes its packs need, and shows them before the consent window opens. The provider’s consent page shows Anlyon’s name, because the app you approve is Anlyon’s.
| Sign-in integration | Token may be sent to | Provider review for Anlyon’s app |
|---|---|---|
| HubSpot (coming) | api.hubapi.com |
None for a public app used outside the marketplace |
Review times are the providers’ published expectations, not promises. An integration is offered once its review clears.
For an API-key integration there is no Anlyon app and nothing to review. You decide what the key may do when you create it.
| API-key integration | Key may be sent to | What to create at the provider |
|---|---|---|
| GitHub | api.github.com |
A fine-grained personal access token, limited to the repositories your agent should work in, with Issues and Pull requests: Read and write and Contents: Read. Merging needs Contents: Read and write |
| Notion | api.notion.com |
An internal integration with Read, Update and Insert content and Read and Insert comments, then share each page with it |
| PagerDuty | api.pagerduty.com |
An API access key that is not read-only |
| Resend | api.resend.com |
An API key with Full access (a sending-only key cannot read an email back) |
| Stripe | api.stripe.com |
A restricted key with Customers, Refunds, Invoices and Subscriptions: Write, and Payment Intents, Charges and Balance: Read. Leave out what your agent should not touch; those operations are refused |
| Intercom | api.intercom.io |
An access token from an app you create in the Developer Hub. US-hosted workspaces only |
| Attio | api.attio.com |
An access token with Records, List entries, Notes and Tasks: Read-write, and Object configuration, List configuration and User management: Read |
| Sentry | sentry.io |
An auth token with org:read, project:read and event:write |
| Asana | app.asana.com |
A personal access token. It acts as the person who made it |
| Discord | discord.com |
A bot token, with the bot invited to your server and given View Channel, Send Messages, Send Messages in Threads, Read Message History, Create Public Threads, Add Reactions and Pin Messages |
Does it still work?
A connected account can stop working without anyone changing anything in Anlyon: a key expires or is deleted at the provider, or the person who signed in withdraws Anlyon’s access there. Anlyon treats both the same way. Every connected account carries a health record, Anlyon asks the provider whether the account still works, and an account that does not is marked needs_reauth with a reason:
health.reason |
What happened | Which kind |
|---|---|---|
key_rejected |
The provider refused the stored key | API key |
access_revoked |
The provider no longer honours the account’s grant: access withdrawn, or the token can no longer be renewed | Sign-in |
refresh_failed |
Anlyon’s connector service tried to renew the token and could not | Sign-in |
Once an account is marked, the next action that uses it fails before anything is sent, with the error code CONNECTION_NEEDS_REAUTH. Nothing reaches the provider with a credential Anlyon knows is dead.
When Anlyon asks
- When you press Check. In the console, on the account’s row under Integrations. From the CLI,
anlyon connections check GITHUB. From the API,POST /api/v2/connections/{name}/check, orconnections.check(name)in an SDK. The answer is the secret with itshealth; an account that does not work is an answer, not an error. - Once a day. Anlyon checks every connected account that has not been checked for a day. An account already marked waits for you, not for the next check.
- After a 401. When the provider answers an action with 401, Anlyon checks the connected accounts the action used, and marks one only if the check confirms it. A request the provider refused for its own reasons leaves a working account alone.
What a check is depends on the kind, and that is the only place the kinds differ. For a key, it is the same single read-only request to the provider’s own API host that was made when you connected it. For a sign-in, Anlyon asks its connector service to renew the token, so the provider itself says whether the grant is still honoured. Neither returns the credential. A check that could not be made (CONNECTION_KEY_CHECK_FAILED, CONNECTION_PROVIDER_ERROR) leaves the status as it was.
Reconnect
Reconnecting makes a needs_reauth account work again under the same name, so nothing that references {{secret:NAME}} changes: not the actions, not the policies, not the limits.
- In the console: Reconnect on the account’s row. It opens the same dialog as Connect, for that account. For a key integration you paste the new key; for a sign-in integration the provider’s consent page opens again.
- From the CLI:
anlyon connections reconnect GITHUBasks for the new key without echoing it (--api-key-stdinreads it from a pipe);anlyon connections reconnect HUBSPOTopens the consent page and waits. - From the API:
POST /api/v2/connections/{name}/reconnect. For a key integration, send{ "apiKey": "..." }: Anlyon checks it with the provider the way it checked the first one, replaces the stored value, and answersstatus: "completed"with the secret. For a sign-in integration, send an empty body: Anlyon answersstatus: "pending"with asessionto open and complete exactly as for a first connect. In the SDKs this isconnections.reconnect(name, { apiKey })(TypeScript) andconnections.reconnect(name, api_key=...)(Python).
You can also reconnect an account that still works, for example to rotate a key before it expires. Checking and reconnecting need secrets:write and count toward the limit of 10 connect sessions per minute per workspace.
Disconnect
Delete the secret: Disconnect in the console, DELETE /api/v2/secrets/{name}, or secrets.delete(name) in an SDK. For an API key, that deletes Anlyon’s copy; delete the key at the provider as well to end its access. For a sign-in, Anlyon revokes its access to the account first, then deletes the secret. If revoking fails, the secret is kept and the request answers CONNECTION_REVOKE_FAILED, so you are never told access is gone while it is still live. In a protected environment, deleting needs confirmProtected: true.
Revoking at the provider is what ends access. You can also remove Anlyon’s access from the provider’s own settings at any time.
Errors
| Code | Status | Meaning |
|---|---|---|
CONNECTIONS_UNAVAILABLE |
501 | Sign-in connections are not configured on this deployment. API-key connections do not need them |
CONNECTION_KEY_REJECTED |
422 | The provider did not accept the API key. Nothing was stored |
CONNECTION_KEY_CHECK_FAILED |
502 | The API key could not be checked with the provider. Nothing was stored |
CONNECTION_SESSION_EXPIRED |
410 | The session expired, or belongs to another workspace or environment |
CONNECTION_NEEDS_REAUTH |
424 | The account’s access was revoked. Nothing was sent |
CONNECTION_PROVIDER_ERROR |
502 | The connected-account service did not answer. Nothing was sent |
CONNECTION_REVOKE_FAILED |
502 | Revoking failed, so the secret was kept |
SECRET_KIND_MISMATCH |
409 | PUT /secrets/{name} cannot turn a connected account into a stored value, or the other way round. Delete it first |
What it is not
- Not per end user. A connected account belongs to a workspace environment. An agent acting as one of your own users, with that user’s account, is not supported.
- Not a way around governance. A connected account is a credential. Limits, approvals, previews and read-backs apply to the actions that use it exactly as to any other.
To set up a whole workflow at once, see Packs.

