attio 0.2.0 → 0.3.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 +4 -4
- data/.github/workflows/release.yml +1 -45
- data/CHANGELOG.md +36 -0
- data/CLAUDE.md +360 -0
- data/Gemfile.lock +1 -1
- data/README.md +154 -11
- data/lib/attio/client.rb +50 -0
- data/lib/attio/errors.rb +30 -2
- data/lib/attio/http_client.rb +4 -0
- data/lib/attio/rate_limiter.rb +212 -0
- data/lib/attio/resources/base.rb +17 -2
- data/lib/attio/resources/bulk.rb +290 -0
- data/lib/attio/resources/deals.rb +183 -0
- data/lib/attio/resources/meta.rb +72 -0
- data/lib/attio/resources/workspace_members.rb +103 -0
- data/lib/attio/version.rb +1 -1
- data/lib/attio.rb +5 -0
- metadata +7 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2af7d69dcfda391c606d9d55ea6acfa950a2bce2271d6f867acdfa9b40ce269
|
4
|
+
data.tar.gz: f8387f9aaf8779af723ebe6a30279a0a8affb639e27aad4089f8353a3687f14a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11fbb524075e860b1c28e01f11b67ae6c28719f4e54a904fe026feabfd41f3f81ed9fe94b13a32228eb377f7125226fca92eb4cb031b260d283d3a03f67c0c8b
|
7
|
+
data.tar.gz: 4f813c14359415e5ca478ca429e7624798f778d040e2d317a50a4538cc4feffdea0b5b65e9cbe7c98a76a1124cd600bbf5914e0f365bde3dfbd514d6ec0b7414
|
@@ -114,48 +114,4 @@ jobs:
|
|
114
114
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
115
115
|
asset_path: ${{ env.GEM_FILE }}
|
116
116
|
asset_name: ${{ env.GEM_FILE }}
|
117
|
-
asset_content_type: application/x-tar
|
118
|
-
|
119
|
-
update-docs:
|
120
|
-
needs: [test, build-and-publish]
|
121
|
-
runs-on: ubuntu-latest
|
122
|
-
permissions:
|
123
|
-
contents: write
|
124
|
-
|
125
|
-
steps:
|
126
|
-
- uses: actions/checkout@v4
|
127
|
-
with:
|
128
|
-
token: ${{ secrets.GITHUB_TOKEN }}
|
129
|
-
ref: main
|
130
|
-
|
131
|
-
- name: Set up Ruby
|
132
|
-
uses: ruby/setup-ruby@v1
|
133
|
-
with:
|
134
|
-
ruby-version: '3.4'
|
135
|
-
bundler-cache: false
|
136
|
-
|
137
|
-
- name: Install dependencies
|
138
|
-
run: |
|
139
|
-
gem install bundler -v 2.4.22
|
140
|
-
bundle config set --local deployment false
|
141
|
-
bundle install
|
142
|
-
|
143
|
-
- name: Extract version from tag
|
144
|
-
id: version
|
145
|
-
run: echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
|
146
|
-
|
147
|
-
- name: Generate documentation
|
148
|
-
run: |
|
149
|
-
bundle exec rake docs:generate
|
150
|
-
|
151
|
-
- name: Commit and push documentation
|
152
|
-
run: |
|
153
|
-
git config --local user.email "action@github.com"
|
154
|
-
git config --local user.name "GitHub Action"
|
155
|
-
git add docs/
|
156
|
-
if ! git diff --staged --quiet; then
|
157
|
-
git commit -m "Update documentation for release ${{ steps.version.outputs.version }}"
|
158
|
-
git push
|
159
|
-
else
|
160
|
-
echo "No documentation changes to commit"
|
161
|
-
fi
|
117
|
+
asset_content_type: application/x-tar
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,42 @@ 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
|
+
## [0.3.0] - 2025-08-11
|
9
|
+
|
10
|
+
### Added
|
11
|
+
- **Workspace Members** resource for managing workspace access and permissions
|
12
|
+
- **Deals** resource for sales pipeline management with win/loss tracking
|
13
|
+
- **Meta API** resource for workspace identification and usage statistics
|
14
|
+
- **Bulk Operations** with automatic batching (100 records per batch)
|
15
|
+
- **Rate Limiting** with exponential backoff and request queuing
|
16
|
+
- **SSL/TLS verification** for enhanced security
|
17
|
+
- **Enhanced error classes** with proper attributes (retry_after for RateLimitError)
|
18
|
+
- **Thread-safe rate limiter** implementation
|
19
|
+
- Comprehensive architectural documentation in CONCEPTS.md
|
20
|
+
- Development guidelines in CLAUDE.md
|
21
|
+
- 116 new tests (392 total, up from 265)
|
22
|
+
|
23
|
+
### Improved
|
24
|
+
- **Security**: Added explicit SSL verification and disabled automatic redirects
|
25
|
+
- **Thread Safety**: Fixed race conditions in rate limiter
|
26
|
+
- **Code Quality**: Achieved 0 RuboCop violations (previously 6)
|
27
|
+
- **Test Coverage**: 99.86% (718/719 lines)
|
28
|
+
- **Performance**: Optimized bulk operations with efficient batching
|
29
|
+
- **Validation**: Enhanced input validation to prevent injection attacks
|
30
|
+
- **Documentation**: Updated README with comprehensive API coverage
|
31
|
+
|
32
|
+
### Fixed
|
33
|
+
- Thread safety issues in RateLimiter#update_from_headers
|
34
|
+
- Complex validation methods refactored to reduce cyclomatic complexity
|
35
|
+
- validate_required_hash now properly handles nil values
|
36
|
+
- Removed unused api_key parameter from Meta#validate_key
|
37
|
+
- Fixed conditional validation in Deals#create
|
38
|
+
|
39
|
+
### Changed
|
40
|
+
- **BREAKING**: Error messages for nil validation now say "must be a hash" instead of "is required"
|
41
|
+
- RateLimitMiddleware simplified to avoid private method calls
|
42
|
+
- Base resource class validation methods extracted for reusability
|
43
|
+
|
8
44
|
## [0.2.0] - 2025-08-11
|
9
45
|
|
10
46
|
### Added
|
data/CLAUDE.md
ADDED
@@ -0,0 +1,360 @@
|
|
1
|
+
# Claude Development Guidelines for Attio Ruby Gem
|
2
|
+
|
3
|
+
This document contains important guidelines for Claude (or any AI assistant) when working on the Attio Ruby gem. Following these guidelines ensures high-quality, consistent, and production-ready code.
|
4
|
+
|
5
|
+
## Pre-Release Checklist
|
6
|
+
|
7
|
+
**IMPORTANT**: Before creating any release tag or pushing to master, ALWAYS complete this checklist:
|
8
|
+
|
9
|
+
### 1. Code Quality
|
10
|
+
- [ ] Run RuboCop and fix all violations: `bundle exec rubocop -A`
|
11
|
+
- [ ] Ensure no RuboCop offenses remain
|
12
|
+
- [ ] Run all tests: `bundle exec rspec`
|
13
|
+
- [ ] Verify 100% test coverage: Check SimpleCov output
|
14
|
+
- [ ] Update version in `lib/attio/version.rb`
|
15
|
+
- [ ] Update CHANGELOG.md with release date
|
16
|
+
|
17
|
+
### 2. Testing Commands
|
18
|
+
```bash
|
19
|
+
# Run all tests
|
20
|
+
bundle exec rspec
|
21
|
+
|
22
|
+
# Run tests with coverage report
|
23
|
+
COVERAGE=true bundle exec rspec
|
24
|
+
|
25
|
+
# Run specific test file
|
26
|
+
bundle exec rspec spec/attio/resources/comments_spec.rb
|
27
|
+
|
28
|
+
# Run RuboCop
|
29
|
+
bundle exec rubocop
|
30
|
+
|
31
|
+
# Auto-fix RuboCop violations
|
32
|
+
bundle exec rubocop -A
|
33
|
+
|
34
|
+
# Check for outdated gems
|
35
|
+
bundle outdated
|
36
|
+
```
|
37
|
+
|
38
|
+
### 3. Documentation
|
39
|
+
- [ ] Update README.md with new features
|
40
|
+
- [ ] Add/update YARD documentation for new methods
|
41
|
+
- [ ] Create example files for new features
|
42
|
+
- [ ] Update API coverage section in README
|
43
|
+
- [ ] Ensure all public methods have proper documentation
|
44
|
+
|
45
|
+
### 4. Git Commit Standards
|
46
|
+
|
47
|
+
#### Commit Message Format
|
48
|
+
```
|
49
|
+
<type>: <subject>
|
50
|
+
|
51
|
+
<body>
|
52
|
+
|
53
|
+
🤖 Generated with [Claude Code](https://claude.ai/code)
|
54
|
+
|
55
|
+
Co-Authored-By: Claude <noreply@anthropic.com>
|
56
|
+
```
|
57
|
+
|
58
|
+
#### Commit Types
|
59
|
+
- `feat`: New feature
|
60
|
+
- `fix`: Bug fix
|
61
|
+
- `docs`: Documentation only changes
|
62
|
+
- `style`: Code style changes (formatting, missing semi-colons, etc)
|
63
|
+
- `refactor`: Code refactoring
|
64
|
+
- `test`: Adding or updating tests
|
65
|
+
- `chore`: Maintenance tasks
|
66
|
+
- `ci`: CI/CD changes
|
67
|
+
|
68
|
+
#### Examples
|
69
|
+
```bash
|
70
|
+
git commit -m "feat: Add Comments resource with emoji reactions
|
71
|
+
|
72
|
+
- Implement full CRUD operations for comments
|
73
|
+
- Add support for emoji reactions with proper URL encoding
|
74
|
+
- Include comprehensive test coverage
|
75
|
+
|
76
|
+
🤖 Generated with [Claude Code](https://claude.ai/code)
|
77
|
+
|
78
|
+
Co-Authored-By: Claude <noreply@anthropic.com>"
|
79
|
+
```
|
80
|
+
|
81
|
+
## Development Guidelines
|
82
|
+
|
83
|
+
### 1. Test-Driven Development (TDD)
|
84
|
+
- Write tests FIRST before implementing features
|
85
|
+
- Ensure semantic correctness in all tests
|
86
|
+
- Use `instance_double` for type safety in RSpec
|
87
|
+
- Mock external API calls appropriately
|
88
|
+
- Achieve and maintain 100% test coverage
|
89
|
+
|
90
|
+
### 2. Code Organization
|
91
|
+
```
|
92
|
+
lib/attio/
|
93
|
+
├── resources/
|
94
|
+
│ ├── base.rb # Base class with common functionality
|
95
|
+
│ ├── comments.rb # Resource-specific implementation
|
96
|
+
│ └── ...
|
97
|
+
├── client.rb # Main client class
|
98
|
+
├── http_client.rb # HTTP handling
|
99
|
+
├── errors.rb # Error classes
|
100
|
+
└── version.rb # Version constant
|
101
|
+
|
102
|
+
spec/attio/
|
103
|
+
├── resources/ # Resource-specific tests
|
104
|
+
├── client_spec.rb # Client tests
|
105
|
+
└── http_client_spec.rb # HTTP client tests
|
106
|
+
```
|
107
|
+
|
108
|
+
### 3. Resource Implementation Pattern
|
109
|
+
|
110
|
+
When implementing a new resource:
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
# lib/attio/resources/new_resource.rb
|
114
|
+
module Attio
|
115
|
+
module Resources
|
116
|
+
class NewResource < Base
|
117
|
+
def list(params = {})
|
118
|
+
# Implementation
|
119
|
+
end
|
120
|
+
|
121
|
+
def get(id:)
|
122
|
+
validate_id!(id, "NewResource")
|
123
|
+
# Implementation
|
124
|
+
end
|
125
|
+
|
126
|
+
def create(data:)
|
127
|
+
validate_required_hash!(data, "Data")
|
128
|
+
# Implementation
|
129
|
+
end
|
130
|
+
|
131
|
+
def update(id:, data:)
|
132
|
+
validate_id!(id, "NewResource")
|
133
|
+
validate_required_hash!(data, "Data")
|
134
|
+
# Implementation
|
135
|
+
end
|
136
|
+
|
137
|
+
def delete(id:)
|
138
|
+
validate_id!(id, "NewResource")
|
139
|
+
# Implementation
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
```
|
145
|
+
|
146
|
+
### 4. Testing Pattern
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
# spec/attio/resources/new_resource_spec.rb
|
150
|
+
RSpec.describe Attio::Resources::NewResource do
|
151
|
+
let(:connection) { instance_double(Attio::HttpClient) }
|
152
|
+
let(:resource) { described_class.new(connection) }
|
153
|
+
|
154
|
+
describe "#list" do
|
155
|
+
it "lists all resources" do
|
156
|
+
expect(connection).to receive(:get)
|
157
|
+
.with("new_resources", {})
|
158
|
+
.and_return({ "data" => [] })
|
159
|
+
|
160
|
+
result = resource.list
|
161
|
+
expect(result).to eq({ "data" => [] })
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# Test all methods with edge cases
|
166
|
+
end
|
167
|
+
```
|
168
|
+
|
169
|
+
### 5. Error Handling
|
170
|
+
- Always validate required parameters
|
171
|
+
- Use specific error classes (ValidationError, NotFoundError, etc.)
|
172
|
+
- Provide clear, actionable error messages
|
173
|
+
- Include parameter names in error messages
|
174
|
+
|
175
|
+
### 6. API Design Principles
|
176
|
+
- Use keyword arguments for clarity
|
177
|
+
- Support optional parameters with defaults
|
178
|
+
- Return full API response (don't extract data)
|
179
|
+
- Maintain consistency across all resources
|
180
|
+
|
181
|
+
## Common Pitfalls to Avoid
|
182
|
+
|
183
|
+
### 1. Test Mocks
|
184
|
+
```ruby
|
185
|
+
# WRONG - Using keyword arguments in mock
|
186
|
+
expect(connection).to receive(:get).with("comments", thread_id: "123")
|
187
|
+
|
188
|
+
# CORRECT - Using hash as second argument
|
189
|
+
expect(connection).to receive(:get).with("comments", { thread_id: "123" })
|
190
|
+
```
|
191
|
+
|
192
|
+
### 2. URL Encoding
|
193
|
+
```ruby
|
194
|
+
# WRONG - Direct string interpolation
|
195
|
+
"comments/#{id}/reactions/#{emoji}"
|
196
|
+
|
197
|
+
# CORRECT - Proper encoding for special characters
|
198
|
+
"comments/#{id}/reactions/#{CGI.escape(emoji)}"
|
199
|
+
```
|
200
|
+
|
201
|
+
### 3. Validation
|
202
|
+
```ruby
|
203
|
+
# WRONG - No validation
|
204
|
+
def get(id:)
|
205
|
+
request(:get, "resources/#{id}")
|
206
|
+
end
|
207
|
+
|
208
|
+
# CORRECT - Validate required parameters
|
209
|
+
def get(id:)
|
210
|
+
validate_id!(id, "Resource")
|
211
|
+
request(:get, "resources/#{id}")
|
212
|
+
end
|
213
|
+
```
|
214
|
+
|
215
|
+
## Release Process
|
216
|
+
|
217
|
+
### 1. Pre-Release
|
218
|
+
```bash
|
219
|
+
# 1. Ensure all tests pass
|
220
|
+
bundle exec rspec
|
221
|
+
|
222
|
+
# 2. Check RuboCop
|
223
|
+
bundle exec rubocop
|
224
|
+
|
225
|
+
# 3. Update version
|
226
|
+
# Edit lib/attio/version.rb
|
227
|
+
|
228
|
+
# 4. Update CHANGELOG
|
229
|
+
# Add release section with date
|
230
|
+
|
231
|
+
# 5. Commit changes
|
232
|
+
git add -A
|
233
|
+
git commit -m "chore: Prepare release v0.2.0"
|
234
|
+
```
|
235
|
+
|
236
|
+
### 2. Create Release
|
237
|
+
```bash
|
238
|
+
# 1. Push to master
|
239
|
+
git push origin master
|
240
|
+
|
241
|
+
# 2. Create and push tag
|
242
|
+
git tag -a v0.2.0 -m "Release v0.2.0"
|
243
|
+
git push origin v0.2.0
|
244
|
+
```
|
245
|
+
|
246
|
+
### 3. Post-Release
|
247
|
+
The CI/CD pipeline will automatically:
|
248
|
+
- Run tests across Ruby 3.0-3.4
|
249
|
+
- Build the gem
|
250
|
+
- Publish to RubyGems (requires RUBYGEMS_AUTH_TOKEN secret)
|
251
|
+
- Create GitHub release
|
252
|
+
|
253
|
+
## RuboCop Configuration
|
254
|
+
|
255
|
+
Key rules enforced:
|
256
|
+
- Line length: 120 characters
|
257
|
+
- Method length: 20 lines
|
258
|
+
- Class length: 250 lines
|
259
|
+
- Cyclomatic complexity: 10
|
260
|
+
- ABC metric: 17
|
261
|
+
- Use `dig` for nested hash access (except single argument)
|
262
|
+
- Prefer string interpolation over concatenation
|
263
|
+
- Use single quotes unless interpolation needed
|
264
|
+
|
265
|
+
## Environment Setup
|
266
|
+
|
267
|
+
### Ruby Version
|
268
|
+
- Minimum: Ruby 3.0
|
269
|
+
- Recommended: Ruby 3.4
|
270
|
+
- CI tests on: 3.0, 3.1, 3.2, 3.3, 3.4
|
271
|
+
|
272
|
+
### Bundler Version
|
273
|
+
- Use bundler 2.4.22 for compatibility
|
274
|
+
- Set in CI: `gem install bundler -v 2.4.22`
|
275
|
+
|
276
|
+
### Development Dependencies
|
277
|
+
```ruby
|
278
|
+
# Gemfile
|
279
|
+
group :development, :test do
|
280
|
+
gem "rspec", "~> 3.13"
|
281
|
+
gem "rubocop", "~> 1.50"
|
282
|
+
gem "rubocop-rspec", "~> 2.22"
|
283
|
+
gem "simplecov", "~> 0.22"
|
284
|
+
gem "webmock", "~> 3.18"
|
285
|
+
gem "yard", "~> 0.9"
|
286
|
+
end
|
287
|
+
```
|
288
|
+
|
289
|
+
## API Coverage Tracking
|
290
|
+
|
291
|
+
Maintain this list in README.md:
|
292
|
+
|
293
|
+
- [x] Records - Full CRUD
|
294
|
+
- [x] Objects - List, Get
|
295
|
+
- [x] Lists - List, Get, Entries, Create/Delete Entry
|
296
|
+
- [x] Comments - Full CRUD, Reactions
|
297
|
+
- [x] Threads - Full CRUD, Participants, Status
|
298
|
+
- [x] Tasks - Full CRUD, Assignment, Completion
|
299
|
+
- [x] Notes - Full CRUD
|
300
|
+
- [x] Workspaces - List, Get
|
301
|
+
- [x] Attributes - List, Create, Update
|
302
|
+
- [x] Users - List, Get
|
303
|
+
|
304
|
+
## Quality Metrics to Maintain
|
305
|
+
|
306
|
+
- **Test Coverage**: 100%
|
307
|
+
- **Test Count**: 265+ tests
|
308
|
+
- **RuboCop Offenses**: 0
|
309
|
+
- **Documentation Coverage**: 100% for public methods
|
310
|
+
- **Example Coverage**: Example for each major feature
|
311
|
+
|
312
|
+
## Final Reminders
|
313
|
+
|
314
|
+
1. **NEVER** push code with failing tests
|
315
|
+
2. **NEVER** push code with RuboCop violations
|
316
|
+
3. **ALWAYS** update documentation with new features
|
317
|
+
4. **ALWAYS** maintain 100% test coverage
|
318
|
+
5. **ALWAYS** run the full test suite before committing
|
319
|
+
6. **ALWAYS** update the version and CHANGELOG for releases
|
320
|
+
7. **NEVER** create git commits without the co-author attribution
|
321
|
+
|
322
|
+
## Useful Commands Reference
|
323
|
+
|
324
|
+
```bash
|
325
|
+
# Build gem locally
|
326
|
+
gem build attio.gemspec
|
327
|
+
|
328
|
+
# Install gem locally
|
329
|
+
gem install ./attio-0.2.0.gem
|
330
|
+
|
331
|
+
# Test gem in IRB
|
332
|
+
irb -r attio
|
333
|
+
|
334
|
+
# Generate YARD documentation
|
335
|
+
bundle exec yard doc
|
336
|
+
|
337
|
+
# View YARD documentation
|
338
|
+
bundle exec yard server
|
339
|
+
|
340
|
+
# Run specific test with line number
|
341
|
+
bundle exec rspec spec/attio/resources/comments_spec.rb:42
|
342
|
+
|
343
|
+
# Check test coverage details
|
344
|
+
open coverage/index.html
|
345
|
+
|
346
|
+
# List all rake tasks
|
347
|
+
bundle exec rake -T
|
348
|
+
```
|
349
|
+
|
350
|
+
## Contact for Issues
|
351
|
+
|
352
|
+
If you encounter any issues or need clarification:
|
353
|
+
1. Check existing issues on GitHub
|
354
|
+
2. Review test files for usage examples
|
355
|
+
3. Consult the API documentation
|
356
|
+
4. Create a detailed issue with reproduction steps
|
357
|
+
|
358
|
+
---
|
359
|
+
|
360
|
+
**Remember**: Quality over speed. It's better to take time and deliver production-ready code than to rush and create technical debt.
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
[](https://github.com/idl3/attio/tree/master/spec)
|
5
5
|
[](https://idl3.github.io/attio)
|
6
6
|
[](https://badge.fury.io/rb/attio)
|
7
|
-
[](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
|
|
@@ -361,6 +361,137 @@ users = client.users.list
|
|
361
361
|
user = client.users.me
|
362
362
|
```
|
363
363
|
|
364
|
+
### Advanced Features
|
365
|
+
|
366
|
+
#### Workspace Members
|
367
|
+
|
368
|
+
```ruby
|
369
|
+
# List workspace members
|
370
|
+
members = client.workspace_members.list
|
371
|
+
|
372
|
+
# Invite a new member
|
373
|
+
invitation = client.workspace_members.invite(
|
374
|
+
email: 'new.member@example.com',
|
375
|
+
role: 'member' # admin, member, or guest
|
376
|
+
)
|
377
|
+
|
378
|
+
# Update member permissions
|
379
|
+
client.workspace_members.update(
|
380
|
+
member_id: 'user-123',
|
381
|
+
data: { role: 'admin' }
|
382
|
+
)
|
383
|
+
|
384
|
+
# Remove a member
|
385
|
+
client.workspace_members.remove(member_id: 'user-123')
|
386
|
+
```
|
387
|
+
|
388
|
+
#### Deals
|
389
|
+
|
390
|
+
```ruby
|
391
|
+
# List all deals
|
392
|
+
deals = client.deals.list
|
393
|
+
|
394
|
+
# Create a new deal
|
395
|
+
deal = client.deals.create(
|
396
|
+
data: {
|
397
|
+
name: 'Enterprise Contract',
|
398
|
+
value: 50000,
|
399
|
+
stage_id: 'stage-negotiation',
|
400
|
+
company_id: 'company-123'
|
401
|
+
}
|
402
|
+
)
|
403
|
+
|
404
|
+
# Update deal stage
|
405
|
+
client.deals.update_stage(id: 'deal-123', stage_id: 'stage-won')
|
406
|
+
|
407
|
+
# Mark deal as won/lost
|
408
|
+
client.deals.mark_won(id: 'deal-123', won_date: Date.today)
|
409
|
+
client.deals.mark_lost(id: 'deal-123', lost_reason: 'Budget constraints')
|
410
|
+
|
411
|
+
# List deals by various criteria
|
412
|
+
pipeline_deals = client.deals.list_by_stage(stage_id: 'stage-proposal')
|
413
|
+
company_deals = client.deals.list_by_company(company_id: 'company-123')
|
414
|
+
my_deals = client.deals.list_by_owner(owner_id: 'user-456')
|
415
|
+
```
|
416
|
+
|
417
|
+
#### Bulk Operations
|
418
|
+
|
419
|
+
```ruby
|
420
|
+
# Bulk create records
|
421
|
+
results = client.bulk.create_records(
|
422
|
+
object: 'people',
|
423
|
+
records: [
|
424
|
+
{ name: 'John Doe', email: 'john@example.com' },
|
425
|
+
{ name: 'Jane Smith', email: 'jane@example.com' },
|
426
|
+
# ... up to 100 records per batch
|
427
|
+
]
|
428
|
+
)
|
429
|
+
|
430
|
+
# Bulk update records
|
431
|
+
results = client.bulk.update_records(
|
432
|
+
object: 'companies',
|
433
|
+
updates: [
|
434
|
+
{ id: 'company-1', data: { status: 'active' } },
|
435
|
+
{ id: 'company-2', data: { status: 'inactive' } }
|
436
|
+
]
|
437
|
+
)
|
438
|
+
|
439
|
+
# Bulk upsert (create or update based on matching)
|
440
|
+
results = client.bulk.upsert_records(
|
441
|
+
object: 'people',
|
442
|
+
match_attribute: 'email',
|
443
|
+
records: [
|
444
|
+
{ email: 'john@example.com', name: 'John Updated' },
|
445
|
+
{ email: 'new@example.com', name: 'New Person' }
|
446
|
+
]
|
447
|
+
)
|
448
|
+
```
|
449
|
+
|
450
|
+
#### Rate Limiting
|
451
|
+
|
452
|
+
```ruby
|
453
|
+
# Initialize client with custom rate limiter
|
454
|
+
limiter = Attio::RateLimiter.new(
|
455
|
+
max_requests: 100,
|
456
|
+
window_seconds: 60,
|
457
|
+
max_retries: 3
|
458
|
+
)
|
459
|
+
client.rate_limiter = limiter
|
460
|
+
|
461
|
+
# Execute with rate limiting
|
462
|
+
limiter.execute { client.records.list(object: 'people') }
|
463
|
+
|
464
|
+
# Queue requests for later processing
|
465
|
+
limiter.queue_request(priority: 1) { important_operation }
|
466
|
+
limiter.queue_request(priority: 5) { less_important_operation }
|
467
|
+
|
468
|
+
# Process queued requests
|
469
|
+
results = limiter.process_queue(max_per_batch: 10)
|
470
|
+
|
471
|
+
# Check rate limit status
|
472
|
+
status = limiter.status
|
473
|
+
puts "Remaining: #{status[:remaining]}/#{status[:limit]}"
|
474
|
+
```
|
475
|
+
|
476
|
+
#### Meta API
|
477
|
+
|
478
|
+
```ruby
|
479
|
+
# Identify current workspace and user
|
480
|
+
info = client.meta.identify
|
481
|
+
puts "Workspace: #{info['workspace']['name']}"
|
482
|
+
puts "User: #{info['user']['email']}"
|
483
|
+
|
484
|
+
# Validate API key
|
485
|
+
validation = client.meta.validate_key
|
486
|
+
puts "Valid: #{validation['valid']}"
|
487
|
+
puts "Permissions: #{validation['permissions']}"
|
488
|
+
|
489
|
+
# Get usage statistics
|
490
|
+
usage = client.meta.usage_stats
|
491
|
+
puts "Records: #{usage['records']['total']}"
|
492
|
+
puts "API calls today: #{usage['api_calls']['today']}"
|
493
|
+
```
|
494
|
+
|
364
495
|
### Error Handling
|
365
496
|
|
366
497
|
The client will raise appropriate exceptions for different error conditions:
|
@@ -390,16 +521,28 @@ end
|
|
390
521
|
|
391
522
|
This client supports all major Attio API endpoints:
|
392
523
|
|
393
|
-
|
394
|
-
- ✅
|
395
|
-
- ✅
|
396
|
-
- ✅
|
397
|
-
- ✅ Attributes
|
398
|
-
- ✅
|
399
|
-
- ✅
|
400
|
-
|
401
|
-
|
402
|
-
- ✅
|
524
|
+
### Core Resources
|
525
|
+
- ✅ **Records** - Full CRUD operations, querying with filters and sorting
|
526
|
+
- ✅ **Objects** - List, get schema information
|
527
|
+
- ✅ **Lists** - List, get entries, manage list entries
|
528
|
+
- ✅ **Attributes** - List, create, update custom attributes
|
529
|
+
- ✅ **Workspaces** - List, get current workspace
|
530
|
+
- ✅ **Users** - List, get current user
|
531
|
+
|
532
|
+
### Collaboration Features
|
533
|
+
- ✅ **Comments** - CRUD operations, emoji reactions on records and threads
|
534
|
+
- ✅ **Threads** - CRUD operations, participant management, status control
|
535
|
+
- ✅ **Tasks** - CRUD operations, assignment, completion tracking
|
536
|
+
- ✅ **Notes** - CRUD operations on records
|
537
|
+
|
538
|
+
### Sales & CRM
|
539
|
+
- ✅ **Deals** - Pipeline management, stage tracking, win/loss tracking
|
540
|
+
- ✅ **Workspace Members** - Member management, invitations, permissions
|
541
|
+
|
542
|
+
### Advanced Features
|
543
|
+
- ✅ **Bulk Operations** - Batch create/update/delete with automatic batching
|
544
|
+
- ✅ **Rate Limiting** - Intelligent retry with exponential backoff and request queuing
|
545
|
+
- ✅ **Meta API** - Identify workspace, validate API keys, get usage stats
|
403
546
|
|
404
547
|
## Development
|
405
548
|
|