[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6F7H3RHS0N9QG7MAT3FJ7HS":3,"skill-same:01M6F7H3RHS0N9QG7MAT3FJ7HS":79},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":44,"linkOnly":45,"markdownContent":46,"markdownBody":47,"frontMatter":48,"refName":56,"commitSha":57,"skillDirectory":58,"forksCount":59,"repositoryHtmlUrl":60,"repositoryHomepageUrl":61,"ownerHtmlUrl":62,"ownerBlogUrl":6,"ownerDescription":63,"updatedAt":64,"install":65,"resources":78},"01M6F7H3RHS0N9QG7MAT3FJ7HS","attio-install-auth",null,"Set up Attio REST API authentication with access tokens or OAuth 2.0.\nUse when configuring API keys, setting token scopes, initializing\nthe Attio client, or connecting an app via OAuth.\nTrigger: \"install attio\", \"setup attio\", \"attio auth\", \"attio API key\",\n\"attio OAuth\", \"attio access token\".","ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",66,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fjeremylongshore\u002Fclaude-code-plugins-plus-skills\u002Fattio-install-auth\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"install","attio install auth","attio","auth","api","Bash","access","read","write","edit","SET","up","authentication","crm","token","tokens","app","io","trigger","code","2026-11-10 10:12:30",false,"---\nname: attio-install-auth\ndescription: |\n  Set up Attio REST API authentication with access tokens or OAuth 2.0.\n  Use when configuring API keys, setting token scopes, initializing\n  the Attio client, or connecting an app via OAuth.\n  Trigger: \"install attio\", \"setup attio\", \"attio auth\", \"attio API key\",\n  \"attio OAuth\", \"attio access token\".\nallowed-tools: Read, Write, Edit, Bash(npm:*), Bash(npx:*), Grep\nversion: 1.0.0\nlicense: MIT\nauthor: Jeremy Longshore \u003Cjeremy@intentsolutions.io>\ntags: [saas, crm, attio]\ncompatible-with: claude-code\n---\n\n# Attio Install & Auth\n\n## Overview\n\nConfigure authentication for the Attio REST API (`https:\u002F\u002Fapi.attio.com\u002Fv2`). 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`.\n\n## Prerequisites\n\n- Node.js 18+ or Python 3.10+\n- Attio account at [app.attio.com](https:\u002F\u002Fapp.attio.com)\n- API access enabled in workspace settings\n\n## Instructions\n\n### Step 1: Generate an Access Token\n\n1. Open **Settings > Developers > Access tokens** in your Attio workspace\n2. Click **Create token** and name it (e.g., `my-integration-dev`)\n3. Configure scopes (tokens have **no scopes by default** -- you must add them):\n\n| Scope | Grants access to |\n|-------|-----------------|\n| `object_configuration:read` | List\u002Fget objects and attributes |\n| `record_permission:read` | Read records (people, companies, deals) |\n| `record_permission:read-write` | Create\u002Fupdate\u002Fdelete records |\n| `list_entry:read` | Read list entries |\n| `list_entry:read-write` | Create\u002Fupdate\u002Fdelete list entries |\n| `note:read-write` | Create and read notes |\n| `task:read` \u002F `task:read-write` | Read or manage tasks |\n| `user_management:read` | Read workspace members |\n| `webhook:read-write` | Manage webhooks |\n\n4. Copy the token -- it starts with `sk_` and **never expires** (but can be revoked)\n\n### Step 2: Configure Environment\n\n```bash\n# .env (add to .gitignore immediately)\nATTIO_API_KEY=sk_your_token_here\n\n# .gitignore\n.env\n.env.local\n.env.*.local\n```\n\n### Step 3: Initialize the Client\n\n```typescript\n\u002F\u002F src\u002Fattio\u002Fclient.ts\nconst ATTIO_BASE = \"https:\u002F\u002Fapi.attio.com\u002Fv2\";\n\ninterface AttioRequestOptions {\n  method?: string;\n  path: string;\n  body?: Record\u003Cstring, unknown>;\n}\n\nexport async function attioFetch\u003CT>({\n  method = \"GET\",\n  path,\n  body,\n}: AttioRequestOptions): Promise\u003CT> {\n  const res = await fetch(`${ATTIO_BASE}${path}`, {\n    method,\n    headers: {\n      Authorization: `Bearer ${process.env.ATTIO_API_KEY}`,\n      \"Content-Type\": \"application\u002Fjson\",\n    },\n    body: body ? JSON.stringify(body) : undefined,\n  });\n\n  if (!res.ok) {\n    const error = await res.json();\n    throw new Error(\n      `Attio ${res.status}: ${error.code} - ${error.message}`\n    );\n  }\n\n  return res.json() as Promise\u003CT>;\n}\n```\n\n### Step 4: Verify Connection\n\n```typescript\n\u002F\u002F Verify by listing workspace objects\nconst objects = await attioFetch\u003C{ data: Array\u003C{ api_slug: string }> }>({\n  path: \"\u002Fobjects\",\n});\n\nconsole.log(\n  \"Connected! Objects:\",\n  objects.data.map((o) => o.api_slug)\n);\n\u002F\u002F Output: Connected! Objects: [\"people\", \"companies\", \"deals\", ...]\n```\n\n```bash\n# Quick verification with curl\ncurl -s https:\u002F\u002Fapi.attio.com\u002Fv2\u002Fobjects \\\n  -H \"Authorization: Bearer ${ATTIO_API_KEY}\" | jq '.data[].api_slug'\n```\n\n## OAuth 2.0 Flow (Multi-Workspace)\n\nFor apps that other workspaces install, use OAuth 2.0 Authorization Code Grant (RFC 6749 section 4.1).\n\n```typescript\n\u002F\u002F Step 1: Redirect user to authorize\nconst authUrl = new URL(\"https:\u002F\u002Fapp.attio.com\u002Fauthorize\");\nauthUrl.searchParams.set(\"client_id\", process.env.ATTIO_CLIENT_ID!);\nauthUrl.searchParams.set(\"redirect_uri\", \"https:\u002F\u002Fyourapp.com\u002Fcallback\");\nauthUrl.searchParams.set(\"response_type\", \"code\");\n\n\u002F\u002F Step 2: Exchange code for access token\nconst tokenRes = await fetch(\"https:\u002F\u002Fapp.attio.com\u002Foauth\u002Ftoken\", {\n  method: \"POST\",\n  headers: { \"Content-Type\": \"application\u002Fjson\" },\n  body: JSON.stringify({\n    grant_type: \"authorization_code\",\n    client_id: process.env.ATTIO_CLIENT_ID,\n    client_secret: process.env.ATTIO_CLIENT_SECRET,\n    code: authorizationCode,\n    redirect_uri: \"https:\u002F\u002Fyourapp.com\u002Fcallback\",\n  }),\n});\n\nconst { access_token } = await tokenRes.json();\n\u002F\u002F Store access_token securely per workspace\n```\n\n## Error Handling\n\n| Error | HTTP Status | Cause | Solution |\n|-------|------------|-------|----------|\n| `invalid_grant` | 401 | Bad or expired auth code | Re-authorize the user |\n| `insufficient_scopes` | 403 | Token missing required scope | Add scope in dashboard, regenerate |\n| `invalid_request` | 400 | Malformed Authorization header | Use `Bearer \u003Ctoken>` format |\n| `not_found` | 404 | Token revoked or workspace deleted | Generate new token |\n\n## Attio Error Response Format\n\nAll Attio errors return JSON with a consistent structure:\n\n```json\n{\n  \"status_code\": 403,\n  \"type\": \"authorization_error\",\n  \"code\": \"insufficient_scopes\",\n  \"message\": \"Token requires 'record_permission:read' scope\"\n}\n```\n\n## Resources\n\n- [Attio Access Token Guide](https:\u002F\u002Fattio.com\u002Fhelp\u002Fapps\u002Fother-apps\u002Fgenerating-an-api-key)\n- [Attio OAuth Tutorial](https:\u002F\u002Fdocs.attio.com\u002Frest-api\u002Ftutorials\u002Fconnect-an-app-through-oauth)\n- [Attio REST API Overview](https:\u002F\u002Fdocs.attio.com\u002Frest-api\u002Foverview)\n- [Attio Authentication](https:\u002F\u002Fdocs.attio.com\u002Frest-api\u002Fguides\u002Fauthentication)\n\n## Next Steps\n\nAfter verifying auth, proceed to `attio-hello-world` for your first real API call.\n\n","# Attio Install & Auth\n\n## Overview\n\nConfigure authentication for the Attio REST API (`https:\u002F\u002Fapi.attio.com\u002Fv2`). 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`.\n\n## Prerequisites\n\n- Node.js 18+ or Python 3.10+\n- Attio account at [app.attio.com](https:\u002F\u002Fapp.attio.com)\n- API access enabled in workspace settings\n\n## Instructions\n\n### Step 1: Generate an Access Token\n\n1. Open **Settings > Developers > Access tokens** in your Attio workspace\n2. Click **Create token** and name it (e.g., `my-integration-dev`)\n3. Configure scopes (tokens have **no scopes by default** -- you must add them):\n\n| Scope | Grants access to |\n|-------|-----------------|\n| `object_configuration:read` | List\u002Fget objects and attributes |\n| `record_permission:read` | Read records (people, companies, deals) |\n| `record_permission:read-write` | Create\u002Fupdate\u002Fdelete records |\n| `list_entry:read` | Read list entries |\n| `list_entry:read-write` | Create\u002Fupdate\u002Fdelete list entries |\n| `note:read-write` | Create and read notes |\n| `task:read` \u002F `task:read-write` | Read or manage tasks |\n| `user_management:read` | Read workspace members |\n| `webhook:read-write` | Manage webhooks |\n\n4. Copy the token -- it starts with `sk_` and **never expires** (but can be revoked)\n\n### Step 2: Configure Environment\n\n```bash\n# .env (add to .gitignore immediately)\nATTIO_API_KEY=sk_your_token_here\n\n# .gitignore\n.env\n.env.local\n.env.*.local\n```\n\n### Step 3: Initialize the Client\n\n```typescript\n\u002F\u002F src\u002Fattio\u002Fclient.ts\nconst ATTIO_BASE = \"https:\u002F\u002Fapi.attio.com\u002Fv2\";\n\ninterface AttioRequestOptions {\n  method?: string;\n  path: string;\n  body?: Record\u003Cstring, unknown>;\n}\n\nexport async function attioFetch\u003CT>({\n  method = \"GET\",\n  path,\n  body,\n}: AttioRequestOptions): Promise\u003CT> {\n  const res = await fetch(`${ATTIO_BASE}${path}`, {\n    method,\n    headers: {\n      Authorization: `Bearer ${process.env.ATTIO_API_KEY}`,\n      \"Content-Type\": \"application\u002Fjson\",\n    },\n    body: body ? JSON.stringify(body) : undefined,\n  });\n\n  if (!res.ok) {\n    const error = await res.json();\n    throw new Error(\n      `Attio ${res.status}: ${error.code} - ${error.message}`\n    );\n  }\n\n  return res.json() as Promise\u003CT>;\n}\n```\n\n### Step 4: Verify Connection\n\n```typescript\n\u002F\u002F Verify by listing workspace objects\nconst objects = await attioFetch\u003C{ data: Array\u003C{ api_slug: string }> }>({\n  path: \"\u002Fobjects\",\n});\n\nconsole.log(\n  \"Connected! Objects:\",\n  objects.data.map((o) => o.api_slug)\n);\n\u002F\u002F Output: Connected! Objects: [\"people\", \"companies\", \"deals\", ...]\n```\n\n```bash\n# Quick verification with curl\ncurl -s https:\u002F\u002Fapi.attio.com\u002Fv2\u002Fobjects \\\n  -H \"Authorization: Bearer ${ATTIO_API_KEY}\" | jq '.data[].api_slug'\n```\n\n## OAuth 2.0 Flow (Multi-Workspace)\n\nFor apps that other workspaces install, use OAuth 2.0 Authorization Code Grant (RFC 6749 section 4.1).\n\n```typescript\n\u002F\u002F Step 1: Redirect user to authorize\nconst authUrl = new URL(\"https:\u002F\u002Fapp.attio.com\u002Fauthorize\");\nauthUrl.searchParams.set(\"client_id\", process.env.ATTIO_CLIENT_ID!);\nauthUrl.searchParams.set(\"redirect_uri\", \"https:\u002F\u002Fyourapp.com\u002Fcallback\");\nauthUrl.searchParams.set(\"response_type\", \"code\");\n\n\u002F\u002F Step 2: Exchange code for access token\nconst tokenRes = await fetch(\"https:\u002F\u002Fapp.attio.com\u002Foauth\u002Ftoken\", {\n  method: \"POST\",\n  headers: { \"Content-Type\": \"application\u002Fjson\" },\n  body: JSON.stringify({\n    grant_type: \"authorization_code\",\n    client_id: process.env.ATTIO_CLIENT_ID,\n    client_secret: process.env.ATTIO_CLIENT_SECRET,\n    code: authorizationCode,\n    redirect_uri: \"https:\u002F\u002Fyourapp.com\u002Fcallback\",\n  }),\n});\n\nconst { access_token } = await tokenRes.json();\n\u002F\u002F Store access_token securely per workspace\n```\n\n## Error Handling\n\n| Error | HTTP Status | Cause | Solution |\n|-------|------------|-------|----------|\n| `invalid_grant` | 401 | Bad or expired auth code | Re-authorize the user |\n| `insufficient_scopes` | 403 | Token missing required scope | Add scope in dashboard, regenerate |\n| `invalid_request` | 400 | Malformed Authorization header | Use `Bearer \u003Ctoken>` format |\n| `not_found` | 404 | Token revoked or workspace deleted | Generate new token |\n\n## Attio Error Response Format\n\nAll Attio errors return JSON with a consistent structure:\n\n```json\n{\n  \"status_code\": 403,\n  \"type\": \"authorization_error\",\n  \"code\": \"insufficient_scopes\",\n  \"message\": \"Token requires 'record_permission:read' scope\"\n}\n```\n\n## Resources\n\n- [Attio Access Token Guide](https:\u002F\u002Fattio.com\u002Fhelp\u002Fapps\u002Fother-apps\u002Fgenerating-an-api-key)\n- [Attio OAuth Tutorial](https:\u002F\u002Fdocs.attio.com\u002Frest-api\u002Ftutorials\u002Fconnect-an-app-through-oauth)\n- [Attio REST API Overview](https:\u002F\u002Fdocs.attio.com\u002Frest-api\u002Foverview)\n- [Attio Authentication](https:\u002F\u002Fdocs.attio.com\u002Frest-api\u002Fguides\u002Fauthentication)\n\n## Next Steps\n\nAfter verifying auth, proceed to `attio-hello-world` for your first real API call.\n\n",{"name":5,"tags":49,"author":51,"license":15,"version":52,"description":53,"allowed-tools":54,"compatible-with":55},[50,37,26],"saas","Jeremy Longshore \u003Cjeremy@intentsolutions.io>","1.0.0","Set up Attio REST API authentication with access tokens or OAuth 2.0.\nUse when configuring API keys, setting token scopes, initializing\nthe Attio client, or connecting an app via OAuth.\nTrigger: \"install attio\", \"setup attio\", \"attio auth\", \"attio API key\",\n\"attio OAuth\", \"attio access token\".\n","Read, Write, Edit, Bash(npm:*), Bash(npx:*), Grep","claude-code","main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Fjeremylongshore\u002Fclaude-code-plugins-plus-skills\u002Fattio-install-auth",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":8,"skillName":5,"commands":66,"prompt":76,"zipAvailable":77},[67,70,73],{"tool":68,"command":69},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill attio-install-auth",{"tool":71,"command":72},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill attio-install-auth",{"tool":74,"command":75},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill attio-install-auth","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fjeremylongshore\u002Fclaude-code-plugins-plus-skills\u002Fattio-install-auth\u002FSKILL.md",true,[],[80,94,104,113,119,126],{"skillNo":81,"name":82,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":83,"categories":84,"keywords":90,"publishedAt":44},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[85],{"categoryNo":86,"categoryName":87,"taxonomyType":88,"taxonomyTypeDesc":89},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[91,92,93],"model","model hierarchy","model hierarchy skill",{"skillNo":95,"name":96,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":97,"categories":98,"keywords":100,"publishedAt":44},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[99],{"categoryNo":86,"categoryName":87,"taxonomyType":88,"taxonomyTypeDesc":89},[101,102,103],"MCP","zoom","zoom mcp",{"skillNo":105,"name":106,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":107,"categories":108,"keywords":109,"publishedAt":44},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[110,111,112,102],"sdk","zoom apps sdk","apps",{"skillNo":114,"name":115,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":116,"categories":117,"keywords":118,"publishedAt":44},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[115],{"skillNo":120,"name":121,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":122,"categories":123,"keywords":125,"publishedAt":44},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[124],{"categoryNo":86,"categoryName":87,"taxonomyType":88,"taxonomyTypeDesc":89},[121],{"skillNo":127,"name":128,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":129,"categories":130,"keywords":131,"publishedAt":44},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[128]]