{
  "id": "7HYhF27BN8ULaB1t",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Automated Zoom User Onboarding v2",
  "tags": [],
  "nodes": [
    {
      "id": "86c1a101-1d65-4e24-aba7-65b19cd7a6d4",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -896,
        176
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "a49eedd9-175a-4ade-bba8-8cf74c30417f",
      "name": "Get row(s)",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        -304,
        176
      ],
      "parameters": {
        "matchType": "allConditions",
        "operation": "get",
        "returnAll": true,
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "yLOjlMChh6CiymeJ",
          "cachedResultUrl": "/projects/9PZd7OskyrnA7ugV/datatables/yLOjlMChh6CiymeJ",
          "cachedResultName": "Zoom Access Token"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "0a9b46a4-a9db-4005-87b4-a09d0859b5d4",
      "name": "Sort",
      "type": "n8n-nodes-base.sort",
      "position": [
        -16,
        176
      ],
      "parameters": {
        "options": {},
        "sortFieldsUi": {
          "sortField": [
            {
              "order": "descending",
              "fieldName": "id"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "acb7d18f-e04f-4509-8f5e-4d1e575a17ac",
      "name": "Limit",
      "type": "n8n-nodes-base.limit",
      "position": [
        208,
        176
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "31d1eab8-819e-4d32-94d3-0408d2c23d92",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        480,
        560
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "a567a5f2-f7b1-42c3-a864-a0b8f5ef37c8",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.id }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "4ee5235d-d9ad-4042-b40a-9a90bba68817",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -624,
        -208
      ],
      "parameters": {
        "width": 224,
        "height": 224,
        "content": "Generate your first access token"
      },
      "typeVersion": 1
    },
    {
      "id": "b261ffe6-83bc-4a01-8d6a-ba8bc7b3261f",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        0,
        560
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineAll"
      },
      "typeVersion": 3.2
    },
    {
      "id": "68556d37-0448-41e3-ac83-77c6acd1df55",
      "name": "Get new token",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        480,
        176
      ],
      "parameters": {
        "url": "https://zoom.us/oauth/token",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "form-urlencoded",
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "grant_type",
              "value": "refresh_token"
            },
            {
              "name": "refresh_token",
              "value": "={{ $json.refreshToken }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Basic XXX"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "d3a7053a-308c-4e02-bd24-437674821ae2",
      "name": "Insert new token",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        -560,
        576
      ],
      "parameters": {
        "columns": {
          "value": {
            "accessToken": "={{ $json.access_token }}",
            "refreshToken": "={{ $json.refresh_token }}"
          },
          "schema": [
            {
              "id": "accessToken",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "accessToken",
              "defaultMatch": false
            },
            {
              "id": "refreshToken",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "refreshToken",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "yLOjlMChh6CiymeJ",
          "cachedResultUrl": "/projects/9PZd7OskyrnA7ugV/datatables/yLOjlMChh6CiymeJ",
          "cachedResultName": "Zoom Access Token"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c60278d2-f67e-4aa9-a7e5-d862619ab4ab",
      "name": "Create new user",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        240,
        560
      ],
      "parameters": {
        "url": "https://api.zoom.us/v2/users",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n    \"action\": \"create\",\n    \"user_info\": {\n      \"email\": \"{{ $('Data').item.json.email }}\",\n      \"type\": 2,\n      \"first_name\": \"{{ $('Data').item.json.first_name }}\",\n      \"last_name\": \"{{ $('Data').item.json.last_name }}\",\n      \"password\": \"{{ $json.password }}\"\n    }\n  }",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $json.accessToken }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "12c4599b-9a36-4005-a9b9-e0268769989f",
      "name": "Generate random Password",
      "type": "n8n-nodes-base.set",
      "position": [
        -288,
        448
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "4992d61a-073a-41e0-8eb1-1c0115e91038",
              "name": "password",
              "type": "string",
              "value": "={{ Array.from({length: 15}, () => Math.random().toString(36).charAt(2)).join('') + ['!', '@', '#', '$', '%', '&', '*'][Math.floor(Math.random() * 7)] }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "b4cc86c6-cc2b-41a4-a341-b39747af65f8",
      "name": "Data",
      "type": "n8n-nodes-base.set",
      "position": [
        -560,
        176
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "59d3e7f1-bdc5-4848-9720-8e0989e38118",
              "name": "first_name",
              "type": "string",
              "value": "XXX"
            },
            {
              "id": "b1dcaf80-3981-441c-a84e-cfac1d673107",
              "name": "last_name",
              "type": "string",
              "value": "XXX"
            },
            {
              "id": "860891be-cd97-4fce-bc42-73eef5fc1f18",
              "name": "email",
              "type": "string",
              "value": "XXX"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "2e331458-bc17-4efb-913c-79f3f6f45c50",
      "name": "Insert token",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        -304,
        -144
      ],
      "parameters": {
        "columns": {
          "value": {
            "accessToken": "={{ $json.access_token }}",
            "refreshToken": "={{ $json.refresh_token }}"
          },
          "schema": [
            {
              "id": "accessToken",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "accessToken",
              "defaultMatch": false
            },
            {
              "id": "refreshToken",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "refreshToken",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "yLOjlMChh6CiymeJ",
          "cachedResultUrl": "/projects/9PZd7OskyrnA7ugV/datatables/yLOjlMChh6CiymeJ",
          "cachedResultName": "Zoom Access Token"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "091e87e3-60da-4f12-a90c-c0b7901e48bc",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1344,
        -720
      ],
      "parameters": {
        "color": 5,
        "width": 880,
        "height": 128,
        "content": "## STEP 2\n- Create a Zoom app OAuth App standard (not Server-to-Server)\n- Get your Zoom account_id\n- In the 'authorization' field insert your BASE64_ENCODED_CLIENTID_CLIENTSECRET (base64 of client_id:client_secret)\n \n"
      },
      "typeVersion": 1
    },
    {
      "id": "7c4edf19-e0a5-4fe8-badf-51ee4d86339b",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1344,
        -560
      ],
      "parameters": {
        "color": 5,
        "width": 880,
        "height": 96,
        "content": "## STEP 3\n- Only for the rist time run the node \"Zoom First Access Token\""
      },
      "typeVersion": 1
    },
    {
      "id": "e3d9e93f-8739-4670-ade8-5f2859560d4e",
      "name": "Zoom First Access Token",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -560,
        -144
      ],
      "parameters": {
        "url": "https://zoom.us/oauth/token",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "form-urlencoded",
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "grant_type",
              "value": "authorization_code"
            },
            {
              "name": "code",
              "value": "g85Ozx4O8sDdreaDztqRAmNk9zb_1Y3sA"
            },
            {
              "name": "redirect_uri",
              "value": "https://oauth.n8n.cloud/oauth2/callback"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "authorization",
              "value": "Basic XXX"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "32b47e94-f15c-4230-9bdc-c841f1e8173c",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1344,
        -1056
      ],
      "parameters": {
        "color": 3,
        "width": 880,
        "height": 176,
        "content": "## Automated Zoom User Onboarding with Automatic Token Management\nThis workflow automates the management of Zoom OAuth tokens and the creation of new Zoom users through the Zoom API.\n\nThis workflow automates the process of creating a new Zoom user by first ensuring a valid OAuth access token is available. It is designed to handle the fact that Zoom access tokens are short-lived (1 hour) by using a longer-lived refresh token (90 days) stored in an n8n Data Table."
      },
      "typeVersion": 1
    },
    {
      "id": "1b56e62a-d711-41ef-bb08-fb0d1667c36b",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1344,
        -848
      ],
      "parameters": {
        "color": 5,
        "width": 880,
        "height": 96,
        "content": "## STEP 1\n- Create a new n8n table with 2 fields: accessToken and refreshToken\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b52a85e3-3fdb-4c47-b167-17253c1df61f",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -608,
        112
      ],
      "parameters": {
        "width": 192,
        "height": 208,
        "content": "First name, Last name about the user to create"
      },
      "typeVersion": 1
    },
    {
      "id": "934e4bd3-4ae3-4ebe-9426-759fcb56f227",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1344,
        -432
      ],
      "parameters": {
        "color": 5,
        "width": 880,
        "height": 96,
        "content": "## STEP 4\n- Set first name, last name and email in the node \"Data\""
      },
      "typeVersion": 1
    },
    {
      "id": "327b0b9d-4908-42b2-b56a-9c437e93d5b3",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -336,
        112
      ],
      "parameters": {
        "width": 672,
        "height": 208,
        "content": "Get only the recent token added"
      },
      "typeVersion": 1
    },
    {
      "id": "6fe40db4-1027-4c36-83f0-079171f82c72",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -608,
        512
      ],
      "parameters": {
        "width": 208,
        "height": 208,
        "content": "Add the new token and refresh_token in the table"
      },
      "typeVersion": 1
    },
    {
      "id": "23a15fb0-5bdb-455f-94c2-8445284c38da",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        176,
        512
      ],
      "parameters": {
        "width": 208,
        "height": 208,
        "content": "Create new Zoom user"
      },
      "typeVersion": 1
    },
    {
      "id": "d4e85960-181b-4e55-b042-6436a414854e",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        448,
        512
      ],
      "parameters": {
        "width": 208,
        "height": 208,
        "content": "If the are seat avaiable, an email to new user"
      },
      "typeVersion": 1
    },
    {
      "id": "3a3a2b9f-29fb-44a2-8fd4-28da6cdb7f97",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -432,
        -1056
      ],
      "parameters": {
        "width": 448,
        "height": 720,
        "content": "## How it works\n1.  **Trigger and Data Retrieval:** The workflow starts manually. It first retrieves user data (first name, last name, email) from the \"Data\" node. In parallel, it fetches all stored token records from a Data Table.\n2.  **Token Management:** The retrieved tokens are sorted and limited to get only the most recent one. This latest token (which contains the `refresh_token`) is then used in an HTTP Request to Zoom's OAuth endpoint to generate a fresh, valid `access_token`.\n3.  **User Creation:** The new `access_token` and `refresh_token` are saved back to the Data Table for future use. The workflow then generates a random password for the new user, merges this password with the initial user data, and finally sends a POST request to the Zoom API to create the new user. If the creation is successful, Zoom automatically sends an invitation email to the new user."
      },
      "typeVersion": 1
    },
    {
      "id": "55a3a748-6117-4ec5-b279-4c5333c4c941",
      "name": "Sticky Note12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        64,
        -1056
      ],
      "parameters": {
        "width": 736,
        "height": 720,
        "content": "## Set up steps\n\n1.  **Prepare the Data Table:**\n    *   Create a new Data Table in your n8n project.\n    *   Add two columns to it: `accessToken` and `refreshToken`.\n\n2.  **Configure Zoom OAuth App:**\n    *   Create a standard OAuth app in the Zoom Marketplace (not a Server-to-Server app).\n    *   Note your Zoom `account_id`.\n    *   Encode your Zoom app's `client_id` and `client_secret` in Base64 format (as `client_id:client_secret`).\n    *   In both the \"Get new token\" and \"Zoom First Access Token\" nodes, replace the `\"XXX\"` in the `Authorization` header with this Base64-encoded string.\n\n3.  **Generate Initial Tokens (First Run Only):**\n    *   Manually execute the \"Zoom First Access Token\" node once. This node uses an authorization code to fetch the first-ever access and refresh tokens and saves them to your Data Table. The main workflow will use these stored tokens from this point forward.\n\n4.  **Configure User Data:**\n    *   In the \"Data\" node, set the default values for the new Zoom user by replacing the `\"XXX\"` placeholders for `first_name`, `last_name`, and `email`.\n\nAfter these setup steps, the main workflow (triggered via \"When clicking 'Execute workflow'\") can be run whenever you need to create a new Zoom user. It will automatically refresh the token and use the provided user data to create the account."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "cb9bf634-795c-46e2-920d-9b06a56efdbd",
  "connections": {
    "If": {
      "main": [
        []
      ]
    },
    "Data": {
      "main": [
        [
          {
            "node": "Get row(s)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sort": {
      "main": [
        [
          {
            "node": "Limit",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Limit": {
      "main": [
        [
          {
            "node": "Get new token",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "Create new user",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get row(s)": {
      "main": [
        [
          {
            "node": "Sort",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get new token": {
      "main": [
        [
          {
            "node": "Insert new token",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create new user": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert new token": {
      "main": [
        [
          {
            "node": "Generate random Password",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Zoom First Access Token": {
      "main": [
        [
          {
            "node": "Insert token",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate random Password": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}