Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
314 changes: 314 additions & 0 deletions app/en/references/auth-providers/attio/page.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,314 @@
import { Tabs, Callout, Steps } from "nextra/components";

# Attio

The Attio auth provider enables tools and agents to call [Attio APIs](https://developers.attio.com) on behalf of a user.

<Callout>
Want to quickly get started with Attio in your agent or AI app? The
[Arcade Attio MCP Server](/resources/integrations/sales/attio) is an [Arcade Optimized](/guides/create-tools/improve/types-of-tools#optimized-tools)
toolkit — hand-crafted and optimized for LLM usage.
Copy link
Contributor

@github-actions github-actions bot Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Google.EmDash: Removed spaces around the em dash

Suggested change
toolkit hand-crafted and optimized for LLM usage.
toolkit: hand-crafted and optimized for LLM usage.

</Callout>

## What's documented here

This page describes how to use and configure Attio auth with Arcade.

This auth provider is used by:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Google.Passive: Changed from passive to active voice

Suggested change
This auth provider is used by:
Use this auth provider with:


- The [Arcade Attio MCP Server](/resources/integrations/sales/attio), which provides [Arcade Optimized](/guides/create-tools/improve/types-of-tools#optimized-tools) pre-built tools for interacting with Attio
- Your [app code](#using-attio-auth-in-app-code) that needs to call Attio APIs
- Or, your [custom tools](#using-attio-auth-in-custom-tools) that need to call Attio APIs

## Use Arcade's Default Attio Auth Provider

<Callout type="warning">
Arcade's default Attio OAuth app is currently pending approval from Attio. Until
approved, you will need to [use your own Attio app credentials](#use-your-own-attio-app-credentials)
to use Attio auth with Arcade.
</Callout>

Arcade offers a default Attio auth provider that you can use in the Arcade Cloud Platform. In this case, your users will see `Arcade` as the name of the application that's requesting permission.

If you choose to use Arcade's Attio auth, you don't need to configure anything. Follow the [Attio MCP Server examples](/resources/integrations/sales/attio) to get started calling Attio tools.

## Use Your Own Attio App Credentials

<Callout type="info">
When using your own app credentials, make sure you configure your project to
use a [custom user
verifier](/guides/user-facing-agents/secure-auth-production#build-a-custom-user-verifier).
Without this, your end-users will not be able to use your app or agent in
production.
</Callout>

In a production environment, you will most likely want to use your own Attio app credentials. This way, your users will see your application's name requesting permission.

Before showing how to configure your Attio app credentials, let's go through the steps to create an Attio integration.
Copy link
Contributor

@github-actions github-actions bot Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Google.We: Remove first-person plural 'let's':

Suggested change
Before showing how to configure your Attio app credentials, let's go through the steps to create an Attio integration.
Before showing how to configure your Attio app credentials, you'll create an Attio integration.


## Create an Attio Integration

<Steps>

### Create a new integration

Go to the [Attio developer dashboard](https://build.attio.com/) and click **Create a new integration**. Give it a name, description, and optionally an icon.

### Enable OAuth 2.0

Head to the **OAuth** tab in your integration's settings and enable OAuth 2.0 via the toggle at the top of the page.

### Configure the redirect URI

Add the **Redirect URL** generated by Arcade (see below) as a redirect URI for your integration.

### Configure scopes

Head to the **Scopes** tab and enable the scopes your tools need. The Arcade Attio MCP Server requires the following scopes:

- `record_permission:read-write`
- `object_configuration:read`
- `user_management:read`
- `note:read-write`
- `task:read-write`
- `list_configuration:read`
- `list_entry:read-write`
- `meeting:read`
- `call_recording:read`

### Copy your credentials

In the **OAuth** tab, copy the **Client ID** and **Client Secret** to use in the Arcade configuration below.

</Steps>

<Callout type="info">
If you are implementing your own [Attio custom
tools](#using-attio-auth-in-custom-tools), make sure to also enable any extra
[scopes](https://docs.attio.com/rest-api/guides/authentication) necessary for
the actions your tools need to perform.
</Callout>

## Configuring your own Attio Auth Provider in Arcade

<Tabs items={["Dashboard GUI"]}>
<Tabs.Tab>

### Configure Attio Auth Using the Arcade Dashboard GUI

<Steps>

#### Access the Arcade Dashboard

To access the Arcade Cloud dashboard, go to [api.arcade.dev/dashboard](https://api.arcade.dev/dashboard). If you are self-hosting, by default the dashboard will be available at http://localhost:9099/dashboard. Adjust the host and port number to match your environment.

#### Navigate to the OAuth Providers page

- Under the **Connections** section of the Arcade Dashboard left-side menu, click **Connected Apps**.
- Click **Add OAuth Provider** in the top right corner.
- Select the **Included Providers** tab at the top.
- In the **Provider** dropdown, select **Attio**.

#### Enter the provider details

- Enter `attio` as the **ID** for your provider.
- Optionally enter a **Description**.
- Enter the **Client ID** and **Client Secret** from your Attio integration.
- Note the **Redirect URL** generated by Arcade. This must be added as a redirect URI in your Attio integration's OAuth settings.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Google.Passive: Changed from passive to active voice

Suggested change
- Note the **Redirect URL** generated by Arcade. This must be added as a redirect URI in your Attio integration's OAuth settings.
- Note the **Redirect URL** generated by Arcade. You must add this as a redirect URI in your Attio integration's OAuth settings.


#### Create the provider

Hit the **Create** button and the provider will be ready to be used.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Google.Passive: Changed from passive to active voice

Suggested change
Hit the **Create** button and the provider will be ready to be used.
Hit the **Create** button and the provider will be ready to use.


</Steps>

When you use tools that require Attio auth using your Arcade account credentials, Arcade will automatically use this Attio OAuth provider. If you have multiple Attio providers, see [using multiple auth providers of the same type](/references/auth-providers#using-multiple-providers-of-the-same-type) for more information.

</Tabs.Tab>
</Tabs>

## Using Attio auth in app code

Use the Attio auth provider in your own agents and AI apps to get a user-scoped token for the Attio API. See [authorizing agents with Arcade](/get-started/about-arcade) to understand how this works.

Use `client.auth.start()` to get a user token for the Attio API:

<Tabs items={["Python", "JavaScript"]} storageKey="preferredLanguage">
<Tabs.Tab>

```python {21}
from arcadepy import Arcade

client = Arcade(base_url="https://api.arcade.dev") # Automatically finds the `ARCADE_API_KEY` env variable

user_id = "{arcade_user_id}"

# Start the authorization process
auth_response = client.auth.start(
user_id=user_id,
provider="attio",
scopes=["record_permission:read", "object_configuration:read"],
)

if auth_response.status != "completed":
print("Please complete the authorization challenge in your browser:")
print(auth_response.url)

# Wait for the authorization to complete
auth_response = client.auth.wait_for_completion(auth_response)

token = auth_response.context.token
# Do something interesting with the token...
```

</Tabs.Tab>

<Tabs.Tab>

```javascript {20}
import { Arcade } from "@arcadeai/arcadejs";

const client = new Arcade({ baseURL: "https://api.arcade.dev" }); // Automatically finds the `ARCADE_API_KEY` env variable

const userId = "{arcade_user_id}";

// Start the authorization process
const authResponse = await client.auth.start(userId, "attio", {
scopes: ["record_permission:read", "object_configuration:read"],
});

if (authResponse.status !== "completed") {
console.log("Please complete the authorization challenge in your browser:");
console.log(authResponse.url);
}

// Wait for the authorization to complete
const response = await client.auth.waitForCompletion(authResponse);

const token = response.context.token;
// Do something interesting with the token...
```

</Tabs.Tab>
</Tabs>

You can use the auth token to call [Attio API endpoints](https://developers.attio.com) and interact with records, lists, tasks, and more. By changing or adding scopes to the `client.auth.start` call, you can access different Attio endpoints.

The scopes supported by the Arcade Attio auth provider are the ones [listed above](#configure-scopes). If you created your own Attio integration, make sure to enable the scopes you intend to use in the `client.auth.start` call.

## Using Attio auth in custom tools

You can author your own [custom tools](/guides/create-tools/tool-basics/build-mcp-server) that interact with the Attio API.

Use the `OAuth2()` auth class with `id="attio"` to specify that a tool requires authorization with Attio. The authentication token needed to call the Attio API is available in the tool context through the `context.get_auth_token_or_empty()` method.

```python {10,23}
from typing import Annotated

import httpx

from arcade_tdk import ToolContext, tool
from arcade_tdk.auth import OAuth2


@tool(
requires_auth=OAuth2(
id="attio",
scopes=["record_permission:read", "object_configuration:read"],
)
)
async def get_company_details(
context: ToolContext,
company_id: Annotated[
str,
"The ID of the company to get the details of.",
],
) -> Annotated[dict, "Details of the company"]:
"""Gets the details of a company."""
url = f"https://api.attio.com/v2/objects/companies/records/{company_id}"
headers = {"Authorization": f"Bearer {context.get_auth_token_or_empty()}"}

async with httpx.AsyncClient() as client:
response = await client.get(url, headers=headers)
response.raise_for_status()
return response.json()
```

Your new tool can be called like demonstrated below:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Google.Passive: Changed from passive to active voice

Suggested change
Your new tool can be called like demonstrated below:
Call your new tool as demonstrated below:


<Tabs items={["Python", "JavaScript"]} storageKey="preferredLanguage">
<Tabs.Tab>
<Callout type="info">
If you are self-hosting, change the `base_url` parameter in the `Arcade` constructor to match your Arcade Engine URL. By default, the Engine will be available at `http://localhost:9099`.
</Callout>

```python
from arcadepy import Arcade

client = Arcade(base_url="https://api.arcade.dev") # Automatically finds the `ARCADE_API_KEY` env variable

USER_ID = "{arcade_user_id}"
TOOL_NAME = "Attio.GetCompanyDetails"

auth_response = client.tools.authorize(tool_name=TOOL_NAME, user_id=USER_ID)

if auth_response.status != "completed":
print(f"Click this link to authorize: {auth_response.url}")

# Wait for the authorization to complete
client.auth.wait_for_completion(auth_response)

tool_input = {
"company_id": "32134490789",
}

response = client.tools.execute(
tool_name=TOOL_NAME,
input=tool_input,
user_id=USER_ID,
)
print(response.output.value)
```

</Tabs.Tab>
<Tabs.Tab>
<Callout type="info">
If you are self-hosting, change the `baseURL` parameter in the `Arcade` constructor to match your Arcade Engine URL. By default, the Engine will be available at `http://localhost:9099`.
</Callout>

```javascript
import { Arcade } from "@arcadeai/arcadejs";

const client = new Arcade({ baseURL: "https://api.arcade.dev" }); // Automatically finds the `ARCADE_API_KEY` env variable

const USER_ID = "{arcade_user_id}";
const TOOL_NAME = "Attio.GetCompanyDetails";

// Start the authorization process
const authResponse = await client.tools.authorize({
tool_name: TOOL_NAME,
user_id: USER_ID,
});

if (authResponse.status !== "completed") {
console.log(`Click this link to authorize: ${authResponse.url}`);
}

// Wait for the authorization to complete
await client.auth.waitForCompletion(authResponse);

const toolInput = {
company_id: "32134490789",
};

const response = await client.tools.execute({
tool_name: TOOL_NAME,
input: toolInput,
user_id: USER_ID,
});

console.log(response.output.value);
```

</Tabs.Tab>
</Tabs>
7 changes: 7 additions & 0 deletions app/en/references/auth-providers/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ For more information on how to customize your auth provider, select an auth prov
<br />

<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
<ToolCard
name="Attio"
image="attio.svg"
summary="Authorize tools and agents with Attio"
link="/references/auth-providers/attio"
category="Auth"
/>
<ToolCard
name="Asana"
image="asana.svg"
Expand Down
3 changes: 3 additions & 0 deletions app/en/resources/integrations/sales/_meta.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ const meta: MetaRecord = {
copyPage: true,
},
},
attio: {
title: "Attio",
},
hubspot: {
title: "HubSpot",
},
Expand Down
Loading