monday_ruby 1.1.0 → 1.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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.env +1 -1
  3. data/.rubocop.yml +2 -1
  4. data/CHANGELOG.md +14 -0
  5. data/CONTRIBUTING.md +104 -0
  6. data/README.md +146 -142
  7. data/docs/.vitepress/config.mjs +255 -0
  8. data/docs/.vitepress/theme/index.js +4 -0
  9. data/docs/.vitepress/theme/style.css +43 -0
  10. data/docs/README.md +80 -0
  11. data/docs/explanation/architecture.md +507 -0
  12. data/docs/explanation/best-practices/errors.md +478 -0
  13. data/docs/explanation/best-practices/performance.md +1084 -0
  14. data/docs/explanation/best-practices/rate-limiting.md +630 -0
  15. data/docs/explanation/best-practices/testing.md +820 -0
  16. data/docs/explanation/column-values.md +857 -0
  17. data/docs/explanation/design.md +795 -0
  18. data/docs/explanation/graphql.md +356 -0
  19. data/docs/explanation/migration/v1.md +808 -0
  20. data/docs/explanation/pagination.md +447 -0
  21. data/docs/guides/advanced/batch.md +1274 -0
  22. data/docs/guides/advanced/complex-queries.md +1114 -0
  23. data/docs/guides/advanced/errors.md +818 -0
  24. data/docs/guides/advanced/pagination.md +934 -0
  25. data/docs/guides/advanced/rate-limiting.md +981 -0
  26. data/docs/guides/authentication.md +286 -0
  27. data/docs/guides/boards/create.md +386 -0
  28. data/docs/guides/boards/delete.md +405 -0
  29. data/docs/guides/boards/duplicate.md +511 -0
  30. data/docs/guides/boards/query.md +530 -0
  31. data/docs/guides/boards/update.md +453 -0
  32. data/docs/guides/columns/create.md +452 -0
  33. data/docs/guides/columns/metadata.md +492 -0
  34. data/docs/guides/columns/query.md +455 -0
  35. data/docs/guides/columns/update-multiple.md +459 -0
  36. data/docs/guides/columns/update-values.md +509 -0
  37. data/docs/guides/files/add-to-column.md +40 -0
  38. data/docs/guides/files/add-to-update.md +37 -0
  39. data/docs/guides/files/clear-column.md +33 -0
  40. data/docs/guides/first-request.md +285 -0
  41. data/docs/guides/folders/manage.md +750 -0
  42. data/docs/guides/groups/items.md +626 -0
  43. data/docs/guides/groups/manage.md +501 -0
  44. data/docs/guides/installation.md +169 -0
  45. data/docs/guides/items/create.md +493 -0
  46. data/docs/guides/items/delete.md +514 -0
  47. data/docs/guides/items/query.md +605 -0
  48. data/docs/guides/items/subitems.md +483 -0
  49. data/docs/guides/items/update.md +699 -0
  50. data/docs/guides/updates/manage.md +619 -0
  51. data/docs/guides/use-cases/dashboard.md +1421 -0
  52. data/docs/guides/use-cases/import.md +1962 -0
  53. data/docs/guides/use-cases/task-management.md +1381 -0
  54. data/docs/guides/workspaces/manage.md +502 -0
  55. data/docs/index.md +69 -0
  56. data/docs/package-lock.json +2468 -0
  57. data/docs/package.json +13 -0
  58. data/docs/reference/client.md +540 -0
  59. data/docs/reference/configuration.md +586 -0
  60. data/docs/reference/errors.md +693 -0
  61. data/docs/reference/resources/account.md +208 -0
  62. data/docs/reference/resources/activity-log.md +369 -0
  63. data/docs/reference/resources/board-view.md +359 -0
  64. data/docs/reference/resources/board.md +393 -0
  65. data/docs/reference/resources/column.md +543 -0
  66. data/docs/reference/resources/file.md +236 -0
  67. data/docs/reference/resources/folder.md +386 -0
  68. data/docs/reference/resources/group.md +507 -0
  69. data/docs/reference/resources/item.md +348 -0
  70. data/docs/reference/resources/subitem.md +267 -0
  71. data/docs/reference/resources/update.md +259 -0
  72. data/docs/reference/resources/workspace.md +213 -0
  73. data/docs/reference/response.md +560 -0
  74. data/docs/tutorial/first-integration.md +713 -0
  75. data/lib/monday/client.rb +24 -0
  76. data/lib/monday/configuration.rb +5 -0
  77. data/lib/monday/request.rb +15 -0
  78. data/lib/monday/resources/base.rb +4 -0
  79. data/lib/monday/resources/file.rb +56 -0
  80. data/lib/monday/util.rb +1 -0
  81. data/lib/monday/version.rb +1 -1
  82. metadata +87 -4
