Query Attio People
Query People records from Attio with filters and sorts, handling pagination automatically
Source Code
import fs from "fs";
const [
filterJson = "",
sortsJson = "",
maxResults = "50",
outputPath = "session/attio-people.json",
] = process.argv.slice(2);
const maxResultsNum = Math.min(parseInt(maxResults) || 50, 500);
// Parse filter and sorts if provided
let filter = null;
let sorts = null;
if (filterJson) {
try {
filter = JSON.parse(filterJson);
} catch (e) {
console.error("Error parsing filter JSON:", e.message);
process.exit(1);
}
}
if (sortsJson) {
try {
sorts = JSON.parse(sortsJson);
} catch (e) {
console.error("Error parsing sorts JSON:", e.message);
process.exit(1);
}
}
console.log(`Querying Attio People...`);
if (filter) console.log(` Filter: ${JSON.stringify(filter)}`);
if (sorts) console.log(` Sort: ${JSON.stringify(sorts)}`);
const ATTIO_API = "https://api.attio.com/v2";
const headers = {
Authorization: "Bearer PLACEHOLDER_TOKEN",
"Content-Type": "application/json",
};
/**
* Extract readable value from an Attio attribute value
*/
function extractAttributeValue(attr) {
if (!attr || !Array.isArray(attr) || attr.length === 0) return null;
// Attio returns attribute values as arrays of value objects
const values = attr.map((v) => {
if (v.value !== undefined) return v.value;
if (v.full_name !== undefined) return v.full_name;
if (v.first_name !== undefined)
return `${v.first_name || ""} ${v.last_name || ""}`.trim();
if (v.email_address !== undefined) return v.email_address;
if (v.phone_number !== undefined) return v.phone_number;
if (v.original_phone_number !== undefined) return v.original_phone_number;
if (v.line_1 !== undefined) {
// Location
return [v.line_1, v.locality, v.region, v.country_code]
.filter(Boolean)
.join(", ");
}
if (v.target_object !== undefined) {
// Record reference (linked record)
return { id: v.target_record_id, object: v.target_object };
}
if (v.referenced_actor_id !== undefined) {
// Actor reference
return v.referenced_actor_id;
}
if (v.option !== undefined) {
// Select/status option
return v.option;
}
// Fallback: return the whole object if we can't extract
return v;
});
// Return single value if only one, otherwise array
return values.length === 1 ? values[0] : values;
}
try {
const records = [];
let cursor = undefined;
let totalFetched = 0;
while (totalFetched < maxResultsNum) {
const pageSize = Math.min(maxResultsNum - totalFetched, 100);
const body = {
limit: pageSize,
...(filter && { filter }),
...(sorts && { sorts }),
...(cursor && { offset: cursor }),
};
const queryRes = await fetch(`${ATTIO_API}/objects/people/records/query`, {
method: "POST",
headers,
body: JSON.stringify(body),
});
if (!queryRes.ok) {
const errorText = await queryRes.text();
console.error(`Query failed: ${queryRes.status}`);
console.error(errorText);
throw new Error(`Query failed: ${queryRes.status}`);
}
const response = await queryRes.json();
for (const record of response.data || []) {
if (totalFetched >= maxResultsNum) break;
const entry = {
id: record.id?.record_id,
createdAt: record.created_at,
values: {},
};
// Extract all attribute values
for (const [slug, attrValue] of Object.entries(record.values || {})) {
entry.values[slug] = extractAttributeValue(attrValue);
}
records.push(entry);
totalFetched++;
}
// Check for more pages
if (!response.next_page_offset || totalFetched >= maxResultsNum) break;
cursor = response.next_page_offset;
console.log(` Fetched ${totalFetched} records...`);
}
// Ensure output directory exists
const dir = outputPath.substring(0, outputPath.lastIndexOf("/"));
if (dir) {
fs.mkdirSync(dir, { recursive: true });
}
const output = {
object: "people",
filter: filter || null,
sorts: sorts || null,
queriedAt: new Date().toISOString(),
count: records.length,
records,
};
fs.writeFileSync(outputPath, JSON.stringify(output, null, 2));
// Log summary
console.log(`\nā Found ${records.length} people`);
console.log(` Written to: ${outputPath}`);
// Show first few records
if (records.length > 0) {
console.log(`\n Sample records:`);
for (const record of records.slice(0, 3)) {
const name =
record.values.name ||
record.values.first_name ||
record.values.full_name ||
"Unknown";
const email = record.values.email_addresses || "";
console.log(` š¤ ${name}${email ? ` (${email})` : ""}`);
}
if (records.length > 3) {
console.log(` ... and ${records.length - 3} more`);
}
}
console.log(
JSON.stringify({
success: true,
outputPath,
count: records.length,
})
);
} catch (error) {
console.error("Error querying Attio:", error.message);
throw error;
} import fs from "fs";
const [
filterJson = "",
sortsJson = "",
maxResults = "50",
outputPath = "session/attio-people.json",
] = process.argv.slice(2);
const maxResultsNum = Math.min(parseInt(maxResults) || 50, 500);
// Parse filter and sorts if provided
let filter = null;
let sorts = null;
if (filterJson) {
try {
filter = JSON.parse(filterJson);
} catch (e) {
console.error("Error parsing filter JSON:", e.message);
process.exit(1);
}
}
if (sortsJson) {
try {
sorts = JSON.parse(sortsJson);
} catch (e) {
console.error("Error parsing sorts JSON:", e.message);
process.exit(1);
}
}
console.log(`Querying Attio People...`);
if (filter) console.log(` Filter: ${JSON.stringify(filter)}`);
if (sorts) console.log(` Sort: ${JSON.stringify(sorts)}`);
const ATTIO_API = "https://api.attio.com/v2";
const headers = {
Authorization: "Bearer PLACEHOLDER_TOKEN",
"Content-Type": "application/json",
};
/**
* Extract readable value from an Attio attribute value
*/
function extractAttributeValue(attr) {
if (!attr || !Array.isArray(attr) || attr.length === 0) return null;
// Attio returns attribute values as arrays of value objects
const values = attr.map((v) => {
if (v.value !== undefined) return v.value;
if (v.full_name !== undefined) return v.full_name;
if (v.first_name !== undefined)
return `${v.first_name || ""} ${v.last_name || ""}`.trim();
if (v.email_address !== undefined) return v.email_address;
if (v.phone_number !== undefined) return v.phone_number;
if (v.original_phone_number !== undefined) return v.original_phone_number;
if (v.line_1 !== undefined) {
// Location
return [v.line_1, v.locality, v.region, v.country_code]
.filter(Boolean)
.join(", ");
}
if (v.target_object !== undefined) {
// Record reference (linked record)
return { id: v.target_record_id, object: v.target_object };
}
if (v.referenced_actor_id !== undefined) {
// Actor reference
return v.referenced_actor_id;
}
if (v.option !== undefined) {
// Select/status option
return v.option;
}
// Fallback: return the whole object if we can't extract
return v;
});
// Return single value if only one, otherwise array
return values.length === 1 ? values[0] : values;
}
try {
const records = [];
let cursor = undefined;
let totalFetched = 0;
while (totalFetched < maxResultsNum) {
const pageSize = Math.min(maxResultsNum - totalFetched, 100);
const body = {
limit: pageSize,
...(filter && { filter }),
...(sorts && { sorts }),
...(cursor && { offset: cursor }),
};
const queryRes = await fetch(`${ATTIO_API}/objects/people/records/query`, {
method: "POST",
headers,
body: JSON.stringify(body),
});
if (!queryRes.ok) {
const errorText = await queryRes.text();
console.error(`Query failed: ${queryRes.status}`);
console.error(errorText);
throw new Error(`Query failed: ${queryRes.status}`);
}
const response = await queryRes.json();
for (const record of response.data || []) {
if (totalFetched >= maxResultsNum) break;
const entry = {
id: record.id?.record_id,
createdAt: record.created_at,
values: {},
};
// Extract all attribute values
for (const [slug, attrValue] of Object.entries(record.values || {})) {
entry.values[slug] = extractAttributeValue(attrValue);
}
records.push(entry);
totalFetched++;
}
// Check for more pages
if (!response.next_page_offset || totalFetched >= maxResultsNum) break;
cursor = response.next_page_offset;
console.log(` Fetched ${totalFetched} records...`);
}
// Ensure output directory exists
const dir = outputPath.substring(0, outputPath.lastIndexOf("/"));
if (dir) {
fs.mkdirSync(dir, { recursive: true });
}
const output = {
object: "people",
filter: filter || null,
sorts: sorts || null,
queriedAt: new Date().toISOString(),
count: records.length,
records,
};
fs.writeFileSync(outputPath, JSON.stringify(output, null, 2));
// Log summary
console.log(`\nā Found ${records.length} people`);
console.log(` Written to: ${outputPath}`);
// Show first few records
if (records.length > 0) {
console.log(`\n Sample records:`);
for (const record of records.slice(0, 3)) {
const name =
record.values.name ||
record.values.first_name ||
record.values.full_name ||
"Unknown";
const email = record.values.email_addresses || "";
console.log(` š¤ ${name}${email ? ` (${email})` : ""}`);
}
if (records.length > 3) {
console.log(` ... and ${records.length - 3} more`);
}
}
console.log(
JSON.stringify({
success: true,
outputPath,
count: records.length,
})
);
} catch (error) {
console.error("Error querying Attio:", error.message);
throw error;
}