folk
folk.
Folk CRM records — people (contacts), companies, deals (or any other
setup & usage
folk provides a personal api key. get it from the api/developer settings of your folk account (docs: developer.folk.app).
/account), folk connectorfolk_group) — deleting a group or a custom field remains reserved to the folk app; removing a member from a group, however, is done via the api (folk_group(op="remove_member"))manage your folk crm (people/contacts, companies, deals or any other custom object) + notes, interactions and tasks from claude. Everything goes through folk_record (parameter entity) — there is no separate folk_company/folk_contact/folk_deal tool.
folk_record(op="search") (entity person), then folk_record(op="get") for the recordfolk_record(op="create") (entity person)folk_record(op="create") (entity interaction, type/title/content)- ⚠️ date_time is required by folk even though it reads as optional; if omitted, it defaults to now. Until 27/08/2026 omitting it returned an opaque 422
folk_record(op="search", entity="interaction", entity_id="per_…"): emails, calendar events, whatsapp messages and logged interactions that folk keeps on this record, then op="get" (with the same entity_id) for the full body of a single one- ⚠️ correction: this document long claimed that folk only told you *when* you had talked to someone, never *what* was said. That was false — it was true of the connector, which only exposed interaction creation, not of folk, whose read endpoints already existed (in open beta)
- an interaction is not addressable on its own: entity_id (the person/company that carries it) is mandatory for search, read, update and delete
- search returns content: {subject, snippet} — not the body. The full body (body) only comes from an op="get" on ONE interaction: scanning tells you what was discussed, reading what was said costs one get per interaction
- imported interactions (email, calendar, whatsapp) are read-only: folk refuses op="update" and op="delete" on them, they belong to their source
- when="past" by default (what has happened); "upcoming" for what is planned, "all" for both — so the default HIDES what is upcoming
- privacyLevel hides the body, not the subject: on subjectOnly/sensitive/internal, the get still returns subject and snippet but body is simply absent. the key is byo → you see what ITS owner sees. a missing body is a permission result, not an empty interaction
folk_record(op="search", entity="task", entity_id="per_…", filters={"completedAt": {"empty": True}}); to close: folk_record(op="mark_done", entity="task", ids=[...]) (up to 50 at once — entity is required), op="mark_todo" to reopen- ⚠️ reminders are deprecated — and they are the SAME records: folk deprecated /reminders on 13/08/2026 (removal announced for February 2027) in favor of tasks. Verified live on 27/08/2026: one store, two views — rmd_<uuid> and tsk_<uuid> designate the same record, and swapping the prefix resolves in both directions (30 reminders = 30 tasks, same uuids). Nothing is orphaned: a reminder set before the switch can be read, filtered and closed like a task today. Write everything new as entity="task", which does strictly more (markdown description, filters by due date/assignee/completion, completion tracking)
- a task NEVER completes by itself in folk (unlike a reminder, which gets marked "triggered"): completedAt only changes on an explicit mark_done/mark_todo — and it is refused in an op="update"
- ⚠️ no task.* webhook event in folk to date — only reminder.* exist
folk_record(op="create") (entity deal), and folk_record(op="search", entity="deal") to list them — object_type is auto-discovered if omitted (see note below); only pass it explicitly if the group has SEVERAL custom objects beyond person/company (auto-discovery then raises an error that lists them)folk_record(op="create") (entity person, items=[...]) in a single callfolk_group(op="create", name="Leads", visibility="private")folk_group(op="create_custom_field") (entity_type="person" by default, custom_field={"type": "singleSelect", "name": "Status", "options": [...]})person/company are FIXED entity_types. Any object beyond those (deal or other) is a custom object that each folk customer names themselves ("Deals" is just the name chosen by THIS workspace — another could call it "Opportunities", in the singular, etc.). For folk_group(op="custom_fields"/...), discover the name: call with any entity_type — Folk's 404 lists the REAL entity_types of this group ("Available entity types are: ..."), then call again with the right name. folk_record's object_type does this discovery on its own (see note above) — only folk_group still requires doing it by handfolk_group(op="add_member") (user_id from folk_user(op="list"), role="admin")folk_group(op="members") / folk_group(op="remove_member")visibility="public") has IMPLICIT membership: folk_group(op="members") lists the WHOLE workspace there with the "admin" role, whether or not anyone was added (verified live) — add_member/remove_member/update_member only have a real effect on a private group (explicit membership)folk_webhook(op="create") (before that: folk_group(op="list") for the group id, folk_group(op="custom_fields") if the filter is on a custom field)folk_webhook(op="list") / folk_webhook(op="update") (fields={"status": "inactive"})this connector accepts multiple comptes: each stored credential becomes a named account (one name per compte), at your level, your team's or your org's.
_account="<name>" on the tool; list them: oto_identity(op='list', connector='folk') (scope='org' or scope='group' for the org's or team's)oto_identity(op='set', connector='folk', identity_id='<name>'); rename: op='rename' with new_name_account) and adding upoutils
utilisation
claude plugin marketplace add otomata-tech/oto-plugin — mcp + skill configurés.pipx install oto-cli puis oto folk …