attio 0.1.3 → 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.
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "attio"
5
+ require "time"
6
+
7
+ # Example: Collaboration Features (Comments, Threads, Tasks, Notes)
8
+ #
9
+ # This example demonstrates how to use Attio's collaboration features
10
+ # to manage team communication and tasks on customer records.
11
+
12
+ # Initialize the client
13
+ client = Attio.client(api_key: ENV.fetch("ATTIO_API_KEY"))
14
+
15
+ puts "Attio Collaboration Features Example"
16
+ puts "=" * 40
17
+
18
+ # 1. Create a company and contact for our example
19
+ puts "\n1. Creating sample company and contact..."
20
+ company = client.records.create(
21
+ object: "companies",
22
+ data: {
23
+ name: "TechCorp Solutions",
24
+ domain: "techcorp.example.com",
25
+ industry: "Software Development",
26
+ }
27
+ )
28
+ puts " ✓ Created company: #{company.dig('data', 'values', 'name', 0, 'value')}"
29
+
30
+ contact = client.records.create(
31
+ object: "people",
32
+ data: {
33
+ name: "Sarah Johnson",
34
+ email: "sarah@techcorp.example.com",
35
+ title: "VP of Engineering",
36
+ }
37
+ )
38
+ puts " ✓ Created contact: #{contact.dig('data', 'values', 'name', 0, 'value')}"
39
+
40
+ company_id = company.dig("data", "id", "record_id")
41
+ contact_id = contact.dig("data", "id", "record_id")
42
+
43
+ # 2. Create a thread for discussion
44
+ puts "\n2. Creating a discussion thread..."
45
+ thread = client.threads.create(
46
+ parent_object: "companies",
47
+ parent_record_id: company_id,
48
+ title: "Q1 2025 Contract Renewal Discussion",
49
+ description: "Thread to track all discussions related to the Q1 2025 contract renewal"
50
+ )
51
+ thread_id = thread.dig("data", "id", "thread_id")
52
+ puts " ✓ Created thread: #{thread.dig('data', 'title')}"
53
+
54
+ # 3. Add comments to the thread
55
+ puts "\n3. Adding comments to the thread..."
56
+ client.comments.create(
57
+ thread_id: thread_id,
58
+ content: "Initial meeting scheduled for next Monday. Key topics:\n\n" \
59
+ "- Review current usage metrics\n" \
60
+ "- Discuss expansion opportunities\n" \
61
+ "- Address any concerns"
62
+ )
63
+ puts " ✓ Added initial comment"
64
+
65
+ comment2 = client.comments.create(
66
+ thread_id: thread_id,
67
+ content: "Sarah confirmed attendance. She mentioned interest in our new API features."
68
+ )
69
+ puts " ✓ Added follow-up comment"
70
+
71
+ # 4. React to a comment
72
+ puts "\n4. Adding reactions to comments..."
73
+ client.comments.react(id: comment2.dig("data", "id", "comment_id"), emoji: "👍")
74
+ puts " ✓ Added 👍 reaction"
75
+
76
+ # 5. Create tasks
77
+ puts "\n5. Creating tasks..."
78
+ task1 = client.tasks.create(
79
+ parent_object: "companies",
80
+ parent_record_id: company_id,
81
+ title: "Prepare renewal proposal",
82
+ due_date: (Date.today + 7).iso8601,
83
+ description: "Create comprehensive renewal proposal including pricing and new features"
84
+ )
85
+ puts " ✓ Created task: #{task1.dig('data', 'title')}"
86
+
87
+ task2 = client.tasks.create(
88
+ parent_object: "people",
89
+ parent_record_id: contact_id,
90
+ title: "Schedule follow-up call",
91
+ due_date: (Date.today + 14).iso8601
92
+ )
93
+ puts " ✓ Created task: #{task2.dig('data', 'title')}"
94
+
95
+ # 6. Create meeting notes
96
+ puts "\n6. Creating meeting notes..."
97
+ client.notes.create(
98
+ parent_object: "companies",
99
+ parent_record_id: company_id,
100
+ title: "Contract Renewal Meeting - #{Date.today}",
101
+ content: <<~CONTENT
102
+ ## Attendees
103
+ - Sarah Johnson (TechCorp)
104
+ - Our team: Sales, Customer Success
105
+
106
+ ## Key Points Discussed
107
+ 1. Current contract value: $50,000/year
108
+ 2. Usage has grown 40% in last quarter
109
+ 3. Interest in API expansion package
110
+
111
+ ## Action Items
112
+ - [ ] Send updated pricing proposal by EOW
113
+ - [ ] Schedule technical demo for API features
114
+ - [ ] Review SLA requirements
115
+
116
+ ## Next Steps
117
+ Follow-up call scheduled for next week
118
+ CONTENT
119
+ )
120
+ puts " ✓ Created meeting notes"
121
+
122
+ # 7. List all collaboration items
123
+ puts "\n7. Listing collaboration items..."
124
+
125
+ # List threads
126
+ threads = client.threads.list(
127
+ parent_object: "companies",
128
+ parent_record_id: company_id
129
+ )
130
+ puts " Threads on company: #{threads['data']&.length || 0}"
131
+
132
+ # List comments in thread
133
+ comments = client.comments.list(thread_id: thread_id)
134
+ puts " Comments in thread: #{comments['data']&.length || 0}"
135
+
136
+ # List tasks
137
+ all_tasks = client.tasks.list
138
+ puts " Total tasks: #{all_tasks['data']&.length || 0}"
139
+
140
+ # List notes
141
+ notes = client.notes.list(
142
+ parent_object: "companies",
143
+ parent_record_id: company_id
144
+ )
145
+ puts " Notes on company: #{notes['data']&.length || 0}"
146
+
147
+ # 8. Update task status
148
+ puts "\n8. Updating task status..."
149
+ client.tasks.complete(
150
+ id: task1.dig("data", "id", "task_id"),
151
+ completed_at: Time.now.iso8601
152
+ )
153
+ puts " ✓ Marked task as complete"
154
+
155
+ # 9. Close the thread
156
+ puts "\n9. Closing the discussion thread..."
157
+ client.threads.close(id: thread_id)
158
+ puts " ✓ Thread closed"
159
+
160
+ puts "\n#{'=' * 40}"
161
+ puts "Example completed successfully!"
162
+ puts "\nThis example demonstrated:"
163
+ puts " • Creating and managing discussion threads"
164
+ puts " • Adding comments and reactions"
165
+ puts " • Creating and completing tasks"
166
+ puts " • Creating detailed meeting notes"
167
+ puts " • Listing collaboration items"
168
+
169
+ # Clean up (optional - uncomment to delete created records)
170
+ # puts "\nCleaning up..."
171
+ # client.records.delete(object: "companies", id: company_id)
172
+ # client.records.delete(object: "people", id: contact_id)
173
+ # puts " ✓ Cleanup complete"
@@ -0,0 +1,348 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "attio"
5
+ require "time"
6
+
7
+ # Example: Complete CRM Workflow
8
+ #
9
+ # This example demonstrates a complete CRM workflow including:
10
+ # - Creating and managing companies and contacts
11
+ # - Working with lists and workspace management
12
+ # - Using collaboration features
13
+ # - Error handling
14
+
15
+ # Initialize the client
16
+ client = Attio.client(api_key: ENV.fetch("ATTIO_API_KEY"))
17
+
18
+ puts "Attio Complete CRM Workflow Example"
19
+ puts "=" * 40
20
+
21
+ # Error handling wrapper
22
+ def safe_execute(description)
23
+ print "#{description}..."
24
+ result = yield
25
+ puts " ✓"
26
+ result
27
+ rescue Attio::NotFoundError => e
28
+ puts " ✗ Not found: #{e.message}"
29
+ nil
30
+ rescue Attio::ValidationError => e
31
+ puts " ✗ Validation error: #{e.message}"
32
+ nil
33
+ rescue Attio::Error => e
34
+ puts " ✗ Error: #{e.message}"
35
+ nil
36
+ end
37
+
38
+ # 1. Get workspace information
39
+ puts "\n1. Workspace Information"
40
+ puts "-" * 20
41
+ workspace = safe_execute("Getting current workspace") do
42
+ client.workspaces.get
43
+ end
44
+
45
+ if workspace
46
+ puts " Workspace: #{workspace.dig('data', 'name')}"
47
+ puts " ID: #{workspace.dig('data', 'id', 'workspace_id')}"
48
+ end
49
+
50
+ # 2. List available objects and attributes
51
+ puts "\n2. Schema Information"
52
+ puts "-" * 20
53
+ objects = safe_execute("Listing objects") do
54
+ client.objects.list
55
+ end
56
+
57
+ if objects && objects["data"]
58
+ puts " Available objects:"
59
+ objects["data"].each do |obj|
60
+ puts " - #{obj['api_slug']}: #{obj['name']}"
61
+ end
62
+ end
63
+
64
+ # 3. Create a sales pipeline workflow
65
+ puts "\n3. Sales Pipeline Setup"
66
+ puts "-" * 20
67
+
68
+ # Create a company
69
+ company = safe_execute("Creating prospect company") do
70
+ client.records.create(
71
+ object: "companies",
72
+ data: {
73
+ name: "Innovation Labs Inc",
74
+ domain: "innovationlabs.example.com",
75
+ industry: "Technology",
76
+ description: "Potential enterprise customer",
77
+ }
78
+ )
79
+ end
80
+ company_id = company&.dig("data", "id", "record_id")
81
+
82
+ # Create primary contact
83
+ contact = safe_execute("Creating primary contact") do
84
+ client.records.create(
85
+ object: "people",
86
+ data: {
87
+ name: "Michael Chen",
88
+ email: "m.chen@innovationlabs.example.com",
89
+ title: "CTO",
90
+ phone: "+1-555-0123",
91
+ }
92
+ )
93
+ end
94
+ contact&.dig("data", "id", "record_id")
95
+
96
+ # Create additional contacts
97
+ if company_id
98
+ safe_execute("Creating additional contact") do
99
+ client.records.create(
100
+ object: "people",
101
+ data: {
102
+ name: "Lisa Park",
103
+ email: "l.park@innovationlabs.example.com",
104
+ title: "VP of Product",
105
+ }
106
+ )
107
+ end
108
+ end
109
+
110
+ # 4. Create and manage lists
111
+ puts "\n4. List Management"
112
+ puts "-" * 20
113
+
114
+ lists = safe_execute("Getting available lists") do
115
+ client.lists.list
116
+ end
117
+
118
+ if lists && lists["data"] && !lists["data"].empty?
119
+ list_id = lists["data"].first["id"]["list_id"]
120
+
121
+ # Add company to a list
122
+ if company_id
123
+ safe_execute("Adding company to list") do
124
+ client.lists.create_entry(
125
+ id: list_id,
126
+ data: {
127
+ record_id: company_id,
128
+ notes: "High priority prospect",
129
+ }
130
+ )
131
+ end
132
+ end
133
+
134
+ # Get list entries
135
+ entries = safe_execute("Getting list entries") do
136
+ client.lists.entries(id: list_id, limit: 5)
137
+ end
138
+
139
+ puts " List has #{entries['data']&.length || 0} entries" if entries
140
+ end
141
+
142
+ # 5. Collaboration workflow
143
+ puts "\n5. Collaboration Workflow"
144
+ puts "-" * 20
145
+
146
+ if company_id
147
+ # Create a discussion thread
148
+ thread = safe_execute("Creating sales discussion thread") do
149
+ client.threads.create(
150
+ parent_object: "companies",
151
+ parent_record_id: company_id,
152
+ title: "Sales Opportunity - Innovation Labs",
153
+ description: "Track all sales activities and discussions"
154
+ )
155
+ end
156
+ thread_id = thread&.dig("data", "id", "thread_id")
157
+
158
+ # Add initial comment
159
+ if thread_id
160
+ safe_execute("Adding sales strategy comment") do
161
+ client.comments.create(
162
+ thread_id: thread_id,
163
+ content: <<~CONTENT
164
+ ## Opportunity Overview
165
+ - **Company**: Innovation Labs Inc
166
+ - **Potential Value**: $100K ARR
167
+ - **Timeline**: Q1 2025
168
+
169
+ ## Next Steps
170
+ 1. Schedule discovery call
171
+ 2. Prepare custom demo
172
+ 3. Send pricing proposal
173
+ CONTENT
174
+ )
175
+ end
176
+ end
177
+
178
+ # Create tasks
179
+ safe_execute("Creating discovery call task") do
180
+ client.tasks.create(
181
+ parent_object: "companies",
182
+ parent_record_id: company_id,
183
+ title: "Schedule discovery call with Michael Chen",
184
+ due_date: (Date.today + 3).iso8601,
185
+ description: "Initial discovery call to understand their requirements"
186
+ )
187
+ end
188
+
189
+ safe_execute("Creating demo prep task") do
190
+ client.tasks.create(
191
+ parent_object: "companies",
192
+ parent_record_id: company_id,
193
+ title: "Prepare customized product demo",
194
+ due_date: (Date.today + 7).iso8601
195
+ )
196
+ end
197
+
198
+ # Create meeting notes
199
+ safe_execute("Creating initial contact notes") do
200
+ client.notes.create(
201
+ parent_object: "companies",
202
+ parent_record_id: company_id,
203
+ title: "Initial Contact - #{Date.today}",
204
+ content: <<~CONTENT
205
+ ## Contact Method
206
+ Inbound inquiry via website
207
+
208
+ ## Requirements
209
+ - Looking for enterprise CRM solution
210
+ - Team size: 200+ employees
211
+ - Current solution: Spreadsheets
212
+
213
+ ## Pain Points
214
+ - No centralized customer data
215
+ - Manual reporting processes
216
+ - Limited collaboration features
217
+
218
+ ## Budget
219
+ Approved budget: $100-150K annually
220
+
221
+ ## Decision Timeline
222
+ Looking to implement in Q1 2025
223
+ CONTENT
224
+ )
225
+ end
226
+ end
227
+
228
+ # 6. Query and reporting
229
+ puts "\n6. Queries and Reporting"
230
+ puts "-" * 20
231
+
232
+ # Get all high-priority tasks
233
+ tasks = safe_execute("Getting pending tasks") do
234
+ client.tasks.list(status: "pending", limit: 5)
235
+ end
236
+
237
+ if tasks
238
+ puts " Pending tasks: #{tasks['data']&.length || 0}"
239
+ tasks["data"]&.each do |task|
240
+ puts " - #{task['title']}"
241
+ end
242
+ end
243
+
244
+ # Query recent companies
245
+ recent_companies = safe_execute("Finding recent companies") do
246
+ client.records.list(
247
+ object: "companies",
248
+ sorts: [{ field: "created_at", direction: "desc" }],
249
+ limit: 5
250
+ )
251
+ end
252
+
253
+ puts " Recent companies: #{recent_companies['data']&.length || 0}" if recent_companies
254
+
255
+ # 7. User management
256
+ puts "\n7. User Information"
257
+ puts "-" * 20
258
+
259
+ # Get current user
260
+ me = safe_execute("Getting current user") do
261
+ client.users.me
262
+ end
263
+
264
+ if me
265
+ puts " Current user: #{me.dig('data', 'name')}"
266
+ puts " Email: #{me.dig('data', 'email')}"
267
+ end
268
+
269
+ # List all users
270
+ users = safe_execute("Listing workspace users") do
271
+ client.users.list
272
+ end
273
+
274
+ puts " Total users: #{users['data']&.length || 0}" if users
275
+
276
+ # 8. Advanced features
277
+ puts "\n8. Advanced Features"
278
+ puts "-" * 20
279
+
280
+ # Get custom attributes
281
+ if company_id
282
+ attributes = safe_execute("Getting company attributes") do
283
+ client.attributes.list(object: "companies")
284
+ end
285
+
286
+ puts " Company attributes: #{attributes['data']&.length || 0}" if attributes
287
+ end
288
+
289
+ # Demonstrate pagination
290
+ puts " Demonstrating pagination..."
291
+ all_records = []
292
+ cursor = nil
293
+ pages = 0
294
+
295
+ loop do
296
+ params = { object: "companies", limit: 2 }
297
+ params[:cursor] = cursor if cursor
298
+
299
+ page = safe_execute(" Fetching page #{pages + 1}") do
300
+ client.records.list(**params)
301
+ end
302
+
303
+ break unless page && page["data"]
304
+
305
+ all_records.concat(page["data"])
306
+ pages += 1
307
+
308
+ cursor = page.dig("pagination", "next_cursor")
309
+ break unless cursor && pages < 3 # Limit to 3 pages for demo
310
+ end
311
+
312
+ puts " Fetched #{all_records.length} records across #{pages} pages"
313
+
314
+ # 9. Summary
315
+ puts "\n9. Workflow Summary"
316
+ puts "-" * 20
317
+ puts " ✓ Workspace configured"
318
+ puts " ✓ Company and contacts created"
319
+ puts " ✓ Lists managed"
320
+ puts " ✓ Collaboration tools utilized"
321
+ puts " ✓ Tasks and notes created"
322
+ puts " ✓ Queries executed"
323
+ puts " ✓ User information retrieved"
324
+
325
+ puts "\n#{'=' * 40}"
326
+ puts "Complete workflow example finished!"
327
+ puts "\nThis example demonstrated:"
328
+ puts " • Complete CRM setup"
329
+ puts " • Record creation and management"
330
+ puts " • List operations"
331
+ puts " • Collaboration features"
332
+ puts " • Task management"
333
+ puts " • Querying and reporting"
334
+ puts " • User management"
335
+ puts " • Error handling"
336
+ puts " • Pagination"
337
+
338
+ # Optional cleanup
339
+ # if company_id
340
+ # safe_execute("Cleaning up company") do
341
+ # client.records.delete(object: "companies", id: company_id)
342
+ # end
343
+ # end
344
+ # if contact_id
345
+ # safe_execute("Cleaning up contact") do
346
+ # client.records.delete(object: "people", id: contact_id)
347
+ # end
348
+ # end