The getContacts tool retrieves contact records for a specific customer from the Firebase/Firestore database with support for pagination and sorting.
tools/getContacts.js
Retrieves contacts for a specific customer with cursor-based pagination support. Contacts are retrieved from the Firestore path: /Accounts/{accountId}/Customers/{customerId}/Contacts.
{
customerId: string; // REQUIRED: Customer ID to fetch contacts for
limit?: number; // Number of records to retrieve (1-100, default: 50)
cursor?: string; // Document ID for cursor-based pagination
orderBy?: string; // Field to order by (default: "contactId")
orderDirection?: "asc" | "desc"; // Sort direction (default: "asc")
cursorDirection?: "next" | "previous"; // Direction for pagination (default: "next")
includeTotal?: boolean; // Include total count of all contacts (default: false)
}
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
customerId |
string | Yes | - | ID of the customer to fetch contacts for |
limit |
number | No | 50 | Maximum number of contacts to return (1-100) |
cursor |
string | No | - | Document ID to start pagination from |
orderBy |
string | No | “contactId” | Field name to sort by |
orderDirection |
enum | No | “asc” | Sort direction: “asc” or “desc” |
cursorDirection |
enum | No | “next” | Pagination direction: “next” or “previous” |
includeTotal |
boolean | No | false | Whether to include total count (expensive) |
{
contacts: Contact[];
pagination: PaginationMetadata;
}
{
id: string; // Firestore document ID
path: string; // Full Firestore path
contactId: number; // Unique contact ID
createdAt: string | Date; // Creation timestamp
createdBy: string; // Creator user ID
customer: string; // Customer reference path
email: string; // Contact email address
firstName: string; // First name
greeting: string; // Greeting/salutation
imported: boolean; // Whether contact was imported
lastName: string; // Last name
mailchimp: {
id: string | null; // Mailchimp ID if synced
};
metadata: Record<string, any>; // Additional metadata
mobilePhone: string; // Mobile phone number
opt_out_email?: boolean; // Email opt-out status
opt_out_letter?: boolean; // Letter opt-out status
ownedBy: string; // Owner user ID
tags: any[]; // Contact tags
telePhone: string; // Telephone number
}
{
limit: number; // Applied limit
hasMore: boolean; // Whether more results exist
nextCursor: string | null; // Cursor for next page
previousCursor: string | null; // Cursor for previous page
total?: number | null; // Total count (if includeTotal was true)
}
// Get first 10 contacts for a customer
const result = await getContacts(context, {
customerId: "customer123",
limit: 10
});
console.log(result.contacts); // Array of 10 contacts
console.log(result.pagination); // Pagination metadata
// First page
const page1 = await getContacts(context, {
customerId: "customer123",
limit: 20,
orderBy: "contactId",
orderDirection: "asc"
});
// Next page
const page2 = await getContacts(context, {
customerId: "customer123",
limit: 20,
cursor: page1.pagination.nextCursor,
cursorDirection: "next"
});
// Get contacts sorted by email
const result = await getContacts(context, {
customerId: "customer123",
limit: 10,
orderBy: "email",
orderDirection: "asc"
});
const result = await getContacts(context, {
customerId: "customer123",
limit: 10,
includeTotal: true
});
console.log(`Customer has ${result.pagination.total} total contacts`);
The tool transforms Firestore documents by:
id and full pathcreatedAt timestamp to Date objectconst transformContact = (doc) => {
const data = doc.data();
return {
id: doc.id,
path: doc.ref.path,
...data,
createdAt: safeToDate(data.createdAt) || data.createdAt,
};
};
The tool validates that customerId is provided:
if (!customerId) {
throw new Error("The 'customerId' parameter is required.");
}
By default, contacts are ordered by contactId in ascending order.
| Error | Cause | Solution |
|---|---|---|
| “The ‘customerId’ parameter is required.” | Missing customerId | Provide customerId in params |
| “Error fetching contacts for customer [id]: [message]” | Firestore query failed | Check Firebase connection and customer exists |
| “Failed to fetch contacts for customer [id].” | Query error | Verify customer ID is valid |
Errors are logged with the customer ID and re-thrown:
catch (error) {
console.error(`Error fetching contacts for customer ${customerId}:`, error);
throw new Error(`Failed to fetch contacts for customer ${customerId}.`);
}
includeTotal: true requires an additional query/Accounts/{accountId}/Customers/{customerId}/Contacts/{contactId}
- contactId: number
- createdAt: timestamp
- createdBy: string
- customer: string (reference)
- email: string
- firstName: string
- greeting: string
- imported: boolean
- lastName: string
- mailchimp: { id: string | null }
- metadata: object
- mobilePhone: string
- opt_out_email: boolean
- opt_out_letter: boolean
- ownedBy: string
- tags: array
- telePhone: string