fathom-ruby 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +4 -0
- data/.rubocop.yml +59 -0
- data/CHANGELOG.md +33 -0
- data/CODE_OF_CONDUCT.md +38 -0
- data/Gemfile +19 -0
- data/LICENSE +22 -0
- data/README.md +509 -0
- data/Rakefile +10 -0
- data/TESTING.md +123 -0
- data/fathom-ruby.gemspec +36 -0
- data/lib/fathom/client.rb +138 -0
- data/lib/fathom/errors.rb +40 -0
- data/lib/fathom/rate_limiter.rb +44 -0
- data/lib/fathom/resource.rb +110 -0
- data/lib/fathom/resources/meeting.rb +41 -0
- data/lib/fathom/resources/recording.rb +42 -0
- data/lib/fathom/resources/team.rb +17 -0
- data/lib/fathom/resources/team_member.rb +38 -0
- data/lib/fathom/resources/webhook.rb +33 -0
- data/lib/fathom/version.rb +5 -0
- data/lib/fathom.rb +58 -0
- data/scripts/README.md +138 -0
- data/scripts/test_live_api.rb +374 -0
- metadata +68 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f0c6eb3ccab98b13b2c4f4dacb7e2ef07f6659f9bfb24b2a834d5983194628f6
|
4
|
+
data.tar.gz: 30783d708be6bac671f90739022765abec159da0bbf91b779fe0312e2a9658cf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: acdcb1635c7fb6d30d48c66aa02e9878d4ae4c1e6ee49f4a91dba102133bbb90af14f389d90cec728603d2fbc522decad1adeadce600c1dd018d88e894d6df13
|
7
|
+
data.tar.gz: 88c8c3124dfbfcbcd02b060f9b6ba929361fe4cb676765b87882ab84d3944fb2d36715a930f867aad37fc48a3b031763759d30e987be8dcaa197c0af7552d489
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 3.1
|
3
|
+
NewCops: enable
|
4
|
+
SuggestExtensions: false
|
5
|
+
Exclude:
|
6
|
+
- 'vendor/**/*'
|
7
|
+
- 'bin/**/*'
|
8
|
+
- 'tmp/**/*'
|
9
|
+
|
10
|
+
Style/Documentation:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
Style/StringLiterals:
|
14
|
+
Enabled: true
|
15
|
+
EnforcedStyle: double_quotes
|
16
|
+
|
17
|
+
Style/StringLiteralsInInterpolation:
|
18
|
+
Enabled: true
|
19
|
+
EnforcedStyle: double_quotes
|
20
|
+
|
21
|
+
Layout/LineLength:
|
22
|
+
Max: 120
|
23
|
+
|
24
|
+
Metrics/MethodLength:
|
25
|
+
Max: 20
|
26
|
+
|
27
|
+
Metrics/AbcSize:
|
28
|
+
Max: 20
|
29
|
+
Exclude:
|
30
|
+
- 'lib/fathom/client.rb' # HTTP client needs complex response handling
|
31
|
+
|
32
|
+
Metrics/CyclomaticComplexity:
|
33
|
+
Max: 7
|
34
|
+
Exclude:
|
35
|
+
- 'lib/fathom/client.rb' # HTTP client has many response codes to handle
|
36
|
+
|
37
|
+
Metrics/ParameterLists:
|
38
|
+
Max: 5
|
39
|
+
Exclude:
|
40
|
+
- 'lib/fathom/client.rb' # Request retry logic needs multiple params
|
41
|
+
|
42
|
+
Metrics/ClassLength:
|
43
|
+
Max: 100
|
44
|
+
Exclude:
|
45
|
+
- 'lib/fathom/client.rb' # HTTP client is inherently complex
|
46
|
+
|
47
|
+
Metrics/BlockLength:
|
48
|
+
Exclude:
|
49
|
+
- 'spec/**/*'
|
50
|
+
- '*.gemspec'
|
51
|
+
|
52
|
+
Style/FrozenStringLiteralComment:
|
53
|
+
Enabled: true
|
54
|
+
EnforcedStyle: always
|
55
|
+
|
56
|
+
Naming/PredicateMethod:
|
57
|
+
Exclude:
|
58
|
+
- 'lib/fathom/resource.rb' # delete is a REST method, not a predicate
|
59
|
+
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
+
|
8
|
+
## [Unreleased]
|
9
|
+
|
10
|
+
## [1.0.0] - 2025-10-17
|
11
|
+
|
12
|
+
### Added
|
13
|
+
- Full support for Fathom API v1
|
14
|
+
- **Meetings API**: List, retrieve, fetch summaries and transcripts
|
15
|
+
- **Recordings API**: Get summaries and transcripts with async delivery support
|
16
|
+
- **Teams API**: List teams and manage team members
|
17
|
+
- **Team Members API**: List and filter team members
|
18
|
+
- **Webhooks API**: Full CRUD operations (create, list, retrieve, delete)
|
19
|
+
- Automatic rate limiting with exponential backoff and configurable retries
|
20
|
+
- Comprehensive error handling with custom error classes
|
21
|
+
- Built with Ruby's native `Net::HTTP` (no external HTTP dependencies)
|
22
|
+
- Ruby 3.1+ support with modern syntax (endless methods, shorthand hash, pattern matching)
|
23
|
+
- Extensive test coverage (125 examples, 94.87% coverage)
|
24
|
+
- Live API integration test script
|
25
|
+
- Full RuboCop compliance
|
26
|
+
|
27
|
+
### Technical Details
|
28
|
+
- Authentication via `X-Api-Key` header
|
29
|
+
- Dynamic attribute access with `method_missing`
|
30
|
+
- Rate limit tracking and automatic retry logic
|
31
|
+
- Pagination support with cursor-based navigation
|
32
|
+
- Proper handling of API response formats
|
33
|
+
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity
|
10
|
+
and orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to a positive environment for our
|
15
|
+
community include:
|
16
|
+
|
17
|
+
* Demonstrating empathy and kindness toward other people
|
18
|
+
* Being respectful of differing opinions, viewpoints, and experiences
|
19
|
+
* Giving and gracefully accepting constructive feedback
|
20
|
+
* Accepting responsibility and apologizing to those affected by our mistakes,
|
21
|
+
and learning from the experience
|
22
|
+
* Focusing on what is best not just for us as individuals, but for the
|
23
|
+
overall community
|
24
|
+
|
25
|
+
## Enforcement
|
26
|
+
|
27
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
28
|
+
reported to the community leaders responsible for enforcement.
|
29
|
+
All complaints will be reviewed and investigated promptly and fairly.
|
30
|
+
|
31
|
+
## Attribution
|
32
|
+
|
33
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
34
|
+
version 2.0, available at
|
35
|
+
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
36
|
+
|
37
|
+
[homepage]: https://www.contributor-covenant.org
|
38
|
+
|
data/Gemfile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
# Specify your gem's dependencies in fathom-ruby.gemspec
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
gem "rake", "~> 13.0"
|
9
|
+
|
10
|
+
# Development dependencies
|
11
|
+
group :development do
|
12
|
+
gem "irb", "~> 1.0"
|
13
|
+
gem "openssl"
|
14
|
+
gem "rdoc", "~> 6.0"
|
15
|
+
gem "rspec", "~> 3.0"
|
16
|
+
gem "rubocop", "~> 1.21"
|
17
|
+
gem "simplecov", "~> 0.22"
|
18
|
+
gem "webmock", "~> 3.0"
|
19
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Juan Rodriguez
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
@@ -0,0 +1,509 @@
|
|
1
|
+
# Fathom Ruby
|
2
|
+
|
3
|
+
[Fathom](https://fathom.ai) is an AI meeting assistant that records, transcribes, highlights, and summarizes your meetings so you can focus on the conversation.
|
4
|
+
|
5
|
+
This is a comprehensive Ruby gem for interacting with the [Fathom API](https://developers.fathom.ai). This gem provides easy access to Fathom's REST API for managing meetings, recordings, teams, webhooks, and more.
|
6
|
+
|
7
|
+
[](https://github.com/j4rs/fathom-ruby/actions)
|
8
|
+
[](https://badge.fury.io/rb/fathom-ruby)
|
9
|
+
|
10
|
+
## Features
|
11
|
+
|
12
|
+
- 🔄 Automatic rate limiting with configurable retries
|
13
|
+
- 🛡️ Comprehensive error handling
|
14
|
+
- 📝 Full support for all the existing Fathom API resources
|
15
|
+
- 🎯 Simple and intuitive API
|
16
|
+
- ✅ Verified against [official Fathom API documentation](https://developers.fathom.ai/api-reference)
|
17
|
+
|
18
|
+
## Requirements
|
19
|
+
|
20
|
+
- Ruby >= 3.1.0
|
21
|
+
|
22
|
+
## Installation
|
23
|
+
|
24
|
+
Add this line to your application's Gemfile:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
gem 'fathom-ruby'
|
28
|
+
```
|
29
|
+
|
30
|
+
And then execute:
|
31
|
+
|
32
|
+
```bash
|
33
|
+
$ bundle install
|
34
|
+
```
|
35
|
+
|
36
|
+
Or install it yourself as:
|
37
|
+
|
38
|
+
```bash
|
39
|
+
$ gem install fathom-ruby
|
40
|
+
```
|
41
|
+
|
42
|
+
## Configuration
|
43
|
+
|
44
|
+
### Basic Setup
|
45
|
+
|
46
|
+
Configure the gem with your Fathom API key:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
require 'fathom'
|
50
|
+
|
51
|
+
Fathom.api_key = "your_api_key_here"
|
52
|
+
```
|
53
|
+
|
54
|
+
### Configuration Options
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
Fathom.configure do |config|
|
58
|
+
config.api_key = "your_api_key_here"
|
59
|
+
|
60
|
+
# Enable/disable automatic retries on rate limits (default: true)
|
61
|
+
config.auto_retry = true
|
62
|
+
|
63
|
+
# Maximum number of retry attempts (default: 3)
|
64
|
+
config.max_retries = 3
|
65
|
+
|
66
|
+
# Enable debug logging (default: false)
|
67
|
+
config.debug = Rails.env.development?
|
68
|
+
|
69
|
+
# Enable HTTP request/response logging (default: false)
|
70
|
+
config.debug_http = Rails.env.development?
|
71
|
+
end
|
72
|
+
```
|
73
|
+
|
74
|
+
### Rails Configuration
|
75
|
+
|
76
|
+
Create an initializer at `config/initializers/fathom.rb`:
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
require 'fathom'
|
80
|
+
|
81
|
+
Fathom.configure do |config|
|
82
|
+
config.api_key = ENV['FATHOM_API_KEY']
|
83
|
+
# ... rest of the settings (like above)
|
84
|
+
end
|
85
|
+
```
|
86
|
+
|
87
|
+
## Usage
|
88
|
+
|
89
|
+
> **📋 Important Notes:**
|
90
|
+
> - The Fathom API uses **cursor-based pagination**, not offset-based
|
91
|
+
> - Response format is `{ items: [...] }`, not `{ data: [...] }`
|
92
|
+
> - **Team Members**: No individual IDs - filter by team name instead
|
93
|
+
> - **Recordings**: No list/retrieve endpoints - use specialized endpoints for summary/transcript
|
94
|
+
> - See [API_CORRECTIONS.md](API_CORRECTIONS.md) for complete details on API structure
|
95
|
+
|
96
|
+
### Meetings
|
97
|
+
|
98
|
+
List all meetings:
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
# Get all meetings
|
102
|
+
meetings = Fathom::Meeting.all
|
103
|
+
|
104
|
+
# With query parameters
|
105
|
+
meetings = Fathom::Meeting.all(
|
106
|
+
cursor: "eyJwYWdlX251bSI6Mn0=", # Cursor-based pagination
|
107
|
+
include_summary: true, # Include default_summary
|
108
|
+
include_transcript: true, # Include transcript
|
109
|
+
include_action_items: true, # Include action_items
|
110
|
+
teams: ["Sales", "Engineering"] # Filter by team names
|
111
|
+
)
|
112
|
+
|
113
|
+
# Filter by date range
|
114
|
+
meetings = Fathom::Meeting.all(
|
115
|
+
created_after: "2025-01-01T00:00:00Z",
|
116
|
+
created_before: "2025-01-31T23:59:59Z"
|
117
|
+
)
|
118
|
+
|
119
|
+
# Filter by calendar invitees
|
120
|
+
meetings = Fathom::Meeting.all(
|
121
|
+
"calendar_invitees[]" => "ceo@acme.com"
|
122
|
+
)
|
123
|
+
```
|
124
|
+
|
125
|
+
Access meeting data:
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
meeting = meetings.first
|
129
|
+
|
130
|
+
# Basic fields
|
131
|
+
puts meeting.title
|
132
|
+
puts meeting.recording_id
|
133
|
+
|
134
|
+
# Embedded data (when requested with include_* params)
|
135
|
+
puts meeting.summary # Returns default_summary hash
|
136
|
+
puts meeting.summary["markdown_formatted"]
|
137
|
+
puts meeting.transcript # Returns transcript array
|
138
|
+
puts meeting.participants # Returns calendar_invitees array
|
139
|
+
puts meeting.action_items # Returns action_items array
|
140
|
+
```
|
141
|
+
|
142
|
+
Fetch recording data for a meeting:
|
143
|
+
|
144
|
+
```ruby
|
145
|
+
meeting = meetings.first
|
146
|
+
|
147
|
+
# Fetch summary from Recording API
|
148
|
+
if meeting.recording?
|
149
|
+
summary = meeting.fetch_summary
|
150
|
+
puts summary["template_name"]
|
151
|
+
puts summary["markdown_formatted"]
|
152
|
+
|
153
|
+
# Fetch transcript from Recording API
|
154
|
+
transcript = meeting.fetch_transcript
|
155
|
+
transcript.each do |segment|
|
156
|
+
puts "#{segment['speaker']['display_name']}: #{segment['text']}"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
```
|
160
|
+
|
161
|
+
### Recordings
|
162
|
+
|
163
|
+
**Note**: Recordings don't have standard list/retrieve endpoints. They're accessed via their specialized endpoints:
|
164
|
+
|
165
|
+
Get summary for a recording:
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
# Synchronous - returns summary immediately
|
169
|
+
summary = Fathom::Recording.get_summary(123456789)
|
170
|
+
|
171
|
+
puts summary["template_name"] # e.g., "general"
|
172
|
+
puts summary["markdown_formatted"] # Formatted summary text
|
173
|
+
```
|
174
|
+
|
175
|
+
Get transcript for a recording:
|
176
|
+
|
177
|
+
```ruby
|
178
|
+
# Synchronous - returns transcript immediately
|
179
|
+
transcript = Fathom::Recording.get_transcript(123456789)
|
180
|
+
|
181
|
+
transcript.each do |segment|
|
182
|
+
speaker = segment["speaker"]["display_name"]
|
183
|
+
text = segment["text"]
|
184
|
+
timestamp = segment["timestamp"]
|
185
|
+
|
186
|
+
puts "[#{timestamp}] #{speaker}: #{text}"
|
187
|
+
end
|
188
|
+
```
|
189
|
+
|
190
|
+
Async mode with webhooks:
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
# Async - sends result to your webhook URL
|
194
|
+
Fathom::Recording.get_summary(
|
195
|
+
123456789,
|
196
|
+
destination_url: "https://your-app.com/webhooks/summary"
|
197
|
+
)
|
198
|
+
|
199
|
+
Fathom::Recording.get_transcript(
|
200
|
+
123456789,
|
201
|
+
destination_url: "https://your-app.com/webhooks/transcript"
|
202
|
+
)
|
203
|
+
```
|
204
|
+
|
205
|
+
### Teams
|
206
|
+
|
207
|
+
List all teams:
|
208
|
+
|
209
|
+
```ruby
|
210
|
+
teams = Fathom::Team.all
|
211
|
+
|
212
|
+
teams.each do |team|
|
213
|
+
puts team.name
|
214
|
+
puts "Created: #{team.created_at}"
|
215
|
+
end
|
216
|
+
```
|
217
|
+
|
218
|
+
Get a specific team:
|
219
|
+
|
220
|
+
```ruby
|
221
|
+
team = Fathom::Team.retrieve("team_id")
|
222
|
+
puts team.name
|
223
|
+
```
|
224
|
+
|
225
|
+
List team members:
|
226
|
+
|
227
|
+
```ruby
|
228
|
+
team = Fathom::Team.retrieve("team_id")
|
229
|
+
members = team.members # Automatically filters by team name
|
230
|
+
|
231
|
+
# Or directly by team name
|
232
|
+
members = Fathom::TeamMember.all(team: "Engineering")
|
233
|
+
```
|
234
|
+
|
235
|
+
### Team Members
|
236
|
+
|
237
|
+
List all team members:
|
238
|
+
|
239
|
+
```ruby
|
240
|
+
# List all team members
|
241
|
+
members = Fathom::TeamMember.all
|
242
|
+
|
243
|
+
members.each do |member|
|
244
|
+
puts "#{member.name} (#{member.email})"
|
245
|
+
puts "Created: #{member.created_at}"
|
246
|
+
end
|
247
|
+
```
|
248
|
+
|
249
|
+
Filter by team name:
|
250
|
+
|
251
|
+
```ruby
|
252
|
+
# Filter by specific team name
|
253
|
+
members = Fathom::TeamMember.all(team: "Engineering")
|
254
|
+
|
255
|
+
members.each do |member|
|
256
|
+
puts "#{member.name} - #{member.email}"
|
257
|
+
end
|
258
|
+
```
|
259
|
+
|
260
|
+
Pagination with cursor:
|
261
|
+
|
262
|
+
```ruby
|
263
|
+
# First page
|
264
|
+
response = Fathom::TeamMember.all(team: "Sales")
|
265
|
+
|
266
|
+
# Next page (if cursor is available from API response)
|
267
|
+
next_page = Fathom::TeamMember.all(team: "Sales", cursor: "next_cursor_value")
|
268
|
+
```
|
269
|
+
|
270
|
+
**Note:** Team members don't have individual IDs in the Fathom API. Use filtering instead of retrieving individual members.
|
271
|
+
|
272
|
+
### Webhooks
|
273
|
+
|
274
|
+
List all webhooks:
|
275
|
+
|
276
|
+
```ruby
|
277
|
+
webhooks = Fathom::Webhook.all
|
278
|
+
|
279
|
+
webhooks.each do |webhook|
|
280
|
+
puts "#{webhook.url}"
|
281
|
+
puts " Includes transcript: #{webhook.include_transcript?}"
|
282
|
+
puts " Includes summary: #{webhook.include_summary?}"
|
283
|
+
puts " Active: #{webhook.active?}"
|
284
|
+
end
|
285
|
+
```
|
286
|
+
|
287
|
+
Create a webhook:
|
288
|
+
|
289
|
+
```ruby
|
290
|
+
webhook = Fathom::Webhook.create(
|
291
|
+
url: "https://example.com/webhook",
|
292
|
+
# Specify which recordings should trigger the webhook:
|
293
|
+
# - my_recordings: Your own recordings
|
294
|
+
# - shared_external_recordings: Recordings shared with you externally
|
295
|
+
# - my_shared_with_team_recordings: Your recordings shared with your team
|
296
|
+
# - shared_team_recordings: Team recordings shared with you
|
297
|
+
triggered_for: ["my_recordings", "shared_external_recordings"],
|
298
|
+
include_transcript: true,
|
299
|
+
include_summary: true,
|
300
|
+
include_action_items: true,
|
301
|
+
include_crm_matches: false
|
302
|
+
)
|
303
|
+
|
304
|
+
puts webhook.id
|
305
|
+
puts webhook.secret
|
306
|
+
puts webhook.triggered_for # => ["my_recordings", "shared_external_recordings"]
|
307
|
+
```
|
308
|
+
|
309
|
+
Get a specific webhook:
|
310
|
+
|
311
|
+
```ruby
|
312
|
+
webhook = Fathom::Webhook.retrieve("webhook_id")
|
313
|
+
|
314
|
+
if webhook.active?
|
315
|
+
puts "Webhook is active"
|
316
|
+
end
|
317
|
+
```
|
318
|
+
|
319
|
+
Delete a webhook:
|
320
|
+
|
321
|
+
```ruby
|
322
|
+
webhook = Fathom::Webhook.retrieve("webhook_id")
|
323
|
+
webhook.delete
|
324
|
+
```
|
325
|
+
|
326
|
+
Check webhook configuration:
|
327
|
+
|
328
|
+
```ruby
|
329
|
+
webhook = Fathom::Webhook.retrieve("webhook_id")
|
330
|
+
|
331
|
+
puts "Active: #{webhook.active?}"
|
332
|
+
puts "Triggered for: #{webhook.triggered_for.join(', ')}"
|
333
|
+
puts "Includes transcript: #{webhook.include_transcript?}"
|
334
|
+
puts "Includes summary: #{webhook.include_summary?}"
|
335
|
+
puts "Includes action items: #{webhook.include_action_items?}"
|
336
|
+
puts "Includes CRM matches: #{webhook.include_crm_matches?}"
|
337
|
+
```
|
338
|
+
|
339
|
+
## Rate Limiting
|
340
|
+
|
341
|
+
The Fathom API has a rate limit of 60 requests per 60 seconds. This gem handles rate limiting automatically.
|
342
|
+
|
343
|
+
### Automatic Retries (Default)
|
344
|
+
|
345
|
+
By default, the gem will automatically retry requests when rate limited:
|
346
|
+
|
347
|
+
```ruby
|
348
|
+
Fathom.auto_retry = true # This is the default
|
349
|
+
Fathom.max_retries = 3 # Maximum retry attempts
|
350
|
+
|
351
|
+
# Requests will automatically retry with exponential backoff
|
352
|
+
meetings = Fathom::Meeting.all
|
353
|
+
```
|
354
|
+
|
355
|
+
### Manual Rate Limit Handling
|
356
|
+
|
357
|
+
Disable automatic retries and handle rate limits manually:
|
358
|
+
|
359
|
+
```ruby
|
360
|
+
Fathom.auto_retry = false
|
361
|
+
|
362
|
+
begin
|
363
|
+
meetings = Fathom::Meeting.all
|
364
|
+
rescue Fathom::RateLimitError => e
|
365
|
+
# Handle rate limit error
|
366
|
+
puts "Rate limited. Remaining: #{e.rate_limit_remaining}"
|
367
|
+
puts "Reset in: #{e.rate_limit_reset} seconds"
|
368
|
+
|
369
|
+
# Wait and retry manually
|
370
|
+
sleep(e.rate_limit_reset)
|
371
|
+
retry
|
372
|
+
end
|
373
|
+
```
|
374
|
+
|
375
|
+
### Checking Rate Limit Info
|
376
|
+
|
377
|
+
Access rate limit information from any resource:
|
378
|
+
|
379
|
+
```ruby
|
380
|
+
meetings = Fathom::Meeting.all
|
381
|
+
rate_info = meetings.first.rate_limit_info
|
382
|
+
|
383
|
+
puts "Limit: #{rate_info[:limit]}"
|
384
|
+
puts "Remaining: #{rate_info[:remaining]}"
|
385
|
+
puts "Reset in: #{rate_info[:reset]} seconds"
|
386
|
+
```
|
387
|
+
|
388
|
+
## Error Handling
|
389
|
+
|
390
|
+
The gem provides specific error classes for different scenarios:
|
391
|
+
|
392
|
+
```ruby
|
393
|
+
begin
|
394
|
+
meeting = Fathom::Meeting.retrieve("invalid_id")
|
395
|
+
rescue Fathom::AuthenticationError => e
|
396
|
+
# 401 - Invalid API key
|
397
|
+
puts "Authentication failed: #{e.message}"
|
398
|
+
rescue Fathom::NotFoundError => e
|
399
|
+
# 404 - Resource not found
|
400
|
+
puts "Meeting not found: #{e.message}"
|
401
|
+
rescue Fathom::RateLimitError => e
|
402
|
+
# 429 - Rate limit exceeded
|
403
|
+
puts "Rate limited: #{e.message}"
|
404
|
+
rescue Fathom::BadRequestError => e
|
405
|
+
# 400 - Bad request
|
406
|
+
puts "Bad request: #{e.message}"
|
407
|
+
rescue Fathom::ForbiddenError => e
|
408
|
+
# 403 - Forbidden
|
409
|
+
puts "Access forbidden: #{e.message}"
|
410
|
+
rescue Fathom::ServerError => e
|
411
|
+
# 5xx - Server error
|
412
|
+
puts "Server error: #{e.message}"
|
413
|
+
rescue Fathom::Error => e
|
414
|
+
# Any other Fathom error
|
415
|
+
puts "Error: #{e.message}"
|
416
|
+
end
|
417
|
+
```
|
418
|
+
|
419
|
+
All error objects include:
|
420
|
+
|
421
|
+
- `message` - Human-readable error message
|
422
|
+
- `http_status` - HTTP status code
|
423
|
+
- `response` - Raw response object
|
424
|
+
|
425
|
+
## Dynamic Attribute Access
|
426
|
+
|
427
|
+
All resources support dynamic attribute access:
|
428
|
+
|
429
|
+
```ruby
|
430
|
+
meeting = Fathom::Meeting.retrieve("meeting_id")
|
431
|
+
|
432
|
+
# Access attributes
|
433
|
+
meeting.title
|
434
|
+
meeting.summary
|
435
|
+
meeting["custom_field"]
|
436
|
+
|
437
|
+
# Set attributes
|
438
|
+
meeting.title = "New Title"
|
439
|
+
meeting["custom_field"] = "value"
|
440
|
+
|
441
|
+
# Convert to hash
|
442
|
+
meeting.to_h
|
443
|
+
|
444
|
+
# Convert to JSON
|
445
|
+
meeting.to_json
|
446
|
+
```
|
447
|
+
|
448
|
+
## Debugging
|
449
|
+
|
450
|
+
Enable debug logging to see what's happening:
|
451
|
+
|
452
|
+
```ruby
|
453
|
+
# Basic debug logging
|
454
|
+
Fathom.debug = true
|
455
|
+
|
456
|
+
# HTTP request/response logging
|
457
|
+
Fathom.debug_http = true
|
458
|
+
|
459
|
+
# Now all API calls will be logged
|
460
|
+
meetings = Fathom::Meeting.all
|
461
|
+
# [Fathom] Rate limit: 59/60, resets in 60s
|
462
|
+
# [Fathom HTTP] GET https://api.fathom.ai/v1/meetings
|
463
|
+
# [Fathom HTTP] Response: 200 OK
|
464
|
+
```
|
465
|
+
|
466
|
+
### Testing live
|
467
|
+
Check [Test Live API Readme](./scripts/README.md) for instructions to test the API using a real API Key.
|
468
|
+
|
469
|
+
## Development
|
470
|
+
|
471
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
472
|
+
|
473
|
+
### Running Tests
|
474
|
+
|
475
|
+
```bash
|
476
|
+
bundle exec rspec
|
477
|
+
```
|
478
|
+
|
479
|
+
### Running Rubocop
|
480
|
+
|
481
|
+
```bash
|
482
|
+
bundle exec rubocop
|
483
|
+
```
|
484
|
+
|
485
|
+
## Contributing
|
486
|
+
|
487
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/yourusername/fathom-ruby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](CODE_OF_CONDUCT.md).
|
488
|
+
|
489
|
+
1. Fork it
|
490
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
491
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
492
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
493
|
+
5. Create a new Pull Request
|
494
|
+
|
495
|
+
## License
|
496
|
+
|
497
|
+
The gem is available as open source under the terms of the [MIT License](LICENSE).
|
498
|
+
|
499
|
+
## Code of Conduct
|
500
|
+
|
501
|
+
Everyone interacting in the Fathom Ruby project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](CODE_OF_CONDUCT.md).
|
502
|
+
|
503
|
+
## Links
|
504
|
+
|
505
|
+
- [Fathom API Documentation](https://developers.fathom.ai)
|
506
|
+
- [Gem Documentation](https://rubydoc.info/gems/fathom-ruby)
|
507
|
+
- [GitHub Repository](https://github.com/yourusername/fathom-ruby)
|
508
|
+
- [Bug Reports](https://github.com/yourusername/fathom-ruby/issues)
|
509
|
+
|