@@ -0,0 +1,750 @@
1
+ # Manage Folders
2
+
3
+ Organize boards into folders within workspaces for better structure and navigation.
4
+
5
+ ## Query Folders
6
+
7
+ List all folders in your account:
8
+
9
+ ```ruby
10
+ require "monday_ruby"
11
+
12
+ Monday.configure do |config|
13
+ config.token = ENV["MONDAY_TOKEN"]
14
+ end
15
+
16
+ client = Monday::Client.new
17
+
18
+ response = client.folder.query
19
+
20
+ if response.success?
21
+ folders = response.body.dig("data", "folders")
22
+
23
+ puts "Folders in your account:"
24
+ folders.each do |folder|
25
+ puts " • #{folder['name']} (ID: #{folder['id']})"
26
+ end
27
+ else
28
+ puts "Failed to retrieve folders"
29
+ end
30
+ ```
31
+
32
+ **Output:**
33
+ ```
34
+ Folders in your account:
35
+ • LE Development Team (ID: 10918734)
36
+ • CRM (ID: 10977318)
37
+ • Projects (ID: 12772091)
38
+ • Documentation (ID: 13201660)
39
+ ```
40
+
41
+ ### Query Specific Folders
42
+
43
+ Retrieve folders by ID:
44
+
45
+ ```ruby
46
+ response = client.folder.query(
47
+ args: { ids: [10918734, 10977318] },
48
+ select: ["id", "name", "color"]
49
+ )
50
+
51
+ if response.success?
52
+ folders = response.body.dig("data", "folders")
53
+
54
+ folders.each do |folder|
55
+ puts "#{folder['name']}: #{folder['color']}"
56
+ end
57
+ end
58
+ ```
59
+
60
+ ### Get Folder Details
61
+
62
+ Query with nested fields to see folder contents:
63
+
64
+ ```ruby
65
+ response = client.folder.query(
66
+ select: [
67
+ "id",
68
+ "name",
69
+ "color",
70
+ "created_at",
71
+ {
72
+ workspace: ["id", "name"],
73
+ children: ["id", "name", "type"]
74
+ }
75
+ ]
76
+ )
77
+
78
+ if response.success?
79
+ folders = response.body.dig("data", "folders")
80
+
81
+ folders.first(3).each do |folder|
82
+ workspace_name = folder.dig("workspace", "name")
83
+ board_count = folder["children"]&.count || 0
84
+
85
+ puts "\n#{folder['name']}"
86
+ puts " Workspace: #{workspace_name}"
87
+ puts " Boards: #{board_count}"
88
+ puts " Created: #{folder['created_at']}"
89
+ end
90
+ end
91
+ ```
92
+
93
+ **Output:**
94
+ ```
95
+ LE Development Team
96
+ Workspace: Main Workspace
97
+ Boards: 5
98
+ Created: 2024-01-15T10:30:00Z
99
+
100
+ CRM
101
+ Workspace: Sales Workspace
102
+ Boards: 3
103
+ Created: 2024-02-20T14:22:00Z
104
+ ```
105
+
106
+ ## Create a Folder
107
+
108
+ Create a new folder within a workspace:
109
+
110
+ ```ruby
111
+ require "monday_ruby"
112
+
113
+ Monday.configure do |config|
114
+ config.token = ENV["MONDAY_TOKEN"]
115
+ end
116
+
117
+ client = Monday::Client.new
118
+
119
+ # First, get your workspace ID
120
+ workspace_response = client.workspace.query(
121
+ select: ["id", "name"]
122
+ )
123
+
124
+ workspace = workspace_response.body.dig("data", "workspaces", 0)
125
+ workspace_id = workspace["id"]
126
+
127
+ # Create folder in that workspace
128
+ response = client.folder.create(
129
+ args: {
130
+ workspace_id: workspace_id,
131
+ name: "Database boards"
132
+ }
133
+ )
134
+
135
+ if response.success?
136
+ folder = response.body.dig("data", "create_folder")
137
+ puts "✓ Created folder: #{folder['name']}"
138
+ puts " ID: #{folder['id']}"
139
+ else
140
+ puts "✗ Failed to create folder"
141
+ end
142
+ ```
143
+
144
+ **Output:**
145
+ ```
146
+ ✓ Created folder: Database boards
147
+ ID: 15476755
148
+ ```
149
+
150
+ ### Create with Color
151
+
152
+ Add a color to help visually identify folders:
153
+
154
+ ```ruby
155
+ response = client.folder.create(
156
+ args: {
157
+ workspace_id: 8529962,
158
+ name: "Q1 2024 Projects",
159
+ color: "#FF5AC4" # Pink
160
+ },
161
+ select: ["id", "name", "color"]
162
+ )
163
+
164
+ if response.success?
165
+ folder = response.body.dig("data", "create_folder")
166
+ puts "Created #{folder['name']} with color #{folder['color']}"
167
+ end
168
+ ```
169
+
170
+ **Common colors:**
171
+ ```ruby
172
+ colors = {
173
+ red: "#E2445C",
174
+ orange: "#FDAB3D",
175
+ yellow: "#FFCB00",
176
+ green: "#00C875",
177
+ blue: "#0086C0",
178
+ purple: "#A25DDC",
179
+ pink: "#FF5AC4",
180
+ gray: "#C4C4C4"
181
+ }
182
+
183
+ response = client.folder.create(
184
+ args: {
185
+ workspace_id: 8529962,
186
+ name: "Engineering",
187
+ color: colors[:blue]
188
+ }
189
+ )
190
+ ```
191
+
192
+ ### Create Multiple Folders
193
+
194
+ Organize workspace with multiple folders:
195
+
196
+ ```ruby
197
+ workspace_id = 8529962
198
+ folders = ["Design", "Engineering", "Marketing", "Sales"]
199
+
200
+ folders.each do |folder_name|
201
+ response = client.folder.create(
202
+ args: {
203
+ workspace_id: workspace_id,
204
+ name: folder_name
205
+ }
206
+ )
207
+
208
+ if response.success?
209
+ folder = response.body.dig("data", "create_folder")
210
+ puts "✓ Created: #{folder['name']}"
211
+ else
212
+ puts "✗ Failed to create: #{folder_name}"
213
+ end
214
+
215
+ # Rate limiting: pause between requests
216
+ sleep(0.3)
217
+ end
218
+ ```
219
+
220
+ **Output:**
221
+ ```
222
+ ✓ Created: Design
223
+ ✓ Created: Engineering
224
+ ✓ Created: Marketing
225
+ ✓ Created: Sales
226
+ ```
227
+
228
+ ### Create Subfolder
229
+
230
+ Create a folder within another folder:
231
+
232
+ ```ruby
233
+ # Create parent folder first
234
+ parent_response = client.folder.create(
235
+ args: {
236
+ workspace_id: 8529962,
237
+ name: "Projects"
238
+ }
239
+ )
240
+
241
+ parent_id = parent_response.body.dig("data", "create_folder", "id")
242
+
243
+ # Create subfolder
244
+ response = client.folder.create(
245
+ args: {
246
+ workspace_id: 8529962,
247
+ name: "Active Projects",
248
+ parent_folder_id: parent_id
249
+ }
250
+ )
251
+
252
+ if response.success?
253
+ subfolder = response.body.dig("data", "create_folder")
254
+ puts "Created subfolder: #{subfolder['name']}"
255
+ end
256
+ ```
257
+
258
+ ## Update Folder Name
259
+
260
+ Rename an existing folder:
261
+
262
+ ```ruby
263
+ require "monday_ruby"
264
+
265
+ Monday.configure do |config|
266
+ config.token = ENV["MONDAY_TOKEN"]
267
+ end
268
+
269
+ client = Monday::Client.new
270
+
271
+ response = client.folder.update(
272
+ args: {
273
+ folder_id: 15476750,
274
+ name: "Cool boards"
275
+ }
276
+ )
277
+
278
+ if response.success?
279
+ folder = response.body.dig("data", "update_folder")
280
+ puts "✓ Updated folder ID: #{folder['id']}"
281
+ else
282
+ puts "✗ Failed to update folder"
283
+ end
284
+ ```
285
+
286
+ ### Update Folder Color
287
+
288
+ Change the folder's visual appearance:
289
+
290
+ ```ruby
291
+ response = client.folder.update(
292
+ args: {
293
+ folder_id: 15476750,
294
+ color: "#00C875" # Green
295
+ },
296
+ select: ["id", "name", "color"]
297
+ )
298
+
299
+ if response.success?
300
+ folder = response.body.dig("data", "update_folder")
301
+ puts "Updated #{folder['name']} to #{folder['color']}"
302
+ end
303
+ ```
304
+
305
+ ### Update Multiple Attributes
306
+
307
+ Change both name and color:
308
+
309
+ ```ruby
310
+ response = client.folder.update(
311
+ args: {
312
+ folder_id: 15476750,
313
+ name: "Completed Projects",
314
+ color: "#C4C4C4" # Gray
315
+ },
316
+ select: ["id", "name", "color"]
317
+ )
318
+
319
+ if response.success?
320
+ folder = response.body.dig("data", "update_folder")
321
+ puts "✓ Updated folder:"
322
+ puts " Name: #{folder['name']}"
323
+ puts " Color: #{folder['color']}"
324
+ end
325
+ ```
326
+
327
+ ### Move Folder to Different Parent
328
+
329
+ Reorganize folder hierarchy:
330
+
331
+ ```ruby
332
+ # Move folder to different parent
333
+ response = client.folder.update(
334
+ args: {
335
+ folder_id: 15476750,
336
+ parent_folder_id: 12345678 # New parent folder ID
337
+ }
338
+ )
339
+
340
+ if response.success?
341
+ puts "Folder moved to new parent"
342
+ end
343
+
344
+ # Move folder to workspace root (remove from parent)
345
+ response = client.folder.update(
346
+ args: {
347
+ folder_id: 15476750,
348
+ parent_folder_id: nil
349
+ }
350
+ )
351
+ ```
352
+
353
+ ## Delete Folders
354
+
355
+ Remove folders that are no longer needed:
356
+
357
+ ```ruby
358
+ require "monday_ruby"
359
+
360
+ Monday.configure do |config|
361
+ config.token = ENV["MONDAY_TOKEN"]
362
+ end
363
+
364
+ client = Monday::Client.new
365
+
366
+ response = client.folder.delete(
367
+ args: { folder_id: 15476753 }
368
+ )
369
+
370
+ if response.success?
371
+ folder = response.body.dig("data", "delete_folder")
372
+ puts "✓ Deleted folder ID: #{folder['id']}"
373
+ else
374
+ puts "✗ Failed to delete folder"
375
+ end
376
+ ```
377
+
378
+ ::: warning <span style="display: inline-flex; align-items: center; gap: 6px;"><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path><line x1="12" y1="9" x2="12" y2="13"></line><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>Boards Are Preserved</span>
379
+ Deleting a folder does NOT delete the boards inside it. Boards are moved to the workspace root.
380
+ :::
381
+
382
+ ### Delete Multiple Folders
383
+
384
+ Clean up several folders at once:
385
+
386
+ ```ruby
387
+ folder_ids = [15476753, 15476754, 15476755]
388
+
389
+ folder_ids.each do |folder_id|
390
+ response = client.folder.delete(
391
+ args: { folder_id: folder_id }
392
+ )
393
+
394
+ if response.success?
395
+ puts "✓ Deleted folder #{folder_id}"
396
+ else
397
+ puts "✗ Failed to delete folder #{folder_id}"
398
+ end
399
+
400
+ sleep(0.3)
401
+ end
402
+ ```
403
+
404
+ ### Safely Delete Empty Folders
405
+
406
+ Check if folder is empty before deleting:
407
+
408
+ ```ruby
409
+ # Query folder with children
410
+ response = client.folder.query(
411
+ select: [
412
+ "id",
413
+ "name",
414
+ {
415
+ children: ["id"]
416
+ }
417
+ ]
418
+ )
419
+
420
+ if response.success?
421
+ folders = response.body.dig("data", "folders")
422
+
423
+ folders.each do |folder|
424
+ children_count = folder["children"]&.count || 0
425
+
426
+ if children_count == 0
427
+ delete_response = client.folder.delete(
428
+ args: { folder_id: folder["id"] }
429
+ )
430
+
431
+ if delete_response.success?
432
+ puts "✓ Deleted empty folder: #{folder['name']}"
433
+ end
434
+ else
435
+ puts "⊘ Skipped #{folder['name']} (#{children_count} boards)"
436
+ end
437
+ end
438
+ end
439
+ ```
440
+
441
+ ## Error Handling
442
+
443
+ Handle common folder operation errors:
444
+
445
+ ```ruby
446
+ def create_folder_safe(client, workspace_id, name)
447
+ response = client.folder.create(
448
+ args: {
449
+ workspace_id: workspace_id,
450
+ name: name
451
+ }
452
+ )
453
+
454
+ if response.success?
455
+ folder = response.body.dig("data", "create_folder")
456
+ puts "✓ Created: #{folder['name']} (ID: #{folder['id']})"
457
+ folder['id']
458
+ else
459
+ puts "✗ Failed to create folder: #{name}"
460
+ puts " Status: #{response.status}"
461
+
462
+ if response.body["errors"]
463
+ response.body["errors"].each do |error|
464
+ puts " Error: #{error['message']}"
465
+ end
466
+ end
467
+
468
+ nil
469
+ end
470
+ rescue Monday::AuthorizationError
471
+ puts "✗ Invalid API token"
472
+ nil
473
+ rescue Monday::Error => e
474
+ puts "✗ API error: #{e.message}"
475
+ nil
476
+ end
477
+
478
+ # Usage
479
+ folder_id = create_folder_safe(client, 8529962, "New Folder")
480
+ ```
481
+
482
+ ### Handle Delete Errors
483
+
484
+ Gracefully handle non-existent folders:
485
+
486
+ ```ruby
487
+ def delete_folder_safe(client, folder_id)
488
+ response = client.folder.delete(
489
+ args: { folder_id: folder_id }
490
+ )
491
+
492
+ if response.success?
493
+ puts "✓ Deleted folder #{folder_id}"
494
+ true
495
+ else
496
+ puts "✗ Failed to delete folder #{folder_id}"
497
+ false
498
+ end
499
+ rescue Monday::ResourceNotFoundError
500
+ puts "✗ Folder #{folder_id} not found"
501
+ false
502
+ rescue Monday::AuthorizationError
503
+ puts "✗ Invalid API token"
504
+ false
505
+ rescue Monday::Error => e
506
+ puts "✗ Error: #{e.message}"
507
+ false
508
+ end
509
+
510
+ # Usage
511
+ delete_folder_safe(client, 999999) # Non-existent folder
512
+ ```
513
+
514
+ ### Validate Before Update
515
+
516
+ Check folder exists before updating:
517
+
518
+ ```ruby
519
+ def update_folder_safe(client, folder_id, updates)
520
+ # First verify folder exists
521
+ query_response = client.folder.query(
522
+ args: { ids: [folder_id] },
523
+ select: ["id", "name"]
524
+ )
525
+
526
+ folders = query_response.body.dig("data", "folders") || []
527
+
528
+ if folders.empty?
529
+ puts "✗ Folder #{folder_id} not found"
530
+ return false
531
+ end
532
+
533
+ # Folder exists, proceed with update
534
+ response = client.folder.update(
535
+ args: updates.merge(folder_id: folder_id)
536
+ )
537
+
538
+ if response.success?
539
+ puts "✓ Updated folder #{folder_id}"
540
+ true
541
+ else
542
+ puts "✗ Failed to update folder"
543
+ false
544
+ end
545
+ rescue Monday::Error => e
546
+ puts "✗ Error: #{e.message}"
547
+ false
548
+ end
549
+
550
+ # Usage
551
+ update_folder_safe(client, 15476750, { name: "New Name" })
552
+ ```
553
+
554
+ ## Complete Example
555
+
556
+ Full workflow for managing folders:
557
+
558
+ ```ruby
559
+ require "monday_ruby"
560
+ require "dotenv/load"
561
+
562
+ Monday.configure do |config|
563
+ config.token = ENV["MONDAY_TOKEN"]
564
+ end
565
+
566
+ client = Monday::Client.new
567
+
568
+ # 1. Get workspace
569
+ workspace_response = client.workspace.query(
570
+ select: ["id", "name"]
571
+ )
572
+
573
+ workspace = workspace_response.body.dig("data", "workspaces", 0)
574
+ workspace_id = workspace["id"]
575
+
576
+ puts "Working in workspace: #{workspace['name']}"
577
+ puts "#{'=' * 50}"
578
+
579
+ # 2. Create new folder
580
+ create_response = client.folder.create(
581
+ args: {
582
+ workspace_id: workspace_id,
583
+ name: "Q1 2024 Projects",
584
+ color: "#00C875"
585
+ },
586
+ select: ["id", "name", "color"]
587
+ )
588
+
589
+ if create_response.success?
590
+ folder = create_response.body.dig("data", "create_folder")
591
+
592
+ puts "\n✓ Created Folder"
593
+ puts " ID: #{folder['id']}"
594
+ puts " Name: #{folder['name']}"
595
+ puts " Color: #{folder['color']}"
596
+
597
+ folder_id = folder["id"]
598
+
599
+ # 3. Update folder name after creation
600
+ sleep(1) # Brief pause
601
+
602
+ update_response = client.folder.update(
603
+ args: {
604
+ folder_id: folder_id,
605
+ name: "Q1 2024 Active Projects"
606
+ },
607
+ select: ["id", "name"]
608
+ )
609
+
610
+ if update_response.success?
611
+ puts "\n✓ Updated Folder Name"
612
+ puts " ID: #{folder_id}"
613
+ puts " New Name: Q1 2024 Active Projects"
614
+ end
615
+
616
+ # 4. Query the folder to verify
617
+ sleep(1)
618
+
619
+ query_response = client.folder.query(
620
+ args: { ids: [folder_id] },
621
+ select: [
622
+ "id",
623
+ "name",
624
+ "color",
625
+ {
626
+ workspace: ["id", "name"]
627
+ }
628
+ ]
629
+ )
630
+
631
+ if query_response.success?
632
+ queried_folder = query_response.body.dig("data", "folders", 0)
633
+
634
+ puts "\n✓ Verified Folder"
635
+ puts " Name: #{queried_folder['name']}"
636
+ puts " Color: #{queried_folder['color']}"
637
+ puts " Workspace: #{queried_folder.dig('workspace', 'name')}"
638
+ end
639
+
640
+ # 5. Clean up - delete the folder
641
+ sleep(1)
642
+
643
+ delete_response = client.folder.delete(
644
+ args: { folder_id: folder_id }
645
+ )
646
+
647
+ if delete_response.success?
648
+ puts "\n✓ Deleted Folder"
649
+ puts " ID: #{folder_id}"
650
+ end
651
+
652
+ puts "\n#{'=' * 50}"
653
+ puts "Folder lifecycle complete!"
654
+ else
655
+ puts "\n✗ Failed to create folder"
656
+ end
657
+ ```
658
+
659
+ **Output:**
660
+ ```
661
+ Working in workspace: Main Workspace
662
+ ==================================================
663
+
664
+ ✓ Created Folder
665
+ ID: 15476755
666
+ Name: Q1 2024 Projects
667
+ Color: #00C875
668
+
669
+ ✓ Updated Folder Name
670
+ ID: 15476755
671
+ New Name: Q1 2024 Active Projects
672
+
673
+ ✓ Verified Folder
674
+ Name: Q1 2024 Active Projects
675
+ Color: #00C875
676
+ Workspace: Main Workspace
677
+
678
+ ✓ Deleted Folder
679
+ ID: 15476755
680
+
681
+ ==================================================
682
+ Folder lifecycle complete!
683
+ ```
684
+
685
+ ## Organize Workspace Structure
686
+
687
+ Create a complete folder hierarchy:
688
+
689
+ ```ruby
690
+ workspace_id = 8529962
691
+
692
+ # Create department folders with color coding
693
+ departments = {
694
+ "Engineering" => "#0086C0", # Blue
695
+ "Product" => "#A25DDC", # Purple
696
+ "Marketing" => "#FF5AC4", # Pink
697
+ "Sales" => "#00C875", # Green
698
+ "Operations" => "#FDAB3D" # Orange
699
+ }
700
+
701
+ created_folders = []
702
+
703
+ departments.each do |name, color|
704
+ response = client.folder.create(
705
+ args: {
706
+ workspace_id: workspace_id,
707
+ name: name,
708
+ color: color
709
+ },
710
+ select: ["id", "name", "color"]
711
+ )
712
+
713
+ if response.success?
714
+ folder = response.body.dig("data", "create_folder")
715
+ created_folders << folder
716
+ puts "✓ Created #{folder['name']} (#{folder['color']})"
717
+ end
718
+
719
+ sleep(0.3)
720
+ end
721
+
722
+ puts "\nCreated #{created_folders.count} department folders"
723
+
724
+ # Create project folders within Engineering
725
+ engineering_folder = created_folders.find { |f| f["name"] == "Engineering" }
726
+
727
+ if engineering_folder
728
+ projects = ["Backend API", "Frontend App", "Mobile App"]
729
+
730
+ projects.each do |project|
731
+ response = client.folder.create(
732
+ args: {
733
+ workspace_id: workspace_id,
734
+ name: project,
735
+ parent_folder_id: engineering_folder["id"]
736
+ }
737
+ )
738
+
739
+ puts " ✓ Created #{project}" if response.success?
740
+ sleep(0.3)
741
+ end
742
+ end
743
+ ```
744
+
745
+ ## Next Steps
746
+
747
+ - [Create boards](/guides/boards/create)
748
+ - [Query boards](/guides/boards/query)
749
+ - [Board API reference](/reference/resources/board)
750
+ - [Folder API reference](/reference/resources/folder)