Folk
Integrate with Folk CRM API for managing contacts, pipelines, groups,
You are an expert in Folk CRM API integration. You build lightweight relationship management workflows that leverage Folk's contact-centric model, pipeline management, contact enrichment, and mail merge capabilities using Folk's REST API and TypeScript. ## Key Points - **Skipping duplicate check before creating contacts**: Folk does not auto-merge duplicates. Always search by email before creating a new person record. - **Ignoring group membership when deleting contacts**: Removing a contact does not remove them from groups or pipelines. Clean up memberships first to avoid orphaned references. - **Sending mail merge without enrichment**: Personalization tokens fail silently if the contact data is incomplete. Run enrichment and verify field coverage before launching campaigns. - **Not paginating people lists**: The API returns a limited page size by default. Always paginate to retrieve the full contact list. - Building lightweight contact management for small teams without heavyweight CRM overhead - Importing and organizing contact lists from events, conferences, or lead sources into groups - Automating pipeline stage transitions based on external signals or qualification criteria - Running enrichment workflows before outbound email campaigns for higher personalization - Syncing contact data between Folk and other tools like email, calendar, or marketing platforms ## Quick Example ```bash npm install axios ``` ``` FOLK_API_KEY=fk_xxxxxxxxxxxxxxxxxxxxxxxx ```
skilldb get crm-services-skills/FolkFull skill: 198 linesFolk CRM Integration
You are an expert in Folk CRM API integration. You build lightweight relationship management workflows that leverage Folk's contact-centric model, pipeline management, contact enrichment, and mail merge capabilities using Folk's REST API and TypeScript.
Core Philosophy
Contact-First Design
Folk organizes everything around contacts (people and organizations). Contacts can belong to multiple groups and pipelines simultaneously. Design integrations around contact lifecycle rather than deal-centric models.
Group-Based Organization
Groups in Folk are the primary organizational unit, similar to tags or segments. A contact can exist in many groups. Use groups to represent lists, campaigns, or cohorts rather than duplicating contacts across pipelines.
Enrichment Before Outreach
Folk provides contact enrichment that fills in missing data (company, title, social profiles). Always trigger enrichment after importing contacts and before running mail merge campaigns to maximize deliverability and personalization.
Setup
npm install axios
FOLK_API_KEY=fk_xxxxxxxxxxxxxxxxxxxxxxxx
Initialize the client:
import axios, { AxiosInstance } from "axios";
const folk: AxiosInstance = axios.create({
baseURL: "https://api.folk.app/v1",
headers: {
Authorization: `Bearer ${process.env.FOLK_API_KEY}`,
"Content-Type": "application/json",
},
});
Key Patterns
Do: Use the search endpoint to find contacts before creating
async function findContact(email: string) {
const { data } = await folk.get("/people", {
params: { filter: JSON.stringify({ emails: { contains: email } }) },
});
return data.data.length > 0 ? data.data[0] : null;
}
Not: Creating contacts without checking for duplicates
// WRONG - Folk does not auto-deduplicate
await folk.post("/people", {
firstName: "Jane",
lastName: "Doe",
emails: [{ value: "jane@example.com" }],
});
// This creates a duplicate if Jane already exists
Do: Add contacts to groups for organized segmentation
async function addToGroup(personId: string, groupId: string) {
const { data } = await folk.post(`/groups/${groupId}/members`, {
personIds: [personId],
});
return data;
}
Common Patterns
Create a Person with Full Details
async function createPerson(
firstName: string,
lastName: string,
email: string,
company?: string,
title?: string,
phone?: string
) {
const payload: Record<string, unknown> = {
firstName,
lastName,
emails: [{ value: email, label: "work" }],
};
if (company) payload.company = company;
if (title) payload.jobTitle = title;
if (phone) payload.phones = [{ value: phone, label: "work" }];
const { data } = await folk.post("/people", payload);
return data;
}
Upsert Contact by Email
async function upsertPerson(
email: string,
fields: { firstName: string; lastName: string; company?: string }
) {
const existing = await findContact(email);
if (existing) {
const { data } = await folk.patch(`/people/${existing.id}`, fields);
return { action: "updated", person: data };
}
const { data } = await folk.post("/people", {
...fields,
emails: [{ value: email, label: "work" }],
});
return { action: "created", person: data };
}
Manage Pipeline Stages
async function moveToPipelineStage(
pipelineId: string,
personId: string,
stageId: string
) {
const { data } = await folk.patch(
`/pipelines/${pipelineId}/people/${personId}`,
{ stageId }
);
return data;
}
async function getPipelineStages(pipelineId: string) {
const { data } = await folk.get(`/pipelines/${pipelineId}/stages`);
return data.data;
}
Bulk Import Contacts into a Group
async function bulkImportToGroup(
groupId: string,
contacts: { firstName: string; lastName: string; email: string }[]
) {
const personIds: string[] = [];
for (const contact of contacts) {
const person = await upsertPerson(contact.email, {
firstName: contact.firstName,
lastName: contact.lastName,
});
personIds.push(person.person.id);
}
// Add all to group in one call
const { data } = await folk.post(`/groups/${groupId}/members`, { personIds });
return { imported: personIds.length, group: data };
}
Fetch All People with Pagination
async function getAllPeople() {
const allPeople: any[] = [];
let page = 1;
let hasMore = true;
while (hasMore) {
const { data } = await folk.get("/people", {
params: { page, limit: 100 },
});
allPeople.push(...data.data);
hasMore = data.data.length === 100;
page++;
}
return allPeople;
}
Anti-Patterns
- Skipping duplicate check before creating contacts: Folk does not auto-merge duplicates. Always search by email before creating a new person record.
- Ignoring group membership when deleting contacts: Removing a contact does not remove them from groups or pipelines. Clean up memberships first to avoid orphaned references.
- Sending mail merge without enrichment: Personalization tokens fail silently if the contact data is incomplete. Run enrichment and verify field coverage before launching campaigns.
- Not paginating people lists: The API returns a limited page size by default. Always paginate to retrieve the full contact list.
When to Use
- Building lightweight contact management for small teams without heavyweight CRM overhead
- Importing and organizing contact lists from events, conferences, or lead sources into groups
- Automating pipeline stage transitions based on external signals or qualification criteria
- Running enrichment workflows before outbound email campaigns for higher personalization
- Syncing contact data between Folk and other tools like email, calendar, or marketing platforms
Install this skill directly: skilldb add crm-services-skills
Related Skills
Airtable
Integrate with Airtable API for managing bases, tables, records, views,
Attio
Integrate with Attio CRM API for managing objects, records, lists, notes,
Close Crm
Integrate with Close CRM API for managing leads, contacts, activities,
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,