folk
folk.
Folk CRM records — people (contacts), companies, deals (or any other
setup & usage
folk fournit une clé api personnelle. récupère-la dans les réglages api/développeur de ton compte folk (doc : developer.folk.app).
/account), connecteur folkfolk_group) — la suppression d'un groupe ou d'un champ custom reste réservée à l'app folk ; retirer un membre d'un groupe, en revanche, se fait via l'api (folk_group(op="remove_member"))gère ton crm folk (personnes/contacts, entreprises, deals ou tout autre objet custom) + notes, interactions et tâches depuis claude. Tout passe par folk_record (paramètre entity) — il n'y a pas de tool séparé folk_company/folk_contact/folk_deal.
folk_record(op="search") (entity person), puis folk_record(op="get") pour la fichefolk_record(op="create") (entity person)folk_record(op="create") (entity interaction, type/titre/contenu)- ⚠️ date_time est requis par folk même s'il se lit comme optionnel ; omis, il vaut maintenant. Jusqu'au 27/08/2026 l'omettre rendait un 422 opaque
folk_record(op="search", entity="interaction", entity_id="per_…") : emails, événements d'agenda, messages whatsapp et interactions loggées que folk garde sur cette fiche, puis op="get" (avec le même entity_id) pour le corps complet d'une seule- ⚠️ correctif : ce document a longtemps affirmé que folk ne disait QUE *quand* on avait parlé à quelqu'un, jamais *quoi*. C'était faux — c'était vrai du connecteur, qui n'exposait que la création d'interaction, pas de folk, dont les endpoints de lecture existaient déjà (en open beta)
- une interaction n'est pas adressable seule : entity_id (la personne/société porteuse) est obligatoire en recherche, lecture, modification et suppression
- la recherche rend content: {subject, snippet} — pas le corps. Le corps complet (body) ne vient que d'un op="get" sur UNE interaction : balayer dit de quoi on a parlé, lire ce qui a été dit coûte un get par interaction
- les interactions importées (email, agenda, whatsapp) sont en lecture seule : folk refuse op="update" et op="delete" dessus, elles appartiennent à leur source
- when="past" par défaut (ce qui a eu lieu) ; "upcoming" pour ce qui est prévu, "all" pour les deux — le défaut MASQUE donc l'à-venir
- privacyLevel cache le corps, pas le sujet : sur subjectOnly/sensitive/internal, le get rend toujours subject et snippet mais body est simplement absent. la clé est byo → tu vois ce que voit SON propriétaire. un body manquant est un résultat de permission, pas une interaction vide
folk_record(op="search", entity="task", entity_id="per_…", filters={"completedAt": {"empty": True}}) ; pour clore : folk_record(op="mark_done", entity="task", ids=[...]) (jusqu'à 50 d'un coup — entity est requis), op="mark_todo" pour rouvrir- ⚠️ rappels dépréciés — et ce sont les MÊMES enregistrements : folk a déprécié /reminders le 13/08/2026 (retrait annoncé février 2027) au profit des tâches. Vérifié en live le 27/08/2026 : un seul stock, deux vues — rmd_<uuid> et tsk_<uuid> désignent le même enregistrement, et l'échange de préfixe résout dans les deux sens (30 rappels = 30 tâches, mêmes uuid). Rien n'est donc orphelin : un rappel posé avant la bascule se lit, se filtre et se ferme comme une tâche aujourd'hui. Écris tout ce qui est nouveau en entity="task", qui fait strictement plus (description markdown, filtres par échéance/assigné/complétion, suivi de complétion)
- une tâche ne se termine JAMAIS toute seule chez folk (contrairement à un rappel qui se marque « déclenché ») : completedAt ne bouge que sur un mark_done/mark_todo explicite — et il est refusé dans un op="update"
- ⚠️ pas d'événement webhook task.* chez folk à ce jour — seuls les reminder.* existent
folk_record(op="create") (entity deal), et folk_record(op="search", entity="deal") pour les lister — object_type est auto-découvert si omis (voir note ci-dessous) ; ne le passer explicitement que si le groupe a PLUSIEURS objets custom au-delà de person/company (l'auto-découverte lève alors une erreur qui les liste)folk_record(op="create") (entity person, items=[...]) en un seul appelfolk_group(op="create", name="Leads", visibility="private")folk_group(op="create_custom_field") (entity_type="person" par défaut, custom_field={"type": "singleSelect", "name": "Statut", "options": [...]})person/company sont des entity_type FIXES. Tout objet au-delà (deal ou autre) est un objet custom que chaque client folk nomme lui-même ("Deals" n'est que le nom choisi par CE workspace — un autre pourrait l'appeler "Opportunités", au singulier, etc.). Pour folk_group(op="custom_fields"/...), découvrir le nom : appeler avec n'importe quel entity_type — le 404 de Folk liste les VRAIS entity_type de ce groupe ("Available entity types are: ..."), puis rappeler avec le bon nom. folk_record's object_type fait cette découverte tout seul (voir note ci-dessus) — seul folk_group demande encore de la faire à la mainfolk_group(op="add_member") (user_id depuis folk_user(op="list"), role="admin")folk_group(op="members") / folk_group(op="remove_member")visibility="public") a une appartenance IMPLICITE : folk_group(op="members") y liste TOUT le workspace en rôle "admin", que quelqu'un ait été ajouté ou non (vérifié en live) — add_member/remove_member/update_member n'ont d'effet réel que sur un groupe private (appartenance explicite)folk_webhook(op="create") (avant ça : folk_group(op="list") pour l'id du groupe, folk_group(op="custom_fields") si le filtre porte sur un champ custom)folk_webhook(op="list") / folk_webhook(op="update") (fields={"status": "inactive"})outils
usage
claude plugin marketplace add otomata-tech/oto-plugin — mcp + skill configured.pipx install oto-cli then oto folk …