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,286 @@
1
+ # Authentication
2
+
3
+ Manage API tokens and authenticate your monday.com requests securely.
4
+
5
+ ## Overview
6
+
7
+ monday_ruby uses API tokens for authentication. Every request to the monday.com API requires a valid token.
8
+
9
+ ## Token Types
10
+
11
+ ### Personal API Token
12
+
13
+ For individual use and testing:
14
+
15
+ 1. Log in to monday.com
16
+ 2. Click your profile picture → **Administration**
17
+ 3. Go to **Connections** → **Personal API token**
18
+ 4. Copy your token
19
+
20
+ ::: 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>Token Permissions</span>
21
+ Personal API tokens have the same permissions as your monday.com account. Use carefully in production.
22
+ :::
23
+
24
+ ### App-Based Tokens
25
+
26
+ For production integrations, create a monday.com app:
27
+
28
+ 1. Go to the monday.com Developers Center
29
+ 2. Create a new app
30
+ 3. Generate OAuth tokens for users
31
+
32
+ See [monday.com's OAuth documentation](https://developer.monday.com/apps/docs/oauth) for details.
33
+
34
+ ## Secure Token Storage
35
+
36
+ ### Development: Environment Variables
37
+
38
+ Use a `.env` file:
39
+
40
+ ```bash
41
+ # .env
42
+ MONDAY_TOKEN=your_token_here
43
+ ```
44
+
45
+ Add to `.gitignore`:
46
+
47
+ ```bash
48
+ # .gitignore
49
+ .env
50
+ ```
51
+
52
+ Load in your application:
53
+
54
+ ```ruby
55
+ require "dotenv/load"
56
+
57
+ Monday.configure do |config|
58
+ config.token = ENV["MONDAY_TOKEN"]
59
+ end
60
+ ```
61
+
62
+ ### Production: Credential Management
63
+
64
+ Use secure credential storage:
65
+
66
+ **Rails Credentials:**
67
+
68
+ ```bash
69
+ rails credentials:edit
70
+ ```
71
+
72
+ Add:
73
+
74
+ ```yaml
75
+ monday:
76
+ token: your_token_here
77
+ ```
78
+
79
+ Load:
80
+
81
+ ```ruby
82
+ Monday.configure do |config|
83
+ config.token = Rails.application.credentials.monday[:token]
84
+ end
85
+ ```
86
+
87
+ **Environment Variables:**
88
+
89
+ Set on your hosting platform:
90
+
91
+ ```bash
92
+ # Heroku
93
+ heroku config:set MONDAY_TOKEN=your_token_here
94
+
95
+ # AWS Lambda
96
+ # Set in Lambda environment variables
97
+
98
+ # Docker
99
+ docker run -e MONDAY_TOKEN=your_token_here
100
+ ```
101
+
102
+ ## Configuration Methods
103
+
104
+ ### Global Configuration
105
+
106
+ Set once, use everywhere:
107
+
108
+ ```ruby
109
+ Monday.configure do |config|
110
+ config.token = ENV["MONDAY_TOKEN"]
111
+ end
112
+
113
+ # All clients use this token
114
+ client = Monday::Client.new
115
+ ```
116
+
117
+ ### Per-Client Configuration
118
+
119
+ Use different tokens for different clients:
120
+
121
+ ```ruby
122
+ # Client 1 with token A
123
+ client_a = Monday::Client.new(token: ENV["MONDAY_TOKEN_A"])
124
+
125
+ # Client 2 with token B
126
+ client_b = Monday::Client.new(token: ENV["MONDAY_TOKEN_B"])
127
+ ```
128
+
129
+ ### Dynamic Token Switching
130
+
131
+ Change tokens at runtime:
132
+
133
+ ```ruby
134
+ Monday.configure do |config|
135
+ config.token = user.monday_token
136
+ end
137
+
138
+ client = Monday::Client.new
139
+ ```
140
+
141
+ ## Verify Authentication
142
+
143
+ Test if your token is valid:
144
+
145
+ ```ruby
146
+ client = Monday::Client.new
147
+
148
+ response = client.account.query(
149
+ select: ["id", "name"]
150
+ )
151
+
152
+ if response.success?
153
+ account = response.body.dig("data", "account")
154
+ puts "Authenticated as: #{account['name']}"
155
+ else
156
+ puts "Authentication failed"
157
+ end
158
+ ```
159
+
160
+ ## Handle Authentication Errors
161
+
162
+ Catch authentication failures:
163
+
164
+ ```ruby
165
+ begin
166
+ client = Monday::Client.new(token: "invalid_token")
167
+ response = client.boards
168
+
169
+ unless response.success?
170
+ puts "Request failed: #{response.code}"
171
+ end
172
+ rescue Monday::AuthorizationError => e
173
+ puts "Invalid API token: #{e.message}"
174
+ rescue Monday::Error => e
175
+ puts "API error: #{e.message}"
176
+ end
177
+ ```
178
+
179
+ ## Token Rotation
180
+
181
+ Rotate tokens regularly for security:
182
+
183
+ ```ruby
184
+ # 1. Generate new token in monday.com
185
+ # 2. Update environment variable
186
+ # 3. Deploy with new token
187
+ # 4. Revoke old token after verification
188
+
189
+ Monday.configure do |config|
190
+ config.token = ENV["MONDAY_TOKEN_NEW"]
191
+ end
192
+
193
+ # Test new token
194
+ client = Monday::Client.new
195
+ response = client.boards
196
+
197
+ if response.success?
198
+ puts "New token works. Safe to revoke old token."
199
+ end
200
+ ```
201
+
202
+ ## Multi-Tenant Applications
203
+
204
+ Handle multiple monday.com accounts:
205
+
206
+ ```ruby
207
+ class MondayService
208
+ def initialize(user)
209
+ @client = Monday::Client.new(token: user.monday_token)
210
+ end
211
+
212
+ def fetch_boards
213
+ @client.boards
214
+ end
215
+ end
216
+
217
+ # Usage
218
+ service = MondayService.new(current_user)
219
+ response = service.fetch_boards
220
+ ```
221
+
222
+ ## Security Best Practices
223
+
224
+ ### Never Log Tokens
225
+
226
+ Avoid logging sensitive data:
227
+
228
+ ```ruby
229
+ # Bad
230
+ logger.info "Token: #{ENV['MONDAY_TOKEN']}"
231
+
232
+ # Good
233
+ logger.info "Authenticating with monday.com"
234
+ ```
235
+
236
+ ### Use Read-Only Tokens
237
+
238
+ For read-only operations, create tokens with limited scopes in your monday.com app settings.
239
+
240
+ ### Validate Tokens on Startup
241
+
242
+ Check authentication before running:
243
+
244
+ ```ruby
245
+ def validate_monday_token!
246
+ client = Monday::Client.new
247
+ response = client.account.query(select: ["id"])
248
+
249
+ raise "Invalid monday.com token" unless response.success?
250
+ end
251
+
252
+ validate_monday_token!
253
+ ```
254
+
255
+ ### Rotate Regularly
256
+
257
+ Change tokens every 90 days or after team member changes.
258
+
259
+ ## Troubleshooting
260
+
261
+ ### "Invalid token" Error
262
+
263
+ - Verify token is copied correctly (no extra spaces)
264
+ - Check token hasn't been revoked
265
+ - Ensure token has necessary permissions
266
+
267
+ ### "Unauthorized" Error
268
+
269
+ - Token may lack permissions for the requested operation
270
+ - Verify your monday.com account has access to the board/workspace
271
+
272
+ ### Token Not Loading
273
+
274
+ ```ruby
275
+ # Debug environment variable loading
276
+ puts "Token loaded: #{ENV['MONDAY_TOKEN'] ? 'Yes' : 'No'}"
277
+
278
+ # Verify dotenv is loaded
279
+ require "dotenv/load"
280
+ ```
281
+
282
+ ## Next Steps
283
+
284
+ - [Make your first request →](/guides/first-request)
285
+ - [Understand error handling →](/guides/advanced/errors)
286
+ - [Learn about configuration →](/reference/configuration)
@@ -0,0 +1,386 @@
1
+ # Create a Board
2
+
3
+ Create new boards programmatically in your monday.com account.
4
+
5
+ ## Basic Board Creation
6
+
7
+ Create a board with just a name:
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.board.create(
19
+ args: {
20
+ board_name: "My New Board",
21
+ board_kind: :public
22
+ }
23
+ )
24
+
25
+ if response.success?
26
+ board = response.body.dig("data", "create_board")
27
+ puts "✓ Created board: #{board['name']}"
28
+ puts " ID: #{board['id']}"
29
+ else
30
+ puts "✗ Failed to create board"
31
+ end
32
+ ```
33
+
34
+ **Output:**
35
+ ```
36
+ ✓ Created board: My New Board
37
+ ID: 1234567890
38
+ ```
39
+
40
+ ## Board Privacy Levels
41
+
42
+ Specify who can access the board:
43
+
44
+ ### Public Board
45
+
46
+ Visible to all workspace members:
47
+
48
+ ```ruby
49
+ response = client.board.create(
50
+ args: {
51
+ board_name: "Team Announcements",
52
+ board_kind: :public
53
+ }
54
+ )
55
+ ```
56
+
57
+ ### Private Board
58
+
59
+ Only visible to board subscribers:
60
+
61
+ ```ruby
62
+ response = client.board.create(
63
+ args: {
64
+ board_name: "Executive Planning",
65
+ board_kind: :private
66
+ }
67
+ )
68
+ ```
69
+
70
+ ### Shareable Board
71
+
72
+ Can be shared via link outside your workspace:
73
+
74
+ ```ruby
75
+ response = client.board.create(
76
+ args: {
77
+ board_name: "Client Collaboration",
78
+ board_kind: :share
79
+ }
80
+ )
81
+ ```
82
+
83
+ ## Add Description
84
+
85
+ Include a board description:
86
+
87
+ ```ruby
88
+ response = client.board.create(
89
+ args: {
90
+ board_name: "Q1 Marketing Campaign",
91
+ board_kind: :public,
92
+ description: "Track all marketing initiatives for Q1 2024"
93
+ }
94
+ )
95
+
96
+ if response.success?
97
+ board = response.body.dig("data", "create_board")
98
+ puts "Created: #{board['name']}"
99
+ puts "Description: #{board['description']}"
100
+ end
101
+ ```
102
+
103
+ ## Create from Template
104
+
105
+ Use an existing board as a template:
106
+
107
+ ```ruby
108
+ template_id = 1234567890 # ID of the template board
109
+
110
+ response = client.board.create(
111
+ args: {
112
+ board_name: "New Project from Template",
113
+ board_kind: :public,
114
+ template_id: template_id
115
+ }
116
+ )
117
+
118
+ if response.success?
119
+ board = response.body.dig("data", "create_board")
120
+ puts "✓ Created from template: #{board['name']}"
121
+ end
122
+ ```
123
+
124
+ ::: tip <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"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg>Templates</span>
125
+ Templates copy the board structure (columns, groups, automations) but not the items. Perfect for recurring project types.
126
+ :::
127
+
128
+ ## Create in Workspace
129
+
130
+ Add the board to a specific workspace:
131
+
132
+ ```ruby
133
+ workspace_id = 9876543210
134
+
135
+ response = client.board.create(
136
+ args: {
137
+ board_name: "Product Development",
138
+ board_kind: :public,
139
+ workspace_id: workspace_id
140
+ }
141
+ )
142
+ ```
143
+
144
+ ## Create in Folder
145
+
146
+ Organize boards by placing them in folders:
147
+
148
+ ```ruby
149
+ folder_id = 5555555555
150
+
151
+ response = client.board.create(
152
+ args: {
153
+ board_name: "Sprint Planning",
154
+ board_kind: :public,
155
+ folder_id: folder_id
156
+ }
157
+ )
158
+ ```
159
+
160
+ ## Customize Response Fields
161
+
162
+ Choose which fields to return:
163
+
164
+ ```ruby
165
+ response = client.board.create(
166
+ args: {
167
+ board_name: "Custom Fields Board",
168
+ board_kind: :public
169
+ },
170
+ select: [
171
+ "id",
172
+ "name",
173
+ "description",
174
+ "state",
175
+ "board_folder_id",
176
+ "workspace_id"
177
+ ]
178
+ )
179
+
180
+ if response.success?
181
+ board = response.body.dig("data", "create_board")
182
+
183
+ puts "Board Details:"
184
+ puts " ID: #{board['id']}"
185
+ puts " Name: #{board['name']}"
186
+ puts " State: #{board['state']}"
187
+ puts " Workspace: #{board['workspace_id']}"
188
+ puts " Folder: #{board['board_folder_id'] || 'None'}"
189
+ end
190
+ ```
191
+
192
+ ## Get Board URL
193
+
194
+ Retrieve the board's URL after creation:
195
+
196
+ ```ruby
197
+ response = client.board.create(
198
+ args: {
199
+ board_name: "New Board",
200
+ board_kind: :public
201
+ },
202
+ select: ["id", "name", "url"]
203
+ )
204
+
205
+ if response.success?
206
+ board = response.body.dig("data", "create_board")
207
+ puts "✓ Board created!"
208
+ puts " View at: #{board['url']}"
209
+ end
210
+ ```
211
+
212
+ ## Create with Columns
213
+
214
+ Query the created board to see default columns:
215
+
216
+ ```ruby
217
+ response = client.board.create(
218
+ args: {
219
+ board_name: "Board with Columns",
220
+ board_kind: :public
221
+ },
222
+ select: [
223
+ "id",
224
+ "name",
225
+ {
226
+ columns: ["id", "title", "type"]
227
+ }
228
+ ]
229
+ )
230
+
231
+ if response.success?
232
+ board = response.body.dig("data", "create_board")
233
+
234
+ puts "Board: #{board['name']}"
235
+ puts "Default columns:"
236
+
237
+ board["columns"].each do |column|
238
+ puts " • #{column['title']} (#{column['type']})"
239
+ end
240
+ end
241
+ ```
242
+
243
+ **Example output:**
244
+ ```
245
+ Board: Board with Columns
246
+ Default columns:
247
+ • Name (name)
248
+ • Person (people)
249
+ • Status (color)
250
+ • Date (date)
251
+ ```
252
+
253
+ ## Error Handling
254
+
255
+ Handle common creation errors:
256
+
257
+ ```ruby
258
+ def create_board_safe(client, name, kind)
259
+ response = client.board.create(
260
+ args: {
261
+ board_name: name,
262
+ board_kind: kind
263
+ }
264
+ )
265
+
266
+ if response.success?
267
+ board = response.body.dig("data", "create_board")
268
+ puts "✓ Created: #{board['name']} (ID: #{board['id']})"
269
+ board['id']
270
+ else
271
+ puts "✗ Failed to create board"
272
+ puts " Status: #{response.status}"
273
+
274
+ if response.body["errors"]
275
+ response.body["errors"].each do |error|
276
+ puts " Error: #{error['message']}"
277
+ end
278
+ end
279
+
280
+ nil
281
+ end
282
+ rescue Monday::AuthorizationError
283
+ puts "✗ Invalid API token"
284
+ nil
285
+ rescue Monday::Error => e
286
+ puts "✗ API error: #{e.message}"
287
+ nil
288
+ end
289
+
290
+ # Usage
291
+ board_id = create_board_safe(client, "Safe Board", :public)
292
+ ```
293
+
294
+ ## Complete Example
295
+
296
+ Create a fully configured board:
297
+
298
+ ```ruby
299
+ require "monday_ruby"
300
+ require "dotenv/load"
301
+
302
+ Monday.configure do |config|
303
+ config.token = ENV["MONDAY_TOKEN"]
304
+ end
305
+
306
+ client = Monday::Client.new
307
+
308
+ # Create board with all options
309
+ response = client.board.create(
310
+ args: {
311
+ board_name: "Q1 2024 Projects",
312
+ board_kind: :public,
313
+ description: "All projects planned for Q1 2024",
314
+ workspace_id: 9876543210, # Optional: your workspace ID
315
+ folder_id: 5555555555 # Optional: your folder ID
316
+ },
317
+ select: [
318
+ "id",
319
+ "name",
320
+ "description",
321
+ "url",
322
+ "state",
323
+ {
324
+ columns: ["id", "title", "type"]
325
+ }
326
+ ]
327
+ )
328
+
329
+ if response.success?
330
+ board = response.body.dig("data", "create_board")
331
+
332
+ puts "\n✓ Board Created Successfully\n"
333
+ puts "#{'=' * 50}"
334
+ puts "Name: #{board['name']}"
335
+ puts "ID: #{board['id']}"
336
+ puts "URL: #{board['url']}"
337
+ puts "Description: #{board['description']}"
338
+ puts "\nDefault Columns:"
339
+
340
+ board["columns"].each do |column|
341
+ puts " • #{column['title']} (type: #{column['type']})"
342
+ end
343
+
344
+ puts "#{'=' * 50}"
345
+ else
346
+ puts "\n✗ Failed to create board"
347
+ puts "Status code: #{response.status}"
348
+
349
+ if response.body["error_message"]
350
+ puts "Error: #{response.body['error_message']}"
351
+ end
352
+ end
353
+ ```
354
+
355
+ ## Validate Board Name
356
+
357
+ Check for valid board names before creating:
358
+
359
+ ```ruby
360
+ def valid_board_name?(name)
361
+ return false if name.nil? || name.empty?
362
+ return false if name.length > 255
363
+
364
+ true
365
+ end
366
+
367
+ board_name = "My New Board"
368
+
369
+ if valid_board_name?(board_name)
370
+ response = client.board.create(
371
+ args: {
372
+ board_name: board_name,
373
+ board_kind: :public
374
+ }
375
+ )
376
+ else
377
+ puts "Invalid board name"
378
+ end
379
+ ```
380
+
381
+ ## Next Steps
382
+
383
+ - [Query boards](/guides/boards/query)
384
+ - [Update board settings](/guides/boards/update)
385
+ - [Add items to boards](/guides/items/create)
386
+ - [Duplicate boards](/guides/boards/duplicate)