Attio
Integrate with Attio CRM API for managing objects, records, lists, notes, and relationship intelligence. Build next-generation CRM workflows using Attio's REST API v2 and TypeScript.
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: 199 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
Close Crm
Integrate with Close CRM API for managing leads, contacts, activities, sequences, and smart views. Build inside-sales automations using Close's REST API and TypeScript.
Folk
Integrate with Folk CRM API for managing contacts, pipelines, groups, enrichment, and mail merge. Build lightweight relationship management workflows using Folk's REST API and TypeScript.
Hubspot
Integrate with HubSpot CRM API for managing contacts, deals, companies, pipelines, workflows, and webhooks. Build robust sales and marketing automation using HubSpot's v3 REST API and TypeScript client.
Monday Com
Integrate with Monday.com GraphQL API for managing boards, items, columns, updates, and webhooks. Build work management automations using Monday.com's API v2 and TypeScript.
Pipedrive
Integrate with Pipedrive CRM API for managing deals, persons, organizations, activities, and webhooks. Build sales pipeline automations using Pipedrive's REST API v1 and TypeScript.
Salesforce
Integrate with Salesforce REST and SOQL APIs for querying records, managing objects, executing Apex, and performing bulk data operations. Build scalable enterprise CRM integrations using jsforce and TypeScript.