> attio-install-auth

Set up Attio REST API authentication with access tokens or OAuth 2.0. Use when configuring API keys, setting token scopes, initializing the Attio client, or connecting an app via OAuth. Trigger: "install attio", "setup attio", "attio auth", "attio API key", "attio OAuth", "attio access token".

fetch
$curl "https://skillshub.wtf/jeremylongshore/claude-code-plugins-plus-skills/attio-install-auth?format=md"
SKILL.mdattio-install-auth

Attio Install & Auth

Overview

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.

Prerequisites

  • Node.js 18+ or Python 3.10+
  • Attio account at app.attio.com
  • API access enabled in workspace settings

Instructions

Step 1: Generate an Access Token

  1. Open Settings > Developers > Access tokens in your Attio workspace
  2. Click Create token and name it (e.g., my-integration-dev)
  3. Configure scopes (tokens have no scopes by default -- you must add them):
ScopeGrants access to
object_configuration:readList/get objects and attributes
record_permission:readRead records (people, companies, deals)
record_permission:read-writeCreate/update/delete records
list_entry:readRead list entries
list_entry:read-writeCreate/update/delete list entries
note:read-writeCreate and read notes
task:read / task:read-writeRead or manage tasks
user_management:readRead workspace members
webhook:read-writeManage webhooks
  1. Copy the token -- it starts with sk_ and never expires (but can be revoked)

Step 2: Configure Environment

# .env (add to .gitignore immediately)
ATTIO_API_KEY=sk_your_token_here

# .gitignore
.env
.env.local
.env.*.local

Step 3: Initialize the Client

// 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>;
}

Step 4: Verify Connection

// 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'

OAuth 2.0 Flow (Multi-Workspace)

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 Handling

ErrorHTTP StatusCauseSolution
invalid_grant401Bad or expired auth codeRe-authorize the user
insufficient_scopes403Token missing required scopeAdd scope in dashboard, regenerate
invalid_request400Malformed Authorization headerUse Bearer <token> format
not_found404Token revoked or workspace deletedGenerate new token

Attio Error Response Format

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"
}

Resources

Next Steps

After verifying auth, proceed to attio-hello-world for your first real API call.

┌ stats

installs/wk0
░░░░░░░░░░
github stars1.7K
██████████
first seenMar 23, 2026
└────────────

┌ repo

jeremylongshore/claude-code-plugins-plus-skills
by jeremylongshore
└────────────