# Help > Using FanConvert, screen by screen. URL : https://docs.fanconvert.ai/en/aide FanConvert help, screen by screen. In the app, the **?** button opens the guided tour of the screen you are on. --- # Connect your assistant (MCP) > Connect Claude Code or another MCP client to FanConvert with the Authorization Bearer header. URL : https://docs.fanconvert.ai/en/api/assistant The FanConvert MCP server lives at **`https://app.fanconvert.ai/mcp`** (HTTP transport, "Streamable HTTP"). Every request carries your key in the `Authorization: Bearer fc_sk_…` header. First [create a key](/en/api/cles) and choose **Brancher un assistant IA** (Connect an AI assistant): FanConvert then gives you the block to paste, **with your key already in it**, and a **Copier le bloc** (Copy block) button. ## Claude Code [#claude-code] 1. Open a terminal on the computer where Claude Code is installed. 2. Paste this command (in FanConvert your key is already in it), then press Enter: ```bash claude mcp add --transport http fanconvert https://app.fanconvert.ai/mcp \ --header "Authorization: Bearer fc_sk_…" ``` 3. In Claude Code, type `/mcp`: **fanconvert shows as connected.** Then ask your question in plain language, for example: "How many sales did Emma make this week?" ## Other MCP client [#other-mcp-client] Any client that accepts a remote MCP server with a fixed header: 1. Add a remote MCP server, "HTTP" transport (Streamable HTTP). 2. Address: `https://app.fanconvert.ai/mcp` 3. Header sent with every request: **`Authorization: Bearer `**. ## Other assistants [#other-assistants] In Settings › API & MCP, the **Claude**, **Cursor** and **ChatGPT** tabs show that their setup guide is still being verified, or, for ChatGPT, that it does not accept keys yet (it requires an OAuth sign-in that FanConvert does not offer yet). This page will cover each of them as soon as its setup is verified in the app. ## What the assistant sees [#what-the-assistant-sees] The assistant only sees the tools its key allows: a read-only key offers no write tool. The full list is on [What the assistant can read and do](/en/api/outils-mcp). ## If it does not work [#if-it-does-not-work] | Symptom | What to do | |---|---| | `401` or "unauthorized" | Key badly copied, expired or revoked: check it in Settings › API & MCP, create another one if needed. | | The assistant does not see a creator | The key does not include her: a creator added after the key was created is not in it. Create a new key. | | A tool is missing | The key lacks the matching permission. A key's permissions do not change: create one with the right choice. | | `429` | Too many requests at once: wait a few seconds. | --- # Create a key > Settings › API & MCP › New key — use, creators, permissions, expiry; the fc_sk_ key is shown only once. URL : https://docs.fanconvert.ai/en/api/cles A key works for both the API and MCP. It starts with `fc_sk_` and **is shown only once**, when it is created. Admins only. If FanConvert asks you to change your password before creating a key, change it first in your account settings. This screen is displayed in French. Labels below are quoted as they appear on screen, with a translation. ## Open the panel [#open-the-panel] In FanConvert: **Réglages › API & MCP** (Settings › API & MCP), then **Nouvelle clé** (New key). The panel has six steps. ### 1. « À quoi va-t-elle servir ? » (What is it for?) [#1--à-quoi-va-t-elle-servir---what-is-it-for] - **Brancher un assistant IA** (Connect an AI assistant) — Claude, Cursor… you get the block to paste. - **Connecter un outil ou un développeur (API)** (Connect a tool or a developer) — Zapier, Make, CRM, your own script. You get a test request. This choice decides which permissions are offered: an AI assistant never gets permissions it cannot use (writing on a fan, pausing the AI on a fan, webhooks: these only exist in the REST API). ### 2. « Nom » (Name) [#2--nom--name] A name to recognize it in the list, for example "Claude – management". ### 3. « Créatrices » (Creators) [#3--créatrices--creators] Tick the creators the key can see. **A creator added later is not included automatically**: create a new key if needed. ### 4. « Droits » (Permissions) [#4--droits--permissions] | Preset | What it allows | |---|---| | **Lecture seule** (Read only, recommended) | See creators, chats, sales, statistics, scripts, media and emergencies. Changes nothing. | | **Lecture + actions** (Read + actions, API only) | Everything above, plus: label a fan, write the team note, pause the AI on a fan, receive sales by webhook. | | **Personnalisé** (Custom) | Domain by domain, in plain words: none, read or write. | The domains of **Personnalisé**: | Domain | What it covers | |---|---| | Créatrices et profils (Creators and profiles) | Name, platforms, profile | | Discussions (Chats) | MYM and Telegram messages | | Fans : étiquettes et note (Fans: labels and note) | Add a label, write the team note | | Pause de l'IA sur un fan (AI pause on a fan) | Stop or restart chatting with a fan | | Ventes et statistiques (Sales and statistics) | Sales, revenue and sends per creator | | Scripts et médias (Scripts and media) | Sales scripts, media library; write: import media | | Réglages de l'agent (Agent settings) | A creator's chatting and negotiation settings | | Comportement de l'IA (AI behavior) | Guidelines, style, pace, follow-ups, memory; every change is approved | | Urgences (Emergencies) | What is waiting for a human | | Webhooks | Receive sales, emergencies and AI pauses live | | Essais dans le Playground (Playground tests) | Test a creator's AI, nothing is sent | A key's permissions never change after creation. The technical name of each permission (`creators:read`, `sales:read`…) is on the [Authentication](/en/api/rest/authentification) page. ### 5. « Expiration » (Expiry) [#5--expiration--expiry] 7, 30 or 90 days. The exact expiry date is shown under the choice. ### 6. « Confirmez avec votre mot de passe » (Confirm with your password) [#6--confirmez-avec-votre-mot-de-passe--confirm-with-your-password] Type your **Mot de passe actuel** (current password), then **Créer la clé** (Create key). If refused, check the password and the fields. ## After creation [#after-creation] The key is shown **only once**, with the next step: - "AI assistant" key: **Brancher votre assistant** — the block to paste, already filled with your key. See [Connect your assistant](/en/api/assistant). - "API" key: **Ensuite : tester la clé** (Next: test the key) — a test request in curl, JavaScript or Python, returning its creators (`creatorIds`), permissions (`scopes`) and expiry (`expiresAt`). Store it in a password manager. Never paste it in a chat with the assistant, an email or a message. **Lost it? Revoke it and create another one.** ## The « Vos clés » list (Your keys) [#the--vos-clés--list-your-keys] For each key: its name, what it is for, its creators, its permissions, when it expires and its last use ("Jamais" — never — if it has not been used yet). - **Révoquer** (Revoke) cuts access from its next request. - An expired key shows **Supprimer** (Delete) instead of **Révoquer**. --- # Overview > Connect an AI assistant or a tool to your FanConvert account with an fc_sk_ key. URL : https://docs.fanconvert.ai/en/api FanConvert opens up to your tools in two ways, with **the same key**: | | AI assistant (MCP) | Tool or developer (REST API) | |---|---|---| | For | you and your team | a developer or an automation tool | | Examples | Claude Code, or any MCP client | Zapier, Make, CRM, Google Sheets, your own script | | Address | `https://app.fanconvert.ai/mcp` | `https://app.fanconvert.ai/public/v1` | | What you do | ask questions about your creators in plain language, no code | read your data, receive sales live (webhooks) | ## What never changes [#what-never-changes] - **No key can send a message to a fan.** Neither the API nor the MCP server has a sending route. - **Admins only**: only the organization's admins create and use a key. - **The same isolation as the dashboard**: a key only sees the creators chosen when it was created; any other creator answers "not found". - **Revocable at any time** in Settings › API & MCP: the key is cut off from its next request. The public API and the MCP server are in Beta: some routes and fields may still change. Every change is listed in the [changelog](/en/api/rest/journal). ## Where to start [#where-to-start] ## For an AI writing code [#for-an-ai-writing-code] - Index of this documentation: [`/llms.txt`](https://docs.fanconvert.ai/llms.txt), full text: [`/en/llms-full.txt`](https://docs.fanconvert.ai/en/llms-full.txt). - Every page exists in Markdown: add `.md` to its address. - Full contract: [`openapi.json`](https://app.fanconvert.ai/public/v1/openapi.json) (OpenAPI 3.1). --- # What the assistant can read and do > The tools of the FanConvert MCP server, domain by domain, and the key permission each one needs. URL : https://docs.fanconvert.ai/en/api/outils-mcp Your assistant **only sees the tools its key can call**: the list is recomputed on every request with the key's permissions. The names below are those the assistant displays; you do not need to remember them, just ask your question. Send a message to a fan, connect a platform account, turn a creator's agent on or off: no tool allows it. ## Read [#read] | Domain (permission) | What you can ask | Tools | |---|---|---| | Creators and profiles (`creators:read`, `profile:read`) | the list of creators, their profile, the state of their agent | `creators_list`, `creator_get`, `creator_runtime_get`, `creator_profile_get` | | MYM chats (`conversations:read`) | conversations, their messages, events and sales | `conversations_list`, `conversation_get`, `conversation_messages`, `conversation_events`, `conversation_sales`, `conversation_decisions` | | Telegram chats (`telegram:read`) | conversations, messages, received media, offers, welcome message, bot | `telegram_conversations_list`, `telegram_conversation_get`, `telegram_conversation_messages`, `telegram_conversation_events`, `telegram_conversation_decisions`, `telegram_conversation_state`, `telegram_conversation_received_media`, `telegram_media_list`, `telegram_offers_list`, `telegram_welcome_get`, `telegram_bot_get`, `telegram_fan_filter_get`, `telegram_fan_filter_resolve` | | Fans (`fans:read`) | the team note on a fan | `fan_note_get`, `telegram_fan_note_get` | | AI pause (`chatting:read`) | who answers a fan, human takeovers, offered media, message ratings | `conversation_control_get`, `conversation_interventions_list`, `conversation_command_get`, `conversation_offered_media`, `conversation_fan_scripts`, `conversation_ratings_list`, `message_ratings_export`, `telegram_conversation_interventions`, `telegram_conversation_ratings_list` | | Sales and statistics (`sales:read`, `statistics:read`) | a sale's funnel, Telegram sales, statistics per creator and per agent | `conversation_sale_tunnel`, `telegram_sales_list`, `statistics_summary`, `statistics_creators`, `statistics_agents`, `creator_media_stats_get`, `creator_script_stats_list` | | Scripts and media (`scripts:read`, `media:read`) | sales scripts, a creator's review, the media library and packs | `scripts_list`, `script_get`, `creator_review_get`, `media_list`, `media_pack_get`, `media_files_list`, `media_file_get` | | Agent settings (`settings:read`, `schedule:read`, `filters:read`) | chatting settings, schedule, fan filter, negotiation and its A/B tests | `creator_settings_get`, `creator_schedule_get`, `fan_filter_get`, `fan_filter_resolve`, `negotiation_get`, `negotiation_organization_get`, `negotiation_gifts_get`, `negotiation_journal`, `negotiation_stats`, `ab_tests_list`, `ab_tests_get`, `ab_tests_results` | | AI Agent screen (`settings:read`, `profile:read`, `scripts:read`) | guidelines, style, voice, memory, pace, re-engagement, threshold, live, "Her life", script ending, priorities | `creator_behavior_guidance_get`, `creator_instructions_get`, `creator_style_get`, `creator_voice_get`, `creator_memory_guidance_get`, `creator_rythme_get`, `creator_reengagement_get`, `creator_initial_threshold_get`, `creator_fan_discovery_get`, `creator_live_get`, `creator_life_get`, `creator_script_ending_get`, `creator_script_priority_get` | | Emergencies (`notifications:read`) | what is waiting for a human | `notifications_list`, `notification_get` | ## Act [#act] | Domain (permission) | What the assistant can do | How | |---|---|---| | AI behavior (`ai:write`) | change a creator's guidelines, style, pace, follow-ups, memory | the assistant **prepares** the change; it only applies after **your approval** in FanConvert | | Agent settings (`settings:write`) | change negotiation settings | prepared, then approved by you | | Scripts and media (`media:write`) | import a file into a creator's media library (Beta) | in one call, within your agency's limits | | Playground tests (`playground:run`) | open a test chat, play the fan, compare, replay | sandbox: **nothing is sent to a fan** | Tracking of prepared actions (`command_get`, `commands_list`, `job_get`, `job_items_list`) comes with these permissions. ## Approve an action [#approve-an-action] When the assistant prepares a change, it appears in **Réglages › API & MCP › Actions à approuver** (Actions to approve), if actions to approve are enabled for your agency. Select the action to see its preview, then decide. FanConvert asks for your password before approving. | Message (in French on screen) | What it means | |---|---| | Approbation expirée. Demandez un nouvel aperçu. | The preview waited too long: ask the assistant to prepare it again. | | Cet aperçu a expiré ou a changé… | The setting changed since the preview: nothing was applied. | | Approbation utilisée. Consultez l'état de la commande. | This approval was already used. | | Approuvée, exécution non confirmée. | Reload the action to see whether the change went through before trying again. | | Cette action n'est plus accessible avec vos droits actuels. | Your permissions or the key's changed. | | Changez votre mot de passe avant d'approuver une action. | Change your password, then come back. | --- # API key > Reference generated from the OpenAPI contract: API key. URL : https://docs.fanconvert.ai/en/api/reference/cle-api {/* Généré par scripts/generer-reference.mjs depuis openapi/public-v1.json : ne pas modifier à la main. */} ## La clé utilisée [#la-clé-utilisée] `GET /public/v1/me` · `getApiKey` ### Response 200 [#response-200] **`ApiKeyInfo`** | Field | Type | Required | Description | |---|---|---|---| | `keyId` | string | yes | | | `organizationId` | string | yes | | | `scopes` | string[] | yes | | | `creatorIds` | string[] | yes | Les créatrices que cette clé voit. | | `expiresAt` | string (date-time) | yes | | ### Possible errors [#possible-errors] `401` · `403` · `404` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example] ```bash curl -X GET "https://app.fanconvert.ai/public/v1/me" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" ``` --- # Conversations > Reference generated from the OpenAPI contract: Conversations. URL : https://docs.fanconvert.ai/en/api/reference/conversations {/* Généré par scripts/generer-reference.mjs depuis openapi/public-v1.json : ne pas modifier à la main. */} ## Les conversations d'une créatrice [#les-conversations-dune-créatrice] `GET /public/v1/creators/{creator_id}/conversations` · `listConversations` ### Parameters [#parameters] | Name | In | Type | Required | Description | |---|---|---|---|---| | `creator_id` | path | string | yes | Identifiant de la créatrice. | | `platform` | query | "mym" \| "telegram" \| "onlyfans" | no | La plateforme de la conversation. (default : `mym`) | | `limit` | query | integer | no | Taille de la page. (default : `50`) | | `cursor` | query | string \| null | no | Le `nextCursor` de la page précédente. | ### Response 200 [#response-200] **`Page_Conversation_`** | Field | Type | Required | Description | |---|---|---|---| | `items` | Conversation[] | yes | | | `nextCursor` | string \| null | no | À repasser en `cursor` pour lire la page suivante ; null = dernière page. | **`Conversation`** | Field | Type | Required | Description | |---|---|---|---| | `id` | string | yes | Identifiant de la conversation sur sa plateforme (MYM : le chat id). | | `platform` | "mym" \| "telegram" \| "onlyfans" | yes | | | `fan` | Fan | yes | | | `lastFanMessageAt` | string (date-time) \| null | yes | | | `lastMessageAt` | string (date-time) \| null | yes | | | `unreadCount` | integer \| null | no | Messages du fan non lus, quand la plateforme les compte. | | `hasPurchased` | boolean \| null | no | | **`Fan`** | Field | Type | Required | Description | |---|---|---|---| | `name` | string \| null | yes | | | `username` | string \| null | no | | ### Possible errors [#possible-errors] `401` · `403` · `404` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example] ```bash curl -X GET "https://app.fanconvert.ai/public/v1/creators/{creator_id}/conversations" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" ``` ## Les messages d'une conversation [#les-messages-dune-conversation] `GET /public/v1/creators/{creator_id}/conversations/{conversation_id}/messages` · `listMessages` ### Parameters [#parameters-1] | Name | In | Type | Required | Description | |---|---|---|---|---| | `creator_id` | path | string | yes | Identifiant de la créatrice. | | `conversation_id` | path | string | yes | Identifiant de la conversation. | | `platform` | query | "mym" \| "telegram" \| "onlyfans" | no | La plateforme de la conversation. (default : `mym`) | | `limit` | query | integer | no | Taille de la page. (default : `50`) | | `cursor` | query | string \| null | no | Le `nextCursor` de la page précédente. | ### Response 200 [#response-200-1] **`Page_Message_`** | Field | Type | Required | Description | |---|---|---|---| | `items` | Message[] | yes | | | `nextCursor` | string \| null | no | À repasser en `cursor` pour lire la page suivante ; null = dernière page. | **`Message`** | Field | Type | Required | Description | |---|---|---|---| | `id` | string | yes | | | `direction` | "fan" \| "creator" | yes | | | `text` | string | yes | | | `sentAt` | string (date-time) \| null | yes | | | `media` | MessageMedia[] | yes | | **`MessageMedia`** | Field | Type | Required | Description | |---|---|---|---| | `status` | "paid" \| "pending" \| "refused" \| "free" \| "unknown" | yes | | | `priceMinor` | integer \| null | no | | | `currency` | string \| null | no | | ### Possible errors [#possible-errors-1] `401` · `403` · `404` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example-1] ```bash curl -X GET "https://app.fanconvert.ai/public/v1/creators/{creator_id}/conversations/{conversation_id}/messages" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" ``` --- # Creators > Reference generated from the OpenAPI contract: Creators. URL : https://docs.fanconvert.ai/en/api/reference/creatrices {/* Généré par scripts/generer-reference.mjs depuis openapi/public-v1.json : ne pas modifier à la main. */} ## Les créatrices de la clé [#les-créatrices-de-la-clé] `GET /public/v1/creators` · `listCreators` ### Response 200 [#response-200] **`Page_Creator_`** | Field | Type | Required | Description | |---|---|---|---| | `items` | Creator[] | yes | | | `nextCursor` | string \| null | no | À repasser en `cursor` pour lire la page suivante ; null = dernière page. | **`Creator`** | Field | Type | Required | Description | |---|---|---|---| | `id` | string | yes | | | `name` | string | yes | | | `status` | "active" \| "inactive" \| "error" | yes | | | `platforms` | string[] | yes | | | `aiEnabled` | boolean | yes | L'interrupteur de l'IA de la créatrice, comme sur le dashboard. | ### Possible errors [#possible-errors] `401` · `403` · `404` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example] ```bash curl -X GET "https://app.fanconvert.ai/public/v1/creators" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" ``` ## Une créatrice [#une-créatrice] `GET /public/v1/creators/{creator_id}` · `getCreator` ### Parameters [#parameters] | Name | In | Type | Required | Description | |---|---|---|---|---| | `creator_id` | path | string | yes | Identifiant de la créatrice. | ### Response 200 [#response-200-1] **`Creator`** | Field | Type | Required | Description | |---|---|---|---| | `id` | string | yes | | | `name` | string | yes | | | `status` | "active" \| "inactive" \| "error" | yes | | | `platforms` | string[] | yes | | | `aiEnabled` | boolean | yes | L'interrupteur de l'IA de la créatrice, comme sur le dashboard. | ### Possible errors [#possible-errors-1] `401` · `403` · `404` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example-1] ```bash curl -X GET "https://app.fanconvert.ai/public/v1/creators/{creator_id}" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" ``` --- # Fans > Reference generated from the OpenAPI contract: Fans. URL : https://docs.fanconvert.ai/en/api/reference/fans {/* Généré par scripts/generer-reference.mjs depuis openapi/public-v1.json : ne pas modifier à la main. */} ## Les étiquettes de fans d'une créatrice [#les-étiquettes-de-fans-dune-créatrice] `GET /public/v1/creators/{creator_id}/labels` · `listFanLabels` ### Parameters [#parameters] | Name | In | Type | Required | Description | |---|---|---|---|---| | `creator_id` | path | string | yes | Identifiant de la créatrice. | | `platform` | query | "mym" \| "telegram" | no | La plateforme du fan. (default : `mym`) | ### Response 200 [#response-200] **`Page_FanLabel_`** | Field | Type | Required | Description | |---|---|---|---| | `items` | FanLabel[] | yes | | | `nextCursor` | string \| null | no | À repasser en `cursor` pour lire la page suivante ; null = dernière page. | **`FanLabel`** | Field | Type | Required | Description | |---|---|---|---| | `id` | string | yes | | | `name` | string | yes | | | `color` | string | yes | | ### Possible errors [#possible-errors] `401` · `403` · `404` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example] ```bash curl -X GET "https://app.fanconvert.ai/public/v1/creators/{creator_id}/labels" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" ``` ## La fiche d'un fan : étiquettes et note de l'équipe [#la-fiche-dun-fan--étiquettes-et-note-de-léquipe] `GET /public/v1/creators/{creator_id}/fans/{conversation_id}` · `getFan` ### Parameters [#parameters-1] | Name | In | Type | Required | Description | |---|---|---|---|---| | `creator_id` | path | string | yes | Identifiant de la créatrice. | | `conversation_id` | path | string | yes | Identifiant de la conversation. | | `platform` | query | "mym" \| "telegram" | no | La plateforme du fan. (default : `mym`) | ### Response 200 [#response-200-1] **`FanCard`** | Field | Type | Required | Description | |---|---|---|---| | `conversationId` | string | yes | | | `platform` | "mym" \| "telegram" | yes | | | `labels` | FanLabel[] | yes | | | `note` | TeamNote | yes | | **`FanLabel`** | Field | Type | Required | Description | |---|---|---|---| | `id` | string | yes | | | `name` | string | yes | | | `color` | string | yes | | **`TeamNote`** | Field | Type | Required | Description | |---|---|---|---| | `text` | string \| null | yes | | | `revision` | integer | yes | À renvoyer en `expectedRevision` pour écrire. | | `updatedAt` | string (date-time) \| null | yes | | ### Possible errors [#possible-errors-1] `401` · `403` · `404` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example-1] ```bash curl -X GET "https://app.fanconvert.ai/public/v1/creators/{creator_id}/fans/{conversation_id}" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" ``` ## Écrire la note de l'équipe sur un fan [#écrire-la-note-de-léquipe-sur-un-fan] `PUT /public/v1/creators/{creator_id}/fans/{conversation_id}/note` · `putFanNote` ### Parameters [#parameters-2] | Name | In | Type | Required | Description | |---|---|---|---|---| | `creator_id` | path | string | yes | Identifiant de la créatrice. | | `conversation_id` | path | string | yes | Identifiant de la conversation. | | `platform` | query | "mym" \| "telegram" | no | La plateforme du fan. (default : `mym`) | ### Request body [#request-body] **`TeamNoteWrite`** | Field | Type | Required | Description | |---|---|---|---| | `text` | string | yes | La note, 1 000 caractères au plus ; vide = retirée. | | `expectedRevision` | integer | yes | La `revision` lue : une autre écriture entre-temps → 409. | ### Response 200 [#response-200-2] **`FanCard`** | Field | Type | Required | Description | |---|---|---|---| | `conversationId` | string | yes | | | `platform` | "mym" \| "telegram" | yes | | | `labels` | FanLabel[] | yes | | | `note` | TeamNote | yes | | **`FanLabel`** | Field | Type | Required | Description | |---|---|---|---| | `id` | string | yes | | | `name` | string | yes | | | `color` | string | yes | | **`TeamNote`** | Field | Type | Required | Description | |---|---|---|---| | `text` | string \| null | yes | | | `revision` | integer | yes | À renvoyer en `expectedRevision` pour écrire. | | `updatedAt` | string (date-time) \| null | yes | | ### Possible errors [#possible-errors-2] `401` · `403` · `404` · `409` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example-2] ```bash curl -X PUT "https://app.fanconvert.ai/public/v1/creators/{creator_id}/fans/{conversation_id}/note" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ … }' ``` ## Poser une étiquette sur un fan (sans effet si elle y est déjà) [#poser-une-étiquette-sur-un-fan-sans-effet-si-elle-y-est-déjà] `PUT /public/v1/creators/{creator_id}/fans/{conversation_id}/labels/{label_id}` · `addFanLabel` ### Parameters [#parameters-3] | Name | In | Type | Required | Description | |---|---|---|---|---| | `creator_id` | path | string | yes | Identifiant de la créatrice. | | `conversation_id` | path | string | yes | Identifiant de la conversation. | | `label_id` | path | string | yes | Identifiant de l'étiquette. | | `platform` | query | "mym" \| "telegram" | no | La plateforme du fan. (default : `mym`) | ### Response 200 [#response-200-3] **`FanCard`** | Field | Type | Required | Description | |---|---|---|---| | `conversationId` | string | yes | | | `platform` | "mym" \| "telegram" | yes | | | `labels` | FanLabel[] | yes | | | `note` | TeamNote | yes | | **`FanLabel`** | Field | Type | Required | Description | |---|---|---|---| | `id` | string | yes | | | `name` | string | yes | | | `color` | string | yes | | **`TeamNote`** | Field | Type | Required | Description | |---|---|---|---| | `text` | string \| null | yes | | | `revision` | integer | yes | À renvoyer en `expectedRevision` pour écrire. | | `updatedAt` | string (date-time) \| null | yes | | ### Possible errors [#possible-errors-3] `401` · `403` · `404` · `409` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example-3] ```bash curl -X PUT "https://app.fanconvert.ai/public/v1/creators/{creator_id}/fans/{conversation_id}/labels/{label_id}" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" ``` ## Retirer une étiquette d'un fan [#retirer-une-étiquette-dun-fan] `DELETE /public/v1/creators/{creator_id}/fans/{conversation_id}/labels/{label_id}` · `removeFanLabel` ### Parameters [#parameters-4] | Name | In | Type | Required | Description | |---|---|---|---|---| | `creator_id` | path | string | yes | Identifiant de la créatrice. | | `conversation_id` | path | string | yes | Identifiant de la conversation. | | `label_id` | path | string | yes | Identifiant de l'étiquette. | | `platform` | query | "mym" \| "telegram" | no | La plateforme du fan. (default : `mym`) | ### Response 200 [#response-200-4] **`FanCard`** | Field | Type | Required | Description | |---|---|---|---| | `conversationId` | string | yes | | | `platform` | "mym" \| "telegram" | yes | | | `labels` | FanLabel[] | yes | | | `note` | TeamNote | yes | | **`FanLabel`** | Field | Type | Required | Description | |---|---|---|---| | `id` | string | yes | | | `name` | string | yes | | | `color` | string | yes | | **`TeamNote`** | Field | Type | Required | Description | |---|---|---|---| | `text` | string \| null | yes | | | `revision` | integer | yes | À renvoyer en `expectedRevision` pour écrire. | | `updatedAt` | string (date-time) \| null | yes | | ### Possible errors [#possible-errors-4] `401` · `403` · `404` · `409` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example-4] ```bash curl -X DELETE "https://app.fanconvert.ai/public/v1/creators/{creator_id}/fans/{conversation_id}/labels/{label_id}" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" ``` --- # AI > Reference generated from the OpenAPI contract: AI. URL : https://docs.fanconvert.ai/en/api/reference/ia {/* Généré par scripts/generer-reference.mjs depuis openapi/public-v1.json : ne pas modifier à la main. */} ## Qui répond à ce fan : l'IA, une personne, ou personne [#qui-répond-à-ce-fan--lia-une-personne-ou-personne] `GET /public/v1/creators/{creator_id}/conversations/{conversation_id}/ai` · `getAiState` ### Parameters [#parameters] | Name | In | Type | Required | Description | |---|---|---|---|---| | `creator_id` | path | string | yes | Identifiant de la créatrice. | | `conversation_id` | path | string | yes | Identifiant de la conversation. | | `platform` | query | "mym" \| "telegram" | no | La plateforme du fan. (default : `mym`) | ### Response 200 [#response-200] **`AiState`** | Field | Type | Required | Description | |---|---|---|---| | `conversationId` | string | yes | | | `platform` | "mym" \| "telegram" | yes | | | `creatorAiEnabled` | boolean | yes | | | `control` | "ai" \| "human" \| "paused" \| "blocked" \| "transition" | yes | ai = l'IA répond ; human = une personne a la main ; paused = personne ne répond ; blocked = un envoi précédent est à vérifier ; transition = un changement est en cours. | ### Possible errors [#possible-errors] `401` · `403` · `404` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example] ```bash curl -X GET "https://app.fanconvert.ai/public/v1/creators/{creator_id}/conversations/{conversation_id}/ai" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" ``` ## Mettre l'IA en pause sur ce fan (« Arrêter le chatting »), MYM [#mettre-lia-en-pause-sur-ce-fan--arrêter-le-chatting--mym] `POST /public/v1/creators/{creator_id}/conversations/{conversation_id}/ai/pause` · `pauseAi` `Idempotency-Key` header required: see [Writes and idempotency](/en/api/rest/ecritures). ### Parameters [#parameters-1] | Name | In | Type | Required | Description | |---|---|---|---|---| | `creator_id` | path | string | yes | Identifiant de la créatrice. | | `conversation_id` | path | string | yes | Identifiant de la conversation. | | `Idempotency-Key` | header | string | yes | Obligatoire : la même clé rejoue la même réponse, sans 2e écriture. | ### Response 200 [#response-200-1] **`AiPause`** | Field | Type | Required | Description | |---|---|---|---| | `conversationId` | string | yes | | | `platform` | string | yes | | | `paused` | boolean | yes | true = l'IA ne répond plus à ce fan. | | `filterMode` | "none" \| "whitelist" \| "blacklist" | yes | Le mode du filtre de la créatrice, inchangé par l'API. | ### Possible errors [#possible-errors-1] `401` · `403` · `404` · `409` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example-1] ```bash curl -X POST "https://app.fanconvert.ai/public/v1/creators/{creator_id}/conversations/{conversation_id}/ai/pause" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" ``` ## Rendre ce fan à l'IA (« Relancer le chatting »), MYM [#rendre-ce-fan-à-lia--relancer-le-chatting--mym] `POST /public/v1/creators/{creator_id}/conversations/{conversation_id}/ai/resume` · `resumeAi` `Idempotency-Key` header required: see [Writes and idempotency](/en/api/rest/ecritures). ### Parameters [#parameters-2] | Name | In | Type | Required | Description | |---|---|---|---|---| | `creator_id` | path | string | yes | Identifiant de la créatrice. | | `conversation_id` | path | string | yes | Identifiant de la conversation. | | `Idempotency-Key` | header | string | yes | Obligatoire : la même clé rejoue la même réponse, sans 2e écriture. | ### Response 200 [#response-200-2] **`AiPause`** | Field | Type | Required | Description | |---|---|---|---| | `conversationId` | string | yes | | | `platform` | string | yes | | | `paused` | boolean | yes | true = l'IA ne répond plus à ce fan. | | `filterMode` | "none" \| "whitelist" \| "blacklist" | yes | Le mode du filtre de la créatrice, inchangé par l'API. | ### Possible errors [#possible-errors-2] `401` · `403` · `404` · `409` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example-2] ```bash curl -X POST "https://app.fanconvert.ai/public/v1/creators/{creator_id}/conversations/{conversation_id}/ai/resume" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" ``` --- # API reference > Every route of the public API, generated from the OpenAPI 3.1 contract. URL : https://docs.fanconvert.ai/en/api/reference {/* Généré par scripts/generer-reference.mjs : ne pas modifier à la main. */} This reference is generated on every site build from [the OpenAPI 3.1 contract](https://app.fanconvert.ai/public/v1/openapi.json) served by the API, so it cannot drift from what the API accepts. Descriptions come from the contract and are written in French. Base URL: `https://app.fanconvert.ai/public/v1`. ## Routes [#routes] - [API key](/en/api/reference/cle-api) - `GET /public/v1/me` — La clé utilisée - [Creators](/en/api/reference/creatrices) - `GET /public/v1/creators` — Les créatrices de la clé - `GET /public/v1/creators/{creator_id}` — Une créatrice - [Conversations](/en/api/reference/conversations) - `GET /public/v1/creators/{creator_id}/conversations` — Les conversations d'une créatrice - `GET /public/v1/creators/{creator_id}/conversations/{conversation_id}/messages` — Les messages d'une conversation - [Fans](/en/api/reference/fans) - `GET /public/v1/creators/{creator_id}/labels` — Les étiquettes de fans d'une créatrice - `GET /public/v1/creators/{creator_id}/fans/{conversation_id}` — La fiche d'un fan : étiquettes et note de l'équipe - `PUT /public/v1/creators/{creator_id}/fans/{conversation_id}/note` — Écrire la note de l'équipe sur un fan - `PUT /public/v1/creators/{creator_id}/fans/{conversation_id}/labels/{label_id}` — Poser une étiquette sur un fan (sans effet si elle y est déjà) - `DELETE /public/v1/creators/{creator_id}/fans/{conversation_id}/labels/{label_id}` — Retirer une étiquette d'un fan - [AI](/en/api/reference/ia) - `GET /public/v1/creators/{creator_id}/conversations/{conversation_id}/ai` — Qui répond à ce fan : l'IA, une personne, ou personne - `POST /public/v1/creators/{creator_id}/conversations/{conversation_id}/ai/pause` — Mettre l'IA en pause sur ce fan (« Arrêter le chatting »), MYM - `POST /public/v1/creators/{creator_id}/conversations/{conversation_id}/ai/resume` — Rendre ce fan à l'IA (« Relancer le chatting »), MYM - [Sales and statistics](/en/api/reference/ventes-et-statistiques) - `GET /public/v1/sales` — Les ventes, par plateforme - `GET /public/v1/statistics/creators` — Revenus et envois par créatrice sur une période - [Scripts and media](/en/api/reference/scripts-et-medias) - `GET /public/v1/creators/{creator_id}/scripts` — Les scripts de vente d'une créatrice - `GET /public/v1/creators/{creator_id}/media` — La médiathèque d'une créatrice - [Emergencies](/en/api/reference/urgences) - `GET /public/v1/emergencies` — Les urgences : ce qui attend un humain - [Webhooks](/en/api/reference/webhooks) - `POST /public/v1/webhooks` — Enregistrer une adresse qui recevra les événements - `GET /public/v1/webhooks` — Les webhooks de cette clé - `DELETE /public/v1/webhooks/{endpoint_id}` — Désactiver un webhook (son journal est gardé) - `GET /public/v1/webhooks/{endpoint_id}/deliveries` — Le journal des livraisons, les plus récentes d'abord - `POST /public/v1/webhooks/{endpoint_id}/ping` — Envoyer un événement `ping` (aucune donnée) pour tester la réception --- # Scripts and media > Reference generated from the OpenAPI contract: Scripts and media. URL : https://docs.fanconvert.ai/en/api/reference/scripts-et-medias {/* Généré par scripts/generer-reference.mjs depuis openapi/public-v1.json : ne pas modifier à la main. */} ## Les scripts de vente d'une créatrice [#les-scripts-de-vente-dune-créatrice] `GET /public/v1/creators/{creator_id}/scripts` · `listScripts` ### Parameters [#parameters] | Name | In | Type | Required | Description | |---|---|---|---|---| | `creator_id` | path | string | yes | Identifiant de la créatrice. | | `platform` | query | "mym" \| "telegram" \| "onlyfans" \| "fanvue" | no | (default : `mym`) | ### Response 200 [#response-200] **`Page_Script_`** | Field | Type | Required | Description | |---|---|---|---| | `items` | Script[] | yes | | | `nextCursor` | string \| null | no | À repasser en `cursor` pour lire la page suivante ; null = dernière page. | **`Script`** | Field | Type | Required | Description | |---|---|---|---| | `id` | string | yes | | | `name` | string | yes | | | `description` | string | yes | | | `enabled` | boolean | yes | | | `stepsCount` | integer | yes | | | `mediaCount` | integer | yes | | | `folderId` | string \| null | yes | | ### Possible errors [#possible-errors] `401` · `403` · `404` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example] ```bash curl -X GET "https://app.fanconvert.ai/public/v1/creators/{creator_id}/scripts" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" ``` ## La médiathèque d'une créatrice [#la-médiathèque-dune-créatrice] `GET /public/v1/creators/{creator_id}/media` · `listMedia` ### Parameters [#parameters-1] | Name | In | Type | Required | Description | |---|---|---|---|---| | `creator_id` | path | string | yes | Identifiant de la créatrice. | | `platform` | query | string | no | La médiathèque n'existe que sur MYM. (default : `mym`) | ### Response 200 [#response-200-1] **`Page_MediaPack_`** | Field | Type | Required | Description | |---|---|---|---| | `items` | MediaPack[] | yes | | | `nextCursor` | string \| null | no | À repasser en `cursor` pour lire la page suivante ; null = dernière page. | **`MediaPack`** | Field | Type | Required | Description | |---|---|---|---| | `id` | string | yes | | | `name` | string | yes | | | `description` | string | yes | | | `fileCount` | integer | yes | | ### Possible errors [#possible-errors-1] `401` · `403` · `404` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example-1] ```bash curl -X GET "https://app.fanconvert.ai/public/v1/creators/{creator_id}/media" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" ``` --- # Emergencies > Reference generated from the OpenAPI contract: Emergencies. URL : https://docs.fanconvert.ai/en/api/reference/urgences {/* Généré par scripts/generer-reference.mjs depuis openapi/public-v1.json : ne pas modifier à la main. */} ## Les urgences : ce qui attend un humain [#les-urgences--ce-qui-attend-un-humain] `GET /public/v1/emergencies` · `listEmergencies` ### Parameters [#parameters] | Name | In | Type | Required | Description | |---|---|---|---|---| | `platform` | query | "mym" \| "telegram" | no | La plateforme du fan. (default : `mym`) | | `status` | query | "open" \| "to_handle" \| "in_progress" \| "resolved" \| null | no | | | `creatorId` | query | string \| null | no | | | `limit` | query | integer | no | Taille de la page. (default : `50`) | | `cursor` | query | string \| null | no | Le `nextCursor` de la page précédente. | ### Response 200 [#response-200] **`Page_Emergency_`** | Field | Type | Required | Description | |---|---|---|---| | `items` | Emergency[] | yes | | | `nextCursor` | string \| null | no | À repasser en `cursor` pour lire la page suivante ; null = dernière page. | **`Emergency`** | Field | Type | Required | Description | |---|---|---|---| | `id` | string | yes | | | `creatorId` | string | yes | | | `conversationId` | string | yes | | | `fanName` | string | yes | | | `reason` | string | yes | | | `level` | string | yes | | | `priority` | string | yes | | | `status` | "to_handle" \| "in_progress" \| "resolved" | yes | | | `occurrences` | integer | yes | | | `openedAt` | string (date-time) | yes | | | `lastSignalAt` | string (date-time) | yes | | | `resolvedAt` | string (date-time) \| null | yes | | | `excerpt` | string \| null | yes | Le message du fan qui l'a déclenchée. | ### Possible errors [#possible-errors] `401` · `403` · `404` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example] ```bash curl -X GET "https://app.fanconvert.ai/public/v1/emergencies" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" ``` --- # Sales and statistics > Reference generated from the OpenAPI contract: Sales and statistics. URL : https://docs.fanconvert.ai/en/api/reference/ventes-et-statistiques {/* Généré par scripts/generer-reference.mjs depuis openapi/public-v1.json : ne pas modifier à la main. */} ## Les ventes, par plateforme [#les-ventes-par-plateforme] `GET /public/v1/sales` · `listSales` ### Parameters [#parameters] | Name | In | Type | Required | Description | |---|---|---|---|---| | `platform` | query | "mym" \| "telegram" \| "onlyfans" \| "fanvue" | no | (default : `mym`) | | `creatorId` | query | string \| null | no | Filtre. | | `from` | query | string (date-time) \| null | no | MYM seulement. | | `to` | query | string (date-time) \| null | no | MYM seulement. | | `limit` | query | integer | no | Taille de la page. (default : `50`) | | `cursor` | query | string \| null | no | Le `nextCursor` de la page précédente. | ### Response 200 [#response-200] **`SalesPage`** | Field | Type | Required | Description | |---|---|---|---| | `items` | Sale[] | yes | | | `nextCursor` | string \| null | no | À repasser en `cursor` pour lire la page suivante ; null = dernière page. | | `platform` | "mym" \| "telegram" \| "onlyfans" \| "fanvue" | yes | | | `currency` | string | yes | | | `totalMinor` | integer \| null | no | Total de la période, quand la plateforme le donne. | **`Sale`** | Field | Type | Required | Description | |---|---|---|---| | `id` | string | yes | | | `platform` | "mym" \| "telegram" \| "onlyfans" \| "fanvue" | yes | | | `creatorId` | string | yes | | | `conversationId` | string \| null | yes | | | `at` | string (date-time) \| null | yes | | | `amountMinor` | integer | yes | Montant payé, en unité mineure de la devise (centimes ; Stars pour XTR). | | `currency` | string | yes | | | `kind` | string \| null | no | Ce qui a été payé : média, pourboire, abonnement… | | `refundedAt` | string (date-time) \| null | no | | ### Possible errors [#possible-errors] `401` · `403` · `404` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example] ```bash curl -X GET "https://app.fanconvert.ai/public/v1/sales" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" ``` ## Revenus et envois par créatrice sur une période [#revenus-et-envois-par-créatrice-sur-une-période] `GET /public/v1/statistics/creators` · `listCreatorStatistics` ### Parameters [#parameters-1] | Name | In | Type | Required | Description | |---|---|---|---|---| | `from` | query | string (date-time) | yes | | | `to` | query | string (date-time) | yes | | | `platform` | query | "mym" \| "telegram" \| "onlyfans" \| "fanvue" | no | (default : `mym`) | ### Response 200 [#response-200-1] **`Page_CreatorStats_`** | Field | Type | Required | Description | |---|---|---|---| | `items` | CreatorStats[] | yes | | | `nextCursor` | string \| null | no | À repasser en `cursor` pour lire la page suivante ; null = dernière page. | **`CreatorStats`** | Field | Type | Required | Description | |---|---|---|---| | `creatorId` | string | yes | | | `name` | string | yes | | | `platform` | string | yes | | | `currency` | string | yes | | | `revenueMinor` | integer | yes | | | `sales` | integer | yes | | | `messagesSent` | integer | yes | | | `paidMediaSent` | integer | yes | | | `freeMediaSent` | integer | yes | | ### Possible errors [#possible-errors-1] `401` · `403` · `404` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example-1] ```bash curl -X GET "https://app.fanconvert.ai/public/v1/statistics/creators" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" ``` --- # Webhooks > Reference generated from the OpenAPI contract: Webhooks. URL : https://docs.fanconvert.ai/en/api/reference/webhooks {/* Généré par scripts/generer-reference.mjs depuis openapi/public-v1.json : ne pas modifier à la main. */} ## Enregistrer une adresse qui recevra les événements [#enregistrer-une-adresse-qui-recevra-les-événements] `POST /public/v1/webhooks` · `createWebhook` `Idempotency-Key` header required: see [Writes and idempotency](/en/api/rest/ecritures). ### Parameters [#parameters] | Name | In | Type | Required | Description | |---|---|---|---|---| | `Idempotency-Key` | header | string | yes | | ### Request body [#request-body] **`WebhookCreate`** | Field | Type | Required | Description | |---|---|---|---| | `url` | string | yes | https://, hôte public, port 443 ou 8443. | | `events` | "sale.created" \| "emergency.created" \| "ai.paused"[] | yes | | ### Response 201 [#response-201] **`WebhookCreated`** | Field | Type | Required | Description | |---|---|---|---| | `webhook` | Webhook | yes | | | `secret` | string | yes | Le secret de signature `whsec_…` : affiché UNE fois, gardez-le. | **`Webhook`** | Field | Type | Required | Description | |---|---|---|---| | `id` | string | yes | | | `url` | string | yes | | | `events` | string[] | yes | | | `createdAt` | string (date-time) | yes | | | `disabledAt` | string (date-time) \| null | yes | | | `disabledReason` | string \| null | yes | | ### Possible errors [#possible-errors] `401` · `403` · `404` · `409` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example] ```bash curl -X POST "https://app.fanconvert.ai/public/v1/webhooks" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ … }' ``` ## Les webhooks de cette clé [#les-webhooks-de-cette-clé] `GET /public/v1/webhooks` · `listWebhooks` ### Response 200 [#response-200] ### Possible errors [#possible-errors-1] `401` · `403` · `404` · `409` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example-1] ```bash curl -X GET "https://app.fanconvert.ai/public/v1/webhooks" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" ``` ## Désactiver un webhook (son journal est gardé) [#désactiver-un-webhook-son-journal-est-gardé] `DELETE /public/v1/webhooks/{endpoint_id}` · `disableWebhook` ### Parameters [#parameters-1] | Name | In | Type | Required | Description | |---|---|---|---|---| | `endpoint_id` | path | string | yes | | ### Response 200 [#response-200-1] **`Webhook`** | Field | Type | Required | Description | |---|---|---|---| | `id` | string | yes | | | `url` | string | yes | | | `events` | string[] | yes | | | `createdAt` | string (date-time) | yes | | | `disabledAt` | string (date-time) \| null | yes | | | `disabledReason` | string \| null | yes | | ### Possible errors [#possible-errors-2] `401` · `403` · `404` · `409` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example-2] ```bash curl -X DELETE "https://app.fanconvert.ai/public/v1/webhooks/{endpoint_id}" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" ``` ## Le journal des livraisons, les plus récentes d'abord [#le-journal-des-livraisons-les-plus-récentes-dabord] `GET /public/v1/webhooks/{endpoint_id}/deliveries` · `listWebhookDeliveries` ### Parameters [#parameters-2] | Name | In | Type | Required | Description | |---|---|---|---|---| | `endpoint_id` | path | string | yes | | | `limit` | query | integer | no | (default : `50`) | | `cursor` | query | string \| null | no | | ### Response 200 [#response-200-2] **`DeliveryPage`** | Field | Type | Required | Description | |---|---|---|---| | `items` | Delivery[] | yes | | | `nextCursor` | string \| null | no | | **`Delivery`** | Field | Type | Required | Description | |---|---|---|---| | `id` | string | yes | | | `eventId` | string | yes | | | `eventType` | string | yes | | | `status` | "pending" \| "delivered" \| "failed" | yes | | | `attempts` | integer | yes | | | `lastStatusCode` | integer \| null | yes | | | `lastError` | string \| null | yes | Motif court : timeout, connexion, http_<code>, adresse_refusee… | | `createdAt` | string (date-time) | yes | | | `nextAttemptAt` | string (date-time) \| null | yes | | | `deliveredAt` | string (date-time) \| null | yes | | ### Possible errors [#possible-errors-3] `401` · `403` · `404` · `409` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example-3] ```bash curl -X GET "https://app.fanconvert.ai/public/v1/webhooks/{endpoint_id}/deliveries" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" ``` ## Envoyer un événement `ping` (aucune donnée) pour tester la réception [#envoyer-un-événement-ping-aucune-donnée-pour-tester-la-réception] `POST /public/v1/webhooks/{endpoint_id}/ping` · `pingWebhook` `Idempotency-Key` header required: see [Writes and idempotency](/en/api/rest/ecritures). ### Parameters [#parameters-3] | Name | In | Type | Required | Description | |---|---|---|---|---| | `endpoint_id` | path | string | yes | | ### Response 202 [#response-202] **`Webhook`** | Field | Type | Required | Description | |---|---|---|---| | `id` | string | yes | | | `url` | string | yes | | | `events` | string[] | yes | | | `createdAt` | string (date-time) | yes | | | `disabledAt` | string (date-time) \| null | yes | | | `disabledReason` | string \| null | yes | | ### Possible errors [#possible-errors-4] `401` · `403` · `404` · `409` · `422` · `429` · `503` — Error format: [Errors](/en/api/rest/erreurs). ### Example [#example-4] ```bash curl -X POST "https://app.fanconvert.ai/public/v1/webhooks/{endpoint_id}/ping" \ -H "Authorization: Bearer $FANCONVERT_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" ``` --- # Authentication and permissions > The Authorization Bearer fc_sk_ header, what a key sees, and the list of permissions. URL : https://docs.fanconvert.ai/en/api/rest/authentification Every request carries the key in the `Authorization: Bearer fc_sk_…` header. A key: - belongs to **one person** in the organization, who must be an **admin**; - only sees **the creators chosen** when it was created (any other answers `404`, as if she did not exist); - only has **the permissions chosen** (a missing permission answers `403` and names it); - expires (7, 30 or 90 days) and can be **revoked at any time** in Settings › API & MCP: revocation applies from the next request; - is the same as the MCP server's: one key system. Keys created before 7 November 2026 start with `fc_pat_`: they are still accepted. ## REST API permissions [#rest-api-permissions] | Permission | What it opens | |---|---| | `creators:read` | creators | | `conversations:read` | MYM and OnlyFans conversations and messages | | `telegram:read` | Telegram conversations and messages | | `fans:read` | a fan's labels and team note | | `chatting:read` | who answers a fan (AI, a person, paused) | | `sales:read` | sales | | `statistics:read` | statistics per creator | | `scripts:read` · `media:read` | sales scripts, media library | | `notifications:read` | emergencies | | `fans:write` | write the team note and add/remove a label (with `fans:read`) | | `chatting:write` | pause the AI on a fan, or hand the fan back (with `chatting:read`) | | `webhooks:read` · `webhooks:write` | list and create [webhooks](/en/api/rest/webhooks) | **No permission allows sending a message to a fan.** ## Personal data [#personal-data] The API only returns what the dashboard already shows an admin: fan names, messages, notes. Treat them as personal data: minimal storage, restricted access, deletion when you no longer need them. --- # Quick start > Your first request to the FanConvert public API, in curl, JavaScript and Python. URL : https://docs.fanconvert.ai/en/api/rest/demarrage The public API reads your creators, conversations, fans, sales, statistics, scripts, media and emergencies, with the same isolation as the dashboard. It can **never send a message to a fan**. Base URL: `https://app.fanconvert.ai/public/v1` ## 1. Create a key [#1-create-a-key] In FanConvert: **Réglages › API & MCP › Nouvelle clé** (Settings › API & MCP › New key), choosing **Connecter un outil ou un développeur (API)**. Details: [Create a key](/en/api/cles). Keep it in an environment variable, never in code. ## 2. First request [#2-first-request] `GET /me` describes the key in use: its creators, permissions and expiry. ```bash curl https://app.fanconvert.ai/public/v1/me \ -H "Authorization: Bearer $FANCONVERT_API_KEY" ``` ```json { "keyId": "3f1c…", "organizationId": "org_…", "scopes": ["creators:read", "statistics:read"], "creatorIds": ["emma-demo"], "expiresAt": "2026-12-07T05:40:00Z" } ``` ## 3. List your creators [#3-list-your-creators] ```bash curl https://app.fanconvert.ai/public/v1/creators \ -H "Authorization: Bearer $FANCONVERT_API_KEY" ``` ```js const res = await fetch("https://app.fanconvert.ai/public/v1/creators", { headers: { Authorization: `Bearer ${process.env.FANCONVERT_API_KEY}` }, }); if (!res.ok) throw new Error((await res.json()).detail); const { items } = await res.json(); ``` ```python import os, requests r = requests.get( "https://app.fanconvert.ai/public/v1/creators", headers={"Authorization": f"Bearer {os.environ['FANCONVERT_API_KEY']}"}, timeout=30, ) r.raise_for_status() print(r.json()["items"]) ``` ## Next [#next] - [Authentication and permissions](/en/api/rest/authentification) - [Pagination](/en/api/rest/pagination), [Errors](/en/api/rest/erreurs), [Rate limits](/en/api/rest/limites) - [Webhooks](/en/api/rest/webhooks): receive sales without polling - [Full reference](/en/api/reference) --- # Writes and idempotency > Idempotency-Key on every POST, expected revision, pausing the AI on a fan. URL : https://docs.fanconvert.ai/en/api/rest/ecritures ## Idempotency-Key [#idempotency-key] Every `POST` requires an **`Idempotency-Key`** header: 8 to 128 characters `A-Z a-z 0-9 _ . : -`, a UUID for example. - Replaying the same key with the same request returns **the same response without a second write** (header `Idempotent-Replayed: true`), for 24 h. - The same key for another request answers `422`. - `PUT` and `DELETE` are idempotent by nature. ## The team note [#the-team-note] Writing the note requires the revision you read (`expectedRevision`): a concurrent write answers `409`. Read the fan again, then write. ## Pause the AI on a fan (MYM) [#pause-the-ai-on-a-fan-mym] It is the same action as « Arrêter le chatting » (Stop chatting) in the dashboard: the creator's fan filter. Two cases answer `409` and must be done from the dashboard, because they go beyond this fan: - a creator who answers everyone (the action would change her mode); - the last fan of an allow list (removing it would cut off the whole creator). ```bash curl -X POST https://app.fanconvert.ai/public/v1/creators/emma-demo/conversations/123/ai/pause \ -H "Authorization: Bearer $FANCONVERT_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" ``` `…/ai/resume` hands the fan back to the AI (« Relancer le chatting »). --- # Errors > RFC 9457 errors (application/problem+json), HTTP statuses and the stable code field. URL : https://docs.fanconvert.ai/en/api/rest/erreurs Every error follows [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) (`application/problem+json`): ```json { "type": "https://fanconvert.app/problems/not-found", "title": "Ressource introuvable", "status": 404, "detail": "Créatrice introuvable : emma-demo", "instance": "urn:request:6c1e…", "code": "not-found", "params": {}, "errors": [] } ``` - `code` is **stable**: that is what your code should test. - `detail` is a sentence for a human (in French): it may change. - `instance` is the request number: give it to [support](https://t.me/fanconvert), it finds the call. - `errors` details a rejected input field by field (`422`). | Status | When | What to do | |---|---|---| | 401 | key missing, invalid, expired or revoked | check the `Authorization` header, create a new key if needed | | 403 | missing permission, or the person is not an admin | `detail` names the permission; create a key that has it | | 404 | resource not found **or outside the key** | check the identifier and that the creator is in the key | | 409 | write conflict (stale revision) | read the resource again, then write with the current revision | | 422 | invalid parameter, or `Idempotency-Key` reused for another request | fix it using `errors` | | 429 | rate limit reached | wait `Retry-After` seconds ([Rate limits](/en/api/rest/limites)) | | 503 | service temporarily unavailable | retry later, with an increasing delay | --- # Changelog > What changed in the public API and the MCP server. URL : https://docs.fanconvert.ai/en/api/rest/journal - **2026-11-11 — documentation.** The API documentation moves to this site, docs.fanconvert.ai; the contract is still served at `https://app.fanconvert.ai/public/v1/openapi.json`. - **2026-11-07 — webhooks.** `sale.created`, `emergency.created`, `ai.paused`, `ping`; timestamped HMAC-SHA256 signature, six attempts, delivery log. - **2026-11-07 — safe writes.** A fan's team note and labels (`fans:write`), pausing and resuming the AI on an MYM fan (`chatting:write`), `Idempotency-Key` on every `POST`. The media library now only reports `mym`. - **2026-11-07 — v1 Beta.** Read: creators, conversations and messages (MYM, Telegram, OnlyFans), a fan's card, AI state, sales (MYM, Telegram, OnlyFans, Fanvue), statistics, scripts, media, emergencies. `fc_sk_…` keys. --- # Rate limits > 120 requests per minute per key, RateLimit and Retry-After headers. URL : https://docs.fanconvert.ai/en/api/rest/limites **120 requests per minute per key.** Every response announces them, errors included: ``` RateLimit-Policy: "cle";q=120;w=60 RateLimit: "cle";r=117;t=42 ``` IETF draft format `draft-ietf-httpapi-ratelimit-headers-11`: `q` the quota, `w` the window (seconds), `r` what remains, `t` seconds until reset. The older `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` are still sent. Beyond that: `429` with `Retry-After` (in seconds). Wait that long before retrying. --- # Amounts and dates > Amounts as minor-unit integers with their currency; Telegram in Stars (XTR); UTC dates. URL : https://docs.fanconvert.ai/en/api/rest/montants-dates - **Amounts**: integers in the currency's minor unit, `…Minor` fields, always with their `currency` (ISO 4217). `1250` in `EUR` = €12.50. - **Telegram** counts in Stars (`XTR`), with no minor unit: `250` = 250 Stars. - **Dates**: UTC, ISO-8601 (`2026-11-07T05:40:00Z`). --- # Pagination > Cursor pagination — items, nextCursor, cursor and limit. URL : https://docs.fanconvert.ai/en/api/rest/pagination Growing lists are paginated by **cursor**: ```json { "items": [ … ], "nextCursor": "eyJ…" } ``` - Pass `nextCursor` back as the `cursor` parameter for the next page; `null` = last page. - `limit` goes from 1 to 100 (50 by default). - A cursor is opaque: do not build or edit it. ```js let cursor = null; do { const url = new URL("https://app.fanconvert.ai/public/v1/creators/emma-demo/conversations"); if (cursor) url.searchParams.set("cursor", cursor); const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.FANCONVERT_API_KEY}` } }); const page = await res.json(); for (const conversation of page.items) console.log(conversation.id); cursor = page.nextCursor; } while (cursor); ``` --- # Webhooks > Receive sales, emergencies and AI pauses live — events, HMAC signature, deliveries. URL : https://docs.fanconvert.ai/en/api/rest/webhooks Receive events without polling the API: `POST /public/v1/webhooks` with a public `https://` address (port 443 or 8443) and the events you want. The response gives the signing secret `whsec_…` **only once**. Permissions: `webhooks:write` (and `webhooks:read` to list and read the log), plus the read permission of each event. | Event | When | Read permission required | |---|---|---| | `sale.created` | a sale (MYM, Telegram, OnlyFans, Fanvue) | `sales:read` (+ `telegram:read` for Telegram) | | `emergency.created` | a new emergency | `notifications:read` | | `ai.paused` | the AI paused on a fan, or turned off for a creator | `chatting:read` | | `ping` | `POST /public/v1/webhooks/{id}/ping`, to test | — | An event **only carries identifiers and amounts**, never a fan's name or a message: read the details with your key. ```json { "id": "evt_9b1c…", "type": "sale.created", "apiVersion": "v1-beta", "createdAt": "2026-11-07T12:30:00Z", "data": {"platform": "mym", "creatorId": "emma-demo", "saleId": "s_…", "conversationId": "123", "amountMinor": 1500, "currency": "EUR", "at": "…"} } ``` ## Verify the signature [#verify-the-signature] Header `FanConvert-Signature: t=,v1=`: compute HMAC-SHA256 of `"."` with your secret, compare in constant time, reject a `t` older than 5 minutes. ```python import hashlib, hmac, time def verify(secret: str, header: str, body: bytes) -> bool: fields = dict(p.split("=", 1) for p in header.split(",")) if abs(time.time() - int(fields["t"])) > 300: return False expected = hmac.new(secret.encode(), f"{fields['t']}.".encode() + body, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, fields["v1"]) ``` ## Delivery [#delivery] - Answer `2xx` within 10 s. Otherwise, retries after 1 min, 5 min, 30 min, 2 h and 6 h (six attempts), then `failed`. - Redirects are never followed. - The `FanConvert-Event-Id` header lets you ignore a duplicate. - The log: `GET /public/v1/webhooks/{id}/deliveries`. - A webhook lives with its key: key revoked or expired, it is disabled. `DELETE /public/v1/webhooks/{id}` disables it (the log stays). - Events are detected about every 30 s; on creation, nothing from the past is replayed. Reference: [Webhooks](/en/api/reference/webhooks). --- # FanConvert documentation > Everything to use FanConvert day to day, and to connect it to your tools. URL : https://docs.fanconvert.ai/en ## Search [#search] Press ⌘ K (or Ctrl K) to search the whole documentation. ## For an AI [#for-an-ai] Every page exists in Markdown (add `.md` to its address); the full index is at [`/llms.txt`](https://docs.fanconvert.ai/llms.txt). On every page, **Copy as Markdown**, **Open in ChatGPT** and **Open in Claude** hand the page to your assistant.