From attio-pack
Sets up Attio REST API authentication with access tokens or OAuth 2.0. Guides token generation, scopes, .env config, TypeScript fetch client, and verification.
How this skill is triggered — by the user, by Claude, or both
Slash command
/attio-pack:attio-install-authThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Configure authentication for the Attio REST API (`https://api.attio.com/v2`). Attio offers two auth methods: **access tokens** (scoped to a single workspace) and **OAuth 2.0** (for multi-workspace integrations). There is no official first-party Node SDK -- use `fetch` or a community client like `attio-js`.
Configure authentication for the Attio REST API (https://api.attio.com/v2). Attio offers two auth methods: access tokens (scoped to a single workspace) and OAuth 2.0 (for multi-workspace integrations). There is no official first-party Node SDK -- use fetch or a community client like attio-js.
my-integration-dev)| Scope | Grants access to |
|---|---|
object_configuration:read | List/get objects and attributes |
record_permission:read | Read records (people, companies, deals) |
record_permission:read-write | Create/update/delete records |
list_entry:read | Read list entries |
list_entry:read-write | Create/update/delete list entries |
note:read-write | Create and read notes |
task:read / task:read-write | Read or manage tasks |
user_management:read | Read workspace members |
webhook:read-write | Manage webhooks |
sk_ and never expires (but can be revoked)# .env (add to .gitignore immediately)
ATTIO_API_KEY=sk_your_token_here
# .gitignore
.env
.env.local
.env.*.local
// src/attio/client.ts
const ATTIO_BASE = "https://api.attio.com/v2";
interface AttioRequestOptions {
method?: string;
path: string;
body?: Record<string, unknown>;
}
export async function attioFetch<T>({
method = "GET",
path,
body,
}: AttioRequestOptions): Promise<T> {
const res = await fetch(`${ATTIO_BASE}${path}`, {
method,
headers: {
Authorization: `Bearer ${process.env.ATTIO_API_KEY}`,
"Content-Type": "application/json",
},
body: body ? JSON.stringify(body) : undefined,
});
if (!res.ok) {
const error = await res.json();
throw new Error(
`Attio ${res.status}: ${error.code} - ${error.message}`
);
}
return res.json() as Promise<T>;
}
// Verify by listing workspace objects
const objects = await attioFetch<{ data: Array<{ api_slug: string }> }>({
path: "/objects",
});
console.log(
"Connected! Objects:",
objects.data.map((o) => o.api_slug)
);
// Output: Connected! Objects: ["people", "companies", "deals", ...]
# Quick verification with curl
curl -s https://api.attio.com/v2/objects \
-H "Authorization: Bearer ${ATTIO_API_KEY}" | jq '.data[].api_slug'
For apps that other workspaces install, use OAuth 2.0 Authorization Code Grant (RFC 6749 section 4.1).
// Step 1: Redirect user to authorize
const authUrl = new URL("https://app.attio.com/authorize");
authUrl.searchParams.set("client_id", process.env.ATTIO_CLIENT_ID!);
authUrl.searchParams.set("redirect_uri", "https://yourapp.com/callback");
authUrl.searchParams.set("response_type", "code");
// Step 2: Exchange code for access token
const tokenRes = await fetch("https://app.attio.com/oauth/token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
grant_type: "authorization_code",
client_id: process.env.ATTIO_CLIENT_ID,
client_secret: process.env.ATTIO_CLIENT_SECRET,
code: authorizationCode,
redirect_uri: "https://yourapp.com/callback",
}),
});
const { access_token } = await tokenRes.json();
// Store access_token securely per workspace
| Error | HTTP Status | Cause | Solution |
|---|---|---|---|
invalid_grant | 401 | Bad or expired auth code | Re-authorize the user |
insufficient_scopes | 403 | Token missing required scope | Add scope in dashboard, regenerate |
invalid_request | 400 | Malformed Authorization header | Use Bearer <token> format |
not_found | 404 | Token revoked or workspace deleted | Generate new token |
All Attio errors return JSON with a consistent structure:
{
"status_code": 403,
"type": "authorization_error",
"code": "insufficient_scopes",
"message": "Token requires 'record_permission:read' scope"
}
After verifying auth, proceed to attio-hello-world for your first real API call.
npx claudepluginhub ia23a-lachnita/claude-code-plugins-plus-fix-skills --plugin attio-pack5plugins reuse this skill
First indexed Jul 10, 2026
Configures Attio REST API authentication with access tokens or OAuth 2.0. Covers token generation, scope setup, client initialization, and connection verification.
Configures Attio as a programmable CRM for B2B SaaS GTM, including custom objects, workflow automation, enrichment, and migration from HubSpot/Salesforce.
Guides collaborative design exploration before implementation: explores context, asks clarifying questions, proposes approaches, and writes a design doc for user approval.