Skill: byungkyu/fireflies-api (version 1.0.1)

--- name: fireflies description: | Fireflies.ai GraphQL API integration with managed OAuth. Access meeting transcripts, summaries, users, contacts, and AI-powered meeting analysis. Use this skill when users want to retrieve meeting transcripts, search conversations, analyze meeting content with AskFred, or manage meeting recordings. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway). Requires network access and valid Maton API key. metadata: author: maton version: "1.0" clawdbot: emoji: 🧠 requires: env: - MATON_API_KEY --- # Fireflies Access the Fireflies.ai GraphQL API with managed OAuth authentication. Retrieve meeting transcripts, summaries, users, contacts, channels, and use AI-powered meeting analysis with AskFred. ## Quick Start ```bash # Get current user python <<'EOF' import urllib.request, os, json data = json.dumps({'query': '{ user { user_id name email is_admin } }'}).encode() req = urllib.request.Request('https://api.maton.ai/fireflies/graphql', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ``` ## Base URL ``` https://api.maton.ai/fireflies/graphql ``` All requests are sent to a single GraphQL endpoint. Maton proxies requests to `api.fireflies.ai/graphql` and automatically injects your OAuth token. ## Authentication All requests require the Maton API key in the Authorization header: ``` Authorization: Bearer $MATON_API_KEY ``` **Environment Variable:** Set your API key as `MATON_API_KEY`: ```bash export MATON_API_KEY="YOUR_API_KEY" ``` ### Getting Your API Key 1. Sign in or create an account at [maton.ai](https://maton.ai) 2. Go to [maton.ai/settings](https://maton.ai/settings) 3. Copy your API key ## Connection Management Manage your Fireflies OAuth connections at `https://api.maton.ai`. ### List Connections ```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://api.maton.ai/connections?app=fireflies&status=ACTIVE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ``` ### Create Connection ```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'app': 'fireflies'}).encode() req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ``` ### Get Connection ```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ``` **Response:** ```json { "connection": { "connection_id": "{connection_id}", "status": "ACTIVE", "creation_time": "2026-02-11T00:45:25.802991Z", "last_updated_time": "2026-02-11T00:46:04.771700Z", "url": "https://connect.maton.ai/?session_token=...", "app": "fireflies", "metadata": {} } } ``` Open the returned `url` in a browser to complete OAuth authorization. ### Delete Connection ```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ``` ### Specifying Connection If you have multiple Fireflies connections, specify which one to use with the `Maton-Connection` header: ```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'query': '{ user { user_id name email } }'}).encode() req = urllib.request.Request('https://api.maton.ai/fireflies/graphql', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') req.add_header('Maton-Connection', '{connection_id}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ``` If you have multiple connections, always include this header to ensure requests go to the intended account. ## Security & Permissions - Access is scoped to meeting transcripts, notes, users, and audio recordings within the connected Fireflies account. - **All write operations require explicit user approval.** Before executing any create, update, or delete mutation, confirm the target resource and intended effect with the user. ## GraphQL API Fireflies uses GraphQL, which means all requests are POST requests to a single `/graphql` endpoint with a JSON body containing the query. ### Request Format ```bash POST /fireflies/graphql Content-Type: application/json { "query": "{ ... }", "variables": { ... } } ``` --- ## Queries ### Get Current User ```graphql { user { user_id name email is_admin num_transcripts minutes_consumed recent_transcript recent_meeting } } ``` **Response:** ```json { "data": { "user": { "user_id": "01KH5131Z0W4TS7BBSEP66CV6V", "name": "John Doe", "email": "[REDACTED_SECRET]", "is_admin": true, "num_transcripts": null, "minutes_consumed": 0 } } } ``` ### List Users ```graphql { users { user_id name email is_admin num_transcripts minutes_consumed } } ``` ### List Transcripts ```graphql { transcripts { id title date duration host_email organizer_email privacy transcript_url audio_url video_url dateString calendar_type meeting_link } } ``` **With Variables (filtering):** ```json { "query": "query($limit: Int, $skip: Int) { transcripts(limit: $limit, skip: $skip) { id title date duration } }", "variables": { "limit": 10, "skip": 0 } } ``` ### Get Transcript by ID ```graphql query($id: String!) { transcript(id: $id) { id title date duration host_email privacy transcript_url audio_url summary { overview short_summary action_items outline keywords meeting_type } sentences { text speaker_name start_time end_time } participants speakers { name } } } ``` ### List Channels ```graphql { channels { id title created_at updated_at is_private created_by } } ``` ### Get Channel by ID ```graphql query($id: String!) { channel(id: $id) { id title created_at is_private members } } ``` ### List Contacts ```graphql { contacts { email name picture last_meeting_date } } ``` ### List User Groups ```graphql { user_groups { id name } } ``` ### List Bites (Soundbites) ```graphql { bites { id name transcript_id thumbnail preview status summary start_time end_time media_type created_at } } ``` ### Get Bite by ID ```graphql query($id: String!) { bite(id: $id) { id name transcript_id summary start_time end_time captions } } ``` ### List Active Meetings ```graphql { active_meetings { id title date } } ``` ### AskFred Threads Query meeting content using AI. **List Threads:** ```graphql { askfred_threads { id title created_at } } ``` **Get Thread by ID:** ```graphql query($id: String!) { askfred_thread(id: $id) { id title messages { content role } } } ``` --- ## Mutations ### Upload Audio ```graphql mutation($input: AudioUploadInput!) { uploadAudio(input: $input) { success title message } } ``` **Variables:** ```json { "input": { "url": "https://example.com/audio.mp3", "title": "Meeting Recording" } } ``` ### Delete Transcript ```graphql mutation($id: String!) { deleteTranscript(id: $id) { success message } } ``` ### Update Meeting Title ```graphql mutation($id: String!, $title: String!) { updateMeetingTitle(id: $id, title: $title) { success } } ``` ### Update Meeting Privacy ```graphql mutation($id: String!, $privacy: String!) { updateMeetingPrivacy(id: $id, privacy: $privacy) { success } } ``` ### Update Meeting Channel ```graphql mutation($id: String!, $channelId: String!) { updateMeetingChannel(id: $id, channelId: $channelId) { success } } ``` ### Set User Role ```graphql mutation($userId: String!, $role: String!) { setUserRole(userId: $userId, role: $role) { success } } ``` ### Create Bite ```graphql mutation($input: CreateBiteInput!) { createBite(input: $input) { id name } } ``` ### AskFred Mutations **Create Thread:** ```graphql mutation($input: CreateAskFredThreadInput!) { createAskFredThread(input: $input) { id title } } ``` **Continue Thread:** ```graphql mutation($id: String!, $question: String!) { continueAskFredThread(id: $id, question: $question) { id messages { content role } } } ``` **Delete Thread:** ```graphql mutation($id: String!) { deleteAskFredThread(id: $id) { success } } ``` ### Live Meeting Mutations **Update Meeting State (pause/resume):** ```graphql mutation($id: String!, $state: String!) { updateMeetingState(id: $id, state: $state) { success } } ``` **Create Live Action Item:** ```graphql mutation($meetingId: String!, $text: String!) { createLiveActionItem(meetingId: $meetingId, text: $text) { success } } ``` **Create Live Soundbite:** ```graphql mutation($meetingId: String!, $name: String!) { createLiveSoundbite(meetingId: $meetingId, name: $name) { success } } ``` **Add Bot to Live Meeting:** ```graphql mutation($meetingLink: String!) { addToLiveMeeting(meetingLink: $meetingLink) { success } } ``` --- ## Code Examples ### JavaScript ```javascript const query = `{ user { user_id name email } }`; const response = await fetch( 'https://api.maton.ai/fireflies/graphql', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.MATON_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ query }) } ); const data = await response.json(); console.log(data.data.user); ``` ### Python ```python import os import requests query = ''' { transcripts { id title date duration } } ''' response = requests.post( 'https://api.maton.ai/fireflies/graphql', headers={ 'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}', 'Content-Type': 'application/json' }, json={'query': query} ) data = response.json() for transcript in data['data']['transcripts']: print(f"{transcript['title']}: {transcript['duration']}s") ``` ## Notes - Fireflies uses GraphQL, not REST - all requests are POST to `/graphql` - User IDs are ULIDs (e.g., `01KH5131Z0W4TS7BBSEP66CV6V`) - Timestamps are Unix timestamps (milliseconds) - The `summary` field on transcripts contains AI-generated content: overview, action_items, outline, keywords - AskFred allows natural language queries across meeting transcripts - Rate limits: 50 API calls/day on free plan, more on Business plan - IMPORTANT: All GraphQL queries and mutations must be sent as POST requests with Content-Type: application/json - IMPORTANT: When piping curl output to `jq` or other commands, environment variables like `$MATON_API_KEY` may not expand correctly in some shell environments ## Error Handling | Status | Meaning | |--------|---------| | 400 | Invalid GraphQL query or missing connection | | 401 | Invalid or missing Maton API key | | 403 | Insufficient permissions | | 429 | Rate limited | | 500 | Internal server error | **GraphQL Errors:** ```json { "errors": [ { "message": "Cannot query field \"id\" on type \"User\".", "code": "GRAPHQL_VALIDATION_FAILED" } ] } ``` ### Troubleshooting: API Key Issues 1. Check that the `MATON_API_KEY` environment variable is set: ```bash echo $MATON_API_KEY ``` 2. Verify the API key is valid by listing connections: ```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://api.maton.ai/connections') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ``` ### Troubleshooting: Invalid App Name 1. Ensure your URL path starts with `fireflies`. For example: - Correct: `https://api.maton.ai/fireflies/graphql` - Incorrect: `https://api.maton.ai/graphql` ## Resources - [Fireflies API Documentation](https://docs.fireflies.ai/) - [Fireflies GraphQL API Reference](https://docs.fireflies.ai/graphql-api) - [Fireflies Developer Program](https://docs.fireflies.ai/getting-started/developer-program) - [Maton Community](https://discord.com/invite/dBfFAcefs2) - [Maton Support](mailto:[REDACTED_SECRET])


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)