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
@@ -0,0 +1,183 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Attio
|
4
|
+
module Resources
|
5
|
+
# Deals resource for managing sales opportunities
|
6
|
+
#
|
7
|
+
# @example List all deals
|
8
|
+
# client.deals.list
|
9
|
+
#
|
10
|
+
# @example Create a new deal
|
11
|
+
# client.deals.create(
|
12
|
+
# data: {
|
13
|
+
# name: "Enterprise Contract",
|
14
|
+
# value: 50000,
|
15
|
+
# stage_id: "stage_123",
|
16
|
+
# company_id: "company_456"
|
17
|
+
# }
|
18
|
+
# )
|
19
|
+
#
|
20
|
+
# @example Update deal stage
|
21
|
+
# client.deals.update_stage(id: "deal_123", stage_id: "stage_won")
|
22
|
+
class Deals < Base
|
23
|
+
# List all deals
|
24
|
+
#
|
25
|
+
# @param params [Hash] Optional query parameters
|
26
|
+
# @option params [Hash] :filter Filter conditions
|
27
|
+
# @option params [Array<Hash>] :sorts Sort criteria
|
28
|
+
# @option params [Integer] :limit Maximum number of results
|
29
|
+
# @option params [String] :offset Pagination offset
|
30
|
+
# @return [Hash] The API response
|
31
|
+
def list(params = {})
|
32
|
+
request(:get, "objects/deals/records", params)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Get a specific deal
|
36
|
+
#
|
37
|
+
# @param id [String] The deal ID
|
38
|
+
# @return [Hash] The deal data
|
39
|
+
def get(id:)
|
40
|
+
validate_id!(id, "Deal")
|
41
|
+
request(:get, "objects/deals/records/#{id}")
|
42
|
+
end
|
43
|
+
|
44
|
+
# Create a new deal
|
45
|
+
#
|
46
|
+
# @param data [Hash] The deal data
|
47
|
+
# @option data [String] :name The deal name (required)
|
48
|
+
# @option data [Float] :value The deal value
|
49
|
+
# @option data [String] :stage_id The stage ID
|
50
|
+
# @option data [String] :company_id Associated company ID
|
51
|
+
# @option data [String] :owner_id The owner user ID
|
52
|
+
# @option data [Date] :close_date Expected close date
|
53
|
+
# @option data [String] :currency Currency code (USD, EUR, etc.)
|
54
|
+
# @option data [Float] :probability Win probability (0-100)
|
55
|
+
# @return [Hash] The created deal
|
56
|
+
def create(data:)
|
57
|
+
validate_required_hash!(data, "Data")
|
58
|
+
validate_required_string!(data[:name], "Deal name")
|
59
|
+
|
60
|
+
request(:post, "objects/deals/records", { data: data })
|
61
|
+
end
|
62
|
+
|
63
|
+
# Update a deal
|
64
|
+
#
|
65
|
+
# @param id [String] The deal ID to update
|
66
|
+
# @param data [Hash] The data to update
|
67
|
+
# @return [Hash] The updated deal
|
68
|
+
def update(id:, data:)
|
69
|
+
validate_id!(id, "Deal")
|
70
|
+
validate_required_hash!(data, "Data")
|
71
|
+
|
72
|
+
request(:patch, "objects/deals/records/#{id}", { data: data })
|
73
|
+
end
|
74
|
+
|
75
|
+
# Delete a deal
|
76
|
+
#
|
77
|
+
# @param id [String] The deal ID to delete
|
78
|
+
# @return [Hash] Confirmation of deletion
|
79
|
+
def delete(id:)
|
80
|
+
validate_id!(id, "Deal")
|
81
|
+
request(:delete, "objects/deals/records/#{id}")
|
82
|
+
end
|
83
|
+
|
84
|
+
# Update a deal's stage
|
85
|
+
#
|
86
|
+
# @param id [String] The deal ID
|
87
|
+
# @param stage_id [String] The new stage ID
|
88
|
+
# @return [Hash] The updated deal
|
89
|
+
def update_stage(id:, stage_id:)
|
90
|
+
validate_id!(id, "Deal")
|
91
|
+
validate_required_string!(stage_id, "Stage")
|
92
|
+
|
93
|
+
update(id: id, data: { stage_id: stage_id })
|
94
|
+
end
|
95
|
+
|
96
|
+
# Mark a deal as won
|
97
|
+
#
|
98
|
+
# @param id [String] The deal ID
|
99
|
+
# @param won_date [Date, String] The date the deal was won (defaults to today)
|
100
|
+
# @param actual_value [Float] The actual value (optional, defaults to deal value)
|
101
|
+
# @return [Hash] The updated deal
|
102
|
+
def mark_won(id:, won_date: nil, actual_value: nil)
|
103
|
+
validate_id!(id, "Deal")
|
104
|
+
|
105
|
+
data = { status: "won" }
|
106
|
+
data[:won_date] = won_date if won_date
|
107
|
+
data[:actual_value] = actual_value if actual_value
|
108
|
+
|
109
|
+
update(id: id, data: data)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Mark a deal as lost
|
113
|
+
#
|
114
|
+
# @param id [String] The deal ID
|
115
|
+
# @param lost_reason [String] The reason for losing the deal
|
116
|
+
# @param lost_date [Date, String] The date the deal was lost (defaults to today)
|
117
|
+
# @return [Hash] The updated deal
|
118
|
+
def mark_lost(id:, lost_reason: nil, lost_date: nil)
|
119
|
+
validate_id!(id, "Deal")
|
120
|
+
|
121
|
+
data = { status: "lost" }
|
122
|
+
data[:lost_reason] = lost_reason if lost_reason
|
123
|
+
data[:lost_date] = lost_date if lost_date
|
124
|
+
|
125
|
+
update(id: id, data: data)
|
126
|
+
end
|
127
|
+
|
128
|
+
# List deals by stage
|
129
|
+
#
|
130
|
+
# @param stage_id [String] The stage ID to filter by
|
131
|
+
# @param params [Hash] Additional query parameters
|
132
|
+
# @return [Hash] Deals in the specified stage
|
133
|
+
def list_by_stage(stage_id:, params: {})
|
134
|
+
validate_required_string!(stage_id, "Stage")
|
135
|
+
|
136
|
+
filter = { stage_id: { "$eq" => stage_id } }
|
137
|
+
merged_params = params.merge(filter: filter)
|
138
|
+
list(merged_params)
|
139
|
+
end
|
140
|
+
|
141
|
+
# List deals by company
|
142
|
+
#
|
143
|
+
# @param company_id [String] The company ID to filter by
|
144
|
+
# @param params [Hash] Additional query parameters
|
145
|
+
# @return [Hash] Deals for the specified company
|
146
|
+
def list_by_company(company_id:, params: {})
|
147
|
+
validate_required_string!(company_id, "Company")
|
148
|
+
|
149
|
+
filter = { company_id: { "$eq" => company_id } }
|
150
|
+
merged_params = params.merge(filter: filter)
|
151
|
+
list(merged_params)
|
152
|
+
end
|
153
|
+
|
154
|
+
# List deals by owner
|
155
|
+
#
|
156
|
+
# @param owner_id [String] The owner user ID to filter by
|
157
|
+
# @param params [Hash] Additional query parameters
|
158
|
+
# @return [Hash] Deals owned by the specified user
|
159
|
+
def list_by_owner(owner_id:, params: {})
|
160
|
+
validate_required_string!(owner_id, "Owner")
|
161
|
+
|
162
|
+
filter = { owner_id: { "$eq" => owner_id } }
|
163
|
+
merged_params = params.merge(filter: filter)
|
164
|
+
list(merged_params)
|
165
|
+
end
|
166
|
+
|
167
|
+
# Calculate pipeline value
|
168
|
+
#
|
169
|
+
# @param stage_id [String] Optional stage ID to filter by
|
170
|
+
# @param owner_id [String] Optional owner ID to filter by
|
171
|
+
# @return [Hash] Pipeline statistics including total value, count, and average
|
172
|
+
def pipeline_value(stage_id: nil, owner_id: nil)
|
173
|
+
params = { filter: {} }
|
174
|
+
params[:filter][:stage_id] = { "$eq" => stage_id } if stage_id
|
175
|
+
params[:filter][:owner_id] = { "$eq" => owner_id } if owner_id
|
176
|
+
|
177
|
+
# This would typically be a specialized endpoint, but we'll use list
|
178
|
+
# and let the client calculate the statistics
|
179
|
+
list(params)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Attio
|
4
|
+
module Resources
|
5
|
+
# Meta resource for API metadata and identification
|
6
|
+
#
|
7
|
+
# @example Identify the current API key
|
8
|
+
# client.meta.identify
|
9
|
+
# # => { "workspace" => { "id" => "...", "name" => "..." }, "user" => { ... } }
|
10
|
+
#
|
11
|
+
# @example Get API status
|
12
|
+
# client.meta.status
|
13
|
+
# # => { "status" => "operational", "version" => "v2" }
|
14
|
+
class Meta < Base
|
15
|
+
# Identify the current API key and get workspace/user information
|
16
|
+
#
|
17
|
+
# @return [Hash] Information about the authenticated workspace and user
|
18
|
+
def identify
|
19
|
+
request(:get, "meta/identify")
|
20
|
+
end
|
21
|
+
|
22
|
+
# Get API status and version information
|
23
|
+
#
|
24
|
+
# @return [Hash] API status and version details
|
25
|
+
def status
|
26
|
+
request(:get, "meta/status")
|
27
|
+
end
|
28
|
+
|
29
|
+
# Get rate limit information for the current API key
|
30
|
+
#
|
31
|
+
# @return [Hash] Current rate limit status
|
32
|
+
def rate_limits
|
33
|
+
request(:get, "meta/rate_limits")
|
34
|
+
end
|
35
|
+
|
36
|
+
# Get workspace configuration and settings
|
37
|
+
#
|
38
|
+
# @return [Hash] Workspace configuration details
|
39
|
+
def workspace_config
|
40
|
+
request(:get, "meta/workspace_config")
|
41
|
+
end
|
42
|
+
|
43
|
+
# Validate an API key without making changes
|
44
|
+
#
|
45
|
+
# @return [Hash] Validation result with key permissions
|
46
|
+
def validate_key
|
47
|
+
request(:post, "meta/validate", {})
|
48
|
+
end
|
49
|
+
|
50
|
+
# Get available API endpoints and their documentation
|
51
|
+
#
|
52
|
+
# @return [Hash] List of available endpoints with descriptions
|
53
|
+
def endpoints
|
54
|
+
request(:get, "meta/endpoints")
|
55
|
+
end
|
56
|
+
|
57
|
+
# Get workspace usage statistics
|
58
|
+
#
|
59
|
+
# @return [Hash] Usage statistics including record counts, API calls, etc.
|
60
|
+
def usage_stats
|
61
|
+
request(:get, "meta/usage")
|
62
|
+
end
|
63
|
+
|
64
|
+
# Get feature flags and capabilities for the workspace
|
65
|
+
#
|
66
|
+
# @return [Hash] Enabled features and capabilities
|
67
|
+
def features
|
68
|
+
request(:get, "meta/features")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Attio
|
4
|
+
module Resources
|
5
|
+
# Workspace Members resource for managing workspace member access
|
6
|
+
#
|
7
|
+
# @example List all workspace members
|
8
|
+
# client.workspace_members.list
|
9
|
+
#
|
10
|
+
# @example Get a specific member
|
11
|
+
# client.workspace_members.get(member_id: "user_123")
|
12
|
+
#
|
13
|
+
# @example Invite a new member
|
14
|
+
# client.workspace_members.invite(
|
15
|
+
# email: "new.member@example.com",
|
16
|
+
# role: "member"
|
17
|
+
# )
|
18
|
+
class WorkspaceMembers < Base
|
19
|
+
# List all workspace members
|
20
|
+
#
|
21
|
+
# @param params [Hash] Optional query parameters
|
22
|
+
# @option params [Integer] :limit Maximum number of results
|
23
|
+
# @option params [String] :offset Pagination offset
|
24
|
+
# @return [Hash] The API response
|
25
|
+
def list(params = {})
|
26
|
+
request(:get, "workspace_members", params)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Get a specific workspace member
|
30
|
+
#
|
31
|
+
# @param member_id [String] The member ID
|
32
|
+
# @return [Hash] The member data
|
33
|
+
def get(member_id:)
|
34
|
+
validate_id!(member_id, "Member")
|
35
|
+
request(:get, "workspace_members/#{member_id}")
|
36
|
+
end
|
37
|
+
|
38
|
+
# Invite a new member to the workspace
|
39
|
+
#
|
40
|
+
# @param email [String] The email address to invite
|
41
|
+
# @param role [String] The role to assign (admin, member, guest)
|
42
|
+
# @param data [Hash] Additional member data
|
43
|
+
# @return [Hash] The created invitation
|
44
|
+
def invite(email:, role: "member", data: {})
|
45
|
+
validate_required_string!(email, "Email")
|
46
|
+
validate_required_string!(role, "Role")
|
47
|
+
|
48
|
+
raise ArgumentError, "Role must be one of: admin, member, guest" unless %w[admin member guest].include?(role)
|
49
|
+
|
50
|
+
body = data.merge(email: email, role: role)
|
51
|
+
request(:post, "workspace_members/invitations", body)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Update a workspace member's role or permissions
|
55
|
+
#
|
56
|
+
# @param member_id [String] The member ID to update
|
57
|
+
# @param data [Hash] The data to update
|
58
|
+
# @option data [String] :role The new role
|
59
|
+
# @option data [Hash] :permissions Custom permissions
|
60
|
+
# @return [Hash] The updated member
|
61
|
+
def update(member_id:, data:)
|
62
|
+
validate_id!(member_id, "Member")
|
63
|
+
validate_required_hash!(data, "Data")
|
64
|
+
|
65
|
+
request(:patch, "workspace_members/#{member_id}", data)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Remove a member from the workspace
|
69
|
+
#
|
70
|
+
# @param member_id [String] The member ID to remove
|
71
|
+
# @return [Hash] Confirmation of removal
|
72
|
+
def remove(member_id:)
|
73
|
+
validate_id!(member_id, "Member")
|
74
|
+
request(:delete, "workspace_members/#{member_id}")
|
75
|
+
end
|
76
|
+
|
77
|
+
# Accept a workspace invitation
|
78
|
+
#
|
79
|
+
# @param invitation_token [String] The invitation token
|
80
|
+
# @return [Hash] The workspace member data
|
81
|
+
def accept_invitation(invitation_token:)
|
82
|
+
validate_required_string!(invitation_token, "Invitation token")
|
83
|
+
request(:post, "workspace_members/invitations/#{invitation_token}/accept")
|
84
|
+
end
|
85
|
+
|
86
|
+
# Resend an invitation
|
87
|
+
#
|
88
|
+
# @param member_id [String] The member ID with pending invitation
|
89
|
+
# @return [Hash] Confirmation of resent invitation
|
90
|
+
def resend_invitation(member_id:)
|
91
|
+
validate_id!(member_id, "Member")
|
92
|
+
request(:post, "workspace_members/#{member_id}/resend_invitation")
|
93
|
+
end
|
94
|
+
|
95
|
+
# Get current member (self)
|
96
|
+
#
|
97
|
+
# @return [Hash] The current authenticated member's data
|
98
|
+
def me
|
99
|
+
request(:get, "workspace_members/me")
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/lib/attio/version.rb
CHANGED
data/lib/attio.rb
CHANGED
@@ -18,6 +18,11 @@ require "attio/resources/notes"
|
|
18
18
|
require "attio/resources/tasks"
|
19
19
|
require "attio/resources/comments"
|
20
20
|
require "attio/resources/threads"
|
21
|
+
require "attio/resources/workspace_members"
|
22
|
+
require "attio/resources/deals"
|
23
|
+
require "attio/resources/meta"
|
24
|
+
require "attio/resources/bulk"
|
25
|
+
require "attio/rate_limiter"
|
21
26
|
|
22
27
|
# The main Attio module provides access to the Attio API client.
|
23
28
|
#
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ernest Sim
|
@@ -48,6 +48,7 @@ files:
|
|
48
48
|
- ".rubocop.yml"
|
49
49
|
- ".yardopts"
|
50
50
|
- CHANGELOG.md
|
51
|
+
- CLAUDE.md
|
51
52
|
- CODE_OF_CONDUCT.md
|
52
53
|
- CONCEPTS.md
|
53
54
|
- CONTRIBUTING.md
|
@@ -114,16 +115,21 @@ files:
|
|
114
115
|
- lib/attio/errors.rb
|
115
116
|
- lib/attio/http_client.rb
|
116
117
|
- lib/attio/logger.rb
|
118
|
+
- lib/attio/rate_limiter.rb
|
117
119
|
- lib/attio/resources/attributes.rb
|
118
120
|
- lib/attio/resources/base.rb
|
121
|
+
- lib/attio/resources/bulk.rb
|
119
122
|
- lib/attio/resources/comments.rb
|
123
|
+
- lib/attio/resources/deals.rb
|
120
124
|
- lib/attio/resources/lists.rb
|
125
|
+
- lib/attio/resources/meta.rb
|
121
126
|
- lib/attio/resources/notes.rb
|
122
127
|
- lib/attio/resources/objects.rb
|
123
128
|
- lib/attio/resources/records.rb
|
124
129
|
- lib/attio/resources/tasks.rb
|
125
130
|
- lib/attio/resources/threads.rb
|
126
131
|
- lib/attio/resources/users.rb
|
132
|
+
- lib/attio/resources/workspace_members.rb
|
127
133
|
- lib/attio/resources/workspaces.rb
|
128
134
|
- lib/attio/retry_handler.rb
|
129
135
|
- lib/attio/version.rb
|