Work with Items in Groups

Learn how to move items between groups and retrieve paginated items from groups efficiently.

Move Items Between Groups

Reorganize items by moving them to different groups on the same board.

Basic Item Move

Move an item to a different group:

require "monday_ruby"

Monday.configure do |config|
  config.token = ENV["MONDAY_TOKEN"]
end

client = Monday::Client.new

response = client.group.move_item(
  args: {
    item_id: 987654321,
    group_id: "group_mkx1yn2n"
  }
)

if response.success?
  item = response.body.dig("data", "move_item_to_group")
  puts "✓ Moved item #{item['id']} to new group"
end

Move with Group Information

Confirm the new group after moving:

response = client.group.move_item(
  args: {
    item_id: 987654321,
    group_id: "group_mkx1yn2n"
  },
  select: [
    "id",
    "name",
    {
      group: ["id", "title"]
    }
  ]
)

if response.success?
  item = response.body.dig("data", "move_item_to_group")
  group = item["group"]

  puts "✓ Item: #{item['name']}"
  puts "  Moved to: #{group['title']} (#{group['id']})"
end

Output:

✓ Item: Order #1234
  Moved to: Completed Orders (group_mkx1yn2n)

Move Multiple Items

Batch move items to a group:

item_ids = [111, 222, 333, 444, 555]
destination_group = "group_mkx1yn2n"

puts "Moving #{item_ids.length} items..."

item_ids.each do |item_id|
  response = client.group.move_item(
    args: {
      item_id: item_id,
      group_id: destination_group
    }
  )

  if response.success?
    puts "✓ Moved item #{item_id}"
  else
    puts "✗ Failed to move item #{item_id}"
  end
end

puts "Complete!"

Organize Items by Status

Move items based on their status:

# Get items from board
board_response = client.board.items_page(
  board_ids: 123,
  limit: 100,
  select: [
    "id",
    "name",
    {
      column_values: ["id", "text"]
    }
  ]
)

items = board_response.body.dig("data", "boards", 0, "items_page", "items")

# Move completed items to "Done" group
done_group_id = "group_done123"

items.each do |item|
  status_column = item["column_values"].find { |cv| cv["id"] == "status" }

  if status_column && status_column["text"] == "Done"
    response = client.group.move_item(
      args: {
        item_id: item["id"],
        group_id: done_group_id
      }
    )

    puts "✓ Moved #{item['name']} to Done group" if response.success?
  end
end

Paginated Item Retrieval

Efficiently retrieve large numbers of items from groups using cursor-based pagination.

Basic Pagination

Retrieve first page of items:

response = client.group.items_page(
  board_ids: 123,
  group_ids: "group_mkx1yn2n",
  limit: 50
)

if response.success?
  items_page = response.body.dig("data", "boards", 0, "groups", 0, "items_page")
  items = items_page["items"]
  cursor = items_page["cursor"]

  puts "Retrieved #{items.length} items"
  puts "More pages available: #{!cursor.nil?}"
end

Output:

Retrieved 50 items
More pages available: true

Fetch All Pages

Loop through all pages using cursors:

board_id = 123
group_id = "group_mkx1yn2n"
all_items = []
cursor = nil

loop do
  response = client.group.items_page(
    board_ids: board_id,
    group_ids: group_id,
    limit: 100,
    cursor: cursor
  )

  items_page = response.body.dig("data", "boards", 0, "groups", 0, "items_page")
  items = items_page["items"]
  cursor = items_page["cursor"]

  all_items.concat(items)
  puts "Fetched #{items.length} items (total: #{all_items.length})"

  break if cursor.nil?  # No more pages
end

puts "\n✓ Retrieved all #{all_items.length} items"

Output:

Fetched 100 items (total: 100)
Fetched 100 items (total: 200)
Fetched 47 items (total: 247)

✓ Retrieved all 247 items

Multiple Groups

Retrieve items from multiple groups:

response = client.group.items_page(
  board_ids: 123,
  group_ids: ["group_1", "group_2", "group_3"],
  limit: 50
)

if response.success?
  boards = response.body.dig("data", "boards")

  boards.each do |board|
    board["groups"].each do |group|
      items = group["items_page"]["items"]
      cursor = group["items_page"]["cursor"]

      puts "Group has #{items.length} items"
      puts "More pages: #{!cursor.nil?}"
    end
  end
