attio 0.1.3 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6bc8e8104ce0d509fd592dbcfe3d7203998db7ea38352a40162e6a8e8e92f470
4
- data.tar.gz: dd0bac00b8534523bf20f82238cd404cdc8f0ca0929b46a62be0137799d7aec2
3
+ metadata.gz: c28065cbac5cffee49ef7864e60d19543ab116ef2bea68374ec2b995476efbd9
4
+ data.tar.gz: 31036f5bd6d0fd23b827176fe6a52f620d17042fe1bc6d55f2c5f86bb03a09c5
5
5
  SHA512:
6
- metadata.gz: 6413a664b4197e85df9a71caf88bb8f322b17cd330d3c39cbf77666eca06d337f0094781a2207d26fa7e0d2c1cf2eb3178d2a8c2eaf3b4b08708b25ea1f71369
7
- data.tar.gz: 3f240f41215b4713c01a95c61e5076be16ee9702d9c95c997ef3bf009766acb7e1ccc6a245cb35f161f32cb29afcc26ff726c36970c06e5cedc223445f4e479a
6
+ metadata.gz: e0a5e5fb4654d9bbb579babffde8540d6bbd3dc0b1463a22eb8838c42095e8e368fbe3f712a6e85a49bfdaf8d3adeb2386769591c36ebf0bb035b22bdeb407c6
7
+ data.tar.gz: fe5085f5f9b20e688ff8f4c7e21f42482432c911fe135f9df5f4acab92e101585c5b5d719f78d8fd349e020e038a0f8fd3d144e80816eeabe1b78b25570e7e1d
@@ -72,13 +72,9 @@ jobs:
72
72
  echo "GEM_FILE=$(ls attio-*.gem)" >> $GITHUB_ENV
73
73
 
74
74
  - name: Publish to RubyGems
75
+ env:
76
+ GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_AUTH_TOKEN }}
75
77
  run: |
76
- mkdir -p ~/.gem
77
- cat << 'EOF' > ~/.gem/credentials
78
- ---
79
- :rubygems_api_key: ${{ secrets.RUBYGEMS_API_KEY }}
80
- EOF
81
- chmod 0600 ~/.gem/credentials
82
78
  gem push ${{ env.GEM_FILE }}
83
79
 
84
80
  - name: Generate changelog
data/CHANGELOG.md CHANGED
@@ -5,7 +5,32 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [Unreleased]
8
+ ## [0.2.0] - 2025-08-11
9
+
10
+ ### Added
11
+ - Comments resource with full CRUD operations and emoji reactions
12
+ - Threads resource with participant management and status control
13
+ - Tasks resource with assignment and completion tracking
14
+ - Notes resource for creating and managing notes on records
15
+ - DELETE with body support in HttpClient for participant management
16
+ - URL encoding for emoji reactions using CGI.escape
17
+ - Comprehensive examples for collaboration features
18
+ - Advanced filtering and querying examples
19
+ - Complete CRM workflow example
20
+
21
+ ### Improved
22
+ - Achieved 100% test coverage (376/376 lines)
23
+ - Increased test count from 147 to 265 tests
24
+ - Refactored Base class to reduce code duplication across resources
25
+ - Extracted common validation methods to base class
26
+ - Standardized error messages across all resources
27
+ - Fixed keyword arguments vs options hash issues in test mocks
28
+ - Updated README with all new features and comprehensive examples
29
+
30
+ ### Fixed
31
+ - Semantic correctness in all test files
32
+ - REST convention compliance for DELETE operations
33
+ - Proper URL encoding for special characters in API paths
9
34
 
10
35
  ## [0.1.3] - 2025-08-11
11
36
 
