# Monday.com

Connect Monday.com to read and write boards, items, and updates from your workflows.

JsWorkflows provides a platform-managed Monday.com OAuth app. You do not need to create a Monday.com app or provide credentials.

Use this connector when your store team manages follow-up work in Monday.com boards. A workflow can detect something in Shopify, then create or update a Monday item for the right team to review.

Good fits include:

- Creating an operations task for delayed fulfillment, high-risk orders, or failed workflow runs
- Sending wholesale, B2B, or custom-order requests into a Monday sales pipeline
- Creating product cleanup tasks for missing images, low stock, incomplete metafields, or catalog review
- Adding return, refund, fraud, or customer-service review items to a shared board
- Updating existing Monday items as Shopify orders, products, or customers move through a process

Monday.com is most useful when the board is already part of your team workflow. If you only need a quick alert, Slack or email is usually simpler.

## Connecting

1. Go to **Settings → OAuth2 Tokens**, click **Connect to Service**, and choose **Monday.com**.
2. Give the connection a name and a handle (e.g., `my-monday`) and click **Generate and Authorize**.
3. A popup opens. If the app is not yet installed on your Monday.com account, you will be prompted to install it first. Click **Install**.
4. After installation, Monday.com shows the authorization screen. Click **Authorize**.
5. The connection appears in your list.

Use lowercase letters, numbers, and hyphens only for the handle.

## Monday.com API

Monday.com uses a GraphQL API. All requests go to `https://api.monday.com/v2` with a `POST` method and the access token in the `Authorization` header. This page uses JsWorkflows' OAuth connector, so the examples send the OAuth token as `Authorization: Bearer <token>`.

The main objects you will usually work with are:

- **Boards**: containers for your operational process
- **Groups**: sections inside a board, such as `New`, `In progress`, or `Done`
- **Items**: tasks or records in a board
- **Columns**: board-specific fields such as status, date, email, long text, people, or numbers

Column IDs are specific to each board. Check the board column settings in Monday.com or query them through the API before writing column values.

## Recommended pattern

Create a small helper so every step handles tokens, HTTP errors, and GraphQL errors consistently.

```js
async function mondayQuery(api, query, variables = {}) {
  const { token, error } = await api.getOAuthToken('my-monday');
  if (error || !token) throw new Error(error || 'Missing Monday.com token');

  const res = await fetch('https://api.monday.com/v2', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${token}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ query, variables }),
  });

  const text = await res.text();
  let json = {};
  try {
    json = text ? JSON.parse(text) : {};
  } catch (_error) {
    json = { raw: text };
  }

  if (!res.ok) {
    throw new Error(`Monday.com HTTP ${res.status}: ${JSON.stringify(json)}`);
  }

  if (json.errors?.length) {
    throw new Error(`Monday.com GraphQL errors: ${JSON.stringify(json.errors)}`);
  }

  return json.data;
}
```

## Example: list boards

```js
export class Workflow {
  async start(_data, _headers, api) {
    const { token, error } = await api.getOAuthToken('my-monday');
    if (error || !token) throw new Error(error || 'Missing Monday.com token');

    const res = await fetch('https://api.monday.com/v2', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${token}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        query: `{ boards(limit: 10) { id name state } }`,
      }),
    });

    if (!res.ok) throw new Error(`Monday.com ${res.status}: ${await res.text()}`);

    const { data } = await res.json();
    data.boards.forEach(b => console.log(b.id, b.name));
  }
}
```

## Example: fetch items from a board

```js
const { token, error } = await api.getOAuthToken('my-monday');
if (error || !token) throw new Error(error || 'Missing Monday.com token');

const boardId = 1234567890; // replace with your board ID

const res = await fetch('https://api.monday.com/v2', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${token}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    query: `{
      boards(ids: [${boardId}]) {
        items_page(limit: 50) {
          cursor
          items {
            id
            name
            column_values { id text }
          }
        }
      }
    }`,
  }),
});

if (!res.ok) throw new Error(`Monday.com ${res.status}: ${await res.text()}`);

const { data } = await res.json();
const { cursor, items } = data.boards[0].items_page;
console.log(`Fetched ${items.length} items`);
```

## Example: create an item

Use GraphQL variables for item names and column values. This avoids escaping problems when order names, customer names, or notes contain quotes or special characters.