end

Multiple Boards and Groups

Query across multiple boards:

response = client.group.items_page(
  board_ids: [123, 456],
  group_ids: ["group_mkx1yn2n", "group_abc123"],
  limit: 100
)

boards = response.body.dig("data", "boards")

boards.each_with_index do |board, board_index|
  board["groups"].each_with_index do |group, group_index|
    items = group["items_page"]["items"]
    puts "Board #{board_index + 1}, Group #{group_index + 1}: #{items.length} items"
  end
end

Filter Items with Query Params

Retrieve only items matching specific criteria.

Filter by Column Value

Get items with specific status:

response = client.group.items_page(
  board_ids: 123,
  group_ids: "group_mkx1yn2n",
  limit: 100,
  query_params: {
    rules: [
      { column_id: "status", compare_value: [1] }  # Status index 1
    ],
    operator: :and
  }
)

items = response.body.dig("data", "boards", 0, "groups", 0, "items_page", "items")
puts "Found #{items.length} items with selected status"

Multiple Filter Rules

Combine multiple conditions:

response = client.group.items_page(
  board_ids: 123,
  group_ids: "group_mkx1yn2n",
  limit: 100,
  query_params: {
    rules: [
      { column_id: "status", compare_value: [1, 2] },      # Status 1 or 2
      { column_id: "priority", compare_value: [0] }        # High priority
    ],
    operator: :and  # Items must match ALL rules
  }
)

items = response.body.dig("data", "boards", 0, "groups", 0, "items_page", "items")
puts "Found #{items.length} high-priority items in progress"

Filter with OR Operator

Match items meeting any condition:

response = client.group.items_page(
  board_ids: 123,
  group_ids: "group_mkx1yn2n",
  limit: 100,
  query_params: {
    rules: [
      { column_id: "status", compare_value: [0] },    # Not started
      { column_id: "status", compare_value: [5] }     # Stuck
    ],
    operator: :or  # Items matching ANY rule
  }
)

items = response.body.dig("data", "boards", 0, "groups", 0, "items_page", "items")
puts "Found #{items.length} items needing attention"

Filter by Text Column

Search by item name or text column:

response = client.group.items_page(
  board_ids: 123,
  group_ids: "group_mkx1yn2n",
  limit: 100,
  query_params: {
    rules: [
      { column_id: "name", compare_value: ["Test Item 1"] }
    ],
    operator: :and
  }
)

items = response.body.dig("data", "boards", 0, "groups", 0, "items_page", "items")
items.each do |item|
  puts "• #{item['name']}"
end

Custom Field Selection

Retrieve specific fields to reduce response size and improve performance.

Basic Fields

Get essential item information:

response = client.group.items_page(
  board_ids: 123,
  group_ids: "group_mkx1yn2n",
  limit: 50,
  select: ["id", "name", "created_at", "updated_at"]
)

items = response.body.dig("data", "boards", 0, "groups", 0, "items_page", "items")

items.each do |item|
  puts "#{item['name']} (created: #{item['created_at']})"
end

Include Column Values

Get item data with column values:

response = client.group.items_page(
  board_ids: 123,
  group_ids: "group_mkx1yn2n",
  limit: 50,
  select: [
    "id",
    "name",
    {
      column_values: ["id", "text", "value"]
    }
  ]
)

items = response.body.dig("data", "boards", 0, "groups", 0, "items_page", "items")

items.each do |item|
  puts "\nItem: #{item['name']}"
  item["column_values"].each do |cv|
    puts "  #{cv['id']}: #{cv['text']}"
  end
end

Output:

Item: Order #1234
  status: In Progress
  person: John Doe
  date: 2024-01-15

Item: Order #1235
  status: Done
  person: Jane Smith
  date: 2024-01-16

Get group and board information with items:

response = client.group.items_page(
  board_ids: 123,
  group_ids: "group_mkx1yn2n",
  limit: 50,
  select: [
    "id",
    "name",
    {
      group: ["id", "title", "color"]
    },
    {
      board: ["id", "name"]
    }
  ]
)

items = response.body.dig("data", "boards", 0, "groups", 0, "items_page", "items")