data/CONCEPTS.md ADDED
@@ -0,0 +1,428 @@
1
+ # Attio Ruby Gem - Architectural Concepts
2
+
3
+ This document explains the key architectural decisions, design patterns, and concepts behind the Attio Ruby gem implementation.
4
+
5
+ ## Table of Contents
6
+ - [Overall Architecture](#overall-architecture)
7
+ - [Template Method Pattern](#template-method-pattern-in-base-class)
8
+ - [DELETE with Body Support](#delete-with-body-support)
9
+ - [URL Encoding for Special Characters](#url-encoding-for-special-characters)
10
+ - [Collaboration Features Workflow](#collaboration-features-workflow)
11
+ - [Error Handling Strategy](#error-handling-strategy)
12
+ - [Testing Strategy](#testing-strategy)
13
+ - [Key Design Decisions](#key-design-decisions-explained)
14
+
15
+ ## Overall Architecture
16
+
17
+ The Attio Ruby gem follows a modular resource-based architecture with a clear separation of concerns:
18
+
19
+ ```mermaid
20
+ graph TD
21
+ Client[Attio::Client] --> HttpClient[HTTP Client Layer]
22
+ Client --> Resources[Resource Classes]
23
+
24
+ Resources --> Base[Base Resource]
25
+ Resources --> Records[Records]
26
+ Resources --> Comments[Comments]
27
+ Resources --> Threads[Threads]
28
+ Resources --> Tasks[Tasks]
29
+ Resources --> Notes[Notes]
30
+ Resources --> Lists[Lists]
31
+ Resources --> Objects[Objects]
32
+ Resources --> Attributes[Attributes]
33
+ Resources --> Users[Users]
34
+ Resources --> Workspaces[Workspaces]
35
+
36
+ Base --> Validations[Common Validations]
37
+ Base --> Request[Request Handler]
38
+
39
+ HttpClient --> Typhoeus[Typhoeus HTTP]
40
+ HttpClient --> ErrorHandling[Error Handling]
41
+ HttpClient --> ConnectionPool[Connection Pooling]
42
+ ```
43
+
44
+ ### Key Components:
45
+ - **Client**: Entry point that initializes all resources and manages configuration
46
+ - **HttpClient**: Handles all HTTP communication, retries, and error responses
47
+ - **Base Resource**: Provides common functionality to all resource classes
48
+ - **Resource Classes**: Implement specific API endpoints for each Attio resource type
49
+
50
+ ## Template Method Pattern in Base Class
51
+
52
+ We implemented the Template Method pattern to eliminate code duplication across resources:
53
+
54
+ ```mermaid
55
+ classDiagram
56
+ class Base {
57
+ -connection
58
+ +request(method, path, params)
59
+ #validate_id!(id, resource_name)
60
+ #validate_required_string!(value, field_name)
61
+ #validate_required_hash!(value, field_name)
62
+ #handle_delete_request(connection, path, params)
63
+ }
64
+
65
+ class Comments {
66
+ +list(params)
67
+ +create(data)
68
+ +react(id, emoji)
69
+ +unreact(id, emoji)
70
+ }
71
+
72
+ class Threads {
73
+ +list(params)
74
+ +create(data)
75
+ +add_participant(id, member_id)
76
+ +remove_participant(id, member_id)
77
+ +close(id)
78
+ +reopen(id)
79
+ }
80
+
81
+ class Tasks {
82
+ +list(params)
83
+ +create(data)
84
+ +complete(id, completed_at)
85
+ +uncomplete(id)
86
+ }
87
+
88
+ Base <|-- Comments
89
+ Base <|-- Threads
90
+ Base <|-- Tasks
91
+ Base <|-- Notes
92
+ Base <|-- Records
93
+ Base <|-- Lists
94
+ ```
95
+
96
+ ### Benefits:
97
+ - **Code Reuse**: ~150 lines of duplicated validation code eliminated
98
+ - **Consistency**: Standardized error messages and validation logic
99
+ - **Maintainability**: Changes to common functionality only need to be made once
100
+ - **Extensibility**: New resources can easily inherit common behavior
101
+
102
+ ## DELETE with Body Support
103
+
104
+ A key architectural decision for REST compliance when managing thread participants:
105
+
106
+ ```mermaid
107
+ sequenceDiagram
108
+ participant Client
109
+ participant Threads
110
+ participant Base
111
+ participant HttpClient
112
+ participant API
113
+
114
+ Client->>Threads: remove_participant(id, member_id)
115
+ Threads->>Threads: validate_id!(id)
116
+ Threads->>Threads: validate_required_string!(member_id)
117
+ Threads->>Base: request(:delete, path, params)
118
+ Base->>Base: handle_delete_request
119
+ Base->>HttpClient: delete(path, {member_id: ...})
120
+ HttpClient->>HttpClient: Check if params exist
121
+ alt Has Parameters
122
+ HttpClient->>API: DELETE with JSON body
123
+ Note over HttpClient,API: Content-Type: application/json
124
+ else No Parameters
125
+ HttpClient->>API: DELETE without body
126
+ end
127
+ API-->>HttpClient: 200 OK
128
+ HttpClient-->>Client: Response
129
+ ```
130
+
131
+ ### Implementation Details:
132
+ ```ruby
133
+ # In HttpClient
134
+ def delete(path, params = nil)
135
+ if params
136
+ execute_request(:delete, path, body: params.to_json)
137
+ else
138
+ execute_request(:delete, path)
139
+ end
140
+ end
141
+
142
+ # In Base
143
+ private def handle_delete_request(connection, path, params)
144
+ params.empty? ? connection.delete(path) : connection.delete(path, params)
145
+ end
146
+ ```
147
+
148
+ ## URL Encoding for Special Characters
149
+
150
+ Critical for emoji reactions support and other special characters in URLs:
151
+
152
+ ```mermaid
153
+ flowchart LR
154
+ Input["Emoji Input: 👍"] --> Validate[Validate Required String]
155
+ Validate --> Encode[CGI.escape emoji]
156
+ Encode --> Build[Build URL Path]
157
+ Build --> URL["comments/123/reactions/%F0%9F%91%8D"]
158
+ URL --> Request[HTTP DELETE Request]
159
+ Request --> API[Attio API]
160
+ ```
161
+
162
+ ### Example Implementation:
163
+ ```ruby
164
+ def unreact(id:, emoji:)
165
+ validate_id!(id, "Comment")
166
+ validate_required_string!(emoji, "Emoji")
167
+
168
+ # CGI.escape properly encodes the emoji for URL usage
169
+ request(:delete, "comments/#{id}/reactions/#{CGI.escape(emoji)}")
170
+ end
171
+ ```
172
+
173
+ ### Why CGI.escape?
174
+ - Properly handles UTF-8 characters like emojis
175
+ - Converts special characters to percent-encoded format
176
+ - Ensures URL compatibility across different systems
177
+ - Standard Ruby library method, no additional dependencies
178
+
179
+ ## Collaboration Features Workflow
180
+
181
+ The interconnected nature of collaboration resources in a CRM context:
182
+
183
+ ```mermaid
184
+ graph TB
185
+ Record[Record<br/>Company/Person] --> Thread[Discussion Thread]
186
+ Record --> Task[Task]
187
+ Record --> Note[Note]
188
+
189
+ Thread --> Comment[Comment]
190
+ Comment --> Reaction[Emoji Reaction]
191
+ Thread --> Participants[Thread Participants]
192
+ Thread --> Status[Thread Status<br/>Open/Closed]
193
+
194
+ Task --> Assignment[Task Assignment]
195
+ Task --> DueDate[Due Date]
196
+ Task --> Completion[Completion Status]
197
+
198
+ Note --> Title[Note Title]
199
+ Note --> Content[Rich Text Content]
200
+ Note --> Timestamps[Created/Updated]
201
+
202
+ style Record fill:#f9f,stroke:#333,stroke-width:2px
203
+ style Thread fill:#bbf,stroke:#333,stroke-width:2px
204
+ style Task fill:#bfb,stroke:#333,stroke-width:2px
205
+ style Note fill:#ffb,stroke:#333,stroke-width:2px
206
+ ```
207
+
208
+ ### Resource Relationships:
209
+ - **Records** (Companies/People) serve as parent objects for collaboration features
210
+ - **Threads** enable team discussions with participant management
211
+ - **Comments** support rich text and emoji reactions within threads
212
+ - **Tasks** track actionable items with assignments and due dates
213
+ - **Notes** capture meeting notes and important information
214
+
215
+ ## Error Handling Strategy
216
+
217
+ Comprehensive error handling with specific exception types and retry logic:
218
+
219
+ ```mermaid
220
+ flowchart TD
221
+ Request[API Request] --> Response{Response Status}
222
+ Response -->|200-299| Success[Parse & Return Data]
223
+ Response -->|400| Validation[ValidationError]
224
+ Response -->|401| Auth[AuthenticationError]
225
+ Response -->|404| NotFound[NotFoundError]
226
+ Response -->|429| RateLimit[RateLimitError]
227
+ Response -->|500+| Server[ServerError]
228
+ Response -->|Other| Generic[Attio::Error]
229
+
230
+ Validation --> Details[Extract Error Details]
231
+ Auth --> Details
232
+ NotFound --> Details
233
+ RateLimit --> Details
234
+ Server --> Details
235
+ Generic --> Details
236
+
237
+ Details --> Retry{Retryable?}
238
+
239
+ Retry -->|Rate Limit| Backoff[Exponential Backoff]
240
+ Retry -->|Server Error| Backoff
241
+ Retry -->|No| Raise[Raise Exception]
242
+
243
+ Backoff --> Wait[Wait Period]
244
+ Wait --> Request
245
+
246
+ Raise --> Client[Client Handles Error]
247
+ ```
248
+
249
+ ### Error Classes:
250
+ ```ruby
251
+ module Attio
252
+ class Error < StandardError; end
253
+ class ValidationError < Error; end
254
+ class AuthenticationError < Error; end
255
+ class NotFoundError < Error; end
256
+ class RateLimitError < Error; end
257
+ class ServerError < Error; end
258
+ end
259
+ ```
260
+
261
+ ### Retry Logic:
262
+ - **Rate Limits**: Automatic retry with exponential backoff
263
+ - **Server Errors**: Configurable retry attempts (default: 3)
264
+ - **Network Errors**: Automatic retry with connection pooling
265
+ - **Client Errors**: No retry, immediate failure
266
+
267
+ ## Testing Strategy
268
+
269
+ Our approach to achieving 100% test coverage with semantic correctness:
270
+
271
+ ```mermaid
272
+ graph LR
273
+ Tests[Test Suite<br/>265 Tests] --> Unit[Unit Tests]
274
+ Tests --> Integration[Integration Mocks]
275
+ Tests --> Edge[Edge Cases]
276
+
277
+ Unit --> Doubles[Instance Doubles<br/>Type Safety]
278
+ Unit --> Stubs[Method Stubs<br/>Behavior Verification]
279
+ Unit --> Assertions[Response Assertions]
280
+
281
+ Integration --> HTTPMocks[HTTP Response Mocks]
282
+ Integration --> ErrorSim[Error Simulation]
283
+ Integration --> Params[Parameter Validation]
284
+
285
+ Edge --> NilValues[Nil/Empty Values]
286
+ Edge --> Special[Special Characters]
287
+ Edge --> Boundary[Boundary Conditions]
288
+
289
+ Coverage[SimpleCov] --> Report[100% Coverage<br/>376/376 Lines]
290
+
291
+ style Tests fill:#9f9,stroke:#333,stroke-width:2px
292
+ style Report fill:#9f9,stroke:#333,stroke-width:2px
293
+ ```
294
+
295
+ ### Testing Principles:
296
+ 1. **Instance Doubles**: Use RSpec's `instance_double` for type safety
297
+ 2. **Semantic Correctness**: Ensure mocks match actual implementation behavior
298
+ 3. **Edge Case Coverage**: Test nil values, empty strings, special characters
299
+ 4. **Error Simulation**: Test all error paths and exception handling
300
+ 5. **Parameter Validation**: Verify both required and optional parameters
301
+
302
+ ### Example Test Pattern:
303
+ ```ruby
304
+ RSpec.describe Attio::Resources::Comments do
305
+ let(:connection) { instance_double(Attio::HttpClient) }
306
+ let(:comments) { described_class.new(connection) }
307
+
308
+ describe "#unreact" do
309
+ it "properly encodes emoji in URL" do
310
+ expect(connection).to receive(:delete)
311
+ .with("comments/123/reactions/%F0%9F%91%8D")
312
+ .and_return({ "success" => true })
313
+
314
+ comments.unreact(id: "123", emoji: "👍")
315
+ end
316
+ end
317
+ end
318
+ ```
319
+
320
+ ## Key Design Decisions Explained
321
+
322
+ ### 1. Base Class Extraction
323
+ **Problem**: Massive code duplication across resource classes (~150 lines per resource)
324
+
325
+ **Solution**: Extract common validation and request handling into Base class
326
+
327
+ **Benefits**:
328
+ - Reduced codebase by ~1,500 lines
329
+ - Standardized error messages
330
+ - Single source of truth for validations
331
+ - Easier to add new resources
332
+
333
+ ### 2. DELETE with Body Support
334
+ **Problem**: Thread participant management requires sending data with DELETE requests
335
+
336
+ **Solution**: Modified HttpClient to optionally accept body parameters for DELETE
337
+
338
+ **Benefits**:
339
+ - REST-compliant participant removal
340
+ - Consistent with other HTTP methods
341
+ - Clean API interface
342
+
343
+ ### 3. URL Encoding Strategy
344
+ **Problem**: Special characters (emojis) in URL paths causing API errors
345
+
346
+ **Solution**: Use `CGI.escape` for proper URL encoding
347
+
348
+ **Benefits**:
349
+ - Full Unicode support
350
+ - Standard library solution
351
+ - Cross-platform compatibility
352
+
353
+ ### 4. Keyword Arguments Correction
354
+ **Problem**: Test mocks used keyword arguments but implementation used positional arguments
355
+
356
+ **Solution**: Corrected all test mocks to use hash as second positional argument
357
+
358
+ **Example**:
359
+ ```ruby
360
+ # Before (incorrect)
361
+ expect(connection).to receive(:get).with("comments", thread_id: "123")
362
+
363
+ # After (correct)
364
+ expect(connection).to receive(:get).with("comments", { thread_id: "123" })
365
+ ```
366
+
367
+ ### 5. Resource Modularity
368
+ **Problem**: Need to support diverse Attio API resources with different requirements
369
+
370
+ **Solution**: Each resource is self-contained with specific validations while inheriting common functionality
371
+
372
+ **Benefits**:
373
+ - Clear separation of concerns
374
+ - Easy to understand each resource
375
+ - Simple to add new endpoints
376
+ - Maintainable and testable
377
+
378
+ ### 6. Comprehensive Error Handling
379
+ **Problem**: Need to handle various API error conditions gracefully
380
+
381
+ **Solution**: Specific error classes with detailed messages and retry logic
382
+
383
+ **Benefits**:
384
+ - Clear error messages for debugging
385
+ - Automatic retry for transient failures
386
+ - Proper error propagation to client code
387
+
388
+ ## Performance Considerations
389
+
390
+ ### Connection Pooling
391
+ - Reuses HTTP connections for better performance
392
+ - Configurable pool size based on usage patterns
393
+ - Automatic connection management
394
+
395
+ ### Request Optimization
396
+ - Batch operations where supported by API
397
+ - Efficient parameter serialization
398
+ - Minimal memory footprint
399
+
400
+ ### Caching Strategy
401
+ - Response caching for read-heavy operations (future enhancement)
402
+ - ETag support for conditional requests (future enhancement)
403
+
404
+ ## Future Enhancements
405
+
406
+ ### Planned Improvements
407
+ 1. **Webhook Support**: Handle Attio webhook events
408
+ 2. **Bulk Operations**: Batch create/update for better performance
409
+ 3. **Async Operations**: Non-blocking API calls for long-running operations
410
+ 4. **Response Caching**: Intelligent caching with cache invalidation
411
+ 5. **Rate Limit Management**: Proactive rate limit handling with queuing
412
+
413
+ ### API Coverage Expansion
414
+ - Custom field types support
415
+ - Advanced query builders
416
+ - Webhook event processing
417
+ - Real-time subscriptions
418
+
419
+ ## Conclusion
420
+
421
+ The Attio Ruby gem architecture prioritizes:
422
+ - **Maintainability**: Clean, DRY code with clear separation of concerns
423
+ - **Reliability**: Comprehensive error handling and retry logic
424
+ - **Usability**: Intuitive API matching Ruby conventions
425
+ - **Testability**: 100% test coverage with semantic correctness
426
+ - **Extensibility**: Easy to add new features and resources
427
+
428
+ This architecture provides a solid foundation for building CRM integrations with Attio while maintaining code quality and developer experience.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- attio (0.1.2)
4
+ attio (0.2.0)
5
5
  typhoeus (~> 1.4)
6
6
 
7
7
  GEM
@@ -21,6 +21,7 @@ GEM
21
21
  ethon (0.16.0)
22
22
  ffi (>= 1.15.0)
23
23
  ffi (1.17.2-arm64-darwin)
24
+ ffi (1.17.2-x86_64-linux-gnu)
24
25
  hashdiff (1.2.0)
25
26
  json (2.13.2)
26
27
  language_server-protocol (3.17.0.5)
@@ -107,6 +108,7 @@ GEM
107
108
 
108
109
  PLATFORMS
109
110
  arm64-darwin-24
111
+ x86_64-linux
110
112
 
111
113
  DEPENDENCIES
112
114
  attio!
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![Test Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen.svg)](https://github.com/idl3/attio/tree/master/spec)
5
5
  [![Documentation](https://img.shields.io/badge/docs-yard-blue.svg)](https://idl3.github.io/attio)
6
6
  [![Gem Version](https://badge.fury.io/rb/attio.svg)](https://badge.fury.io/rb/attio)
7
- [![RSpec](https://img.shields.io/badge/RSpec-147_tests-green.svg)](https://github.com/idl3/attio/tree/master/spec)
7
+ [![RSpec](https://img.shields.io/badge/RSpec-265_tests-green.svg)](https://github.com/idl3/attio/tree/master/spec)
8
8
 
9
9
  Ruby client for the [Attio CRM API](https://developers.attio.com/). This library provides easy access to the Attio API, allowing you to manage records, objects, lists, and more.
10
10
 
@@ -154,6 +154,156 @@ client.records.update(
154
154
 
155
155
  ### Working with Other Resources
156
156
 
157
+ #### Comments
158
+
159
+ ```ruby
160
+ # List comments on a record
161
+ comments = client.comments.list(
162
+ parent_object: 'people',
163
+ parent_record_id: 'person-123'
164
+ )
165
+
166
+ # List comments in a thread
167
+ thread_comments = client.comments.list(thread_id: 'thread-456')
168
+
169
+ # Create a comment on a record
170
+ comment = client.comments.create(
171
+ parent_object: 'people',
172
+ parent_record_id: 'person-123',
173
+ content: 'This is a comment with **markdown** support!'
174
+ )
175
+
176
+ # Create a comment in a thread
177
+ thread_comment = client.comments.create(
178
+ thread_id: 'thread-456',
179
+ content: 'Following up on this discussion'
180
+ )
181
+
182
+ # Update a comment
183
+ updated_comment = client.comments.update(
184
+ id: 'comment-123',
185
+ content: 'Updated comment content'
186
+ )
187
+
188
+ # React to a comment
189
+ client.comments.react(id: 'comment-123', emoji: '👍')
190
+
191
+ # Remove reaction
192
+ client.comments.unreact(id: 'comment-123', emoji: '👍')
193
+
194
+ # Delete a comment
195
+ client.comments.delete(id: 'comment-123')
196
+ ```
197
+
198
+ #### Threads
199
+
200
+ ```ruby
201
+ # List threads on a record
202
+ threads = client.threads.list(
203
+ parent_object: 'companies',
204
+ parent_record_id: 'company-123'
205
+ )
206
+
207
+ # Get a thread with comments
208
+ thread = client.threads.get(id: 'thread-123', include_comments: true)
209
+
210
+ # Create a thread
211
+ thread = client.threads.create(
212
+ parent_object: 'companies',
213
+ parent_record_id: 'company-123',
214
+ title: 'Q4 Planning Discussion',
215
+ description: 'Thread for Q4 planning discussions',
216
+ participant_ids: ['user-1', 'user-2']
217
+ )
218
+
219
+ # Update thread title
220
+ client.threads.update(id: 'thread-123', title: 'Updated Q4 Planning')
221
+
222
+ # Manage participants
223
+ client.threads.add_participants(id: 'thread-123', user_ids: ['user-3', 'user-4'])
224
+ client.threads.remove_participants(id: 'thread-123', user_ids: ['user-2'])
225
+
226
+ # Close and reopen threads
227
+ client.threads.close(id: 'thread-123')
228
+ client.threads.reopen(id: 'thread-123')
229
+
230
+ # Delete a thread
231
+ client.threads.delete(id: 'thread-123')
232
+ ```
233
+
234
+ #### Tasks
235
+
236
+ ```ruby
237
+ # List all tasks
238
+ tasks = client.tasks.list
239
+
240
+ # List tasks with filters
241
+ my_tasks = client.tasks.list(
242
+ assignee_id: 'user-123',
243
+ status: 'pending'
244
+ )
245
+
246
+ # Get a specific task
247
+ task = client.tasks.get(id: 'task-123')
248
+
249
+ # Create a task
250
+ task = client.tasks.create(
251
+ parent_object: 'people',
252
+ parent_record_id: 'person-123',
253
+ title: 'Follow up with customer',
254
+ due_date: '2025-02-01',
255
+ assignee_id: 'user-456'
256
+ )
257
+
258
+ # Update a task
259
+ client.tasks.update(
260
+ id: 'task-123',
261
+ title: 'Updated task title',
262
+ status: 'in_progress'
263
+ )
264
+
265
+ # Complete a task
266
+ client.tasks.complete(id: 'task-123', completed_at: Time.now.iso8601)
267
+
268
+ # Reopen a task
269
+ client.tasks.reopen(id: 'task-123')
270
+
271
+ # Delete a task
272
+ client.tasks.delete(id: 'task-123')
273
+ ```
274
+
275
+ #### Notes
276
+
277
+ ```ruby
278
+ # List notes on a record
279
+ notes = client.notes.list(
280
+ parent_object: 'companies',
281
+ parent_record_id: 'company-123'
282
+ )
283
+
284
+ # Get a specific note
285
+ note = client.notes.get(id: 'note-123')
286
+
287
+ # Create a note
288
+ note = client.notes.create(
289
+ parent_object: 'companies',
290
+ parent_record_id: 'company-123',
291
+ title: 'Meeting Notes - Q4 Planning',
292
+ content: 'Discussed roadmap and resource allocation...',
293
+ tags: ['important', 'quarterly-planning']
294
+ )
295
+
296
+ # Update a note
297
+ client.notes.update(
298
+ id: 'note-123',
299
+ title: 'Updated Meeting Notes',
300
+ content: 'Added action items from discussion'
301
+ )
302
+
303
+ # Delete a note
304
+ client.notes.delete(id: 'note-123')
305
+ ```
306
+
157
307
  #### Objects
158
308
 
159
309
  ```ruby
@@ -240,12 +390,16 @@ end
240
390
 
241
391
  This client supports all major Attio API endpoints:
242
392
 
243
- - ✅ Records (CRUD operations, querying)
393
+ - ✅ Records (CRUD operations, querying with filters and sorting)
244
394
  - ✅ Objects (list, get schema)
245
- - ✅ Lists (list, get entries)
395
+ - ✅ Lists (list, get entries, manage list entries)
246
396
  - ✅ Workspaces (list, get current)
247
397
  - ✅ Attributes (list, create, update)
248
398
  - ✅ Users (list, get current user)
399
+ - ✅ Comments (CRUD operations, reactions on records and threads)
400
+ - ✅ Threads (CRUD operations, participant management, status control)
401
+ - ✅ Tasks (CRUD operations, assignment, completion tracking)
402
+ - ✅ Notes (CRUD operations on records)
249
403
 
250
404
  ## Development
251
405