Attio
Integrate with Attio CRM API for managing objects, records, lists, notes,
You are an expert in Attio CRM API integration using Attio's REST API v2. You build relationship-intelligence-driven CRM workflows that leverage Attio's flexible object model, automatic data enrichment, and real-time record management. ## Key Points - **Hardcoding attribute slugs**: Attribute slugs can differ between Attio workspaces. Always fetch the object schema first to discover the correct slugs. - **Ignoring the assert (PUT) endpoint**: Using POST to create records bypasses deduplication. Always use PUT with `matching_attribute` for upsert behavior. - **Treating list entries as records**: List entries are separate from the underlying record. Updating a list entry's attributes does not modify the parent record's attributes. - **Not paginating query results**: The query endpoint defaults to 25 results. Always implement offset-based pagination to retrieve complete result sets. - Building relationship-intelligence workflows that track interactions across people and companies - Managing custom sales pipelines using Attio lists as deal stages - Syncing enriched company and contact data from Attio into external systems - Automating note creation and activity logging from third-party communication tools - Creating custom CRM objects and attributes programmatically for new business workflows ## Quick Example ```bash npm install axios ``` ``` ATTIO_API_KEY=attio_key_xxxxxxxxxxxxxxxx ```
skilldb get crm-services-skills/AttioFull skill: 200 linesAttio CRM Integration
You are an expert in Attio CRM API integration using Attio's REST API v2. You build relationship-intelligence-driven CRM workflows that leverage Attio's flexible object model, automatic data enrichment, and real-time record management.
Core Philosophy
Object-Attribute Flexibility
Attio uses a configurable object model where standard objects (people, companies) and custom objects each have user-defined attributes. Never hardcode attribute slugs. Always query the object schema first to discover available attributes and their types.
Record Deduplication by Domain
Attio automatically deduplicates company records by domain and people by email. Leverage this by always providing email addresses and domains in write operations. The API will merge matching records rather than creating duplicates.
List-Driven Workflows
Attio lists are the primary workflow container, similar to pipeline views. Each list has entries that reference records. Use list entries (not raw records) for pipeline management, deal tracking, and process automation.
Setup
npm install axios
ATTIO_API_KEY=attio_key_xxxxxxxxxxxxxxxx
Initialize the client:
import axios, { AxiosInstance } from "axios";
const attio: AxiosInstance = axios.create({
baseURL: "https://api.attio.com/v2",
headers: {
Authorization: `Bearer ${process.env.ATTIO_API_KEY}`,
"Content-Type": "application/json",
},
});
Key Patterns
Do: Assert records using matching attributes for upsert behavior
async function assertCompany(domain: string, name: string) {
const { data } = await attio.put("/objects/companies/records", {
data: {
values: {
domains: [{ domain }],
name: [{ value: name }],
},
},
matching_attribute: "domains",
});
return data.data;
}
Not: Creating records without matching attributes
// WRONG - creates duplicates instead of upserting
await attio.post("/objects/companies/records", {
data: { values: { name: [{ value: "Acme" }] } },
});
Do: Query records using the filter API
async function findCompaniesByIndustry(industry: string) {
const { data } = await attio.post("/objects/companies/records/query", {
filter: {
"categories.title": { "$eq": industry },
},
limit: 50,
offset: 0,
});
return data.data;
}
Common Patterns
Create a Person Record
async function assertPerson(
email: string,
firstName: string,
lastName: string
) {
const { data } = await attio.put("/objects/people/records", {
data: {
values: {
email_addresses: [{ email_address: email }],
first_name: [{ first_name: firstName }],
last_name: [{ last_name: lastName }],
},
},
matching_attribute: "email_addresses",
});
return data.data;
}
Add a Record to a List (Pipeline Entry)
async function addListEntry(
listSlug: string,
recordId: string,
objectSlug: string,
entryAttributes?: Record<string, unknown>
) {
const { data } = await attio.post(`/lists/${listSlug}/entries`, {
data: {
parent_record: { object: objectSlug, record_id: recordId },
entry_values: entryAttributes || {},
},
});
return data.data;
}
Query List Entries with Filters
async function queryListEntries(
listSlug: string,
filter?: Record<string, unknown>
) {
const entries: any[] = [];
let offset = 0;
let hasMore = true;
while (hasMore) {
const { data } = await attio.post(`/lists/${listSlug}/entries/query`, {
filter: filter || {},
limit: 50,
offset,
});
entries.push(...data.data);
hasMore = data.data.length === 50;
offset += 50;
}
return entries;
}
Create a Note on a Record
async function createNote(
parentObject: string,
parentRecordId: string,
title: string,
content: string
) {
const { data } = await attio.post("/notes", {
data: {
parent_object: parentObject,
parent_record_id: parentRecordId,
title,
format: "plaintext",
content,
},
});
return data.data;
}
Fetch Object Schema
async function getObjectAttributes(objectSlug: string) {
const { data } = await attio.get(`/objects/${objectSlug}/attributes`);
return data.data.map((attr: any) => ({
slug: attr.api_slug,
title: attr.title,
type: attr.type,
isRequired: attr.is_required,
}));
}
Anti-Patterns
- Hardcoding attribute slugs: Attribute slugs can differ between Attio workspaces. Always fetch the object schema first to discover the correct slugs.
- Ignoring the assert (PUT) endpoint: Using POST to create records bypasses deduplication. Always use PUT with
matching_attributefor upsert behavior. - Treating list entries as records: List entries are separate from the underlying record. Updating a list entry's attributes does not modify the parent record's attributes.
- Not paginating query results: The query endpoint defaults to 25 results. Always implement offset-based pagination to retrieve complete result sets.
When to Use
- Building relationship-intelligence workflows that track interactions across people and companies
- Managing custom sales pipelines using Attio lists as deal stages
- Syncing enriched company and contact data from Attio into external systems
- Automating note creation and activity logging from third-party communication tools
- Creating custom CRM objects and attributes programmatically for new business workflows
Install this skill directly: skilldb add crm-services-skills
Related Skills
Airtable
Integrate with Airtable API for managing bases, tables, records, views,
Close Crm
Integrate with Close CRM API for managing leads, contacts, activities,
Folk
Integrate with Folk CRM API for managing contacts, pipelines, groups,
Hubspot
Integrate with HubSpot CRM API for managing contacts, deals, companies,
Monday Com
Integrate with Monday.com GraphQL API for managing boards, items, columns,
Pipedrive
Integrate with Pipedrive CRM API for managing deals, persons, organizations,