Agent Skills: Attio Upgrade & Migration

|

UncategorizedID: jeremylongshore/claude-code-plugins-plus-skills/attio-upgrade-migration

Install this agent skill to your local

pnpm dlx add-skill https://github.com/jeremylongshore/claude-code-plugins-plus-skills/tree/HEAD/plugins/saas-packs/attio-pack/skills/attio-upgrade-migration

Skill Files

Browse the full folder contents for attio-upgrade-migration.

Download Skill

Loading file tree…

plugins/saas-packs/attio-pack/skills/attio-upgrade-migration/SKILL.md

Skill Metadata

Name
attio-upgrade-migration
Description
|

Attio Upgrade & Migration

Overview

Attio has two API generations: v1 (legacy, deprecated) and v2 (current). This skill covers the v1-to-v2 migration, community SDK upgrade paths, and how to detect and adapt to API changes since Attio does not publish a traditional SDK changelog.

V1 to V2 Migration Reference

Endpoint Changes

| Operation | V1 Endpoint | V2 Endpoint | |-----------|------------|------------| | List objects | GET /v1/objects | GET /v2/objects | | Query records | GET /v1/objects/{id}/records | POST /v2/objects/{slug}/records/query | | Create record | POST /v1/objects/{id}/records | POST /v2/objects/{slug}/records | | Get record | GET /v1/objects/{id}/records/{rid} | GET /v2/objects/{slug}/records/{rid} | | List entries | GET /v1/lists/{id}/entries | POST /v2/lists/{slug}/entries/query | | Create webhook | POST /v1/webhooks | POST /v2/webhooks | | Search | N/A | POST /v2/records/search |

Key Differences

| Aspect | V1 | V2 | |--------|----|----| | Identifiers | UUIDs only | Slugs (preferred) or UUIDs | | Record query | GET with query params | POST with JSON body (filters, sorts) | | Filtering | Basic query params | Rich operators ($eq, $contains, $gt, $and, $or) | | Pagination | page + per_page | limit + offset or cursor-based | | Webhook payloads | Custom format | Consistent with v2 response shapes | | Webhook filtering | None | Event-type and attribute-level filters |

Step 1: Update Base URL

// Before
const BASE = "https://api.attio.com/v1";

// After
const BASE = "https://api.attio.com/v2";

Step 2: Migrate Record Queries

// V1: GET with query params
const v1 = await fetch(
  `${BASE}/objects/${objectId}/records?page=1&per_page=50`,
  { headers: { Authorization: `Bearer ${token}` } }
);

// V2: POST with filter body, using slug instead of UUID
const v2 = await fetch(
  `${BASE}/objects/people/records/query`,
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      filter: {
        email_addresses: { email_address: { $contains: "@example.com" } },
      },
      sorts: [{ attribute: "created_at", field: "created_at", direction: "desc" }],
      limit: 50,
      offset: 0,
    }),
  }
);

Step 3: Update Record Creation

// V1: values as flat key-value pairs
const v1Body = {
  name: "Ada Lovelace",
  email: "ada@example.com",
};

// V2: values nested under data.values, always arrays
const v2Body = {
  data: {
    values: {
      name: [{ first_name: "Ada", last_name: "Lovelace", full_name: "Ada Lovelace" }],
      email_addresses: ["ada@example.com"],
    },
  },
};

Step 4: Migrate Webhooks from V1 to V2

// V1 webhook event types
"object.record.created"

// V2 webhook event types
"record.created"
"record.updated"
"record.deleted"
"record.merged"
"list-entry.created"
"note.created"
"task.created"
// ... plus filtering support

V2 webhooks support event filtering to reduce volume:

await client.post("/webhooks", {
  target_url: "https://yourapp.com/webhooks/attio",
  subscriptions: [
    {
      event_type: "record.updated",
      filter: {
        // Only trigger for updates to the "stage" attribute on deals
        $and: [
          { object: { $eq: "deals" } },
          { attribute: { $eq: "stage" } },
        ],
      },
    },
  ],
});

Community SDK Migration

Since there is no official Attio SDK, you may be using community packages:

attio-js (most popular community SDK)

# Check current version
npm list attio-js

# Upgrade
npm install attio-js@latest
// attio-js uses the v2 API natively
import { AttioClient } from "attio-js";

const client = new AttioClient({ accessToken: process.env.ATTIO_API_KEY });
const people = await client.records.query("people", { limit: 10 });

Direct fetch (recommended for control)

No upgrade risk -- you control the endpoint URLs directly. See attio-sdk-patterns for a typed wrapper.

Detecting API Changes

Attio does not publish a traditional changelog for the REST API. Monitor for changes:

// Save the OpenAPI spec hash and check periodically
import crypto from "crypto";

async function checkForApiChanges(): Promise<boolean> {
  const spec = await fetch("https://docs.attio.com/openapi.json").then(r => r.text());
  const hash = crypto.createHash("sha256").update(spec).digest("hex");

  const previousHash = await readStoredHash(); // From file or DB
  if (previousHash && hash !== previousHash) {
    console.warn("Attio OpenAPI spec changed! Review for breaking changes.");
    await storeHash(hash);
    return true;
  }
  await storeHash(hash);
  return false;
}

Migration Checklist

[ ] Base URL updated to /v2
[ ] Object references use slugs instead of UUIDs where possible
[ ] Record queries migrated from GET to POST with filter body
[ ] Record creation uses data.values wrapper with arrays
[ ] Webhook subscriptions recreated with v2 event types
[ ] Webhook handlers updated for v2 payload format
[ ] Pagination migrated from page/per_page to limit/offset
[ ] Error handling updated for v2 error response format
[ ] Tests updated and passing against v2 endpoints
[ ] OpenAPI spec monitoring configured for future changes

Error Handling

| Migration issue | Symptom | Fix | |----------------|---------|-----| | Old v1 URL | 404 on all calls | Update base URL to /v2 | | UUID instead of slug | 404 on object endpoints | Use api_slug from GET /v2/objects | | Flat values (v1 format) | 422 validation error | Wrap in { data: { values: { ... } } } | | Old webhook event types | Webhook never fires | Recreate with v2 event types | | Old pagination params | Ignored, only first page returned | Switch to limit + offset |

Resources

Next Steps

For CI integration during upgrades, see attio-ci-integration.