items.each do |item|
  puts "#{item['name']} in #{item['group']['title']} on #{item['board']['name']}"
end

Cursor Expiration

Cursors expire after 60 minutes. Handle expired cursors gracefully:

def fetch_all_items(client, board_id, group_id)
  all_items = []
  cursor = nil
  max_retries = 3
  retry_count = 0

  loop do
    begin
      response = client.group.items_page(
        board_ids: board_id,
        group_ids: group_id,
        limit: 100,
        cursor: cursor
      )

      items_page = response.body.dig("data", "boards", 0, "groups", 0, "items_page")
      items = items_page["items"]
      cursor = items_page["cursor"]

      all_items.concat(items)
      puts "Fetched #{items.length} items"

      retry_count = 0  # Reset on success
      break if cursor.nil?

    rescue Monday::Error => e
      retry_count += 1

      if retry_count <= max_retries
        puts "Error: #{e.message}. Retrying from start..."
        cursor = nil  # Start over
        all_items = []
      else
        puts "Max retries reached. Failed to fetch all items."
        raise
      end
    end
  end

  all_items
end

# Usage
items = fetch_all_items(client, 123, "group_mkx1yn2n")
puts "Total items: #{items.length}"

Performance Tips

Optimize pagination for better performance:

Use Appropriate Page Sizes

# For quick scans - smaller pages
response = client.group.items_page(
  board_ids: 123,
  group_ids: "group_mkx1yn2n",
  limit: 25  # Faster initial response
)

# For bulk processing - larger pages
response = client.group.items_page(
  board_ids: 123,
  group_ids: "group_mkx1yn2n",
  limit: 500  # Maximum, fewer requests
)

Request Only Needed Fields

# Good - only necessary fields
response = client.group.items_page(
  board_ids: 123,
  group_ids: "group_mkx1yn2n",
  limit: 100,
  select: ["id", "name"]  # Minimal payload
)

# Avoid - requesting everything
response = client.group.items_page(
  board_ids: 123,
  group_ids: "group_mkx1yn2n",
  limit: 100,
  select: [
    "id", "name", "created_at", "updated_at", "creator_id", "state",
    { column_values: ["id", "text", "value", "additional_info"] },
    { board: ["id", "name", "description", "state", "board_kind"] }
  ]  # Large payload, slower
)

Complete Example

Full workflow for working with group items:

require "monday_ruby"
require "dotenv/load"

Monday.configure do |config|
  config.token = ENV["MONDAY_TOKEN"]
end

client = Monday::Client.new

board_id = 123
in_progress_group = "group_progress"
done_group = "group_done"

# 1. Get all items from "In Progress" group
puts "=== Fetching In Progress Items ==="
all_items = []
cursor = nil

loop do
  response = client.group.items_page(
    board_ids: board_id,
    group_ids: in_progress_group,
    limit: 100,
    cursor: cursor,
    select: [
      "id",
      "name",
      { column_values: ["id", "text"] }
    ]
  )

  items_page = response.body.dig("data", "boards", 0, "groups", 0, "items_page")
  items = items_page["items"]
  cursor = items_page["cursor"]

  all_items.concat(items)
  break if cursor.nil?
end

puts "Found #{all_items.length} items in progress"

# 2. Identify completed items
completed_items = all_items.select do |item|
  status = item["column_values"].find { |cv| cv["id"] == "status" }
  status && status["text"] == "Done"
end

puts "\n=== Moving Completed Items ==="
puts "#{completed_items.length} items are done"

# 3. Move completed items to Done group
completed_items.each do |item|
  response = client.group.move_item(
    args: {
      item_id: item["id"],
      group_id: done_group
    }
  )

  if response.success?
    puts "✓ Moved: #{item['name']}"
  else
    puts "✗ Failed: #{item['name']}"
  end
end

# 4. Verify Done group
puts "\n=== Verifying Done Group ==="
response = client.group.items_page(
  board_ids: board_id,
  group_ids: done_group,
  limit: 100
)

done_items = response.body.dig("data", "boards", 0, "groups", 0, "items_page", "items")
puts "Done group now has #{done_items.length} items"

puts "\n=== Complete ==="
Edit this page
Last updated