```js
const { token, error } = await api.getOAuthToken('my-monday');
if (error || !token) throw new Error(error || 'Missing Monday.com token');

const boardId = 1234567890;
const groupId = 'topics'; // optional; use the target group ID from Monday.com
const itemName = 'Review high-risk order #1001';
const columnValues = {
  status: { label: 'Needs review' },
  text: 'Order #1001 was flagged by a JsWorkflows risk workflow.',
};

const res = await fetch('https://api.monday.com/v2', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${token}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    query: `mutation CreateItem($boardId: ID!, $groupId: String, $itemName: String!, $columnValues: JSON) {
        create_item(
          board_id: $boardId,
          group_id: $groupId,
          item_name: $itemName,
          column_values: $columnValues
        ) {
          id
          name
        }
      }`,
    variables: {
      boardId,
      groupId,
      itemName,
      columnValues: JSON.stringify(columnValues),
    },
  }),
});

if (!res.ok) throw new Error(`Monday.com ${res.status}: ${await res.text()}`);

const { data } = await res.json();
console.log(`Created item ${data.create_item.id}`);
```

To set column values on creation, add a `column_values` argument as a JSON string where each key is the column's ID (visible in the board's column settings). Column IDs are board-specific.

Common column value examples:

```js
const columnValues = {
  status: { label: 'Needs review' },
  date4: { date: '2026-05-29' },
  email: { email: 'customer@example.com', text: 'customer@example.com' },
  numbers: '125.50',
  long_text: 'Notes for the operations team',
};
```

## Example: create a task from a Shopify order

This example shows the shape of a Shopify-to-Monday workflow. It creates one Monday item when the workflow receives an order payload.

```js
const MONDAY_BOARD_ID = 1234567890;
const MONDAY_GROUP_ID = 'topics';

export class Workflow {
  async start(order, _headers, api) {
    const orderName = order.name || `Order ${order.id}`;
    const customerEmail = order.email || order.customer?.email || '';
    const total = order.total_price || order.current_total_price || '';

    const columnValues = {
      status: { label: 'Needs review' },
      email: customerEmail ? { email: customerEmail, text: customerEmail } : undefined,
      numbers: total ? String(total) : undefined,
      long_text: `Created from Shopify order ${orderName}`,
    };

    Object.keys(columnValues).forEach(key => {
      if (columnValues[key] === undefined) delete columnValues[key];
    });

    const data = await mondayQuery(
      api,
      `mutation CreateOrderTask($boardId: ID!, $groupId: String, $itemName: String!, $columnValues: JSON) {
        create_item(
          board_id: $boardId,
          group_id: $groupId,
          item_name: $itemName,
          column_values: $columnValues
        ) {
          id
          name
        }
      }`,
      {
        boardId: MONDAY_BOARD_ID,
        groupId: MONDAY_GROUP_ID,
        itemName: `Review ${orderName}`,
        columnValues: JSON.stringify(columnValues),
      }
    );

    console.log({ status: 'monday-item-created', item: data.create_item });
  }
}
```

Replace `status`, `email`, `numbers`, and `long_text` with the actual column IDs from your board.

## Finding board IDs

Open a board in Monday.com. The board ID is in the URL:

```text
https://yourteam.monday.com/boards/1234567890
                                   ↑ board ID
```

You can also retrieve IDs from the `boards` query shown in the examples above.

## Finding column IDs

Column labels shown in Monday.com are not always the API IDs. To inspect a board's columns:

```js
const data = await mondayQuery(
  api,
  `query BoardColumns($boardId: ID!) {
    boards(ids: [$boardId]) {
      columns {
        id
        title
        type
      }
    }
  }`,
  { boardId: 1234567890 }
);

console.log(data.boards[0].columns);
```

Use the `id` value when setting `column_values`.

## Notes and limitations

- Monday.com column values are type-specific. A status column, date column, email column, and text column all expect different JSON shapes.
- If a mutation returns GraphQL errors, log the full error response while testing so you can see which column value failed.
- Board IDs, group IDs, and column IDs should be stored as setup/config values in production workflows, not hard-coded inside business logic.
- For high-volume workflows, avoid creating a Monday item for every ordinary event. Use Monday.com for exceptions, reviews, handoffs, and tasks that need human follow-up.

## API reference

The Monday.com GraphQL API schema and full query/mutation reference is available at [developer.monday.com/api-reference](https://developer.monday.com/api-reference/docs).