# nodes

node_type: n8n-nodes-base.GoToWebinar
name: GoToWebinar
display_name: GoToWebinar
description: Consume the GoToWebinar API
category: Other
code_hash: 477c98f0558a9020e82b630957e1037aac792527cbe9a47e226875a9af67f884
documentation_url: https://docs.n8n.io/integrations/builtin/credentials/gotowebinar
example_parameters: {}
properties_schema: []
package_name: n8n-nodes-base
extracted_at: 2025-06-08 08:05:22
updated_at: 2025-06-08 08:05:22
source_code:
  "use strict";
  var __importDefault = (this && this.__importDefault) || function (mod) {
      return (mod && mod.__esModule) ? mod : { "default": mod };
  };
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.GoToWebinar = void 0;
  const n8n_workflow_1 = require("n8n-workflow");
  const descriptions_1 = require("./descriptions");
  const GenericFunctions_1 = require("./GenericFunctions");
  const isEmpty_1 = __importDefault(require("lodash/isEmpty"));
  const omit_1 = __importDefault(require("lodash/omit"));
  const moment_timezone_1 = __importDefault(require("moment-timezone"));
  class GoToWebinar {
      constructor() {
          this.description = {
              displayName: 'GoToWebinar',
              name: 'goToWebinar',
              icon: 'file:gotowebinar.svg',
              group: ['transform'],
              version: 1,
              subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
              description: 'Consume the GoToWebinar API',
              defaults: {
                  name: 'GoToWebinar',
              },
              inputs: ['main'],
              outputs: ['main'],
              credentials: [
                  {
                      name: 'goToWebinarOAuth2Api',
                      required: true,
                  },
              ],
              properties: [
                  {
                      displayName: 'Resource',
                      name: 'resource',
                      type: 'options',
                      noDataExpression: true,
                      options: [
                          {
                              name: 'Attendee',
                              value: 'attendee',
                          },
                          {
                              name: 'Co-Organizer',
                              value: 'coorganizer',
                          },
                          {
                              name: 'Panelist',
                              value: 'panelist',
                          },
                          {
                              name: 'Registrant',
                              value: 'registrant',
                          },
                          {
                              name: 'Session',
                              value: 'session',
                          },
                          {
                              name: 'Webinar',
                              value: 'webinar',
                          },
                      ],
                      default: 'attendee',
                  },
                  ...descriptions_1.attendeeOperations,
                  ...descriptions_1.attendeeFields,
                  ...descriptions_1.coorganizerOperations,
                  ...descriptions_1.coorganizerFields,
                  ...descriptions_1.panelistOperations,
                  ...descriptions_1.panelistFields,
                  ...descriptions_1.registrantOperations,
                  ...descriptions_1.registrantFields,
                  ...descriptions_1.sessionOperations,
                  ...descriptions_1.sessionFields,
                  ...descriptions_1.webinarOperations,
                  ...descriptions_1.webinarFields,
              ],
          };
          this.methods = {
              loadOptions: {
                  async getWebinars() {
                      return GenericFunctions_1.loadWebinars.call(this);
                  },
                  async getAnswers() {
                      return GenericFunctions_1.loadAnswers.call(this);
                  },
                  async getWebinarSessions() {
                      return GenericFunctions_1.loadWebinarSessions.call(this);
                  },
                  async getTimezones() {
                      const returnData = [];
                      for (const timezone of moment_timezone_1.default.tz.names()) {
                          const timezoneName = timezone;
                          const timezoneId = timezone;
                          returnData.push({
                              name: timezoneName,
                              value: timezoneId,
                          });
                      }
                      return returnData;
                  },
                  async getRegistranSimpleQuestions() {
                      return GenericFunctions_1.loadRegistranSimpleQuestions.call(this);
                  },
                  async getRegistranMultiChoiceQuestions() {
                      return GenericFunctions_1.loadRegistranMultiChoiceQuestions.call(this);
                  },
              },
          };
      }
      async execute() {
          const items = this.getInputData();
          const resource = this.getNodeParameter('resource', 0);
          const operation = this.getNodeParameter('operation', 0);
          let responseData;
          const returnData = [];
          const { oauthTokenData } = (await this.getCredentials('goToWebinarOAuth2Api'));
          const accountKey = oauthTokenData.account_key;
          const organizerKey = oauthTokenData.organizer_key;
          for (let i = 0; i < items.length; i++) {
              try {
                  if (resource === 'attendee') {
                      if (operation === 'get') {
                          const webinarKey = this.getNodeParameter('webinarKey', i);
                          const sessionKey = this.getNodeParameter('sessionKey', i);
                          const registrantKey = this.getNodeParameter('registrantKey', i);
                          const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}/sessions/${sessionKey}/attendees/${registrantKey}`;
                          responseData = await GenericFunctions_1.goToWebinarApiRequest.call(this, 'GET', endpoint, {}, {});
                      }
                      else if (operation === 'getAll') {
                          const webinarKey = this.getNodeParameter('webinarKey', i);
                          const sessionKey = this.getNodeParameter('sessionKey', i);
                          const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}/sessions/${sessionKey}/attendees`;
                          responseData = await GenericFunctions_1.handleGetAll.call(this, endpoint, {}, {}, resource);
                      }
                      else if (operation === 'getDetails') {
                          const webinarKey = this.getNodeParameter('webinarKey', i);
                          const sessionKey = this.getNodeParameter('sessionKey', i);
                          const registrantKey = this.getNodeParameter('registrantKey', i);
                          const details = this.getNodeParameter('details', i);
                          const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}/sessions/${sessionKey}/attendees/${registrantKey}/${details}`;
                          responseData = await GenericFunctions_1.goToWebinarApiRequest.call(this, 'GET', endpoint, {}, {});
                      }
                  }
                  else if (resource === 'coorganizer') {
                      if (operation === 'create') {
                          const webinarKey = this.getNodeParameter('webinarKey', i);
                          const body = {
                              external: this.getNodeParameter('isExternal', i),
                          };
                          if (body.external === false) {
                              body.organizerKey = this.getNodeParameter('organizerKey', i);
                          }
                          if (body.external === true) {
                              body.givenName = this.getNodeParameter('givenName', i);
                              body.email = this.getNodeParameter('email', i);
                          }
                          const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}/coorganizers`;
                          responseData = await GenericFunctions_1.goToWebinarApiRequest.call(this, 'POST', endpoint, {}, [body]);
                      }
                      else if (operation === 'delete') {
                          const webinarKey = this.getNodeParameter('webinarKey', i);
                          const coorganizerKey = this.getNodeParameter('coorganizerKey', i);
                          const qs = {
                              external: this.getNodeParameter('isExternal', i),
                          };
                          const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}/coorganizers/${coorganizerKey}`;
                          responseData = await GenericFunctions_1.goToWebinarApiRequest.call(this, 'DELETE', endpoint, qs, {});
                          responseData = { success: true };
                      }
                      else if (operation === 'getAll') {
                          const webinarKey = this.getNodeParameter('webinarKey', i);
                          const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}/coorganizers`;
                          responseData = await GenericFunctions_1.handleGetAll.call(this, endpoint, {}, {}, resource);
                      }
                      else if (operation === 'reinvite') {
                          const webinarKey = this.getNodeParameter('webinarKey', i);
                          const coorganizerKey = this.getNodeParameter('coorganizerKey', i);
                          const qs = {
                              external: this.getNodeParameter('isExternal', i),
                          };
                          const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}/coorganizers/${coorganizerKey}/resendInvitation`;
                          responseData = await GenericFunctions_1.goToWebinarApiRequest.call(this, 'POST', endpoint, qs, {});
                          responseData = { success: true };
                      }
                  }
                  else if (resource === 'panelist') {
                      if (operation === 'create') {
                          const webinarKey = this.getNodeParameter('webinarKey', i);
                          const body = [
                              {
                                  name: this.getNodeParameter('name', i),
                                  email: this.getNodeParameter('email', i),
                              },
                          ];
                          const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}/panelists`;
                          responseData = await GenericFunctions_1.goToWebinarApiRequest.call(this, 'POST', endpoint, {}, body);
                      }
                      else if (operation === 'delete') {
                          const webinarKey = this.getNodeParameter('webinarKey', i);
                          const panelistKey = this.getNodeParameter('panelistKey', i);
                          const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}/panelists/${panelistKey}`;
                          responseData = await GenericFunctions_1.goToWebinarApiRequest.call(this, 'DELETE', endpoint, {}, {});
                          responseData = { success: true };
                      }
                      else if (operation === 'getAll') {
                          const webinarKey = this.getNodeParameter('webinarKey', i);
                          const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}/panelists`;
                          responseData = await GenericFunctions_1.handleGetAll.call(this, endpoint, {}, {}, resource);
                      }
                      else if (operation === 'reinvite') {
                          const webinarKey = this.getNodeParameter('webinarKey', i);
                          const panelistKey = this.getNodeParameter('panelistKey', i);
                          const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}/panelists/${panelistKey}/resendInvitation`;
                          responseData = await GenericFunctions_1.goToWebinarApiRequest.call(this, 'POST', endpoint, {}, {});
                          responseData = { success: true };
                      }
                  }
                  else if (resource === 'registrant') {
                      if (operation === 'create') {
                          const webinarKey = this.getNodeParameter('webinarKey', i);
                          const qs = {};
                          const body = {
                              firstName: this.getNodeParameter('firstName', i),
                              lastName: this.getNodeParameter('lastName', i),
                              email: this.getNodeParameter('email', i),
                              responses: [],
                          };
                          let additionalFields = this.getNodeParameter('additionalFields', i);
                          if (additionalFields.resendConfirmation) {
                              qs.resendConfirmation = additionalFields.resendConfirmation;
                              additionalFields = (0, omit_1.default)(additionalFields, ['resendConfirmation']);
                          }
                          if (additionalFields.fullAddress) {
                              Object.assign(body, additionalFields.fullAddress.details);
                              additionalFields = (0, omit_1.default)(additionalFields, ['fullAddress']);
                          }
                          if (additionalFields.simpleResponses) {
                              body.responses.push(...additionalFields.simpleResponses.details);
                              additionalFields = (0, omit_1.default)(additionalFields, ['simpleResponses']);
                          }
                          if (additionalFields.multiChoiceResponses) {
                              body.responses.push(...additionalFields.multiChoiceResponses.details);
                              additionalFields = (0, omit_1.default)(additionalFields, ['multiChoiceResponses']);
                          }
                          Object.assign(body, additionalFields);
                          const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}/registrants`;
                          responseData = await GenericFunctions_1.goToWebinarApiRequest.call(this, 'POST', endpoint, qs, body);
                      }
                      else if (operation === 'delete') {
                          const webinarKey = this.getNodeParameter('webinarKey', i);
                          const registrantKey = this.getNodeParameter('registrantKey', i);
                          const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}/registrants/${registrantKey}`;
                          responseData = await GenericFunctions_1.goToWebinarApiRequest.call(this, 'DELETE', endpoint, {}, {});
                          responseData = { success: true };
                      }
                      else if (operation === 'get') {
                          const webinarKey = this.getNodeParameter('webinarKey', i);
                          const registrantKey = this.getNodeParameter('registrantKey', i);
                          const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}/registrants/${registrantKey}`;
                          responseData = await GenericFunctions_1.goToWebinarApiRequest.call(this, 'GET', endpoint, {}, {});
                      }
                      else if (operation === 'getAll') {
                          const webinarKey = this.getNodeParameter('webinarKey', i);
                          const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}/registrants`;
                          responseData = await GenericFunctions_1.handleGetAll.call(this, endpoint, {}, {}, resource);
                      }
                  }
                  else if (resource === 'session') {
                      if (operation === 'get') {
                          const webinarKey = this.getNodeParameter('webinarKey', i);
                          const sessionKey = this.getNodeParameter('sessionKey', i);
                          const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}/sessions/${sessionKey}`;
                          responseData = await GenericFunctions_1.goToWebinarApiRequest.call(this, 'GET', endpoint, {}, {});
                      }
                      else if (operation === 'getAll') {
                          const qs = {};
                          const returnAll = this.getNodeParameter('returnAll', 0);
                          if (!returnAll) {
                              qs.limit = this.getNodeParameter('limit', 0);
                          }
                          const { webinarKey, times } = this.getNodeParameter('additionalFields', i);
                          if (times) {
                              qs.fromTime = (0, moment_timezone_1.default)(times.timesProperties.fromTime).format();
                              qs.toTime = (0, moment_timezone_1.default)(times.timesProperties.toTime).format();
                          }
                          else {
                              qs.fromTime = (0, moment_timezone_1.default)().subtract(1, 'years').format();
                              qs.toTime = (0, moment_timezone_1.default)().format();
                          }
                          if (webinarKey !== undefined) {
                              const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}/sessions`;
                              responseData = await GenericFunctions_1.goToWebinarApiRequestAllItems.call(this, 'GET', endpoint, qs, {}, resource);
                          }
                          else {
                              const endpoint = `organizers/${organizerKey}/sessions`;
                              responseData = await GenericFunctions_1.goToWebinarApiRequestAllItems.call(this, 'GET', endpoint, qs, {}, resource);
                          }
                      }
                      else if (operation === 'getDetails') {
                          const webinarKey = this.getNodeParameter('webinarKey', i);
                          const sessionKey = this.getNodeParameter('sessionKey', i);
                          const details = this.getNodeParameter('details', i);
                          const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}/sessions/${sessionKey}/${details}`;
                          responseData = await GenericFunctions_1.goToWebinarApiRequest.call(this, 'GET', endpoint, {}, {});
                      }
                  }
                  else if (resource === 'webinar') {
                      if (operation === 'create') {
                          const timesProperties = this.getNodeParameter('times.timesProperties', i, []);
                          const body = {
                              subject: this.getNodeParameter('subject', i),
                              times: timesProperties,
                          };
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          Object.assign(body, additionalFields);
                          const endpoint = `organizers/${organizerKey}/webinars`;
                          responseData = await GenericFunctions_1.goToWebinarApiRequest.call(this, 'POST', endpoint, {}, body);
                      }
                      else if (operation === 'delete') {
                          const webinarKey = this.getNodeParameter('webinarKey', i);
                          const { sendCancellationEmails } = this.getNodeParameter('additionalFields', i);
                          const qs = {};
                          if (sendCancellationEmails) {
                              qs.sendCancellationEmails = sendCancellationEmails;
                          }
                          const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}`;
                          await GenericFunctions_1.goToWebinarApiRequest.call(this, 'DELETE', endpoint, qs, {});
                          responseData = { success: true };
                      }
                      else if (operation === 'get') {
                          const webinarKey = this.getNodeParameter('webinarKey', i);
                          const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}`;
                          responseData = await GenericFunctions_1.goToWebinarApiRequest.call(this, 'GET', endpoint, {}, {});
                      }
                      else if (operation === 'getAll') {
                          const qs = {};
                          const returnAll = this.getNodeParameter('returnAll', 0);
                          if (!returnAll) {
                              qs.limit = this.getNodeParameter('limit', 0);
                          }
                          const { times } = this.getNodeParameter('additionalFields', i);
                          if (times) {
                              qs.fromTime = (0, moment_timezone_1.default)(times.timesProperties.fromTime).format();
                              qs.toTime = (0, moment_timezone_1.default)(times.timesProperties.toTime).format();
                          }
                          else {
                              qs.fromTime = (0, moment_timezone_1.default)().subtract(1, 'years').format();
                              qs.toTime = (0, moment_timezone_1.default)().format();
                          }
                          const endpoint = `accounts/${accountKey}/webinars`;
                          responseData = await GenericFunctions_1.goToWebinarApiRequestAllItems.call(this, 'GET', endpoint, qs, {}, resource);
                      }
                      else if (operation === 'update') {
                          const webinarKey = this.getNodeParameter('webinarKey', i);
                          const qs = {
                              notifyParticipants: this.getNodeParameter('notifyParticipants', i),
                          };
                          let body = {};
                          let updateFields = this.getNodeParameter('updateFields', i);
                          if (updateFields.times) {
                              const { times } = updateFields;
                              body = {
                                  times: times.timesProperties,
                              };
                              updateFields = (0, omit_1.default)(updateFields, ['times']);
                          }
                          Object.assign(body, updateFields);
                          if ((0, isEmpty_1.default)(updateFields)) {
                              throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Please enter at least one field to update for the ${resource}.`, { itemIndex: i });
                          }
                          const endpoint = `organizers/${organizerKey}/webinars/${webinarKey}`;
                          await GenericFunctions_1.goToWebinarApiRequest.call(this, 'PUT', endpoint, qs, body);
                          responseData = { success: true };
                      }
                  }
              }
              catch (error) {
                  if (this.continueOnFail()) {
                      const executionErrorData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray({ error: error.message }), { itemData: { item: i } });
                      returnData.push(...executionErrorData);
                      continue;
                  }
                  throw error;
              }
              const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
              returnData.push(...executionData);
          }
          return [returnData];
      }
  }
  exports.GoToWebinar = GoToWebinar;
  //# sourceMappingURL=GoToWebinar.node.js.map

documentation_markdown:
  ---
  #https://www.notion.so/n8n/Frontmatter-432c2b8dff1f43d4b1c8d20075510fe4
  title: GoToWebinar credentials
  description: Documentation for GoToWebinar credentials. Use these credentials to authenticate GoToWebinar in n8n, a workflow automation platform.
  contentType: [integration, reference]
  ---

  # GoTo Webinar credentials

  You can use these credentials to authenticate the following nodes:

  - [GoToWebinar](/integrations/builtin/app-nodes/n8n-nodes-base.gotowebinar.md)

  ## Prerequisites

  Create a [GoToWebinar](https://www.goto.com/webinar){:target=_blank .external-link} account with [Developer Center](https://developer.goto.com/){:target=_blank .external-link} access.

  ## Supported authentication methods

  - OAuth2

  ## Related resources

  Refer to [GoToWebinar's API documentation](https://developer.goto.com/GoToWebinarV2){:target=_blank .external-link} for more information about authenticating with the service.

  ## Using OAuth2

  To configure this credential, you'll need:

  - A **Client ID**: Provided once you create an OAuth client
  - A **Client Secret**: Provided once you create an OAuth client

  Refer to the [Create an OAuth client documentation](https://developer.goto.com/guides/Get%20Started/02_HOW_createClient/){:target=_blank .external-link} for detailed instructions on creating an OAuth client. Copy the **OAuth Callback URL** from n8n to use as the **Redirect URI** in your OAuth client. The Client ID and Client secret are provided once you've finished setting up your client.

example_workflow:
  {"nodes":[{"parameters":{},"type":"n8n-nodes-base.node","typeVersion":1,"position":[220,120],"id":"1523fa9b-cd20-4237-94ca-bfacdcf1e473","name":"Node"}],"connections":{"Node":{"main":[[]]}},"pinData":{},"meta":{"templateCredsSetupCompleted":true,"instanceId":"e90e9815c40e0dce524046fda8294ad869f83777caa2b3b071d8093a008aa485"}}


node_type: n8n-nodes-base.Gitlab
name: Gitlab
display_name: GitLab
description: Retrieve data from GitLab API
category: Other
code_hash: 202529f826b67f848238e5d8a754b41d8ad35c4213dab7a775f0a7af3b15fbcd
documentation_url: https://docs.n8n.io/integrations/builtin/credentials/gitlab
example_parameters: {}
properties_schema: []
package_name: n8n-nodes-base
extracted_at: 2025-06-08 08:05:22
updated_at: 2025-06-08 08:05:22
source_code:
  "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.Gitlab = void 0;
  const n8n_workflow_1 = require("n8n-workflow");
  const GenericFunctions_1 = require("./GenericFunctions");
  class Gitlab {
      constructor() {
          this.description = {
              displayName: 'GitLab',
              name: 'gitlab',
              icon: 'file:gitlab.svg',
              group: ['input'],
              version: 1,
              subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
              description: 'Retrieve data from GitLab API',
              defaults: {
                  name: 'GitLab',
              },
              inputs: ['main'],
              outputs: ['main'],
              credentials: [
                  {
                      name: 'gitlabApi',
                      required: true,
                      displayOptions: {
                          show: {
                              authentication: ['accessToken'],
                          },
                      },
                  },
                  {
                      name: 'gitlabOAuth2Api',
                      required: true,
                      displayOptions: {
                          show: {
                              authentication: ['oAuth2'],
                          },
                      },
                  },
              ],
              properties: [
                  {
                      displayName: 'Authentication',
                      name: 'authentication',
                      type: 'options',
                      options: [
                          {
                              name: 'Access Token',
                              value: 'accessToken',
                          },
                          {
                              name: 'OAuth2',
                              value: 'oAuth2',
                          },
                      ],
                      default: 'accessToken',
                  },
                  {
                      displayName: 'Resource',
                      name: 'resource',
                      type: 'options',
                      noDataExpression: true,
                      options: [
                          {
                              name: 'File',
                              value: 'file',
                          },
                          {
                              name: 'Issue',
                              value: 'issue',
                          },
                          {
                              name: 'Release',
                              value: 'release',
                          },
                          {
                              name: 'Repository',
                              value: 'repository',
                          },
                          {
                              name: 'User',
                              value: 'user',
                          },
                      ],
                      default: 'issue',
                  },
                  {
                      displayName: 'Operation',
                      name: 'operation',
                      type: 'options',
                      noDataExpression: true,
                      displayOptions: {
                          show: {
                              resource: ['issue'],
                          },
                      },
                      options: [
                          {
                              name: 'Create',
                              value: 'create',
                              description: 'Create a new issue',
                              action: 'Create an issue',
                          },
                          {
                              name: 'Create Comment',
                              value: 'createComment',
                              description: 'Create a new comment on an issue',
                              action: 'Create a comment on an issue',
                          },
                          {
                              name: 'Edit',
                              value: 'edit',
                              description: 'Edit an issue',
                              action: 'Edit an issue',
                          },
                          {
                              name: 'Get',
                              value: 'get',
                              description: 'Get the data of a single issue',
                              action: 'Get an issue',
                          },
                          {
                              name: 'Lock',
                              value: 'lock',
                              description: 'Lock an issue',
                              action: 'Lock an issue',
                          },
                      ],
                      default: 'create',
                  },
                  {
                      displayName: 'Operation',
                      name: 'operation',
                      type: 'options',
                      noDataExpression: true,
                      displayOptions: {
                          show: {
                              resource: ['repository'],
                          },
                      },
                      options: [
                          {
                              name: 'Get',
                              value: 'get',
                              description: 'Get the data of a single repository',
                              action: 'Get a repository',
                          },
                          {
                              name: 'Get Issues',
                              value: 'getIssues',
                              description: 'Returns issues of a repository',
                              action: 'Get issues of a repository',
                          },
                      ],
                      default: 'getIssues',
                  },
                  {
                      displayName: 'Operation',
                      name: 'operation',
                      type: 'options',
                      noDataExpression: true,
                      displayOptions: {
                          show: {
                              resource: ['user'],
                          },
                      },
                      options: [
                          {
                              name: 'Get Repositories',
                              value: 'getRepositories',
                              description: 'Returns the repositories of a user',
                              action: "Get a user's repositories",
                          },
                      ],
                      default: 'getRepositories',
                  },
                  {
                      displayName: 'Operation',
                      name: 'operation',
                      type: 'options',
                      noDataExpression: true,
                      displayOptions: {
                          show: {
                              resource: ['release'],
                          },
                      },
                      options: [
                          {
                              name: 'Create',
                              value: 'create',
                              description: 'Create a new release',
                              action: 'Create a release',
                          },
                          {
                              name: 'Delete',
                              value: 'delete',
                              description: 'Delete a release',
                              action: 'Delete a release',
                          },
                          {
                              name: 'Get',
                              value: 'get',
                              description: 'Get a release',
                              action: 'Get a release',
                          },
                          {
                              name: 'Get Many',
                              value: 'getAll',
                              description: 'Get many releases',
                              action: 'Get many releases',
                          },
                          {
                              name: 'Update',
                              value: 'update',
                              description: 'Update a release',
                              action: 'Update a release',
                          },
                      ],
                      default: 'create',
                  },
                  {
                      displayName: 'Operation',
                      name: 'operation',
                      type: 'options',
                      noDataExpression: true,
                      displayOptions: {
                          show: {
                              resource: ['file'],
                          },
                      },
                      options: [
                          {
                              name: 'Create',
                              value: 'create',
                              description: 'Create a new file in repository',
                              action: 'Create a file',
                          },
                          {
                              name: 'Delete',
                              value: 'delete',
                              description: 'Delete a file in repository',
                              action: 'Delete a file',
                          },
                          {
                              name: 'Edit',
                              value: 'edit',
                              description: 'Edit a file in repository',
                              action: 'Edit a file',
                          },
                          {
                              name: 'Get',
                              value: 'get',
                              description: 'Get the data of a single file',
                              action: 'Get a file',
                          },
                          {
                              name: 'List',
                              value: 'list',
                              description: 'List contents of a folder',
                              action: 'List files',
                          },
                      ],
                      default: 'create',
                  },
                  {
                      displayName: 'Project Owner',
                      name: 'owner',
                      type: 'string',
                      default: '',
                      required: true,
                      placeholder: 'n8n-io',
                      description: 'User, group or namespace of the project',
                  },
                  {
                      displayName: 'Project Name',
                      name: 'repository',
                      type: 'string',
                      default: '',
                      required: true,
                      displayOptions: {
                          hide: {
                              resource: ['user'],
                              operation: ['getRepositories'],
                          },
                      },
                      placeholder: 'n8n',
                      description: 'The name of the project',
                  },
                  {
                      displayName: 'Title',
                      name: 'title',
                      type: 'string',
                      default: '',
                      required: true,
                      displayOptions: {
                          show: {
                              operation: ['create'],
                              resource: ['issue'],
                          },
                      },
                      description: 'The title of the issue',
                  },
                  {
                      displayName: 'Body',
                      name: 'body',
                      type: 'string',
                      typeOptions: {
                          rows: 5,
                      },
                      default: '',
                      displayOptions: {
                          show: {
                              operation: ['create'],
                              resource: ['issue'],
                          },
                      },
                      description: 'The body of the issue',
                  },
                  {
                      displayName: 'Due Date',
                      name: 'due_date',
                      type: 'dateTime',
                      displayOptions: {
                          show: {
                              operation: ['create'],
                              resource: ['issue'],
                          },
                      },
                      default: '',
                      description: 'Due Date for issue',
                  },
                  {
                      displayName: 'Labels',
                      name: 'labels',
                      type: 'collection',
                      typeOptions: {
                          multipleValues: true,
                          multipleValueButtonText: 'Add Label',
                      },
                      displayOptions: {
                          show: {
                              operation: ['create'],
                              resource: ['issue'],
                          },
                      },
                      default: { label: '' },
                      options: [
                          {
                              displayName: 'Label',
                              name: 'label',
                              type: 'string',
                              default: '',
                              description: 'Label to add to issue',
                          },
                      ],
                  },
                  {
                      displayName: 'Assignees',
                      name: 'assignee_ids',
                      type: 'collection',
                      typeOptions: {
                          multipleValues: true,
                          multipleValueButtonText: 'Add Assignee',
                      },
                      displayOptions: {
                          show: {
                              operation: ['create'],
                              resource: ['issue'],
                          },
                      },
                      default: { assignee: '' },
                      options: [
                          {
                              displayName: 'Assignee',
                              name: 'assignee',
                              type: 'number',
                              default: 0,
                              description: 'User ID to assign issue to',
                          },
                      ],
                  },
                  {
                      displayName: 'Issue Number',
                      name: 'issueNumber',
                      type: 'number',
                      default: 0,
                      required: true,
                      displayOptions: {
                          show: {
                              operation: ['createComment'],
                              resource: ['issue'],
                          },
                      },
                      description: 'The number of the issue on which to create the comment on',
                  },
                  {
                      displayName: 'Body',
                      name: 'body',
                      type: 'string',
                      typeOptions: {
                          rows: 5,
                      },
                      displayOptions: {
                          show: {
                              operation: ['createComment'],
                              resource: ['issue'],
                          },
                      },
                      default: '',
                      description: 'The body of the comment',
                  },
                  {
                      displayName: 'Issue Number',
                      name: 'issueNumber',
                      type: 'number',
                      default: 0,
                      required: true,
                      displayOptions: {
                          show: {
                              operation: ['edit'],
                              resource: ['issue'],
                          },
                      },
                      description: 'The number of the issue edit',
                  },
                  {
                      displayName: 'Edit Fields',
                      name: 'editFields',
                      type: 'collection',
                      typeOptions: {
                          multipleValueButtonText: 'Add Field',
                      },
                      displayOptions: {
                          show: {
                              operation: ['edit'],
                              resource: ['issue'],
                          },
                      },
                      default: {},
                      options: [
                          {
                              displayName: 'Title',
                              name: 'title',
                              type: 'string',
                              default: '',
                              description: 'The title of the issue',
                          },
                          {
                              displayName: 'Body',
                              name: 'description',
                              type: 'string',
                              typeOptions: {
                                  rows: 5,
                              },
                              default: '',
                              description: 'The body of the issue',
                          },
                          {
                              displayName: 'State',
                              name: 'state',
                              type: 'options',
                              options: [
                                  {
                                      name: 'Closed',
                                      value: 'closed',
                                      description: 'Set the state to "closed"',
                                  },
                                  {
                                      name: 'Open',
                                      value: 'open',
                                      description: 'Set the state to "open"',
                                  },
                              ],
                              default: 'open',
                              description: 'The state to set',
                          },
                          {
                              displayName: 'Labels',
                              name: 'labels',
                              type: 'collection',
                              typeOptions: {
                                  multipleValues: true,
                                  multipleValueButtonText: 'Add Label',
                              },
                              default: { label: '' },
                              options: [
                                  {
                                      displayName: 'Label',
                                      name: 'label',
                                      type: 'string',
                                      default: '',
                                      description: 'Label to add to issue',
                                  },
                              ],
                          },
                          {
                              displayName: 'Assignees',
                              name: 'assignee_ids',
                              type: 'collection',
                              typeOptions: {
                                  multipleValues: true,
                                  multipleValueButtonText: 'Add Assignee',
                              },
                              default: { assignee: '' },
                              options: [
                                  {
                                      displayName: 'Assignees',
                                      name: 'assignee',
                                      type: 'string',
                                      default: '',
                                      description: 'User to assign issue too',
                                  },
                              ],
                          },
                          {
                              displayName: 'Due Date',
                              name: 'due_date',
                              type: 'dateTime',
                              default: '',
                              description: 'Due Date for issue',
                          },
                      ],
                  },
                  {
                      displayName: 'Issue Number',
                      name: 'issueNumber',
                      type: 'number',
                      default: 0,
                      required: true,
                      displayOptions: {
                          show: {
                              operation: ['get'],
                              resource: ['issue'],
                          },
                      },
                      description: 'The number of the issue get data of',
                  },
                  {
                      displayName: 'Issue Number',
                      name: 'issueNumber',
                      type: 'number',
                      default: 0,
                      required: true,
                      displayOptions: {
                          show: {
                              operation: ['lock'],
                              resource: ['issue'],
                          },
                      },
                      description: 'The number of the issue to lock',
                  },
                  {
                      displayName: 'Lock Reason',
                      name: 'lockReason',
                      type: 'options',
                      displayOptions: {
                          show: {
                              operation: ['lock'],
                              resource: ['issue'],
                          },
                      },
                      options: [
                          {
                              name: 'Off-Topic',
                              value: 'off-topic',
                              description: 'The issue is Off-Topic',
                          },
                          {
                              name: 'Too Heated',
                              value: 'too heated',
                              description: 'The discussion is too heated',
                          },
                          {
                              name: 'Resolved',
                              value: 'resolved',
                              description: 'The issue got resolved',
                          },
                          {
                              name: 'Spam',
                              value: 'spam',
                              description: 'The issue is spam',
                          },
                      ],
                      default: 'resolved',
                      description: 'The reason to lock the issue',
                  },
                  {
                      displayName: 'Tag',
                      name: 'releaseTag',
                      type: 'string',
                      default: '',
                      required: true,
                      displayOptions: {
                          show: {
                              operation: ['create'],
                              resource: ['release'],
                          },
                      },
                      description: 'The tag of the release',
                  },
                  {
                      displayName: 'Additional Fields',
                      name: 'additionalFields',
                      type: 'collection',
                      typeOptions: {
                          multipleValueButtonText: 'Add Field',
                      },
                      displayOptions: {
                          show: {
                              operation: ['create'],
                              resource: ['release'],
                          },
                      },
                      default: {},
                      options: [
                          {
                              displayName: 'Name',
                              name: 'name',
                              type: 'string',
                              default: '',
                              description: 'The name of the release',
                          },
                          {
                              displayName: 'Description',
                              name: 'description',
                              type: 'string',
                              typeOptions: {
                                  rows: 5,
                              },
                              default: '',
                              description: 'The description of the release',
                          },
                          {
                              displayName: 'Ref',
                              name: 'ref',
                              type: 'string',
                              default: '',
                              description: 'If Tag doesn’t exist, the release will be created from Ref. It can be a commit SHA, another tag name, or a branch name.',
                          },
                      ],
                  },
                  {
                      displayName: 'Project ID',
                      name: 'projectId',
                      type: 'string',
                      default: '',
                      required: true,
                      displayOptions: {
                          show: {
                              operation: ['delete', 'get'],
                              resource: ['release'],
                          },
                      },
                      description: 'The ID or URL-encoded path of the project',
                  },
                  {
                      displayName: 'Tag Name',
                      name: 'tag_name',
                      type: 'string',
                      default: '',
                      required: true,
                      displayOptions: {
                          show: {
                              operation: ['delete', 'get'],
                              resource: ['release'],
                          },
                      },
                      description: 'The Git tag the release is associated with',
                  },
                  {
                      displayName: 'Project ID',
                      name: 'projectId',
                      type: 'string',
                      default: '',
                      required: true,
                      displayOptions: {
                          show: {
                              operation: ['getAll'],
                              resource: ['release'],
                          },
                      },
                      description: 'The ID or URL-encoded path of the project',
                  },
                  {
                      displayName: 'Return All',
                      name: 'returnAll',
                      type: 'boolean',
                      displayOptions: {
                          show: {
                              resource: ['release', 'file'],
                              operation: ['getAll', 'list'],
                          },
                      },
                      default: false,
                      description: 'Whether to return all results or only up to a given limit',
                  },
                  {
                      displayName: 'Limit',
                      name: 'limit',
                      type: 'number',
                      displayOptions: {
                          show: {
                              resource: ['release', 'file'],
                              operation: ['getAll', 'list'],
                              returnAll: [false],
                          },
                      },
                      typeOptions: {
                          minValue: 1,
                          maxValue: 100,
                      },
                      default: 20,
                      description: 'Max number of results to return',
                  },
                  {
                      displayName: 'Additional Fields',
                      name: 'additionalFields',
                      type: 'collection',
                      typeOptions: {
                          multipleValueButtonText: 'Add Field',
                      },
                      displayOptions: {
                          show: {
                              operation: ['getAll'],
                              resource: ['release'],
                          },
                      },
                      default: {},
                      options: [
                          {
                              displayName: 'Order By',
                              name: 'order_by',
                              type: 'options',
                              options: [
                                  {
                                      name: 'Created At',
                                      value: 'created_at',
                                  },
                                  {
                                      name: 'Released At',
                                      value: 'released_at',
                                  },
                              ],
                              default: 'released_at',
                              description: 'The field to use as order',
                          },
                          {
                              displayName: 'Sort',
                              name: 'sort',
                              type: 'options',
                              options: [
                                  {
                                      name: 'ASC',
                                      value: 'asc',
                                  },
                                  {
                                      name: 'DESC',
                                      value: 'desc',
                                  },
                              ],
                              default: 'desc',
                              description: 'The direction of the order. .',
                          },
                      ],
                  },
                  {
                      displayName: 'Project ID',
                      name: 'projectId',
                      type: 'string',
                      default: '',
                      required: true,
                      displayOptions: {
                          show: {
                              operation: ['update'],
                              resource: ['release'],
                          },
                      },
                      description: 'The ID or URL-encoded path of the project',
                  },
                  {
                      displayName: 'Tag Name',
                      name: 'tag_name',
                      type: 'string',
                      default: '',
                      required: true,
                      displayOptions: {
                          show: {
                              operation: ['update'],
                              resource: ['release'],
                          },
                      },
                      description: 'The Git tag the release is associated with',
                  },
                  {
                      displayName: 'Additional Fields',
                      name: 'additionalFields',
                      type: 'collection',
                      typeOptions: {
                          multipleValueButtonText: 'Add Field',
                      },
                      displayOptions: {
                          show: {
                              operation: ['update'],
                              resource: ['release'],
                          },
                      },
                      default: {},
                      options: [
                          {
                              displayName: 'Name',
                              name: 'name',
                              type: 'string',
                              default: '',
                              description: 'The release name',
                          },
                          {
                              displayName: 'Description',
                              name: 'description',
                              type: 'string',
                              default: '',
                              description: 'The description of the release. You can use Markdown.',
                          },
                          {
                              displayName: 'Milestones',
                              name: 'milestones',
                              type: 'string',
                              default: '',
                              description: 'The title of each milestone to associate with the release (provide a titles list spearated with comma)',
                          },
                          {
                              displayName: 'Released At',
                              name: 'released_at',
                              type: 'dateTime',
                              default: '',
                              description: 'The date when the release is/was ready',
                          },
                      ],
                  },
                  {
                      displayName: 'Filters',
                      name: 'getRepositoryIssuesFilters',
                      type: 'collection',
                      typeOptions: {
                          multipleValueButtonText: 'Add Filter',
                      },
                      displayOptions: {
                          show: {
                              operation: ['getIssues'],
                              resource: ['repository'],
                          },
                      },
                      default: {},
                      options: [
                          {
                              displayName: 'Assignee',
                              name: 'assignee_username',
                              type: 'string',
                              default: '',
                              description: 'Return only issues which are assigned to a specific user',
                          },
                          {
                              displayName: 'Creator',
                              name: 'author_username',
                              type: 'string',
                              default: '',
                              description: 'Return only issues which were created by a specific user',
                          },
                          {
                              displayName: 'Labels',
                              name: 'labels',
                              type: 'string',
                              default: '',
                              description: 'Return only issues with the given labels. Multiple lables can be separated by comma.',
                          },
                          {
                              displayName: 'Updated After',
                              name: 'updated_after',
                              type: 'dateTime',
                              default: '',
                              description: 'Return only issues updated at or after this time',
                          },
                          {
                              displayName: 'State',
                              name: 'state',
                              type: 'options',
                              options: [
                                  {
                                      name: 'All',
                                      value: '',
                                      description: 'Returns issues with any state',
                                  },
                                  {
                                      name: 'Closed',
                                      value: 'closed',
                                      description: 'Return issues with "closed" state',
                                  },
                                  {
                                      name: 'Open',
                                      value: 'opened',
                                      description: 'Return issues with "open" state',
                                  },
                              ],
                              default: 'opened',
                              description: 'The state to filter by',
                          },
                          {
                              displayName: 'Sort',
                              name: 'order_by',
                              type: 'options',
                              options: [
                                  {
                                      name: 'Created At',
                                      value: 'created_at',
                                      description: 'Sort by created date',
                                  },
                                  {
                                      name: 'Updated At',
                                      value: 'updated_at',
                                      description: 'Sort by updated date',
                                  },
                                  {
                                      name: 'Priority',
                                      value: 'priority',
                                      description: 'Sort by priority',
                                  },
                              ],
                              default: 'created_at',
                              description: 'The order the issues should be returned in',
                          },
                          {
                              displayName: 'Direction',
                              name: 'sort',
                              type: 'options',
                              options: [
                                  {
                                      name: 'Ascending',
                                      value: 'asc',
                                      description: 'Sort in ascending order',
                                  },
                                  {
                                      name: 'Descending',
                                      value: 'desc',
                                      description: 'Sort in descending order',
                                  },
                              ],
                              default: 'desc',
                              description: 'The sort order',
                          },
                      ],
                  },
                  {
                      displayName: 'File Path',
                      name: 'filePath',
                      type: 'string',
                      default: '',
                      displayOptions: {
                          show: {
                              resource: ['file'],
                          },
                          hide: {
                              operation: ['list'],
                          },
                      },
                      placeholder: 'docs/README.md',
                      description: 'The file path of the file. Has to contain the full path or leave it empty for root folder.',
                  },
                  {
                      displayName: 'Path',
                      name: 'filePath',
                      type: 'string',
                      default: '',
                      displayOptions: {
                          show: {
                              resource: ['file'],
                              operation: ['list'],
                          },
                      },
                      placeholder: 'docs/',
                      description: 'The path of the folder to list',
                  },
                  {
                      displayName: 'Page',
                      name: 'page',
                      type: 'number',
                      displayOptions: {
                          show: {
                              resource: ['file'],
                              operation: ['list'],
                              returnAll: [false],
                          },
                      },
                      typeOptions: {
                          minValue: 1,
                          maxValue: 1000,
                      },
                      default: 1,
                      description: 'Page of results to display',
                  },
                  {
                      displayName: 'Additional Parameters',
                      name: 'additionalParameters',
                      placeholder: 'Add Parameter',
                      description: 'Additional fields to add',
                      type: 'collection',
                      default: {},
                      displayOptions: {
                          show: {
                              resource: ['file'],
                              operation: ['list'],
                          },
                      },
                      options: [
                          {
                              displayName: 'Reference',
                              name: 'ref',
                              type: 'string',
                              default: '',
                              placeholder: 'main',
                              description: 'The name of the commit/branch/tag. Default: the repository’s default branch (usually main).',
                          },
                          {
                              displayName: 'Recursive',
                              name: 'recursive',
                              type: 'boolean',
                              default: false,
                              description: 'Whether or not to get a recursive file tree. Default is false.',
                          },
                      ],
                  },
                  {
                      displayName: 'As Binary Property',
                      name: 'asBinaryProperty',
                      type: 'boolean',
                      default: true,
                      displayOptions: {
                          show: {
                              operation: ['get'],
                              resource: ['file'],
                          },
                      },
                      description: 'Whether to set the data of the file as binary property instead of returning the raw API response',
                  },
                  {
                      displayName: 'Binary Property',
                      name: 'binaryPropertyName',
                      type: 'string',
                      default: 'data',
                      required: true,
                      displayOptions: {
                          show: {
                              asBinaryProperty: [true],
                              operation: ['get'],
                              resource: ['file'],
                          },
                      },
                      placeholder: '',
                      description: 'Name of the binary property in which to save the binary data of the received file',
                  },
                  {
                      displayName: 'Additional Parameters',
                      name: 'additionalParameters',
                      placeholder: 'Add Parameter',
                      description: 'Additional fields to add',
                      type: 'collection',
                      default: {},
                      displayOptions: {
                          show: {
                              operation: ['get'],
                              resource: ['file'],
                          },
                      },
                      options: [
                          {
                              displayName: 'Reference',
                              name: 'reference',
                              type: 'string',
                              default: '',
                              placeholder: 'main',
                              description: 'The name of the commit/branch/tag. Default: the repository’s default branch (usually main).',
                          },
                      ],
                  },
                  {
                      displayName: 'Binary Data',
                      name: 'binaryData',
                      type: 'boolean',
                      default: false,
                      required: true,
                      displayOptions: {
                          show: {
                              operation: ['create', 'edit'],
                              resource: ['file'],
                          },
                      },
                      description: 'Whether the data to upload should be taken from binary field',
                  },
                  {
                      displayName: 'File Content',
                      name: 'fileContent',
                      type: 'string',
                      default: '',
                      required: true,
                      displayOptions: {
                          show: {
                              binaryData: [false],
                              operation: ['create', 'edit'],
                              resource: ['file'],
                          },
                      },
                      placeholder: '',
                      description: 'The text content of the file',
                  },
                  {
                      displayName: 'Binary Property',
                      name: 'binaryPropertyName',
                      type: 'string',
                      default: 'data',
                      required: true,
                      displayOptions: {
                          show: {
                              binaryData: [true],
                              operation: ['create', 'edit'],
                              resource: ['file'],
                          },
                      },
                      placeholder: '',
                      description: 'Name of the binary property which contains the data for the file',
                  },
                  {
                      displayName: 'Commit Message',
                      name: 'commitMessage',
                      type: 'string',
                      default: '',
                      required: true,
                      displayOptions: {
                          show: {
                              operation: ['create', 'delete', 'edit'],
                              resource: ['file'],
                          },
                      },
                  },
                  {
                      displayName: 'Branch',
                      name: 'branch',
                      type: 'string',
                      default: '',
                      description: 'Name of the new branch to create. The commit is added to this branch.',
                      required: true,
                      displayOptions: {
                          show: {
                              operation: ['create', 'delete', 'edit'],
                              resource: ['file'],
                          },
                      },
                  },
                  {
                      displayName: 'Additional Parameters',
                      name: 'additionalParameters',
                      placeholder: 'Add Parameter',
                      description: 'Additional fields to add',
                      type: 'fixedCollection',
                      default: {},
                      displayOptions: {
                          show: {
                              operation: ['create', 'delete', 'edit'],
                              resource: ['file'],
                          },
                      },
                      options: [
                          {
                              displayName: 'Start Branch',
                              name: 'branchStart',
                              values: [
                                  {
                                      displayName: 'Start Branch',
                                      name: 'branchStart',
                                      type: 'string',
                                      default: '',
                                      description: 'Name of the base branch to create the new branch from',
                                  },
                              ],
                          },
                          {
                              name: 'author',
                              displayName: 'Author',
                              values: [
                                  {
                                      displayName: 'Name',
                                      name: 'name',
                                      type: 'string',
                                      default: '',
                                      description: 'The name of the author of the commit',
                                  },
                                  {
                                      displayName: 'Email',
                                      name: 'email',
                                      type: 'string',
                                      placeholder: 'name@email.com',
                                      default: '',
                                      description: 'The email of the author of the commit',
                                  },
                              ],
                          },
                          {
                              name: 'encoding',
                              displayName: 'Encoding',
                              values: [
                                  {
                                      displayName: 'Encoding',
                                      name: 'encoding',
                                      type: 'string',
                                      default: 'text',
                                      description: 'Change encoding to base64. Default is text.',
                                  },
                              ],
                          },
                      ],
                  },
              ],
          };
      }
      async execute() {
          const items = this.getInputData();
          const returnData = [];
          const overwriteDataOperations = [
              'file:get',
              'file:create',
              'file:edit',
              'file:delete',
              'issue:create',
              'issue:createComment',
              'issue:edit',
              'issue:get',
              'release:create',
              'release:delete',
              'release:get',
              'release:update',
              'repository:get',
          ];
          const overwriteDataOperationsArray = [
              'file:list',
              'release:getAll',
              'repository:getIssues',
              'user:getRepositories',
          ];
          let responseData;
          let body;
          let qs;
          let requestMethod;
          let endpoint;
          let returnAll = false;
          const operation = this.getNodeParameter('operation', 0);
          const resource = this.getNodeParameter('resource', 0);
          const fullOperation = `${resource}:${operation}`;
          for (let i = 0; i < items.length; i++) {
              try {
                  requestMethod = 'GET';
                  endpoint = '';
                  body = {};
                  qs = {};
                  let owner = this.getNodeParameter('owner', i);
                  owner = owner.replace(new RegExp(/\//g), '%2F');
                  let repository = '';
                  if (fullOperation !== 'user:getRepositories') {
                      repository = this.getNodeParameter('repository', i);
                  }
                  const baseEndpoint = `/projects/${owner}%2F${repository}`;
                  if (resource === 'issue') {
                      if (operation === 'create') {
                          requestMethod = 'POST';
                          body.title = this.getNodeParameter('title', i);
                          body.description = this.getNodeParameter('body', i);
                          body.due_date = this.getNodeParameter('due_date', i);
                          const labels = this.getNodeParameter('labels', i);
                          const assigneeIds = this.getNodeParameter('assignee_ids', i);
                          body.labels = labels.map((data) => data.label).join(',');
                          body.assignee_ids = assigneeIds.map((data) => data.assignee);
                          endpoint = `${baseEndpoint}/issues`;
                      }
                      else if (operation === 'createComment') {
                          requestMethod = 'POST';
                          const issueNumber = this.getNodeParameter('issueNumber', i);
                          body.body = this.getNodeParameter('body', i);
                          endpoint = `${baseEndpoint}/issues/${issueNumber}/notes`;
                      }
                      else if (operation === 'edit') {
                          requestMethod = 'PUT';
                          const issueNumber = this.getNodeParameter('issueNumber', i);
                          body = this.getNodeParameter('editFields', i, {});
                          if (body.labels !== undefined) {
                              body.labels = body.labels.map((data) => data.label).join(',');
                          }
                          if (body.assignee_ids !== undefined) {
                              body.assignee_ids = body.assignee_ids.map((data) => data.assignee);
                          }
                          endpoint = `${baseEndpoint}/issues/${issueNumber}`;
                      }
                      else if (operation === 'get') {
                          requestMethod = 'GET';
                          const issueNumber = this.getNodeParameter('issueNumber', i);
                          endpoint = `${baseEndpoint}/issues/${issueNumber}`;
                      }
                      else if (operation === 'lock') {
                          requestMethod = 'PUT';
                          const issueNumber = this.getNodeParameter('issueNumber', i);
                          body.discussion_locked = true;
                          endpoint = `${baseEndpoint}/issues/${issueNumber}`;
                      }
                  }
                  else if (resource === 'release') {
                      if (operation === 'create') {
                          requestMethod = 'POST';
                          body = this.getNodeParameter('additionalFields', i, {});
                          body.tag_name = this.getNodeParameter('releaseTag', i);
                          endpoint = `${baseEndpoint}/releases`;
                      }
                      if (operation === 'delete') {
                          requestMethod = 'DELETE';
                          const id = this.getNodeParameter('projectId', i);
                          const tagName = this.getNodeParameter('tag_name', i);
                          endpoint = `/projects/${id}/releases/${tagName}`;
                      }
                      if (operation === 'get') {
                          requestMethod = 'GET';
                          const id = this.getNodeParameter('projectId', i);
                          const tagName = this.getNodeParameter('tag_name', i);
                          endpoint = `/projects/${id}/releases/${tagName}`;
                      }
                      if (operation === 'getAll') {
                          requestMethod = 'GET';
                          const id = this.getNodeParameter('projectId', i);
                          qs = this.getNodeParameter('additionalFields', i, {});
                          returnAll = this.getNodeParameter('returnAll', 0);
                          if (!returnAll) {
                              qs.per_page = this.getNodeParameter('limit', 0);
                          }
                          endpoint = `/projects/${id}/releases`;
                      }
                      if (operation === 'update') {
                          requestMethod = 'PUT';
                          const id = this.getNodeParameter('projectId', i);
                          const tagName = this.getNodeParameter('tag_name', i);
                          body = this.getNodeParameter('additionalFields', i, {});
                          if (body.milestones) {
                              body.milestones = body.milestones.split(',');
                          }
                          endpoint = `/projects/${id}/releases/${tagName}`;
                      }
                  }
                  else if (resource === 'repository') {
                      if (operation === 'get') {
                          requestMethod = 'GET';
                          endpoint = `${baseEndpoint}`;
                      }
                      else if (operation === 'getIssues') {
                          requestMethod = 'GET';
                          qs = this.getNodeParameter('getRepositoryIssuesFilters', i);
                          endpoint = `${baseEndpoint}/issues`;
                      }
                  }
                  else if (resource === 'user') {
                      if (operation === 'getRepositories') {
                          requestMethod = 'GET';
                          endpoint = `/users/${owner}/projects`;
                      }
                  }
                  else if (resource === 'file') {
                      if (['create', 'edit'].includes(operation)) {
                          requestMethod = operation === 'create' ? 'POST' : 'PUT';
                          const filePath = this.getNodeParameter('filePath', i);
                          const additionalParameters = this.getNodeParameter('additionalParameters', i);
                          body.branch = this.getNodeParameter('branch', i);
                          body.commit_message = this.getNodeParameter('commitMessage', i);
                          if (additionalParameters.author) {
                              body.author = additionalParameters.author;
                          }
                          if (additionalParameters.branchStart &&
                              additionalParameters.branchStart.branchStart) {
                              body.start_branch = additionalParameters.branchStart.branchStart;
                          }
                          if (this.getNodeParameter('binaryData', i)) {
                              const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
                              const binaryData = this.helpers.assertBinaryData(i, binaryPropertyName);
                              body.content = binaryData.data;
                              body.encoding = 'base64';
                          }
                          else {
                              if (additionalParameters.encoding === 'base64') {
                                  body.content = Buffer.from(this.getNodeParameter('fileContent', i)).toString('base64');
                              }
                              else {
                                  body.content = this.getNodeParameter('fileContent', i);
                              }
                          }
                          endpoint = `${baseEndpoint}/repository/files/${encodeURIComponent(filePath)}`;
                      }
                      else if (operation === 'delete') {
                          requestMethod = 'DELETE';
                          const additionalParameters = this.getNodeParameter('additionalParameters', i, {});
                          if (additionalParameters.author) {
                              body.author = additionalParameters.author;
                          }
                          body.branch = this.getNodeParameter('branch', i);
                          body.commit_message = this.getNodeParameter('commitMessage', i);
                          const filePath = this.getNodeParameter('filePath', i);
                          endpoint = `${baseEndpoint}/repository/files/${encodeURIComponent(filePath)}`;
                      }
                      else if (operation === 'get') {
                          requestMethod = 'GET';
                          const filePath = this.getNodeParameter('filePath', i);
                          const additionalParameters = this.getNodeParameter('additionalParameters', i);
                          if (additionalParameters.reference) {
                              qs.ref = additionalParameters.reference;
                          }
                          else {
                              qs.ref = 'master';
                          }
                          endpoint = `${baseEndpoint}/repository/files/${encodeURIComponent(filePath)}`;
                      }
                      else if (operation === 'list') {
                          requestMethod = 'GET';
                          const filePath = this.getNodeParameter('filePath', i);
                          qs = this.getNodeParameter('additionalParameters', i, {});
                          returnAll = this.getNodeParameter('returnAll', i);
                          if (!returnAll) {
                              qs.per_page = this.getNodeParameter('limit', i);
                              qs.page = this.getNodeParameter('page', i);
                          }
                          if (filePath) {
                              qs.path = filePath;
                          }
                          endpoint = `${baseEndpoint}/repository/tree`;
                      }
                  }
                  else {
                      throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`, {
                          itemIndex: i,
                      });
                  }
                  const asBinaryProperty = this.getNodeParameter('asBinaryProperty', i, false);
                  if (returnAll) {
                      responseData = await GenericFunctions_1.gitlabApiRequestAllItems.call(this, requestMethod, endpoint, body, qs);
                  }
                  else {
                      responseData = await GenericFunctions_1.gitlabApiRequest.call(this, requestMethod, endpoint, body, qs);
                  }
                  if (fullOperation === 'file:get' && asBinaryProperty) {
                      if (Array.isArray(responseData) && responseData.length > 1) {
                          throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'File Path is a folder, not a file.', {
                              itemIndex: i,
                          });
                      }
                      const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
                      const newItem = {
                          json: items[i].json,
                          binary: {},
                      };
                      if (items[i].binary !== undefined) {
                          Object.assign(newItem.binary, items[i].binary);
                      }
                      const { content, path } = responseData;
                      newItem.binary[binaryPropertyName] = await this.helpers.prepareBinaryData(Buffer.from(content, 'base64'), path);
                      items[i] = newItem;
                      return [items];
                  }
                  if (overwriteDataOperations.includes(fullOperation) ||
                      overwriteDataOperationsArray.includes(fullOperation)) {
                      const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                      returnData.push(...executionData);
                  }
              }
              catch (error) {
                  if (this.continueOnFail()) {
                      if (overwriteDataOperations.includes(fullOperation) ||
                          overwriteDataOperationsArray.includes(fullOperation)) {
                          const executionErrorData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray({ error: error.message }), { itemData: { item: i } });
                          returnData.push(...executionErrorData);
                      }
                      else {
                          items[i].json = { error: error.message };
                      }
                      continue;
                  }
                  throw error;
              }
          }
          if (overwriteDataOperations.includes(fullOperation) ||
              overwriteDataOperationsArray.includes(fullOperation)) {
              return [returnData];
          }
          else {
              return [items];
          }
      }
  }
  exports.Gitlab = Gitlab;
  //# sourceMappingURL=Gitlab.node.js.map

documentation_markdown:
  ---
  #https://www.notion.so/n8n/Frontmatter-432c2b8dff1f43d4b1c8d20075510fe4
  title: GitLab credentials
  description: Documentation for GitLab credentials. Use these credentials to authenticate GitLab in n8n, a workflow automation platform.
  contentType: [integration, reference]
  priority: medium
  ---

  # GitLab credentials

  You can use these credentials to authenticate the following nodes:

  - [GitLab](/integrations/builtin/app-nodes/n8n-nodes-base.gitlab.md)
  - [GitLab Trigger](/integrations/builtin/trigger-nodes/n8n-nodes-base.gitlabtrigger.md)

  ## Supported authentication methods

  - API access token
  - OAuth2 (Recommended)

  ## Related resources

  Refer to [GitLab's API documentation](https://docs.gitlab.com/ee/api/rest/){:target=_blank .external-link} for more information about the service.

  ## Using API access token

  To configure this credential, you'll need a [GitLab](https://gitlab.com/){:target=_blank .external-link} account and:

  - The URL of your **GitLab Server**
  - An **Access Token**

  To set up the credential:

  1. In GitLab, select your avatar, then select **Edit profile**.
  2. In the left sidebar, select **Access tokens**.
  3. Select **Add new token**.
  4. Enter a **Name** for the token, like `n8n integration`.
  5. Enter an **expiry date** for the token. If you don't enter an expiry date, GitLab automatically sets it to 365 days later than the current date.
      - The token expires on that expiry date at midnight UTC.
  6. Select the desired **Scopes**. For the [GitLab](/integrations/builtin/app-nodes/n8n-nodes-base.gitlab.md) node, use the `api` scope to easily grant access for all the node's functionality. Or refer to [Personal access token scopes](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#personal-access-token-scopes){:target=_blank .external-link} to select scopes for the functions you want to use.
  7. Select **Create personal access token**.
  8. Copy the access token this creates and enter it in your n8n credential as the **Access Token**.
  9. Enter the URL of your **GitLab Server** in your n8n credential. 

  Refer to GitLab's [Create a personal access token documentation](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token){:target=_blank .external-link} for more information.

  ## Using OAuth2

  --8<-- "_snippets/integrations/builtin/credentials/cloud-oauth-button.md"

  If you're [self-hosting](/hosting/index.md) n8n, you'll need a [GitLab](https://gitlab.com/){:target=_blank .external-link} account. Then create a new GitLab application:

  1. In GitLab, select your avatar, then select **Edit profile**.
  2. In the left sidebar, select **Applications**.
  3. Select **Add new application**.
  4. Enter a **Name** for your application, like `n8n integration`.
  5. In n8n, copy the **OAuth Redirect URL**. Enter it as the GitLab **Redirect URI**.
  6. Select the desired **Scopes**. For the [GitLab](/integrations/builtin/app-nodes/n8n-nodes-base.gitlab.md) node, use the `api` scope to easily grant access for all the node's functionality. Or refer to [Personal access token scopes](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#personal-access-token-scopes){:target=_blank .external-link} to select scopes for the functions you want to use.
  6. Select **Save application**.
  7. Copy the **Application ID** and enter it as the **Client ID** in your n8n credential.
  8. Copy the **Secret** and enter it as the **Client Secret** in your n8n credential.

  Refer to GitLab's [Configure GitLab as an OAuth 2.0 authentication identity provider](https://docs.gitlab.com/ee/integration/oauth_provider.html){:target=_blank .external-link} documentation for more information. Refer to the [GitLab OAuth 2.0 identity provider API documentation](https://docs.gitlab.com/ee/api/oauth2.html){:target=_blank .external-link} for more information on OAuth2 and GitLab.

example_workflow:
  {"nodes":[{"parameters":{},"type":"n8n-nodes-base.node","typeVersion":1,"position":[220,120],"id":"6473c844-d218-4358-9932-2ab32d669e11","name":"Node"}],"connections":{"Node":{"main":[[]]}},"pinData":{},"meta":{"templateCredsSetupCompleted":true,"instanceId":"c29132ed04d06c3827e2bc2cdf8ad2c40b90d5a1399d4caf5c5af63097aa5ccc"}}


node_type: n8n-nodes-base.Gmail
name: Gmail
display_name: Gmail
description: Consume the Gmail API
category: Other
code_hash: 778830fab42a07b1a235be83dedadc666da237bc40fda6257ed59e3c102fdbbe
documentation_url: https://docs.n8n.io/integrations/builtin/credentials/sendemail/gmail
example_parameters: {}
properties_schema: []
package_name: n8n-nodes-base
extracted_at: 2025-06-08 08:05:22
updated_at: 2025-06-08 08:05:22
source_code:
  "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.Gmail = void 0;
  const n8n_workflow_1 = require("n8n-workflow");
  const GmailV1_node_1 = require("./v1/GmailV1.node");
  const GmailV2_node_1 = require("./v2/GmailV2.node");
  class Gmail extends n8n_workflow_1.VersionedNodeType {
      constructor() {
          const baseDescription = {
              displayName: 'Gmail',
              name: 'gmail',
              icon: 'file:gmail.svg',
              group: ['transform'],
              subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
              description: 'Consume the Gmail API',
              defaultVersion: 2.1,
          };
          const nodeVersions = {
              1: new GmailV1_node_1.GmailV1(baseDescription),
              2: new GmailV2_node_1.GmailV2(baseDescription),
              2.1: new GmailV2_node_1.GmailV2(baseDescription),
          };
          super(nodeVersions, baseDescription);
      }
  }
  exports.Gmail = Gmail;
  //# sourceMappingURL=Gmail.node.js.map

documentation_markdown:
  ---
  #https://www.notion.so/n8n/Frontmatter-432c2b8dff1f43d4b1c8d20075510fe4
  title: Gmail
  description: Documentation for Gmail Send Email credentials. Use these credentials to authenticate Send Email with Gmail in n8n, a workflow automation platform.
  contentType: [integration, reference]
  priority: high
  ---

  # Gmail Send Email credentials

  Follow these steps to configure the Send Email credentials with a Gmail account.

  ## Prerequisites

  To follow these instructions, you must first:

  1. [Enable 2-step Verification](#enable-2-step-verification) on your Gmail account.
  2. [Generate an app password](#generate-an-app-password).

  ### Enable 2-step Verification

  --8<-- "_snippets/integrations/builtin/credentials/email/gmail-two-step-verification.md"

  ### Generate an app password

  --8<-- "_snippets/integrations/builtin/credentials/email/gmail-app-password.md"

  ## Set up the credential

  To set up the Send Email credential to use Gmail:

  1. Enter your Gmail email address as the **User**.
  2. Enter the app password you generated above as the **Password**.
  3. Enter `smtp.gmail.com` as the **Host**.
  4. For the **Port**:
      - Keep the default `465` for SSL or if you're unsure what to use.
      - Enter `587` for TLS.
  5. Turn on the **SSL/TLS** toggle.

  Refer to the Outgoing Mail (SMTP) Server settings in [Read Gmail messages on other email clients using POP](https://support.google.com/mail/answer/7104828?hl=en){:target=_blank .external-link} for more information. If the settings above don't work for you, check with your email administrator.

example_workflow:
  {"nodes":[{"parameters":{},"type":"n8n-nodes-base.node","typeVersion":1,"position":[220,120],"id":"0e1beb90-e672-42a0-b8ba-861908857b42","name":"Node"}],"connections":{"Node":{"main":[[]]}},"pinData":{},"meta":{"templateCredsSetupCompleted":true,"instanceId":"eab9db34b306584398815ce2772e7245141800645c5a981a6d06296612ac1a7d"}}


node_type: n8n-nodes-base.GSuiteAdmin
name: GSuiteAdmin
display_name: Google Workspace Admin
description: Consume Google Workspace Admin API
category: Other
code_hash: f071a02014ea9f596115099ea9f2240ac048a4dd7802ef3d9e499d28cbfc2d21
documentation_url: https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.gsuiteadmin
example_parameters: {}
properties_schema: []
package_name: n8n-nodes-base
extracted_at: 2025-06-08 08:05:22
updated_at: 2025-06-08 08:05:22
source_code:
  "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.GSuiteAdmin = void 0;
  const n8n_workflow_1 = require("n8n-workflow");
  const GenericFunctions_1 = require("./GenericFunctions");
  const UserDescription_1 = require("./UserDescription");
  const GroupDescripion_1 = require("./GroupDescripion");
  class GSuiteAdmin {
      constructor() {
          this.description = {
              displayName: 'Google Workspace Admin',
              name: 'gSuiteAdmin',
              icon: 'file:google-workspace-admin.png',
              group: ['input'],
              version: 1,
              subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
              description: 'Consume Google Workspace Admin API',
              defaults: {
                  name: 'Google Workspace Admin',
              },
              inputs: ['main'],
              outputs: ['main'],
              credentials: [
                  {
                      name: 'gSuiteAdminOAuth2Api',
                      required: true,
                  },
              ],
              properties: [
                  {
                      displayName: 'Resource',
                      name: 'resource',
                      type: 'options',
                      noDataExpression: true,
                      options: [
                          {
                              name: 'Group',
                              value: 'group',
                          },
                          {
                              name: 'User',
                              value: 'user',
                          },
                      ],
                      default: 'user',
                  },
                  ...GroupDescripion_1.groupOperations,
                  ...GroupDescripion_1.groupFields,
                  ...UserDescription_1.userOperations,
                  ...UserDescription_1.userFields,
              ],
          };
          this.methods = {
              loadOptions: {
                  async getDomains() {
                      const returnData = [];
                      const domains = await GenericFunctions_1.googleApiRequestAllItems.call(this, 'domains', 'GET', '/directory/v1/customer/my_customer/domains');
                      for (const domain of domains) {
                          const domainName = domain.domainName;
                          const domainId = domain.domainName;
                          returnData.push({
                              name: domainName,
                              value: domainId,
                          });
                      }
                      return returnData;
                  },
                  async getSchemas() {
                      const returnData = [];
                      const schemas = await GenericFunctions_1.googleApiRequestAllItems.call(this, 'schemas', 'GET', '/directory/v1/customer/my_customer/schemas');
                      for (const schema of schemas) {
                          const schemaName = schema.displayName;
                          const schemaId = schema.schemaName;
                          returnData.push({
                              name: schemaName,
                              value: schemaId,
                          });
                      }
                      return returnData;
                  },
              },
          };
      }
      async execute() {
          const items = this.getInputData();
          const returnData = [];
          const length = items.length;
          const qs = {};
          let responseData;
          const resource = this.getNodeParameter('resource', 0);
          const operation = this.getNodeParameter('operation', 0);
          for (let i = 0; i < length; i++) {
              if (resource === 'group') {
                  if (operation === 'create') {
                      const email = this.getNodeParameter('email', i);
                      const additionalFields = this.getNodeParameter('additionalFields', i);
                      const body = {
                          email,
                      };
                      Object.assign(body, additionalFields);
                      responseData = await GenericFunctions_1.googleApiRequest.call(this, 'POST', '/directory/v1/groups', body);
                  }
                  if (operation === 'delete') {
                      const groupId = this.getNodeParameter('groupId', i);
                      responseData = await GenericFunctions_1.googleApiRequest.call(this, 'DELETE', `/directory/v1/groups/${groupId}`, {});
                      responseData = { success: true };
                  }
                  if (operation === 'get') {
                      const groupId = this.getNodeParameter('groupId', i);
                      responseData = await GenericFunctions_1.googleApiRequest.call(this, 'GET', `/directory/v1/groups/${groupId}`, {});
                  }
                  if (operation === 'getAll') {
                      const returnAll = this.getNodeParameter('returnAll', i);
                      const options = this.getNodeParameter('options', i);
                      Object.assign(qs, options);
                      if (qs.customer === undefined) {
                          qs.customer = 'my_customer';
                      }
                      if (returnAll) {
                          responseData = await GenericFunctions_1.googleApiRequestAllItems.call(this, 'groups', 'GET', '/directory/v1/groups', {}, qs);
                      }
                      else {
                          qs.maxResults = this.getNodeParameter('limit', i);
                          responseData = await GenericFunctions_1.googleApiRequest.call(this, 'GET', '/directory/v1/groups', {}, qs);
                          responseData = responseData.groups;
                      }
                  }
                  if (operation === 'update') {
                      const groupId = this.getNodeParameter('groupId', i);
                      const updateFields = this.getNodeParameter('updateFields', i);
                      const body = {};
                      Object.assign(body, updateFields);
                      responseData = await GenericFunctions_1.googleApiRequest.call(this, 'PUT', `/directory/v1/groups/${groupId}`, body);
                  }
              }
              if (resource === 'user') {
                  if (operation === 'create') {
                      const domain = this.getNodeParameter('domain', i);
                      const firstName = this.getNodeParameter('firstName', i);
                      const lastName = this.getNodeParameter('lastName', i);
                      const password = this.getNodeParameter('password', i);
                      const username = this.getNodeParameter('username', i);
                      const makeAdmin = this.getNodeParameter('makeAdmin', i);
                      const additionalFields = this.getNodeParameter('additionalFields', i);
                      const body = {
                          name: {
                              familyName: lastName,
                              givenName: firstName,
                          },
                          password,
                          primaryEmail: `${username}@${domain}`,
                      };
                      Object.assign(body, additionalFields);
                      if (additionalFields.phoneUi) {
                          const phones = additionalFields.phoneUi.phoneValues;
                          body.phones = phones;
                          delete body.phoneUi;
                      }
                      if (additionalFields.emailUi) {
                          const emails = additionalFields.emailUi.emailValues;
                          body.emails = emails;
                          delete body.emailUi;
                      }
                      responseData = await GenericFunctions_1.googleApiRequest.call(this, 'POST', '/directory/v1/users', body, qs);
                      if (makeAdmin) {
                          await GenericFunctions_1.googleApiRequest.call(this, 'POST', `/directory/v1/users/${responseData.id}/makeAdmin`, { status: true });
                          responseData.isAdmin = true;
                      }
                  }
                  if (operation === 'delete') {
                      const userId = this.getNodeParameter('userId', i);
                      responseData = await GenericFunctions_1.googleApiRequest.call(this, 'DELETE', `/directory/v1/users/${userId}`, {});
                      responseData = { success: true };
                  }
                  if (operation === 'get') {
                      const userId = this.getNodeParameter('userId', i);
                      const projection = this.getNodeParameter('projection', i);
                      const options = this.getNodeParameter('options', i);
                      qs.projection = projection;
                      Object.assign(qs, options);
                      if (qs.customFieldMask) {
                          qs.customFieldMask = qs.customFieldMask.join(' ');
                      }
                      if (qs.projection === 'custom' && qs.customFieldMask === undefined) {
                          throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'When projection is set to custom, the custom schemas field must be defined', { itemIndex: i });
                      }
                      responseData = await GenericFunctions_1.googleApiRequest.call(this, 'GET', `/directory/v1/users/${userId}`, {}, qs);
                  }
                  if (operation === 'getAll') {
                      const returnAll = this.getNodeParameter('returnAll', i);
                      const projection = this.getNodeParameter('projection', i);
                      const options = this.getNodeParameter('options', i);
                      qs.projection = projection;
                      Object.assign(qs, options);
                      if (qs.customer === undefined) {
                          qs.customer = 'my_customer';
                      }
                      if (qs.customFieldMask) {
                          qs.customFieldMask = qs.customFieldMask.join(' ');
                      }
                      if (qs.projection === 'custom' && qs.customFieldMask === undefined) {
                          throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'When projection is set to custom, the custom schemas field must be defined', { itemIndex: i });
                      }
                      if (returnAll) {
                          responseData = await GenericFunctions_1.googleApiRequestAllItems.call(this, 'users', 'GET', '/directory/v1/users', {}, qs);
                      }
                      else {
                          qs.maxResults = this.getNodeParameter('limit', i);
                          responseData = await GenericFunctions_1.googleApiRequest.call(this, 'GET', '/directory/v1/users', {}, qs);
                          responseData = responseData.users;
                      }
                  }
                  if (operation === 'update') {
                      const userId = this.getNodeParameter('userId', i);
                      const updateFields = this.getNodeParameter('updateFields', i);
                      const body = { name: {} };
                      Object.assign(body, updateFields);
                      if (updateFields.firstName) {
                          body.name.givenName = updateFields.firstName;
                          delete body.firstName;
                      }
                      if (updateFields.lastName) {
                          body.name.familyName = updateFields.lastName;
                          delete body.lastName;
                      }
                      if (Object.keys(body.name).length === 0) {
                          delete body.name;
                      }
                      if (updateFields.phoneUi) {
                          const phones = updateFields.phoneUi.phoneValues;
                          body.phones = phones;
                          delete body.phoneUi;
                      }
                      if (updateFields.emailUi) {
                          const emails = updateFields.emailUi.emailValues;
                          body.emails = emails;
                          delete body.emailUi;
                      }
                      responseData = await GenericFunctions_1.googleApiRequest.call(this, 'PUT', `/directory/v1/users/${userId}`, body, qs);
                  }
              }
              const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
              returnData.push(...executionData);
          }
          return [returnData];
      }
  }
  exports.GSuiteAdmin = GSuiteAdmin;
  //# sourceMappingURL=GSuiteAdmin.node.js.map

documentation_markdown:
  ---
  #https://www.notion.so/n8n/Frontmatter-432c2b8dff1f43d4b1c8d20075510fe4
  title: Google Workspace Admin node documentation
  description: Learn how to use the Google Workspace Admin node in n8n. Follow technical documentation to integrate Google Workspace Admin node into your workflows.
  contentType: [integration, reference]
  ---

  # Google Workspace Admin node

  Use the Google Workspace Admin node to automate work in Google Workspace Admin, and integrate Google Workspace Admin with other applications. n8n has built-in support for a wide range of Google Workspace Admin features, including creating, updating, deleting, and getting users, and groups. 

  On this page, you'll find a list of operations the Google Workspace Admin node supports and links to more resources.

  /// note | Credentials
  Refer to [Google credentials](/integrations/builtin/credentials/google/index.md) for guidance on setting up authentication. 
  ///

  --8<-- "_snippets/integrations/builtin/app-nodes/ai-tools.md"

  ## Operations

  * Group
      * Create a group
      * Delete a group
      * Get a group
      * Get all groups
      * Update a group
  * User
      * Create a user
      * Delete a user
      * Get a user
      * Get all users
      * Update a user

  ## Templates and examples

  <!-- see https://www.notion.so/n8n/Pull-in-templates-for-the-integrations-pages-37c716837b804d30a33b47475f6e3780 -->
  [[ templatesWidget(page.title, 'google-workspace-admin') ]]

  ## How to project a user's information

  There are three different ways to project a user's information:

  - **Basic**: Doesn't include any custom fields.
  - **Custom**: Includes the custom fields from schemas in `customField`.
  - **Full**: Include all the fields associated with the user.

  To include custom fields, follow these steps:

  1. Select **Custom** from the **Projection** dropdown list.
  2. Select the **Add Options** button and select **Custom Schemas** from the dropdown list.
  3. Select the schema names you want to include from the **Custom Schemas** dropdown list.

example_workflow:
  {"nodes":[{"parameters":{},"type":"n8n-nodes-base.node","typeVersion":1,"position":[220,120],"id":"277fb3e5-8c55-46c9-9e4d-244247db4bce","name":"Node"}],"connections":{"Node":{"main":[[]]}},"pinData":{},"meta":{"templateCredsSetupCompleted":true,"instanceId":"1c5e671ed735456752ebf1f8a72f43db45c9660d5274f0b325c7ba349fb2a469"}}


node_type: n8n-nodes-base.Gotify
name: Gotify
display_name: Gotify
description: Consume Gotify API
category: Other
code_hash: a3f8bbf0c942d4fce2b47cb39956d8f3ac03218d4307e9f794f4ef07f72bbb76
documentation_url: https://docs.n8n.io/integrations/builtin/credentials/gotify
example_parameters: {}
properties_schema: []
package_name: n8n-nodes-base
extracted_at: 2025-06-08 08:05:23
updated_at: 2025-06-08 08:05:23
source_code:
  "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.Gotify = void 0;
  const GenericFunctions_1 = require("./GenericFunctions");
  class Gotify {
      constructor() {
          this.description = {
              displayName: 'Gotify',
              name: 'gotify',
              icon: 'file:gotify.png',
              group: ['input'],
              version: 1,
              subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
              description: 'Consume Gotify API',
              defaults: {
                  name: 'Gotify',
              },
              inputs: ['main'],
              outputs: ['main'],
              credentials: [
                  {
                      name: 'gotifyApi',
                      required: true,
                  },
              ],
              properties: [
                  {
                      displayName: 'Resource',
                      name: 'resource',
                      type: 'options',
                      noDataExpression: true,
                      options: [
                          {
                              name: 'Message',
                              value: 'message',
                          },
                      ],
                      default: 'message',
                  },
                  {
                      displayName: 'Operation',
                      name: 'operation',
                      type: 'options',
                      noDataExpression: true,
                      displayOptions: {
                          show: {
                              resource: ['message'],
                          },
                      },
                      options: [
                          {
                              name: 'Create',
                              value: 'create',
                              action: 'Create a message',
                          },
                          {
                              name: 'Delete',
                              value: 'delete',
                              action: 'Delete a message',
                          },
                          {
                              name: 'Get Many',
                              value: 'getAll',
                              action: 'Get many messages',
                          },
                      ],
                      default: 'create',
                  },
                  {
                      displayName: 'Message',
                      name: 'message',
                      type: 'string',
                      required: true,
                      displayOptions: {
                          show: {
                              resource: ['message'],
                              operation: ['create'],
                          },
                      },
                      default: '',
                      description: 'The message. Markdown (excluding html) is allowed.',
                  },
                  {
                      displayName: 'Additional Fields',
                      name: 'additionalFields',
                      type: 'collection',
                      placeholder: 'Add Field',
                      displayOptions: {
                          show: {
                              resource: ['message'],
                              operation: ['create'],
                          },
                      },
                      default: {},
                      options: [
                          {
                              displayName: 'Priority',
                              name: 'priority',
                              type: 'number',
                              default: 1,
                              description: 'The priority of the message',
                          },
                          {
                              displayName: 'Title',
                              name: 'title',
                              type: 'string',
                              default: '',
                              description: 'The title of the message',
                          },
                      ],
                  },
                  {
                      displayName: 'Message ID',
                      name: 'messageId',
                      type: 'string',
                      required: true,
                      displayOptions: {
                          show: {
                              resource: ['message'],
                              operation: ['delete'],
                          },
                      },
                      default: '',
                  },
                  {
                      displayName: 'Return All',
                      name: 'returnAll',
                      type: 'boolean',
                      displayOptions: {
                          show: {
                              resource: ['message'],
                              operation: ['getAll'],
                          },
                      },
                      default: false,
                      description: 'Whether to return all results or only up to a given limit',
                  },
                  {
                      displayName: 'Limit',
                      name: 'limit',
                      type: 'number',
                      typeOptions: {
                          minValue: 1,
                      },
                      description: 'Max number of results to return',
                      default: 20,
                      displayOptions: {
                          show: {
                              resource: ['message'],
                              operation: ['getAll'],
                              returnAll: [false],
                          },
                      },
                  },
              ],
          };
      }
      async execute() {
          const items = this.getInputData();
          const returnData = [];
          const length = items.length;
          const qs = {};
          let responseData;
          const resource = this.getNodeParameter('resource', 0);
          const operation = this.getNodeParameter('operation', 0);
          for (let i = 0; i < length; i++) {
              try {
                  if (resource === 'message') {
                      if (operation === 'create') {
                          const message = this.getNodeParameter('message', i);
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          const body = {
                              message,
                          };
                          Object.assign(body, additionalFields);
                          responseData = await GenericFunctions_1.gotifyApiRequest.call(this, 'POST', '/message', body);
                      }
                      if (operation === 'delete') {
                          const messageId = this.getNodeParameter('messageId', i);
                          responseData = await GenericFunctions_1.gotifyApiRequest.call(this, 'DELETE', `/message/${messageId}`);
                          responseData = { success: true };
                      }
                      if (operation === 'getAll') {
                          const returnAll = this.getNodeParameter('returnAll', i);
                          if (returnAll) {
                              responseData = await GenericFunctions_1.gotifyApiRequestAllItems.call(this, 'messages', 'GET', '/message', {}, qs);
                          }
                          else {
                              qs.limit = this.getNodeParameter('limit', i);
                              responseData = await GenericFunctions_1.gotifyApiRequest.call(this, 'GET', '/message', {}, qs);
                              responseData = responseData.messages;
                          }
                      }
                  }
                  const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                  returnData.push(...executionData);
              }
              catch (error) {
                  if (this.continueOnFail()) {
                      returnData.push({ json: { error: error.message } });
                      continue;
                  }
                  throw error;
              }
          }
          return [returnData];
      }
  }
  exports.Gotify = Gotify;
  //# sourceMappingURL=Gotify.node.js.map

documentation_markdown:
  ---
  #https://www.notion.so/n8n/Frontmatter-432c2b8dff1f43d4b1c8d20075510fe4
  title: Gotify credentials
  description: Documentation for Gotify credentials. Use these credentials to authenticate Gotify in n8n, a workflow automation platform.
  contentType: [integration, reference]
  ---

  # Gotify credentials

  You can use these credentials to authenticate the following nodes:

  - [Gotify](/integrations/builtin/app-nodes/n8n-nodes-base.gotify.md)

  ## Prerequisites

  Install [Gotify](https://gotify.net/docs/install){:target=_blank .external-link} on your server.

  ## Supported authentication methods

  - API token

  ## Related resources

  Refer to [Gotify's API documentation](https://gotify.net/api-docs){:target=_blank .external-link} for more information about the service.

  ## Using API token

  To configure this credential, you'll need:

  - An **App API Token**: Only required if you'll use this credential to create messages. To generate an App API token, create an application from the **Apps** menu. Refer to [Gotify's Push messages documentation](https://gotify.net/docs/pushmsg){:target=_blank .external-link} for more information.
  - A **Client API Token**: Required for all actions other than creating messages (such as deleting or retrieving messages). To generate a Client API token, create a client from the **Clients** menu.
  - The **URL** of the Gotify host

example_workflow:
  {"nodes":[{"parameters":{},"type":"n8n-nodes-base.node","typeVersion":1,"position":[220,120],"id":"a22a10b3-ceff-4eb1-99c0-638427ff251c","name":"Node"}],"connections":{"Node":{"main":[[]]}},"pinData":{},"meta":{"templateCredsSetupCompleted":true,"instanceId":"50d7c3a463c46e5ad6105fb531eff0db17ba7cff66e28b13beec7ecafedd059d"}}


node_type: n8n-nodes-base.Grafana
name: Grafana
display_name: Grafana
description: Consume the Grafana API
category: Other
code_hash: 95682e6de4432f32165ece9a16ca1a7af19369715ee5993df156d8c95acbe80f
documentation_url: https://docs.n8n.io/integrations/builtin/credentials/grafana
example_parameters: {}
properties_schema: []
package_name: n8n-nodes-base
extracted_at: 2025-06-08 08:05:23
updated_at: 2025-06-08 08:05:23
source_code:
  "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.Grafana = void 0;
  const n8n_workflow_1 = require("n8n-workflow");
  const GenericFunctions_1 = require("./GenericFunctions");
  const descriptions_1 = require("./descriptions");
  class Grafana {
      constructor() {
          this.description = {
              displayName: 'Grafana',
              name: 'grafana',
              icon: 'file:grafana.svg',
              group: ['transform'],
              version: 1,
              subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
              description: 'Consume the Grafana API',
              defaults: {
                  name: 'Grafana',
              },
              inputs: ['main'],
              outputs: ['main'],
              credentials: [
                  {
                      name: 'grafanaApi',
                      required: true,
                  },
              ],
              properties: [
                  {
                      displayName: 'Resource',
                      name: 'resource',
                      noDataExpression: true,
                      type: 'options',
                      options: [
                          {
                              name: 'Dashboard',
                              value: 'dashboard',
                          },
                          {
                              name: 'Team',
                              value: 'team',
                          },
                          {
                              name: 'Team Member',
                              value: 'teamMember',
                          },
                          {
                              name: 'User',
                              value: 'user',
                          },
                      ],
                      default: 'dashboard',
                  },
                  ...descriptions_1.dashboardOperations,
                  ...descriptions_1.dashboardFields,
                  ...descriptions_1.teamOperations,
                  ...descriptions_1.teamFields,
                  ...descriptions_1.teamMemberOperations,
                  ...descriptions_1.teamMemberFields,
                  ...descriptions_1.userOperations,
                  ...descriptions_1.userFields,
              ],
          };
          this.methods = {
              loadOptions: {
                  async getDashboards() {
                      const dashboards = (await GenericFunctions_1.grafanaApiRequest.call(this, 'GET', '/search', {}, { qs: 'dash-db' }));
                      return dashboards.map(({ id, title }) => ({ value: id, name: title }));
                  },
                  async getFolders() {
                      const folders = (await GenericFunctions_1.grafanaApiRequest.call(this, 'GET', '/folders'));
                      return folders.map(({ id, title }) => ({ value: id, name: title }));
                  },
                  async getTeams() {
                      const res = (await GenericFunctions_1.grafanaApiRequest.call(this, 'GET', '/teams/search'));
                      return res.teams.map(({ id, name }) => ({ value: id, name }));
                  },
                  async getUsers() {
                      const users = (await GenericFunctions_1.grafanaApiRequest.call(this, 'GET', '/org/users'));
                      return users.map(({ userId, email }) => ({ value: userId, name: email }));
                  },
              },
          };
      }
      async execute() {
          const items = this.getInputData();
          const returnData = [];
          const resource = this.getNodeParameter('resource', 0);
          const operation = this.getNodeParameter('operation', 0);
          let responseData;
          for (let i = 0; i < items.length; i++) {
              try {
                  if (resource === 'dashboard') {
                      if (operation === 'create') {
                          const body = {
                              dashboard: {
                                  id: null,
                                  title: this.getNodeParameter('title', i),
                              },
                          };
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          if (Object.keys(additionalFields).length) {
                              if (additionalFields.folderId === '')
                                  delete additionalFields.folderId;
                              Object.assign(body, additionalFields);
                          }
                          responseData = await GenericFunctions_1.grafanaApiRequest.call(this, 'POST', '/dashboards/db', body);
                      }
                      else if (operation === 'delete') {
                          const uidOrUrl = this.getNodeParameter('dashboardUidOrUrl', i);
                          const uid = GenericFunctions_1.deriveUid.call(this, uidOrUrl);
                          const endpoint = `/dashboards/uid/${uid}`;
                          responseData = await GenericFunctions_1.grafanaApiRequest.call(this, 'DELETE', endpoint);
                      }
                      else if (operation === 'get') {
                          const uidOrUrl = this.getNodeParameter('dashboardUidOrUrl', i);
                          const uid = GenericFunctions_1.deriveUid.call(this, uidOrUrl);
                          const endpoint = `/dashboards/uid/${uid}`;
                          responseData = await GenericFunctions_1.grafanaApiRequest.call(this, 'GET', endpoint);
                      }
                      else if (operation === 'getAll') {
                          const qs = {
                              type: 'dash-db',
                          };
                          const filters = this.getNodeParameter('filters', i);
                          if (Object.keys(filters).length) {
                              Object.assign(qs, filters);
                          }
                          const returnAll = this.getNodeParameter('returnAll', i);
                          if (!returnAll) {
                              const limit = this.getNodeParameter('limit', i);
                              Object.assign(qs, { limit });
                          }
                          responseData = await GenericFunctions_1.grafanaApiRequest.call(this, 'GET', '/search', {}, qs);
                      }
                      else if (operation === 'update') {
                          const uidOrUrl = this.getNodeParameter('dashboardUidOrUrl', i);
                          const uid = GenericFunctions_1.deriveUid.call(this, uidOrUrl);
                          await GenericFunctions_1.grafanaApiRequest.call(this, 'GET', `/dashboards/uid/${uid}`);
                          const body = {
                              overwrite: true,
                              dashboard: { uid },
                          };
                          const updateFields = this.getNodeParameter('updateFields', i);
                          GenericFunctions_1.throwOnEmptyUpdate.call(this, resource, updateFields);
                          const { title, ...rest } = updateFields;
                          if (!title) {
                              const { dashboard } = await GenericFunctions_1.grafanaApiRequest.call(this, 'GET', `/dashboards/uid/${uid}`);
                              body.dashboard.title = dashboard.title;
                          }
                          else {
                              const dashboards = (await GenericFunctions_1.grafanaApiRequest.call(this, 'GET', '/search'));
                              const titles = dashboards.map(({ title: entry }) => entry);
                              if (titles.includes(title)) {
                                  throw new n8n_workflow_1.NodeApiError(this.getNode(), {
                                      message: 'A dashboard with the same name already exists in the selected folder',
                                  });
                              }
                              body.dashboard.title = title;
                          }
                          if (title) {
                              body.dashboard.title = title;
                          }
                          if (Object.keys(rest).length) {
                              if (rest.folderId === '')
                                  delete rest.folderId;
                              Object.assign(body, rest);
                          }
                          responseData = await GenericFunctions_1.grafanaApiRequest.call(this, 'POST', '/dashboards/db', body);
                      }
                  }
                  else if (resource === 'team') {
                      if (operation === 'create') {
                          const body = {
                              name: this.getNodeParameter('name', i),
                          };
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          if (Object.keys(additionalFields).length) {
                              Object.assign(body, additionalFields);
                          }
                          responseData = await GenericFunctions_1.grafanaApiRequest.call(this, 'POST', '/teams', body);
                      }
                      else if (operation === 'delete') {
                          const teamId = this.getNodeParameter('teamId', i);
                          responseData = await GenericFunctions_1.grafanaApiRequest.call(this, 'DELETE', `/teams/${teamId}`);
                      }
                      else if (operation === 'get') {
                          const teamId = this.getNodeParameter('teamId', i);
                          responseData = await GenericFunctions_1.grafanaApiRequest.call(this, 'GET', `/teams/${teamId}`);
                      }
                      else if (operation === 'getAll') {
                          const qs = {};
                          const filters = this.getNodeParameter('filters', i);
                          if (Object.keys(filters).length) {
                              Object.assign(qs, filters);
                          }
                          responseData = await GenericFunctions_1.grafanaApiRequest.call(this, 'GET', '/teams/search', {}, qs);
                          responseData = responseData.teams;
                          const returnAll = this.getNodeParameter('returnAll', i);
                          if (!returnAll) {
                              const limit = this.getNodeParameter('limit', i);
                              responseData = responseData.slice(0, limit);
                          }
                      }
                      else if (operation === 'update') {
                          const updateFields = this.getNodeParameter('updateFields', i);
                          GenericFunctions_1.throwOnEmptyUpdate.call(this, resource, updateFields);
                          const body = {};
                          const teamId = this.getNodeParameter('teamId', i);
                          await GenericFunctions_1.grafanaApiRequest.call(this, 'GET', `/teams/${teamId}`);
                          if (!updateFields.email) {
                              const { email } = await GenericFunctions_1.grafanaApiRequest.call(this, 'GET', `/teams/${teamId}`);
                              body.email = email;
                          }
                          if (Object.keys(updateFields).length) {
                              Object.assign(body, updateFields);
                          }
                          responseData = await GenericFunctions_1.grafanaApiRequest.call(this, 'PUT', `/teams/${teamId}`, body);
                      }
                  }
                  else if (resource === 'teamMember') {
                      if (operation === 'add') {
                          const userId = this.getNodeParameter('userId', i);
                          const body = {
                              userId: parseInt(userId, 10),
                          };
                          const teamId = this.getNodeParameter('teamId', i);
                          const endpoint = `/teams/${teamId}/members`;
                          responseData = await GenericFunctions_1.grafanaApiRequest.call(this, 'POST', endpoint, body);
                      }
                      else if (operation === 'remove') {
                          const teamId = this.getNodeParameter('teamId', i);
                          const memberId = this.getNodeParameter('memberId', i);
                          const endpoint = `/teams/${teamId}/members/${memberId}`;
                          responseData = await GenericFunctions_1.grafanaApiRequest.call(this, 'DELETE', endpoint);
                      }
                      else if (operation === 'getAll') {
                          const teamId = this.getNodeParameter('teamId', i);
                          await GenericFunctions_1.grafanaApiRequest.call(this, 'GET', `/teams/${teamId}`);
                          const endpoint = `/teams/${teamId}/members`;
                          responseData = await GenericFunctions_1.grafanaApiRequest.call(this, 'GET', endpoint);
                          const returnAll = this.getNodeParameter('returnAll', i);
                          if (!returnAll) {
                              const limit = this.getNodeParameter('limit', i);
                              responseData = responseData.slice(0, limit);
                          }
                      }
                  }
                  else if (resource === 'user') {
                      if (operation === 'create') {
                          const body = {
                              role: this.getNodeParameter('role', i),
                              loginOrEmail: this.getNodeParameter('loginOrEmail', i),
                          };
                          responseData = await GenericFunctions_1.grafanaApiRequest.call(this, 'POST', '/org/users', body);
                      }
                      else if (operation === 'delete') {
                          const userId = this.getNodeParameter('userId', i);
                          responseData = await GenericFunctions_1.grafanaApiRequest.call(this, 'DELETE', `/org/users/${userId}`);
                      }
                      else if (operation === 'getAll') {
                          responseData = await GenericFunctions_1.grafanaApiRequest.call(this, 'GET', '/org/users');
                          const returnAll = this.getNodeParameter('returnAll', i);
                          if (!returnAll) {
                              const limit = this.getNodeParameter('limit', i);
                              responseData = responseData.slice(0, limit);
                          }
                      }
                      else if (operation === 'update') {
                          const body = {};
                          const updateFields = this.getNodeParameter('updateFields', i);
                          GenericFunctions_1.throwOnEmptyUpdate.call(this, resource, updateFields);
                          if (Object.keys(updateFields).length) {
                              Object.assign(body, updateFields);
                          }
                          const userId = this.getNodeParameter('userId', i);
                          responseData = await GenericFunctions_1.grafanaApiRequest.call(this, 'PATCH', `/org/users/${userId}`, body);
                      }
                  }
                  Array.isArray(responseData)
                      ? returnData.push(...responseData)
                      : returnData.push(responseData);
              }
              catch (error) {
                  if (this.continueOnFail()) {
                      returnData.push({ error: error.message });
                      continue;
                  }
                  throw error;
              }
          }
          return [this.helpers.returnJsonArray(returnData)];
      }
  }
  exports.Grafana = Grafana;
  //# sourceMappingURL=Grafana.node.js.map

documentation_markdown:
  ---
  #https://www.notion.so/n8n/Frontmatter-432c2b8dff1f43d4b1c8d20075510fe4
  title: Grafana credentials
  description: Documentation for Grafana credentials. Use these credentials to authenticate Grafana in n8n, a workflow automation platform.
  contentType: [integration, reference]
  ---

  # Grafana credentials

  You can use these credentials to authenticate the following nodes:

  - [Grafana](/integrations/builtin/app-nodes/n8n-nodes-base.grafana.md)

  ## Prerequisites

  - Create a [Grafana](https://grafana.com/){:target=_blank .external-link} account.

  ## Supported authentication methods

  - API key

  ## Related resources

  Refer to [Grafana's API documentation](https://grafana.com/docs/grafana/latest/developers/http_api/){:target=_blank .external-link} for more information about authenticating with the service.

  ## Using API key

  To configure this credential, you'll need:

  - An **API Key**: Refer to the [Create an API key documentation](https://grafana.com/docs/grafana/latest/administration/api-keys/#create-an-api-key){:target=_blank .external-link} for detailed instructions on creating an API key.
  - The **Base URL** for your Grafana instance, for example: `https://n8n.grafana.net`.

example_workflow:
  {"nodes":[{"parameters":{},"type":"n8n-nodes-base.node","typeVersion":1,"position":[220,120],"id":"c13110c1-b486-44d2-8731-68eaef70aab0","name":"Node"}],"connections":{"Node":{"main":[[]]}},"pinData":{},"meta":{"templateCredsSetupCompleted":true,"instanceId":"01648bdc0be075f06c26b963d4a608bd60cdfab4ba61d1a04b5e320917c5abf9"}}


node_type: n8n-nodes-base.YouTube
name: YouTube
display_name: YouTube
description: Consume YouTube API
category: Other
code_hash: f834b8bd47ceff5c44239f11db43a05b8839404dd4001472a33e5aad9cb7e619
documentation_url: https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.youtube
example_parameters: {}
properties_schema: []
package_name: n8n-nodes-base
extracted_at: 2025-06-08 08:05:23
updated_at: 2025-06-08 08:05:23
source_code:
  "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.YouTube = void 0;
  const n8n_workflow_1 = require("n8n-workflow");
  const GenericFunctions_1 = require("./GenericFunctions");
  const ChannelDescription_1 = require("./ChannelDescription");
  const PlaylistDescription_1 = require("./PlaylistDescription");
  const PlaylistItemDescription_1 = require("./PlaylistItemDescription");
  const VideoDescription_1 = require("./VideoDescription");
  const VideoCategoryDescription_1 = require("./VideoCategoryDescription");
  const CountryCodes_1 = require("./CountryCodes");
  const UPLOAD_CHUNK_SIZE = 1024 * 1024;
  class YouTube {
      constructor() {
          this.description = {
              displayName: 'YouTube',
              name: 'youTube',
              icon: 'file:youTube.png',
              group: ['input'],
              version: 1,
              subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
              description: 'Consume YouTube API',
              defaults: {
                  name: 'YouTube',
              },
              inputs: ['main'],
              outputs: ['main'],
              credentials: [
                  {
                      name: 'youTubeOAuth2Api',
                      required: true,
                  },
              ],
              properties: [
                  {
                      displayName: 'Resource',
                      name: 'resource',
                      type: 'options',
                      noDataExpression: true,
                      options: [
                          {
                              name: 'Channel',
                              value: 'channel',
                          },
                          {
                              name: 'Playlist',
                              value: 'playlist',
                          },
                          {
                              name: 'Playlist Item',
                              value: 'playlistItem',
                          },
                          {
                              name: 'Video',
                              value: 'video',
                          },
                          {
                              name: 'Video Category',
                              value: 'videoCategory',
                          },
                      ],
                      default: 'channel',
                  },
                  ...ChannelDescription_1.channelOperations,
                  ...ChannelDescription_1.channelFields,
                  ...PlaylistDescription_1.playlistOperations,
                  ...PlaylistDescription_1.playlistFields,
                  ...PlaylistItemDescription_1.playlistItemOperations,
                  ...PlaylistItemDescription_1.playlistItemFields,
                  ...VideoDescription_1.videoOperations,
                  ...VideoDescription_1.videoFields,
                  ...VideoCategoryDescription_1.videoCategoryOperations,
                  ...VideoCategoryDescription_1.videoCategoryFields,
              ],
          };
          this.methods = {
              loadOptions: {
                  async getLanguages() {
                      const returnData = [];
                      const languages = await GenericFunctions_1.googleApiRequestAllItems.call(this, 'items', 'GET', '/youtube/v3/i18nLanguages');
                      for (const language of languages) {
                          const languageName = language.id.toUpperCase();
                          const languageId = language.id;
                          returnData.push({
                              name: languageName,
                              value: languageId,
                          });
                      }
                      return returnData;
                  },
                  async getCountriesCodes() {
                      const returnData = [];
                      for (const countryCode of CountryCodes_1.countriesCodes) {
                          const countryCodeName = `${countryCode.name} - ${countryCode.alpha2}`;
                          const countryCodeId = countryCode.alpha2;
                          returnData.push({
                              name: countryCodeName,
                              value: countryCodeId,
                          });
                      }
                      return returnData;
                  },
                  async getVideoCategories() {
                      const countryCode = this.getCurrentNodeParameter('regionCode');
                      const returnData = [];
                      const qs = {};
                      qs.regionCode = countryCode;
                      qs.part = 'snippet';
                      const categories = await GenericFunctions_1.googleApiRequestAllItems.call(this, 'items', 'GET', '/youtube/v3/videoCategories', {}, qs);
                      for (const category of categories) {
                          const categoryName = category.snippet.title;
                          const categoryId = category.id;
                          returnData.push({
                              name: categoryName,
                              value: categoryId,
                          });
                      }
                      return returnData;
                  },
                  async getPlaylists() {
                      const returnData = [];
                      const qs = {};
                      qs.part = 'snippet';
                      qs.mine = true;
                      const playlists = await GenericFunctions_1.googleApiRequestAllItems.call(this, 'items', 'GET', '/youtube/v3/playlists', {}, qs);
                      for (const playlist of playlists) {
                          const playlistName = playlist.snippet.title;
                          const playlistId = playlist.id;
                          returnData.push({
                              name: playlistName,
                              value: playlistId,
                          });
                      }
                      return returnData;
                  },
              },
          };
      }
      async execute() {
          var _a, _b, _c, _d;
          const items = this.getInputData();
          const returnData = [];
          const length = items.length;
          const qs = {};
          let responseData;
          const resource = this.getNodeParameter('resource', 0);
          const operation = this.getNodeParameter('operation', 0);
          for (let i = 0; i < length; i++) {
              try {
                  if (resource === 'channel') {
                      if (operation === 'get') {
                          let part = this.getNodeParameter('part', i);
                          const channelId = this.getNodeParameter('channelId', i);
                          if (part.includes('*')) {
                              part = [
                                  'brandingSettings',
                                  'contentDetails',
                                  'contentOwnerDetails',
                                  'id',
                                  'localizations',
                                  'snippet',
                                  'statistics',
                                  'status',
                                  'topicDetails',
                              ];
                          }
                          qs.part = part.join(',');
                          qs.id = channelId;
                          responseData = await GenericFunctions_1.googleApiRequest.call(this, 'GET', '/youtube/v3/channels', {}, qs);
                          responseData = responseData.items;
                      }
                      if (operation === 'getAll') {
                          const returnAll = this.getNodeParameter('returnAll', i);
                          let part = this.getNodeParameter('part', i);
                          const options = this.getNodeParameter('options', i);
                          const filters = this.getNodeParameter('filters', i);
                          if (part.includes('*')) {
                              part = [
                                  'brandingSettings',
                                  'contentDetails',
                                  'contentOwnerDetails',
                                  'id',
                                  'localizations',
                                  'snippet',
                                  'statistics',
                                  'status',
                                  'topicDetails',
                              ];
                          }
                          qs.part = part.join(',');
                          Object.assign(qs, options, filters);
                          qs.mine = true;
                          if (qs.categoryId || qs.forUsername || qs.id || qs.managedByMe) {
                              delete qs.mine;
                          }
                          if (returnAll) {
                              responseData = await GenericFunctions_1.googleApiRequestAllItems.call(this, 'items', 'GET', '/youtube/v3/channels', {}, qs);
                          }
                          else {
                              qs.maxResults = this.getNodeParameter('limit', i);
                              responseData = await GenericFunctions_1.googleApiRequest.call(this, 'GET', '/youtube/v3/channels', {}, qs);
                              responseData = responseData.items;
                          }
                      }
                      if (operation === 'update') {
                          const channelId = this.getNodeParameter('channelId', i);
                          const updateFields = this.getNodeParameter('updateFields', i);
                          const body = {
                              id: channelId,
                              brandingSettings: {
                                  channel: {},
                                  image: {},
                              },
                          };
                          qs.part = 'brandingSettings';
                          if (updateFields.onBehalfOfContentOwner) {
                              qs.onBehalfOfContentOwner = updateFields.onBehalfOfContentOwner;
                          }
                          if (updateFields.brandingSettingsUi) {
                              const channelSettingsValues = updateFields.brandingSettingsUi
                                  .channelSettingsValues;
                              const channelSettings = {};
                              if (channelSettingsValues === null || channelSettingsValues === void 0 ? void 0 : channelSettingsValues.channel) {
                                  const channelSettingsOptions = channelSettingsValues.channel;
                                  if (channelSettingsOptions.country) {
                                      channelSettings.country = channelSettingsOptions.country;
                                  }
                                  if (channelSettingsOptions.description) {
                                      channelSettings.description = channelSettingsOptions.description;
                                  }
                                  if (channelSettingsOptions.defaultLanguage) {
                                      channelSettings.defaultLanguage = channelSettingsOptions.defaultLanguage;
                                  }
                                  if (channelSettingsOptions.defaultTab) {
                                      channelSettings.defaultTab = channelSettingsOptions.defaultTab;
                                  }
                                  if (channelSettingsOptions.featuredChannelsTitle) {
                                      channelSettings.featuredChannelsTitle =
                                          channelSettingsOptions.featuredChannelsTitle;
                                  }
                                  if (channelSettingsOptions.featuredChannelsUrls) {
                                      channelSettings.featuredChannelsUrls =
                                          channelSettingsOptions.featuredChannelsUrls;
                                  }
                                  if (channelSettingsOptions.keywords) {
                                      channelSettings.keywords = channelSettingsOptions.keywords;
                                  }
                                  if (channelSettingsOptions.moderateComments) {
                                      channelSettings.moderateComments =
                                          channelSettingsOptions.moderateComments;
                                  }
                                  if (channelSettingsOptions.profileColor) {
                                      channelSettings.profileColor = channelSettingsOptions.profileColor;
                                  }
                                  if (channelSettingsOptions.profileColor) {
                                      channelSettings.profileColor = channelSettingsOptions.profileColor;
                                  }
                                  if (channelSettingsOptions.showRelatedChannels) {
                                      channelSettings.showRelatedChannels =
                                          channelSettingsOptions.showRelatedChannels;
                                  }
                                  if (channelSettingsOptions.showBrowseView) {
                                      channelSettings.showBrowseView = channelSettingsOptions.showBrowseView;
                                  }
                                  if (channelSettingsOptions.trackingAnalyticsAccountId) {
                                      channelSettings.trackingAnalyticsAccountId =
                                          channelSettingsOptions.trackingAnalyticsAccountId;
                                  }
                                  if (channelSettingsOptions.unsubscribedTrailer) {
                                      channelSettings.unsubscribedTrailer =
                                          channelSettingsOptions.unsubscribedTrailer;
                                  }
                              }
                              const imageSettingsValues = updateFields.brandingSettingsUi
                                  .imageSettingsValues;
                              const imageSettings = {};
                              if (imageSettingsValues === null || imageSettingsValues === void 0 ? void 0 : imageSettingsValues.image) {
                                  const imageSettingsOptions = imageSettings.image;
                                  if (imageSettingsOptions.bannerExternalUrl) {
                                      imageSettings.bannerExternalUrl =
                                          imageSettingsOptions.bannerExternalUrl;
                                  }
                                  if (imageSettingsOptions.trackingImageUrl) {
                                      imageSettings.trackingImageUrl = imageSettingsOptions.trackingImageUrl;
                                  }
                                  if (imageSettingsOptions.watchIconImageUrl) {
                                      imageSettings.watchIconImageUrl =
                                          imageSettingsOptions.watchIconImageUrl;
                                  }
                              }
                              body.brandingSettings.channel = channelSettings;
                              body.brandingSettings.image = imageSettings;
                          }
                          responseData = await GenericFunctions_1.googleApiRequest.call(this, 'PUT', '/youtube/v3/channels', body, qs);
                      }
                      if (operation === 'uploadBanner') {
                          const channelId = this.getNodeParameter('channelId', i);
                          const binaryProperty = this.getNodeParameter('binaryProperty', i);
                          const binaryData = this.helpers.assertBinaryData(i, binaryProperty);
                          const body = await this.helpers.getBinaryDataBuffer(i, binaryProperty);
                          const requestOptions = {
                              headers: {
                                  ...(binaryData.mimeType ? { 'Content-Type': binaryData.mimeType } : {}),
                              },
                              json: false,
                          };
                          const response = await GenericFunctions_1.googleApiRequest.call(this, 'POST', '/upload/youtube/v3/channelBanners/insert', body, qs, undefined, requestOptions);
                          const { url } = JSON.parse(response);
                          qs.part = 'brandingSettings';
                          responseData = await GenericFunctions_1.googleApiRequest.call(this, 'PUT', '/youtube/v3/channels', {
                              id: channelId,
                              brandingSettings: {
                                  image: {
                                      bannerExternalUrl: url,
                                  },
                              },
                          }, qs);
                      }
                  }
                  if (resource === 'playlist') {
                      if (operation === 'get') {
                          let part = this.getNodeParameter('part', i);
                          const playlistId = this.getNodeParameter('playlistId', i);
                          const options = this.getNodeParameter('options', i);
                          if (part.includes('*')) {
                              part = ['contentDetails', 'id', 'localizations', 'player', 'snippet', 'status'];
                          }
                          qs.part = part.join(',');
                          qs.id = playlistId;
                          Object.assign(qs, options);
                          responseData = await GenericFunctions_1.googleApiRequest.call(this, 'GET', '/youtube/v3/playlists', {}, qs);
                          responseData = responseData.items;
                      }
                      if (operation === 'getAll') {
                          const returnAll = this.getNodeParameter('returnAll', i);
                          let part = this.getNodeParameter('part', i);
                          const options = this.getNodeParameter('options', i);
                          const filters = this.getNodeParameter('filters', i);
                          if (part.includes('*')) {
                              part = ['contentDetails', 'id', 'localizations', 'player', 'snippet', 'status'];
                          }
                          qs.part = part.join(',');
                          Object.assign(qs, options, filters);
                          qs.mine = true;
                          if (qs.channelId || qs.id) {
                              delete qs.mine;
                          }
                          if (returnAll) {
                              responseData = await GenericFunctions_1.googleApiRequestAllItems.call(this, 'items', 'GET', '/youtube/v3/playlists', {}, qs);
                          }
                          else {
                              qs.maxResults = this.getNodeParameter('limit', i);
                              responseData = await GenericFunctions_1.googleApiRequest.call(this, 'GET', '/youtube/v3/playlists', {}, qs);
                              responseData = responseData.items;
                          }
                      }
                      if (operation === 'create') {
                          const title = this.getNodeParameter('title', i);
                          const options = this.getNodeParameter('options', i);
                          qs.part = 'snippet';
                          const body = {
                              snippet: {
                                  title,
                              },
                          };
                          if (options.tags) {
                              body.snippet.tags = options.tags.split(',');
                          }
                          if (options.description) {
                              body.snippet.privacyStatus = options.privacyStatus;
                          }
                          if (options.defaultLanguage) {
                              body.snippet.defaultLanguage = options.defaultLanguage;
                          }
                          if (options.onBehalfOfContentOwner) {
                              qs.onBehalfOfContentOwner = options.onBehalfOfContentOwner;
                          }
                          if (options.onBehalfOfContentOwnerChannel) {
                              qs.onBehalfOfContentOwnerChannel = options.onBehalfOfContentOwnerChannel;
                          }
                          responseData = await GenericFunctions_1.googleApiRequest.call(this, 'POST', '/youtube/v3/playlists', body, qs);
                      }
                      if (operation === 'update') {
                          const playlistId = this.getNodeParameter('playlistId', i);
                          const title = this.getNodeParameter('title', i);
                          const updateFields = this.getNodeParameter('updateFields', i);
                          qs.part = 'snippet, status';
                          const body = {
                              id: playlistId,
                              snippet: {
                                  title,
                              },
                              status: {},
                          };
                          if (updateFields.tags) {
                              body.snippet.tags = updateFields.tags.split(',');
                          }
                          if (updateFields.privacyStatus) {
                              body.status.privacyStatus = updateFields.privacyStatus;
                          }
                          if (updateFields.description) {
                              body.snippet.description = updateFields.description;
                          }
                          if (updateFields.defaultLanguage) {
                              body.snippet.defaultLanguage = updateFields.defaultLanguage;
                          }
                          if (updateFields.onBehalfOfContentOwner) {
                              qs.onBehalfOfContentOwner = updateFields.onBehalfOfContentOwner;
                          }
                          responseData = await GenericFunctions_1.googleApiRequest.call(this, 'PUT', '/youtube/v3/playlists', body, qs);
                      }
                      if (operation === 'delete') {
                          const playlistId = this.getNodeParameter('playlistId', i);
                          const options = this.getNodeParameter('options', i);
                          const body = {
                              id: playlistId,
                          };
                          if (options.onBehalfOfContentOwner) {
                              qs.onBehalfOfContentOwner = options.onBehalfOfContentOwner;
                          }
                          responseData = await GenericFunctions_1.googleApiRequest.call(this, 'DELETE', '/youtube/v3/playlists', body);
                          responseData = { success: true };
                      }
                  }
                  if (resource === 'playlistItem') {
                      if (operation === 'get') {
                          let part = this.getNodeParameter('part', i);
                          const playlistItemId = this.getNodeParameter('playlistItemId', i);
                          const options = this.getNodeParameter('options', i);
                          if (part.includes('*')) {
                              part = ['contentDetails', 'id', 'snippet', 'status'];
                          }
                          qs.part = part.join(',');
                          qs.id = playlistItemId;
                          Object.assign(qs, options);
                          responseData = await GenericFunctions_1.googleApiRequest.call(this, 'GET', '/youtube/v3/playlistItems', {}, qs);
                          responseData = responseData.items;
                      }
                      if (operation === 'getAll') {
                          const returnAll = this.getNodeParameter('returnAll', i);
                          let part = this.getNodeParameter('part', i);
                          const options = this.getNodeParameter('options', i);
                          const playlistId = this.getNodeParameter('playlistId', i);
                          if (part.includes('*')) {
                              part = ['contentDetails', 'id', 'snippet', 'status'];
                          }
                          qs.playlistId = playlistId;
                          qs.part = part.join(',');
                          Object.assign(qs, options);
                          if (returnAll) {
                              responseData = await GenericFunctions_1.googleApiRequestAllItems.call(this, 'items', 'GET', '/youtube/v3/playlistItems', {}, qs);
                          }
                          else {
                              qs.maxResults = this.getNodeParameter('limit', i);
                              responseData = await GenericFunctions_1.googleApiRequest.call(this, 'GET', '/youtube/v3/playlistItems', {}, qs);
                              responseData = responseData.items;
                          }
                      }
                      if (operation === 'add') {
                          const playlistId = this.getNodeParameter('playlistId', i);
                          const videoId = this.getNodeParameter('videoId', i);
                          const options = this.getNodeParameter('options', i);
                          qs.part = 'snippet, contentDetails';
                          const body = {
                              snippet: {
                                  playlistId,
                                  resourceId: {
                                      kind: 'youtube#video',
                                      videoId,
                                  },
                              },
                              contentDetails: {},
                          };
                          if (options.position) {
                              body.snippet.position = options.position;
                          }
                          if (options.note) {
                              body.contentDetails.note = options.note;
                          }
                          if (options.startAt) {
                              body.contentDetails.startAt = options.startAt;
                          }
                          if (options.endAt) {
                              body.contentDetails.endAt = options.endAt;
                          }
                          if (options.onBehalfOfContentOwner) {
                              qs.onBehalfOfContentOwner = options.onBehalfOfContentOwner;
                          }
                          responseData = await GenericFunctions_1.googleApiRequest.call(this, 'POST', '/youtube/v3/playlistItems', body, qs);
                      }
                      if (operation === 'delete') {
                          const playlistItemId = this.getNodeParameter('playlistItemId', i);
                          const options = this.getNodeParameter('options', i);
                          const body = {
                              id: playlistItemId,
                          };
                          if (options.onBehalfOfContentOwner) {
                              qs.onBehalfOfContentOwner = options.onBehalfOfContentOwner;
                          }
                          responseData = await GenericFunctions_1.googleApiRequest.call(this, 'DELETE', '/youtube/v3/playlistItems', body);
                          responseData = { success: true };
                      }
                  }
                  if (resource === 'video') {
                      if (operation === 'getAll') {
                          const returnAll = this.getNodeParameter('returnAll', i);
                          const options = this.getNodeParameter('options', i);
                          const filters = this.getNodeParameter('filters', i);
                          qs.part = 'snippet';
                          qs.type = 'video';
                          qs.forMine = true;
                          Object.assign(qs, options, filters);
                          if (Object.keys(filters).length > 0) {
                              delete qs.forMine;
                          }
                          if (qs.relatedToVideoId && qs.forDeveloper !== undefined) {
                              throw new n8n_workflow_1.NodeOperationError(this.getNode(), "When using the parameter 'related to video' the parameter 'for developer' cannot be set", { itemIndex: i });
                          }
                          if (returnAll) {
                              responseData = await GenericFunctions_1.googleApiRequestAllItems.call(this, 'items', 'GET', '/youtube/v3/search', {}, qs);
                          }
                          else {
                              qs.maxResults = this.getNodeParameter('limit', i);
                              responseData = await GenericFunctions_1.googleApiRequest.call(this, 'GET', '/youtube/v3/search', {}, qs);
                              responseData = responseData.items;
                          }
                      }
                      if (operation === 'get') {
                          let part = this.getNodeParameter('part', i);
                          const videoId = this.getNodeParameter('videoId', i);
                          const options = this.getNodeParameter('options', i);
                          if (part.includes('*')) {
                              part = [
                                  'contentDetails',
                                  'id',
                                  'liveStreamingDetails',
                                  'localizations',
                                  'player',
                                  'recordingDetails',
                                  'snippet',
                                  'statistics',
                                  'status',
                                  'topicDetails',
                              ];
                          }
                          qs.part = part.join(',');
                          qs.id = videoId;
                          Object.assign(qs, options);
                          responseData = await GenericFunctions_1.googleApiRequest.call(this, 'GET', '/youtube/v3/videos', {}, qs);
                          responseData = responseData.items;
                      }
                      if (operation === 'upload') {
                          const title = this.getNodeParameter('title', i);
                          const categoryId = this.getNodeParameter('categoryId', i);
                          const options = this.getNodeParameter('options', i);
                          const binaryProperty = this.getNodeParameter('binaryProperty', i);
                          const binaryData = this.helpers.assertBinaryData(i, binaryProperty);
                          let mimeType;
                          let contentLength;
                          let fileContent;
                          if (binaryData.id) {
                              fileContent = await this.helpers.getBinaryStream(binaryData.id, UPLOAD_CHUNK_SIZE);
                              const metadata = await this.helpers.getBinaryMetadata(binaryData.id);
                              contentLength = metadata.fileSize;
                              mimeType = (_a = metadata.mimeType) !== null && _a !== void 0 ? _a : binaryData.mimeType;
                          }
                          else {
                              fileContent = Buffer.from(binaryData.data, n8n_workflow_1.BINARY_ENCODING);
                              contentLength = fileContent.length;
                              mimeType = binaryData.mimeType;
                          }
                          const payload = {
                              snippet: {
                                  title,
                                  categoryId,
                                  description: options.description,
                                  tags: (_b = options.tags) === null || _b === void 0 ? void 0 : _b.split(','),
                                  defaultLanguage: options.defaultLanguage,
                              },
                              status: {
                                  privacyStatus: options.privacyStatus,
                                  embeddable: options.embeddable,
                                  publicStatsViewable: options.publicStatsViewable,
                                  publishAt: options.publishAt,
                                  selfDeclaredMadeForKids: options.selfDeclaredMadeForKids,
                                  license: options.license,
                              },
                              recordingDetails: {
                                  recordingDate: options.recordingDate,
                              },
                          };
                          const resumableUpload = await GenericFunctions_1.googleApiRequest.call(this, 'POST', '/upload/youtube/v3/videos', payload, {
                              uploadType: 'resumable',
                              part: 'snippet,status,recordingDetails',
                              notifySubscribers: (_c = options.notifySubscribers) !== null && _c !== void 0 ? _c : false,
                          }, undefined, {
                              headers: {
                                  'X-Upload-Content-Length': contentLength,
                                  'X-Upload-Content-Type': mimeType,
                              },
                              json: true,
                              resolveWithFullResponse: true,
                          });
                          const uploadUrl = resumableUpload.headers.location;
                          let uploadId;
                          let offset = 0;
                          for await (const chunk of fileContent) {
                              const nextOffset = offset + Number(chunk.length);
                              try {
                                  const response = await this.helpers.httpRequest({
                                      method: 'PUT',
                                      url: uploadUrl,
                                      headers: {
                                          'Content-Length': chunk.length,
                                          'Content-Range': `bytes ${offset}-${nextOffset - 1}/${contentLength}`,
                                      },
                                      body: chunk,
                                  });
                                  uploadId = response.id;
                              }
                              catch (error) {
                                  if (((_d = error.response) === null || _d === void 0 ? void 0 : _d.status) !== 308)
                                      throw error;
                              }
                              offset = nextOffset;
                          }
                          responseData = { uploadId, ...resumableUpload.body };
                      }
                      if (operation === 'update') {
                          const id = this.getNodeParameter('videoId', i);
                          const title = this.getNodeParameter('title', i);
                          const categoryId = this.getNodeParameter('categoryId', i);
                          const updateFields = this.getNodeParameter('updateFields', i);
                          qs.part = 'snippet, status, recordingDetails';
                          const body = {
                              id,
                              snippet: {
                                  title,
                                  categoryId,
                              },
                              status: {},
                              recordingDetails: {},
                          };
                          if (updateFields.description) {
                              body.snippet.description = updateFields.description;
                          }
                          if (updateFields.privacyStatus) {
                              body.status.privacyStatus = updateFields.privacyStatus;
                          }
                          if (updateFields.tags) {
                              body.snippet.tags = updateFields.tags.split(',');
                          }
                          if (updateFields.embeddable) {
                              body.status.embeddable = updateFields.embeddable;
                          }
                          if (updateFields.publicStatsViewable) {
                              body.status.publicStatsViewable = updateFields.publicStatsViewable;
                          }
                          if (updateFields.publishAt) {
                              body.status.publishAt = updateFields.publishAt;
                          }
                          if (updateFields.selfDeclaredMadeForKids) {
                              body.status.selfDeclaredMadeForKids = updateFields.selfDeclaredMadeForKids;
                          }
                          if (updateFields.recordingDate) {
                              body.recordingDetails.recordingDate = updateFields.recordingDate;
                          }
                          if (updateFields.license) {
                              body.status.license = updateFields.license;
                          }
                          if (updateFields.defaultLanguage) {
                              body.snippet.defaultLanguage = updateFields.defaultLanguage;
                          }
                          responseData = await GenericFunctions_1.googleApiRequest.call(this, 'PUT', '/youtube/v3/videos', body, qs);
                      }
                      if (operation === 'delete') {
                          const videoId = this.getNodeParameter('videoId', i);
                          const options = this.getNodeParameter('options', i);
                          const body = {
                              id: videoId,
                          };
                          if (options.onBehalfOfContentOwner) {
                              qs.onBehalfOfContentOwner = options.onBehalfOfContentOwner;
                          }
                          responseData = await GenericFunctions_1.googleApiRequest.call(this, 'DELETE', '/youtube/v3/videos', body);
                          responseData = { success: true };
                      }
                      if (operation === 'rate') {
                          const videoId = this.getNodeParameter('videoId', i);
                          const rating = this.getNodeParameter('rating', i);
                          const body = {
                              id: videoId,
                              rating,
                          };
                          responseData = await GenericFunctions_1.googleApiRequest.call(this, 'POST', '/youtube/v3/videos/rate', body);
                          responseData = { success: true };
                      }
                  }
                  if (resource === 'videoCategory') {
                      if (operation === 'getAll') {
                          const returnAll = this.getNodeParameter('returnAll', i);
                          const regionCode = this.getNodeParameter('regionCode', i);
                          qs.regionCode = regionCode;
                          qs.part = 'snippet';
                          responseData = await GenericFunctions_1.googleApiRequest.call(this, 'GET', '/youtube/v3/videoCategories', {}, qs);
                          responseData = responseData.items;
                          if (!returnAll) {
                              const limit = this.getNodeParameter('limit', i);
                              responseData = responseData.splice(0, limit);
                          }
                      }
                  }
              }
              catch (error) {
                  if (this.continueOnFail()) {
                      const executionErrorData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray({ error: error.message }), { itemData: { item: i } });
                      returnData.push(...executionErrorData);
                      continue;
                  }
                  throw error;
              }
              const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
              returnData.push(...executionData);
          }
          return [returnData];
      }
  }
  exports.YouTube = YouTube;
  //# sourceMappingURL=YouTube.node.js.map

documentation_markdown:
  ---
  #https://www.notion.so/n8n/Frontmatter-432c2b8dff1f43d4b1c8d20075510fe4
  title: YouTube node documentation
  description: Learn how to use the YouTube node in n8n. Follow technical documentation to integrate YouTube node into your workflows.
  contentType: [integration, reference]
  priority: medium
  ---

  # YouTube node

  Use the YouTube node to automate work in YouTube, and integrate YouTube with other applications. n8n has built-in support for a wide range of YouTube features, including retrieving and updating channels, as well as creating and deleting playlists. 

  On this page, you'll find a list of operations the YouTube node supports and links to more resources.

  /// note | Credentials
  Refer to [YouTube credentials](/integrations/builtin/credentials/google/index.md) for guidance on setting up authentication. 
  ///

  --8<-- "_snippets/integrations/builtin/app-nodes/ai-tools.md"

  ## Operations

  * Channel
      * Retrieve a channel
      * Retrieve all channels
      * Update a channel
      * Upload a channel banner
  * Playlist
      * Create a playlist
      * Delete a playlist
      * Get a playlist
      * Retrieve all playlists
      * Update a playlist
  * Playlist Item
      * Add an item to a playlist
      * Delete a item from a playlist
      * Get a playlist's item
      * Retrieve all playlist items
  * Video
      * Delete a video
      * Get a video
      * Retrieve all videos
      * Rate a video
      * Update a video
      * Upload a video
  * Video Category
      * Retrieve all video categories

  ## Templates and examples

  <!-- see https://www.notion.so/n8n/Pull-in-templates-for-the-integrations-pages-37c716837b804d30a33b47475f6e3780 -->
  [[ templatesWidget(page.title, 'youtube') ]]

  --8<-- "_snippets/integrations/builtin/app-nodes/operation-not-supported.md"

example_workflow:
  {"nodes":[{"parameters":{},"type":"n8n-nodes-base.node","typeVersion":1,"position":[220,120],"id":"71b49f45-475f-4373-811d-8cb831ade87e","name":"Node"}],"connections":{"Node":{"main":[[]]}},"pinData":{},"meta":{"templateCredsSetupCompleted":true,"instanceId":"b81a3a82d6b63d7e9b11e8e7bbfd3c600f92fa99e4e269143800bde888b08e8b"}}


node_type: n8n-nodes-base.GraphQL
name: GraphQL
display_name: GraphQL
description: Makes a GraphQL request and returns the received data
category: Other
code_hash: f9b7d2d27319e62247e107607877b0a9dd51497c47e8eca06c74ba2bd1e36054
documentation_url: https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.graphql
example_parameters: {}
properties_schema: []
package_name: n8n-nodes-base
extracted_at: 2025-06-08 08:05:23
updated_at: 2025-06-08 08:05:23
source_code:
  "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.GraphQL = void 0;
  const n8n_workflow_1 = require("n8n-workflow");
  class GraphQL {
      constructor() {
          this.description = {
              displayName: 'GraphQL',
              name: 'graphql',
              icon: 'file:graphql.png',
              group: ['input'],
              version: 1,
              description: 'Makes a GraphQL request and returns the received data',
              defaults: {
                  name: 'GraphQL',
              },
              inputs: ['main'],
              outputs: ['main'],
              credentials: [
                  {
                      name: 'httpBasicAuth',
                      required: true,
                      displayOptions: {
                          show: {
                              authentication: ['basicAuth'],
                          },
                      },
                  },
                  {
                      name: 'httpCustomAuth',
                      required: true,
                      displayOptions: {
                          show: {
                              authentication: ['customAuth'],
                          },
                      },
                  },
                  {
                      name: 'httpDigestAuth',
                      required: true,
                      displayOptions: {
                          show: {
                              authentication: ['digestAuth'],
                          },
                      },
                  },
                  {
                      name: 'httpHeaderAuth',
                      required: true,
                      displayOptions: {
                          show: {
                              authentication: ['headerAuth'],
                          },
                      },
                  },
                  {
                      name: 'httpQueryAuth',
                      required: true,
                      displayOptions: {
                          show: {
                              authentication: ['queryAuth'],
                          },
                      },
                  },
                  {
                      name: 'oAuth1Api',
                      required: true,
                      displayOptions: {
                          show: {
                              authentication: ['oAuth1'],
                          },
                      },
                  },
                  {
                      name: 'oAuth2Api',
                      required: true,
                      displayOptions: {
                          show: {
                              authentication: ['oAuth2'],
                          },
                      },
                  },
              ],
              properties: [
                  {
                      displayName: 'Authentication',
                      name: 'authentication',
                      type: 'options',
                      options: [
                          {
                              name: 'Basic Auth',
                              value: 'basicAuth',
                          },
                          {
                              name: 'Custom Auth',
                              value: 'customAuth',
                          },
                          {
                              name: 'Digest Auth',
                              value: 'digestAuth',
                          },
                          {
                              name: 'Header Auth',
                              value: 'headerAuth',
                          },
                          {
                              name: 'None',
                              value: 'none',
                          },
                          {
                              name: 'OAuth1',
                              value: 'oAuth1',
                          },
                          {
                              name: 'OAuth2',
                              value: 'oAuth2',
                          },
                          {
                              name: 'Query Auth',
                              value: 'queryAuth',
                          },
                      ],
                      default: 'none',
                      description: 'The way to authenticate',
                  },
                  {
                      displayName: 'HTTP Request Method',
                      name: 'requestMethod',
                      type: 'options',
                      options: [
                          {
                              name: 'GET',
                              value: 'GET',
                          },
                          {
                              name: 'POST',
                              value: 'POST',
                          },
                      ],
                      default: 'POST',
                      description: 'The underlying HTTP request method to use',
                  },
                  {
                      displayName: 'Endpoint',
                      name: 'endpoint',
                      type: 'string',
                      default: '',
                      placeholder: 'http://example.com/graphql',
                      description: 'The GraphQL endpoint',
                      required: true,
                  },
                  {
                      displayName: 'Ignore SSL Issues',
                      name: 'allowUnauthorizedCerts',
                      type: 'boolean',
                      default: false,
                      description: 'Whether to download the response even if SSL certificate validation is not possible',
                  },
                  {
                      displayName: 'Request Format',
                      name: 'requestFormat',
                      type: 'options',
                      required: true,
                      options: [
                          {
                              name: 'GraphQL (Raw)',
                              value: 'graphql',
                          },
                          {
                              name: 'JSON',
                              value: 'json',
                          },
                      ],
                      displayOptions: {
                          show: {
                              requestMethod: ['POST'],
                          },
                      },
                      default: 'graphql',
                      description: 'The format for the query payload',
                  },
                  {
                      displayName: 'Query',
                      name: 'query',
                      type: 'json',
                      default: '',
                      description: 'GraphQL query',
                      required: true,
                  },
                  {
                      displayName: 'Variables',
                      name: 'variables',
                      type: 'json',
                      default: '',
                      description: 'Query variables',
                      displayOptions: {
                          show: {
                              requestFormat: ['json'],
                              requestMethod: ['POST'],
                          },
                      },
                  },
                  {
                      displayName: 'Operation Name',
                      name: 'operationName',
                      type: 'string',
                      default: '',
                      description: 'Name of operation to execute',
                      displayOptions: {
                          show: {
                              requestFormat: ['json'],
                              requestMethod: ['POST'],
                          },
                      },
                  },
                  {
                      displayName: 'Response Format',
                      name: 'responseFormat',
                      type: 'options',
                      options: [
                          {
                              name: 'JSON',
                              value: 'json',
                          },
                          {
                              name: 'String',
                              value: 'string',
                          },
                      ],
                      default: 'json',
                      description: 'The format in which the data gets returned from the URL',
                  },
                  {
                      displayName: 'Response Data Property Name',
                      name: 'dataPropertyName',
                      type: 'string',
                      default: 'data',
                      required: true,
                      displayOptions: {
                          show: {
                              responseFormat: ['string'],
                          },
                      },
                      description: 'Name of the property to which to write the response data',
                  },
                  {
                      displayName: 'Headers',
                      name: 'headerParametersUi',
                      placeholder: 'Add Header',
                      type: 'fixedCollection',
                      typeOptions: {
                          multipleValues: true,
                      },
                      description: 'The headers to send',
                      default: {},
                      options: [
                          {
                              name: 'parameter',
                              displayName: 'Header',
                              values: [
                                  {
                                      displayName: 'Name',
                                      name: 'name',
                                      type: 'string',
                                      default: '',
                                      description: 'Name of the header',
                                  },
                                  {
                                      displayName: 'Value',
                                      name: 'value',
                                      type: 'string',
                                      default: '',
                                      description: 'Value to set for the header',
                                  },
                              ],
                          },
                      ],
                  },
              ],
          };
      }
      async execute() {
          var _a;
          const items = this.getInputData();
          let httpBasicAuth;
          let httpDigestAuth;
          let httpCustomAuth;
          let httpHeaderAuth;
          let httpQueryAuth;
          let oAuth1Api;
          let oAuth2Api;
          try {
              httpBasicAuth = await this.getCredentials('httpBasicAuth');
          }
          catch (error) {
          }
          try {
              httpCustomAuth = await this.getCredentials('httpCustomAuth');
          }
          catch (error) {
          }
          try {
              httpDigestAuth = await this.getCredentials('httpDigestAuth');
          }
          catch (error) {
          }
          try {
              httpHeaderAuth = await this.getCredentials('httpHeaderAuth');
          }
          catch (error) {
          }
          try {
              httpQueryAuth = await this.getCredentials('httpQueryAuth');
          }
          catch (error) {
          }
          try {
              oAuth1Api = await this.getCredentials('oAuth1Api');
          }
          catch (error) {
          }
          try {
              oAuth2Api = await this.getCredentials('oAuth2Api');
          }
          catch (error) {
          }
          let requestOptions;
          const returnItems = [];
          for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
              try {
                  const requestMethod = this.getNodeParameter('requestMethod', itemIndex, 'POST');
                  const endpoint = this.getNodeParameter('endpoint', itemIndex, '');
                  const requestFormat = this.getNodeParameter('requestFormat', itemIndex, 'graphql');
                  const responseFormat = this.getNodeParameter('responseFormat', 0);
                  const { parameter } = this.getNodeParameter('headerParametersUi', itemIndex, {});
                  const headerParameters = (parameter || []).reduce((result, item) => ({
                      ...result,
                      [item.name]: item.value,
                  }), {});
                  requestOptions = {
                      headers: {
                          'content-type': `application/${requestFormat}`,
                          ...headerParameters,
                      },
                      method: requestMethod,
                      uri: endpoint,
                      simple: false,
                      rejectUnauthorized: !this.getNodeParameter('allowUnauthorizedCerts', itemIndex, false),
                  };
                  if (httpBasicAuth !== undefined) {
                      requestOptions.auth = {
                          user: httpBasicAuth.user,
                          pass: httpBasicAuth.password,
                      };
                  }
                  if (httpCustomAuth !== undefined) {
                      const customAuth = (0, n8n_workflow_1.jsonParse)(httpCustomAuth.json || '{}', { errorMessage: 'Invalid Custom Auth JSON' });
                      if (customAuth.headers) {
                          requestOptions.headers = { ...requestOptions.headers, ...customAuth.headers };
                      }
                      if (customAuth.body) {
                          requestOptions.body = { ...requestOptions.body, ...customAuth.body };
                      }
                      if (customAuth.qs) {
                          requestOptions.qs = { ...requestOptions.qs, ...customAuth.qs };
                      }
                  }
                  if (httpHeaderAuth !== undefined) {
                      requestOptions.headers[httpHeaderAuth.name] = httpHeaderAuth.value;
                  }
                  if (httpQueryAuth !== undefined) {
                      if (!requestOptions.qs) {
                          requestOptions.qs = {};
                      }
                      requestOptions.qs[httpQueryAuth.name] = httpQueryAuth.value;
                  }
                  if (httpDigestAuth !== undefined) {
                      requestOptions.auth = {
                          user: httpDigestAuth.user,
                          pass: httpDigestAuth.password,
                          sendImmediately: false,
                      };
                  }
                  const gqlQuery = this.getNodeParameter('query', itemIndex, '');
                  if (requestMethod === 'GET') {
                      if (!requestOptions.qs) {
                          requestOptions.qs = {};
                      }
                      requestOptions.qs.query = gqlQuery;
                  }
                  else {
                      if (requestFormat === 'json') {
                          requestOptions.body = {
                              ...requestOptions.body,
                              query: gqlQuery,
                              variables: this.getNodeParameter('variables', itemIndex, {}),
                              operationName: this.getNodeParameter('operationName', itemIndex),
                          };
                          if (typeof requestOptions.body.variables === 'string') {
                              try {
                                  requestOptions.body.variables = JSON.parse(requestOptions.body.variables || '{}');
                              }
                              catch (error) {
                                  throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Using variables failed:\n' +
                                      requestOptions.body.variables +
                                      '\n\nWith error message:\n' +
                                      error, { itemIndex });
                              }
                          }
                          if (requestOptions.body.operationName === '') {
                              requestOptions.body.operationName = null;
                          }
                          requestOptions.json = true;
                      }
                      else {
                          requestOptions.body = gqlQuery;
                      }
                  }
                  let response;
                  if (oAuth1Api !== undefined) {
                      response = await this.helpers.requestOAuth1.call(this, 'oAuth1Api', requestOptions);
                  }
                  else if (oAuth2Api !== undefined) {
                      response = await this.helpers.requestOAuth2.call(this, 'oAuth2Api', requestOptions, {
                          tokenType: 'Bearer',
                      });
                  }
                  else {
                      response = await this.helpers.request(requestOptions);
                  }
                  if (responseFormat === 'string') {
                      const dataPropertyName = this.getNodeParameter('dataPropertyName', 0);
                      returnItems.push({
                          json: {
                              [dataPropertyName]: response,
                          },
                      });
                  }
                  else {
                      if (typeof response === 'string') {
                          try {
                              response = JSON.parse(response);
                          }
                          catch (error) {
                              throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Response body is not valid JSON. Change "Response Format" to "String"', { itemIndex });
                          }
                      }
                      const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(response), { itemData: { item: itemIndex } });
                      returnItems.push(...executionData);
                  }
                  if (typeof response === 'string' && response.startsWith('{"errors":')) {
                      try {
                          const errorResponse = JSON.parse(response);
                          if (Array.isArray(errorResponse.errors)) {
                              response = errorResponse;
                          }
                      }
                      catch (e) { }
                  }
                  if (typeof response === 'object' && response.errors) {
                      const message = ((_a = response.errors) === null || _a === void 0 ? void 0 : _a.map((error) => error.message).join(', ')) ||
                          'Unexpected error';
                      throw new n8n_workflow_1.NodeApiError(this.getNode(), response.errors, { message });
                  }
              }
              catch (error) {
                  if (this.continueOnFail()) {
                      const errorData = this.helpers.returnJsonArray({
                          $error: error,
                          json: this.getInputData(itemIndex),
                          itemIndex,
                      });
                      const exectionErrorWithMetaData = this.helpers.constructExecutionMetaData(errorData, {
                          itemData: { item: itemIndex },
                      });
                      returnItems.push(...exectionErrorWithMetaData);
                      continue;
                  }
                  throw error;
              }
          }
          return [returnItems];
      }
  }
  exports.GraphQL = GraphQL;
  //# sourceMappingURL=GraphQL.node.js.map

documentation_markdown:
  ---
  #https://www.notion.so/n8n/Frontmatter-432c2b8dff1f43d4b1c8d20075510fe4
  title: GraphQL
  description: Documentation for the GraphQL node in n8n, a workflow automation platform. Includes guidance on usage, and links to examples.
  contentType: [integration, reference]
  priority: medium
  ---

  # GraphQL

  [GraphQL](https://graphql.org/){:target=_blank .external-link} is an open-source data query and manipulation language for APIs, and a runtime for fulfilling queries with existing data. Use the GraphQL node to query a GraphQL endpoint.

  ## Node parameters

  --8<-- "_snippets/integrations/builtin/app-nodes/ai-tools.md"

  ### Authentication

  Select the type of authentication to use.

  If you select anything other than **None**, the **Credential for <selected-auth-type>** parameter appears for you to select an existing or create a new authentication credential for that authentication type.

  ### HTTP Request Method

  Select the underlying HTTP Request method the node should use. Choose from:

  * **GET**
  * **POST**: If you select this method, you'll also need to select the **Request Format** the node should use for the query payload. Choose from:
      * **GraphQL (Raw)**
      * **JSON**

  ### Endpoint

  Enter the GraphQL Endpoint you'd like to hit.

  ### Ignore SSL Issues

  When you turn on this control, n8n ignores SSL certificate validation failure.

  ### Query

  Enter the GraphQL query you want to execute.

  Refer to [Related Resources](#related-resources) for information on writing your query.

  ### Response Format

  Select the format you'd like to receive query results in. Choose between:

  * **JSON**
  * **String**: If you select this format, enter a **Response Data Property Name** to define the property the string is written to.

  ## Headers

  Enter any **Headers** you want to pass as part of the query as **Name** / **Value** pairs.

  ## Templates and examples

  <!-- see https://www.notion.so/n8n/Pull-in-templates-for-the-integrations-pages-37c716837b804d30a33b47475f6e3780 -->
  [[ templatesWidget(page.title, 'graphql') ]]

  ## Related resources

  To use the GraphQL node, you need to understand GraphQL query language. GraphQL have their own [Introduction to GraphQL](https://graphql.org/learn/){:target=_blank .external-link} tutorial.

example_workflow:
  {"nodes":[{"parameters":{},"type":"n8n-nodes-base.node","typeVersion":1,"position":[220,120],"id":"95f4fc07-9bdc-4156-99ef-686057cc325c","name":"Node"}],"connections":{"Node":{"main":[[]]}},"pinData":{},"meta":{"templateCredsSetupCompleted":true,"instanceId":"4d2c6de72bc2256a66965e37e4cfaa72a42886377fed9b502b50a30cf9a151f9"}}


node_type: n8n-nodes-base.HackerNews
name: HackerNews
display_name: Hacker News
description: Consume Hacker News API
category: Other
code_hash: 390a3ac297411fe2c0fc2a82381c6d6bf1ad8892139f36e09da9b1782c055c0e
documentation_url: https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.hackernews
example_parameters: {}
properties_schema: []
package_name: n8n-nodes-base
extracted_at: 2025-06-08 08:05:23
updated_at: 2025-06-08 08:05:23
source_code:
  "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.HackerNews = void 0;
  const n8n_workflow_1 = require("n8n-workflow");
  const GenericFunctions_1 = require("./GenericFunctions");
  class HackerNews {
      constructor() {
          this.description = {
              displayName: 'Hacker News',
              name: 'hackerNews',
              icon: 'file:hackernews.png',
              group: ['transform'],
              version: 1,
              subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
              description: 'Consume Hacker News API',
              defaults: {
                  name: 'Hacker News',
              },
              inputs: ['main'],
              outputs: ['main'],
              properties: [
                  {
                      displayName: 'Resource',
                      name: 'resource',
                      type: 'options',
                      noDataExpression: true,
                      options: [
                          {
                              name: 'All',
                              value: 'all',
                          },
                          {
                              name: 'Article',
                              value: 'article',
                          },
                          {
                              name: 'User',
                              value: 'user',
                          },
                      ],
                      default: 'article',
                  },
                  {
                      displayName: 'Operation',
                      name: 'operation',
                      type: 'options',
                      noDataExpression: true,
                      displayOptions: {
                          show: {
                              resource: ['all'],
                          },
                      },
                      options: [
                          {
                              name: 'Get Many',
                              value: 'getAll',
                              description: 'Get many items',
                              action: 'Get many items',
                          },
                      ],
                      default: 'getAll',
                  },
                  {
                      displayName: 'Operation',
                      name: 'operation',
                      type: 'options',
                      noDataExpression: true,
                      displayOptions: {
                          show: {
                              resource: ['article'],
                          },
                      },
                      options: [
                          {
                              name: 'Get',
                              value: 'get',
                              description: 'Get a Hacker News article',
                              action: 'Get an article',
                          },
                      ],
                      default: 'get',
                  },
                  {
                      displayName: 'Operation',
                      name: 'operation',
                      type: 'options',
                      noDataExpression: true,
                      displayOptions: {
                          show: {
                              resource: ['user'],
                          },
                      },
                      options: [
                          {
                              name: 'Get',
                              value: 'get',
                              description: 'Get a Hacker News user',
                              action: 'Get a user',
                          },
                      ],
                      default: 'get',
                  },
                  {
                      displayName: 'Article ID',
                      name: 'articleId',
                      type: 'string',
                      required: true,
                      default: '',
                      description: 'The ID of the Hacker News article to be returned',
                      displayOptions: {
                          show: {
                              resource: ['article'],
                              operation: ['get'],
                          },
                      },
                  },
                  {
                      displayName: 'Username',
                      name: 'username',
                      type: 'string',
                      required: true,
                      default: '',
                      description: 'The Hacker News user to be returned',
                      displayOptions: {
                          show: {
                              resource: ['user'],
                              operation: ['get'],
                          },
                      },
                  },
                  {
                      displayName: 'Return All',
                      name: 'returnAll',
                      type: 'boolean',
                      default: false,
                      description: 'Whether to return all results or only up to a given limit',
                      displayOptions: {
                          show: {
                              resource: ['all'],
                              operation: ['getAll'],
                          },
                      },
                  },
                  {
                      displayName: 'Limit',
                      name: 'limit',
                      type: 'number',
                      typeOptions: {
                          minValue: 1,
                      },
                      default: 100,
                      description: 'Max number of results to return',
                      displayOptions: {
                          show: {
                              resource: ['all'],
                              operation: ['getAll'],
                              returnAll: [false],
                          },
                      },
                  },
                  {
                      displayName: 'Additional Fields',
                      name: 'additionalFields',
                      type: 'collection',
                      placeholder: 'Add Field',
                      default: {},
                      displayOptions: {
                          show: {
                              resource: ['article'],
                              operation: ['get'],
                          },
                      },
                      options: [
                          {
                              displayName: 'Include Comments',
                              name: 'includeComments',
                              type: 'boolean',
                              default: false,
                              description: 'Whether to include all the comments in a Hacker News article',
                          },
                      ],
                  },
                  {
                      displayName: 'Additional Fields',
                      name: 'additionalFields',
                      type: 'collection',
                      placeholder: 'Add Field',
                      default: {},
                      displayOptions: {
                          show: {
                              resource: ['all'],
                              operation: ['getAll'],
                          },
                      },
                      options: [
                          {
                              displayName: 'Keyword',
                              name: 'keyword',
                              type: 'string',
                              default: '',
                              description: 'The keyword for filtering the results of the query',
                          },
                          {
                              displayName: 'Tags',
                              name: 'tags',
                              type: 'multiOptions',
                              options: [
                                  {
                                      name: 'Ask HN',
                                      value: 'ask_hn',
                                      description: 'Returns query results filtered by Ask HN tag',
                                  },
                                  {
                                      name: 'Comment',
                                      value: 'comment',
                                      description: 'Returns query results filtered by comment tag',
                                  },
                                  {
                                      name: 'Front Page',
                                      value: 'front_page',
                                      description: 'Returns query results filtered by Front Page tag',
                                  },
                                  {
                                      name: 'Poll',
                                      value: 'poll',
                                      description: 'Returns query results filtered by poll tag',
                                  },
                                  {
                                      name: 'Show HN',
                                      value: 'show_hn',
                                      description: 'Returns query results filtered by Show HN tag',
                                  },
                                  {
                                      name: 'Story',
                                      value: 'story',
                                      description: 'Returns query results filtered by story tag',
                                  },
                              ],
                              default: [],
                              description: 'Tags for filtering the results of the query',
                          },
                      ],
                  },
              ],
          };
      }
      async execute() {
          const items = this.getInputData();
          const returnData = [];
          const resource = this.getNodeParameter('resource', 0);
          const operation = this.getNodeParameter('operation', 0);
          let returnAll = false;
          for (let i = 0; i < items.length; i++) {
              try {
                  let qs = {};
                  let endpoint = '';
                  let includeComments = false;
                  if (resource === 'all') {
                      if (operation === 'getAll') {
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          const keyword = additionalFields.keyword;
                          const tags = additionalFields.tags;
                          qs = {
                              query: keyword,
                              tags: tags ? tags.join() : '',
                          };
                          returnAll = this.getNodeParameter('returnAll', i);
                          if (!returnAll) {
                              qs.hitsPerPage = this.getNodeParameter('limit', i);
                          }
                          endpoint = 'search?';
                      }
                      else {
                          throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The operation '${operation}' is unknown!`, { itemIndex: i });
                      }
                  }
                  else if (resource === 'article') {
                      if (operation === 'get') {
                          endpoint = `items/${this.getNodeParameter('articleId', i)}`;
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          includeComments = additionalFields.includeComments;
                      }
                      else {
                          throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The operation '${operation}' is unknown!`, { itemIndex: i });
                      }
                  }
                  else if (resource === 'user') {
                      if (operation === 'get') {
                          endpoint = `users/${this.getNodeParameter('username', i)}`;
                      }
                      else {
                          throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The operation '${operation}' is unknown!`, { itemIndex: i });
                      }
                  }
                  else {
                      throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The resource '${resource}' is unknown!`, {
                          itemIndex: i,
                      });
                  }
                  let responseData;
                  if (returnAll) {
                      responseData = await GenericFunctions_1.hackerNewsApiRequestAllItems.call(this, 'GET', endpoint, qs);
                  }
                  else {
                      responseData = await GenericFunctions_1.hackerNewsApiRequest.call(this, 'GET', endpoint, qs);
                      if (resource === 'all' && operation === 'getAll') {
                          responseData = responseData.hits;
                      }
                  }
                  if (resource === 'article' && operation === 'get' && !includeComments) {
                      delete responseData.children;
                  }
                  const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                  returnData.push(...executionData);
              }
              catch (error) {
                  if (this.continueOnFail()) {
                      const executionErrorData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray({ error: error.message }), { itemData: { item: i } });
                      returnData.push(...executionErrorData);
                      continue;
                  }
                  throw error;
              }
          }
          return [returnData];
      }
  }
  exports.HackerNews = HackerNews;
  //# sourceMappingURL=HackerNews.node.js.map

documentation_markdown:
  ---
  #https://www.notion.so/n8n/Frontmatter-432c2b8dff1f43d4b1c8d20075510fe4
  title: Hacker News node documentation
  description: Learn how to use the Hacker News node in n8n. Follow technical documentation to integrate Hacker News node into your workflows.
  contentType: [integration, reference]
  priority: medium
  ---

  # Hacker News node

  Use the Hacker News node to automate work in Hacker News, and integrate Hacker News with other applications. n8n has built-in support for a wide range of Hacker News features, including getting articles, and users. 

  On this page, you'll find a list of operations the Hacker News node supports and links to more resources.

  /// note | Credentials
  This node doesn't require authentication. 
  ///

  --8<-- "_snippets/integrations/builtin/app-nodes/ai-tools.md"

  ## Operations

  * All
      * Get all items
  * Article
      * Get a Hacker News article
  * User
      * Get a Hacker News user

  ## Templates and examples

  <!-- see https://www.notion.so/n8n/Pull-in-templates-for-the-integrations-pages-37c716837b804d30a33b47475f6e3780 -->
  [[ templatesWidget(page.title, 'hacker-news') ]]

example_workflow:
  {"nodes":[{"parameters":{},"type":"n8n-nodes-base.node","typeVersion":1,"position":[220,120],"id":"d8a000d6-eb1e-4221-9379-3672395ac500","name":"Node"}],"connections":{"Node":{"main":[[]]}},"pinData":{},"meta":{"templateCredsSetupCompleted":true,"instanceId":"7bc2dda55efa4df79009c2d3e880eb0ac343f7d01522833569dee65954c7413e"}}


node_type: n8n-nodes-base.Grist
name: Grist
display_name: Grist
description: Consume the Grist API
category: Other
code_hash: e8f869266965538c4386d983c696a348cc0a78697e10318e33745fa5cc66ab9a
documentation_url: https://docs.n8n.io/integrations/builtin/credentials/grist
example_parameters: {}
properties_schema: []
package_name: n8n-nodes-base
extracted_at: 2025-06-08 08:05:23
updated_at: 2025-06-08 08:05:23
source_code:
  "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.Grist = void 0;
  const GenericFunctions_1 = require("./GenericFunctions");
  const OperationDescription_1 = require("./OperationDescription");
  class Grist {
      constructor() {
          this.description = {
              displayName: 'Grist',
              name: 'grist',
              icon: 'file:grist.svg',
              subtitle: '={{$parameter["operation"]}}',
              group: ['input'],
              version: 1,
              description: 'Consume the Grist API',
              defaults: {
                  name: 'Grist',
              },
              inputs: ['main'],
              outputs: ['main'],
              credentials: [
                  {
                      name: 'gristApi',
                      required: true,
                      testedBy: 'gristApiTest',
                  },
              ],
              properties: OperationDescription_1.operationFields,
          };
          this.methods = {
              loadOptions: {
                  async getTableColumns() {
                      const docId = this.getNodeParameter('docId', 0);
                      const tableId = this.getNodeParameter('tableId', 0);
                      const endpoint = `/docs/${docId}/tables/${tableId}/columns`;
                      const { columns } = (await GenericFunctions_1.gristApiRequest.call(this, 'GET', endpoint));
                      return columns.map(({ id }) => ({ name: id, value: id }));
                  },
              },
              credentialTest: {
                  async gristApiTest(credential) {
                      const { apiKey, planType, customSubdomain, selfHostedUrl } = credential.data;
                      const endpoint = '/orgs';
                      const gristapiurl = planType === 'free'
                          ? `https://docs.getgrist.com/api${endpoint}`
                          : planType === 'paid'
                              ? `https://${customSubdomain}.getgrist.com/api${endpoint}`
                              : `${selfHostedUrl}/api${endpoint}`;
                      const options = {
                          headers: {
                              Authorization: `Bearer ${apiKey}`,
                          },
                          method: 'GET',
                          uri: gristapiurl,
                          qs: { limit: 1 },
                          json: true,
                      };
                      try {
                          await this.helpers.request(options);
                          return {
                              status: 'OK',
                              message: 'Authentication successful',
                          };
                      }
                      catch (error) {
                          return {
                              status: 'Error',
                              message: error.message,
                          };
                      }
                  },
              },
          };
      }
      async execute() {
          const items = this.getInputData();
          let responseData;
          const returnData = [];
          const operation = this.getNodeParameter('operation', 0);
          for (let i = 0; i < items.length; i++) {
              try {
                  if (operation === 'create') {
                      const body = { records: [] };
                      const dataToSend = this.getNodeParameter('dataToSend', 0);
                      if (dataToSend === 'autoMapInputs') {
                          const incomingKeys = Object.keys(items[i].json);
                          const rawInputsToIgnore = this.getNodeParameter('inputsToIgnore', i);
                          const inputsToIgnore = rawInputsToIgnore.split(',').map((c) => c.trim());
                          const fields = (0, GenericFunctions_1.parseAutoMappedInputs)(incomingKeys, inputsToIgnore, items[i].json);
                          body.records.push({ fields });
                      }
                      else if (dataToSend === 'defineInNode') {
                          const { properties } = this.getNodeParameter('fieldsToSend', i, []);
                          GenericFunctions_1.throwOnZeroDefinedFields.call(this, properties);
                          body.records.push({ fields: (0, GenericFunctions_1.parseDefinedFields)(properties) });
                      }
                      const docId = this.getNodeParameter('docId', 0);
                      const tableId = this.getNodeParameter('tableId', 0);
                      const endpoint = `/docs/${docId}/tables/${tableId}/records`;
                      responseData = await GenericFunctions_1.gristApiRequest.call(this, 'POST', endpoint, body);
                      responseData = {
                          id: responseData.records[0].id,
                          ...body.records[0].fields,
                      };
                  }
                  else if (operation === 'delete') {
                      const docId = this.getNodeParameter('docId', 0);
                      const tableId = this.getNodeParameter('tableId', 0);
                      const endpoint = `/docs/${docId}/tables/${tableId}/data/delete`;
                      const rawRowIds = this.getNodeParameter('rowId', i).toString();
                      const body = rawRowIds
                          .split(',')
                          .map((c) => c.trim())
                          .map(Number);
                      await GenericFunctions_1.gristApiRequest.call(this, 'POST', endpoint, body);
                      responseData = { success: true };
                  }
                  else if (operation === 'update') {
                      const body = { records: [] };
                      const rowId = this.getNodeParameter('rowId', i);
                      const dataToSend = this.getNodeParameter('dataToSend', 0);
                      if (dataToSend === 'autoMapInputs') {
                          const incomingKeys = Object.keys(items[i].json);
                          const rawInputsToIgnore = this.getNodeParameter('inputsToIgnore', i);
                          const inputsToIgnore = rawInputsToIgnore.split(',').map((c) => c.trim());
                          const fields = (0, GenericFunctions_1.parseAutoMappedInputs)(incomingKeys, inputsToIgnore, items[i].json);
                          body.records.push({ id: Number(rowId), fields });
                      }
                      else if (dataToSend === 'defineInNode') {
                          const { properties } = this.getNodeParameter('fieldsToSend', i, []);
                          GenericFunctions_1.throwOnZeroDefinedFields.call(this, properties);
                          const fields = (0, GenericFunctions_1.parseDefinedFields)(properties);
                          body.records.push({ id: Number(rowId), fields });
                      }
                      const docId = this.getNodeParameter('docId', 0);
                      const tableId = this.getNodeParameter('tableId', 0);
                      const endpoint = `/docs/${docId}/tables/${tableId}/records`;
                      await GenericFunctions_1.gristApiRequest.call(this, 'PATCH', endpoint, body);
                      responseData = {
                          id: rowId,
                          ...body.records[0].fields,
                      };
                  }
                  else if (operation === 'getAll') {
                      const docId = this.getNodeParameter('docId', 0);
                      const tableId = this.getNodeParameter('tableId', 0);
                      const endpoint = `/docs/${docId}/tables/${tableId}/records`;
                      const qs = {};
                      const returnAll = this.getNodeParameter('returnAll', i);
                      if (!returnAll) {
                          qs.limit = this.getNodeParameter('limit', i);
                      }
                      const { sort, filter } = this.getNodeParameter('additionalOptions', i);
                      if (sort === null || sort === void 0 ? void 0 : sort.sortProperties.length) {
                          qs.sort = (0, GenericFunctions_1.parseSortProperties)(sort.sortProperties);
                      }
                      if (filter === null || filter === void 0 ? void 0 : filter.filterProperties.length) {
                          const parsed = (0, GenericFunctions_1.parseFilterProperties)(filter.filterProperties);
                          qs.filter = JSON.stringify(parsed);
                      }
                      responseData = await GenericFunctions_1.gristApiRequest.call(this, 'GET', endpoint, {}, qs);
                      responseData = responseData.records.map((data) => {
                          return { id: data.id, ...data.fields };
                      });
                  }
              }
              catch (error) {
                  if (this.continueOnFail()) {
                      const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray({ error: error.message }), { itemData: { item: i } });
                      returnData.push(...executionData);
                      continue;
                  }
                  throw error;
              }
              const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
              returnData.push(...executionData);
          }
          return [returnData];
      }
  }
  exports.Grist = Grist;
  //# sourceMappingURL=Grist.node.js.map

documentation_markdown:
  ---
  #https://www.notion.so/n8n/Frontmatter-432c2b8dff1f43d4b1c8d20075510fe4
  title: Grist credentials
  description: Documentation for Grist credentials. Use these credentials to authenticate Grist in n8n, a workflow automation platform.
  contentType: [integration, reference]
  ---

  # Grist credentials

  You can use these credentials to authenticate the following nodes:

  * [Grist](/integrations/builtin/app-nodes/n8n-nodes-base.grist.md)

  ## Prerequisites

  Create a [Grist](https://getgrist.com/){:target=_blank .external-link} account.

  ## Supported authentication methods

  - API key

  ## Related resources

  Refer to [Grist's API documentation](https://support.getgrist.com/api/){:target=_blank .external-link} for more information about the service.

  ## Using API key

  To configure this credential, you'll need:

  - An **API Key**: Refer to the [Grist API authentication documentation](https://support.getgrist.com/rest-api/#authentication){:target=_blank .external-link} for instructions on creating an API key.
  - To select your Grist **Plan Type**. Options include:
      - Free
      - Paid: If selected, provide your Grist **Custom Subdomain**. This is the portion that comes before `.getgrist.com`. For example, if our full Grist domain was `n8n.getgrist.com`, we'd enter `n8n` here.
      - Self-Hosted: If selected, provide your Grist **Self-Hosted URL**. This should be the full URL.

example_workflow:
  {"nodes":[{"parameters":{},"type":"n8n-nodes-base.node","typeVersion":1,"position":[220,120],"id":"e3ee5a4f-cdf2-44d9-b098-4c24cb2895c0","name":"Node"}],"connections":{"Node":{"main":[[]]}},"pinData":{},"meta":{"templateCredsSetupCompleted":true,"instanceId":"7430514af4cc0c5758cd8893d2d40510f4b7daee295d1bf9ed751a761f8eb987"}}


node_type: n8n-nodes-base.HaloPSA
name: HaloPSA
display_name: HaloPSA
description: Consume HaloPSA API
category: Other
code_hash: 348d3698443ef486a9c597678fddb4d72550e7533c4fda90085d98e84585b00a
documentation_url: https://docs.n8n.io/integrations/builtin/credentials/halopsa
example_parameters: {}
properties_schema: []
package_name: n8n-nodes-base
extracted_at: 2025-06-08 08:05:23
updated_at: 2025-06-08 08:05:23
source_code:
  "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.HaloPSA = void 0;
  const descriptions_1 = require("./descriptions");
  const GenericFunctions_1 = require("./GenericFunctions");
  class HaloPSA {
      constructor() {
          this.description = {
              displayName: 'HaloPSA',
              name: 'haloPSA',
              icon: 'file:halopsa.svg',
              group: ['input'],
              version: 1,
              description: 'Consume HaloPSA API',
              subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
              defaults: {
                  name: 'HaloPSA',
              },
              inputs: ['main'],
              outputs: ['main'],
              credentials: [
                  {
                      name: 'haloPSAApi',
                      required: true,
                      testedBy: 'haloPSAApiCredentialTest',
                  },
              ],
              properties: [
                  {
                      displayName: 'Resource',
                      name: 'resource',
                      type: 'options',
                      noDataExpression: true,
                      options: [
                          {
                              name: 'Client',
                              value: 'client',
                          },
                          {
                              name: 'Site',
                              value: 'site',
                          },
                          {
                              name: 'Ticket',
                              value: 'ticket',
                          },
                          {
                              name: 'User',
                              value: 'user',
                          },
                      ],
                      default: 'client',
                      required: true,
                  },
                  ...descriptions_1.clientOperations,
                  ...descriptions_1.clientFields,
                  ...descriptions_1.ticketOperations,
                  ...descriptions_1.ticketFields,
                  ...descriptions_1.siteOperations,
                  ...descriptions_1.siteFields,
                  ...descriptions_1.userOperations,
                  ...descriptions_1.userFields,
              ],
          };
          this.methods = {
              loadOptions: {
                  async getHaloPSASites() {
                      const tokens = await GenericFunctions_1.getAccessTokens.call(this);
                      const response = (await GenericFunctions_1.haloPSAApiRequestAllItems.call(this, 'sites', 'GET', '/site', tokens.access_token));
                      const options = response.map((site) => {
                          return {
                              name: site.clientsite_name,
                              value: site.id,
                          };
                      });
                      return options.sort((a, b) => a.name.localeCompare(b.name));
                  },
                  async getHaloPSAClients() {
                      const tokens = await GenericFunctions_1.getAccessTokens.call(this);
                      const response = (await GenericFunctions_1.haloPSAApiRequestAllItems.call(this, 'clients', 'GET', '/Client', tokens.access_token));
                      const options = response.map((client) => {
                          return {
                              name: client.name,
                              value: client.id,
                          };
                      });
                      return options.sort((a, b) => a.name.localeCompare(b.name));
                  },
                  async getHaloPSATicketsTypes() {
                      const tokens = await GenericFunctions_1.getAccessTokens.call(this);
                      const response = (await GenericFunctions_1.haloPSAApiRequest.call(this, 'GET', '/TicketType', tokens.access_token, {}));
                      const options = response.map((ticket) => {
                          return {
                              name: ticket.name,
                              value: ticket.id,
                          };
                      });
                      return options
                          .filter((ticket) => {
                          if (ticket.name.includes('Request') ||
                              ticket.name.includes('Offboarding') ||
                              ticket.name.includes('Onboarding') ||
                              ticket.name.includes('Other Hardware') ||
                              ticket.name.includes('Software Change')) {
                              return false;
                          }
                          return true;
                      })
                          .sort((a, b) => a.name.localeCompare(b.name));
                  },
                  async getHaloPSAAgents() {
                      const tokens = await GenericFunctions_1.getAccessTokens.call(this);
                      const response = (await GenericFunctions_1.haloPSAApiRequest.call(this, 'GET', '/agent', tokens.access_token, {}));
                      const options = response.map((agent) => {
                          return {
                              name: agent.name,
                              value: agent.id,
                          };
                      });
                      return options.sort((a, b) => a.name.localeCompare(b.name));
                  },
              },
              credentialTest: {
                  async haloPSAApiCredentialTest(credential) {
                      try {
                          await GenericFunctions_1.validateCredentials.call(this, credential.data);
                      }
                      catch (error) {
                          return {
                              status: 'Error',
                              message: error.message,
                          };
                      }
                      return {
                          status: 'OK',
                          message: 'Connection successful!',
                      };
                  },
              },
          };
      }
      async execute() {
          const items = this.getInputData();
          const returnData = [];
          let responseData;
          const tokens = await GenericFunctions_1.getAccessTokens.call(this);
          const resource = this.getNodeParameter('resource', 0);
          const operation = this.getNodeParameter('operation', 0);
          for (let i = 0; i < items.length; i++) {
              try {
                  if (resource === 'client') {
                      const simplifiedOutput = ['id', 'name', 'notes', 'is_vip', 'website'];
                      if (operation === 'create') {
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          const name = this.getNodeParameter('clientName', i);
                          const body = {
                              name,
                              ...additionalFields,
                          };
                          responseData = await GenericFunctions_1.haloPSAApiRequest.call(this, 'POST', '/client', tokens.access_token, [body]);
                      }
                      if (operation === 'delete') {
                          const clientId = this.getNodeParameter('clientId', i);
                          responseData = await GenericFunctions_1.haloPSAApiRequest.call(this, 'DELETE', `/client/${clientId}`, tokens.access_token);
                      }
                      if (operation === 'get') {
                          const clientId = this.getNodeParameter('clientId', i);
                          const simplify = this.getNodeParameter('simplify', i);
                          const response = await GenericFunctions_1.haloPSAApiRequest.call(this, 'GET', `/client/${clientId}`, tokens.access_token);
                          responseData = simplify
                              ? (0, GenericFunctions_1.simplifyHaloPSAGetOutput)([response], simplifiedOutput)
                              : response;
                      }
                      if (operation === 'getAll') {
                          const filters = this.getNodeParameter('filters', i);
                          const returnAll = this.getNodeParameter('returnAll', i);
                          const simplify = this.getNodeParameter('simplify', i);
                          const qs = {};
                          let response;
                          Object.assign(qs, filters, (0, GenericFunctions_1.qsSetStatus)(filters.activeStatus));
                          if (returnAll) {
                              response = await GenericFunctions_1.haloPSAApiRequestAllItems.call(this, 'clients', 'GET', '/client', tokens.access_token, {}, qs);
                          }
                          else {
                              const limit = this.getNodeParameter('limit', i);
                              qs.count = limit;
                              const { clients } = await GenericFunctions_1.haloPSAApiRequest.call(this, 'GET', '/client', tokens.access_token, {}, qs);
                              response = clients;
                          }
                          responseData = simplify
                              ? (0, GenericFunctions_1.simplifyHaloPSAGetOutput)(response, simplifiedOutput)
                              : response;
                      }
                      if (operation === 'update') {
                          const clientId = this.getNodeParameter('clientId', i);
                          const updateFields = this.getNodeParameter('updateFields', i);
                          const body = {
                              id: clientId,
                              ...updateFields,
                          };
                          responseData = await GenericFunctions_1.haloPSAApiRequest.call(this, 'POST', '/client', tokens.access_token, [body]);
                      }
                  }
                  if (resource === 'site') {
                      const simplifiedOutput = [
                          'id',
                          'name',
                          'client_id',
                          'maincontact_name',
                          'notes',
                          'phonenumber',
                      ];
                      if (operation === 'create') {
                          const name = this.getNodeParameter('siteName', i);
                          const clientId = this.getNodeParameter('clientId', i);
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          const body = {
                              name,
                              client_id: clientId,
                              ...additionalFields,
                          };
                          responseData = await GenericFunctions_1.haloPSAApiRequest.call(this, 'POST', '/site', tokens.access_token, [body]);
                      }
                      if (operation === 'delete') {
                          const siteId = this.getNodeParameter('siteId', i);
                          responseData = await GenericFunctions_1.haloPSAApiRequest.call(this, 'DELETE', `/site/${siteId}`, tokens.access_token);
                      }
                      if (operation === 'get') {
                          const siteId = this.getNodeParameter('siteId', i);
                          const simplify = this.getNodeParameter('simplify', i);
                          const response = await GenericFunctions_1.haloPSAApiRequest.call(this, 'GET', `/site/${siteId}`, tokens.access_token);
                          responseData = simplify
                              ? (0, GenericFunctions_1.simplifyHaloPSAGetOutput)([response], simplifiedOutput)
                              : response;
                      }
                      if (operation === 'getAll') {
                          const filters = this.getNodeParameter('filters', i);
                          const returnAll = this.getNodeParameter('returnAll', i);
                          const simplify = this.getNodeParameter('simplify', i);
                          const qs = {};
                          let response;
                          Object.assign(qs, filters, (0, GenericFunctions_1.qsSetStatus)(filters.activeStatus));
                          if (returnAll) {
                              response = await GenericFunctions_1.haloPSAApiRequestAllItems.call(this, 'sites', 'GET', '/site', tokens.access_token, {}, qs);
                          }
                          else {
                              const limit = this.getNodeParameter('limit', i);
                              qs.count = limit;
                              const { sites } = await GenericFunctions_1.haloPSAApiRequest.call(this, 'GET', '/site', tokens.access_token, {}, qs);
                              response = sites;
                          }
                          responseData = simplify
                              ? (0, GenericFunctions_1.simplifyHaloPSAGetOutput)(response, simplifiedOutput)
                              : response;
                      }
                      if (operation === 'update') {
                          const siteId = this.getNodeParameter('siteId', i);
                          const updateFields = this.getNodeParameter('updateFields', i);
                          const body = {
                              id: siteId,
                              ...updateFields,
                          };
                          responseData = await GenericFunctions_1.haloPSAApiRequest.call(this, 'POST', '/site', tokens.access_token, [body]);
                      }
                  }
                  if (resource === 'ticket') {
                      const simplifiedOutput = [
                          'id',
                          'summary',
                          'details',
                          'agent_id',
                          'startdate',
                          'targetdate',
                      ];
                      if (operation === 'create') {
                          const summary = this.getNodeParameter('summary', i);
                          const details = this.getNodeParameter('details', i);
                          const ticketType = this.getNodeParameter('ticketType', i);
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          const body = {
                              tickettype_id: ticketType,
                              summary,
                              details,
                              ...additionalFields,
                          };
                          responseData = await GenericFunctions_1.haloPSAApiRequest.call(this, 'POST', '/tickets', tokens.access_token, [body]);
                      }
                      if (operation === 'delete') {
                          const ticketId = this.getNodeParameter('ticketId', i);
                          responseData = await GenericFunctions_1.haloPSAApiRequest.call(this, 'DELETE', `/tickets/${ticketId}`, tokens.access_token);
                      }
                      if (operation === 'get') {
                          const ticketId = this.getNodeParameter('ticketId', i);
                          const simplify = this.getNodeParameter('simplify', i);
                          const response = await GenericFunctions_1.haloPSAApiRequest.call(this, 'GET', `/tickets/${ticketId}`, tokens.access_token);
                          responseData = simplify
                              ? (0, GenericFunctions_1.simplifyHaloPSAGetOutput)([response], simplifiedOutput)
                              : response;
                      }
                      if (operation === 'getAll') {
                          const filters = this.getNodeParameter('filters', i);
                          const returnAll = this.getNodeParameter('returnAll', i);
                          const simplify = this.getNodeParameter('simplify', i);
                          const qs = {};
                          let response;
                          Object.assign(qs, filters, (0, GenericFunctions_1.qsSetStatus)(filters.activeStatus));
                          if (returnAll) {
                              response = await GenericFunctions_1.haloPSAApiRequestAllItems.call(this, 'tickets', 'GET', '/tickets', tokens.access_token, {}, qs);
                          }
                          else {
                              const limit = this.getNodeParameter('limit', i);
                              qs.count = limit;
                              const { tickets } = await GenericFunctions_1.haloPSAApiRequest.call(this, 'GET', '/tickets', tokens.access_token, {}, qs);
                              response = tickets;
                          }
                          responseData = simplify
                              ? (0, GenericFunctions_1.simplifyHaloPSAGetOutput)(response, simplifiedOutput)
                              : response;
                      }
                      if (operation === 'update') {
                          const ticketId = this.getNodeParameter('ticketId', i);
                          const updateFields = this.getNodeParameter('updateFields', i);
                          const body = {
                              id: ticketId,
                              ...updateFields,
                          };
                          responseData = await GenericFunctions_1.haloPSAApiRequest.call(this, 'POST', '/tickets', tokens.access_token, [body]);
                      }
                  }
                  if (resource === 'user') {
                      const simplifiedOutput = [
                          'id',
                          'name',
                          'site_id',
                          'emailaddress',
                          'notes',
                          'surname',
                          'inactive',
                      ];
                      if (operation === 'create') {
                          const name = this.getNodeParameter('userName', i);
                          const siteId = this.getNodeParameter('siteId', i);
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          const body = {
                              name,
                              site_id: siteId,
                              ...additionalFields,
                          };
                          responseData = await GenericFunctions_1.haloPSAApiRequest.call(this, 'POST', '/users', tokens.access_token, [body]);
                      }
                      if (operation === 'delete') {
                          const userId = this.getNodeParameter('userId', i);
                          responseData = await GenericFunctions_1.haloPSAApiRequest.call(this, 'DELETE', `/users/${userId}`, tokens.access_token);
                      }
                      if (operation === 'get') {
                          const userId = this.getNodeParameter('userId', i);
                          const simplify = this.getNodeParameter('simplify', i);
                          const response = await GenericFunctions_1.haloPSAApiRequest.call(this, 'GET', `/users/${userId}`, tokens.access_token);
                          responseData = simplify
                              ? (0, GenericFunctions_1.simplifyHaloPSAGetOutput)([response], simplifiedOutput)
                              : response;
                      }
                      if (operation === 'getAll') {
                          const filters = this.getNodeParameter('filters', i);
                          const returnAll = this.getNodeParameter('returnAll', i);
                          const simplify = this.getNodeParameter('simplify', i);
                          const qs = {};
                          let response;
                          Object.assign(qs, filters, (0, GenericFunctions_1.qsSetStatus)(filters.activeStatus));
                          if (returnAll) {
                              response = await GenericFunctions_1.haloPSAApiRequestAllItems.call(this, 'users', 'GET', '/users', tokens.access_token, {}, qs);
                          }
                          else {
                              const limit = this.getNodeParameter('limit', i);
                              qs.count = limit;
                              const { users } = await GenericFunctions_1.haloPSAApiRequest.call(this, 'GET', '/users', tokens.access_token, {}, qs);
                              response = users;
                          }
                          responseData = simplify
                              ? (0, GenericFunctions_1.simplifyHaloPSAGetOutput)(response, simplifiedOutput)
                              : response;
                      }
                      if (operation === 'update') {
                          const userId = this.getNodeParameter('userId', i);
                          const updateFields = this.getNodeParameter('updateFields', i);
                          const body = {
                              id: userId,
                              ...updateFields,
                          };
                          responseData = await GenericFunctions_1.haloPSAApiRequest.call(this, 'POST', '/users', tokens.access_token, [body]);
                      }
                  }
                  const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                  returnData.push(...executionData);
              }
              catch (error) {
                  if (this.continueOnFail()) {
                      const executionErrorData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray({ error: error.message }), { itemData: { item: i } });
                      returnData.push(...executionErrorData);
                      continue;
                  }
                  throw error;
              }
          }
          return [returnData];
      }
  }
  exports.HaloPSA = HaloPSA;
  //# sourceMappingURL=HaloPSA.node.js.map

documentation_markdown:
  ---
  #https://www.notion.so/n8n/Frontmatter-432c2b8dff1f43d4b1c8d20075510fe4
  title: HaloPSA credentials
  description: Documentation for HaloPSA credentials. Use these credentials to authenticate HaloPSA in n8n, a workflow automation platform.
  contentType: [integration, reference]
  ---

  # HaloPSA credentials

  You can use these credentials to authenticate the following nodes:

  - [HaloPSA](/integrations/builtin/app-nodes/n8n-nodes-base.halopsa.md)

  ## Prerequisites

  Create a [HaloPSA](https://halopsa.com/) account.

  ## Supported authentication methods

  - API key

  ## Related resources

  Refer to [HaloPSA's API documentation](https://halopsa.com/apidoc/info){:target=_blank .external-link} for more information about the service.

  ## Using API key

  To configure this credential, you'll need:

  - To select your **Hosting Type**:
      - **On Premise Solution**: Choose this option if you're hosting the Halo application on your own server
      - **Hosted Solution Of Halo**: Choose this option if your application is hosted by Halo. If this option is selected, you'll need to provide your **Tenant**.
  - The **HaloPSA Authorisation Server URL**: Your Authorisation Server URL is displayed within HaloPSA in **Configuration > Integrations > Halo API** in [API Details](https://halopsa.com/guides/article/?kbid=1737){:target=_blank .external-link}.
  - The **Resource Server** URL: Your Resource Server is displayed within HaloPSA in **Configuration > Integrations > Halo API** in [API Details](https://halopsa.com/guides/article/?kbid=1737){:target=_blank .external-link}.
  - A **Client ID**: Obtained by registering the application in the Halo API settings. Refer to [HaloPSA's Authorisation documentation](https://halopsa.com/apidoc/authorisation){:target=_blank .external-link} for detailed instructions. n8n recommends using these settings:
      - Choose `Client Credentials` as your **Authentication Method**.
      - Use the `all` permission.
  - A **Client Secret**: Obtained by registering the application in the Halo API settings.
  - Your **Tenant** name: If **Hosted Solution of Halo** is selected as the **Hosting Type**, you must provide your tenant name. Your tenant name is displayed within HaloPSA in **Configuration > Integrations > Halo API** in [API Details](https://halopsa.com/guides/article/?kbid=1737){:target=_blank .external-link}.

  HaloPSA uses both the application permissions and the agent's permissions to determine API access.

example_workflow:
  {"nodes":[{"parameters":{},"type":"n8n-nodes-base.node","typeVersion":1,"position":[220,120],"id":"acc451f5-845e-4d05-acb2-51d68a1c4e21","name":"Node"}],"connections":{"Node":{"main":[[]]}},"pinData":{},"meta":{"templateCredsSetupCompleted":true,"instanceId":"cd24aafcba87ff9e0859408b70e1653f5079de519512c518cf51bb130f7f8ca3"}}


node_type: n8n-nodes-base.Harvest
name: Harvest
display_name: Harvest
description: Access data on Harvest
category: Other
code_hash: 9d20cceef719cdf7c26383c042364997d2be9dcd6083b1a6658b0fbc74462275
documentation_url: https://docs.n8n.io/integrations/builtin/credentials/harvest
example_parameters: {}
properties_schema: []
package_name: n8n-nodes-base
extracted_at: 2025-06-08 08:05:23
updated_at: 2025-06-08 08:05:23
source_code:
  "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.Harvest = void 0;
  const n8n_workflow_1 = require("n8n-workflow");
  const ClientDescription_1 = require("./ClientDescription");
  const ContactDescription_1 = require("./ContactDescription");
  const CompanyDescription_1 = require("./CompanyDescription");
  const EstimateDescription_1 = require("./EstimateDescription");
  const ExpenseDescription_1 = require("./ExpenseDescription");
  const GenericFunctions_1 = require("./GenericFunctions");
  const InvoiceDescription_1 = require("./InvoiceDescription");
  const ProjectDescription_1 = require("./ProjectDescription");
  const TaskDescription_1 = require("./TaskDescription");
  const TimeEntryDescription_1 = require("./TimeEntryDescription");
  const UserDescription_1 = require("./UserDescription");
  class Harvest {
      constructor() {
          this.description = {
              displayName: 'Harvest',
              name: 'harvest',
              icon: 'file:harvest.png',
              group: ['input'],
              version: 1,
              subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
              description: 'Access data on Harvest',
              defaults: {
                  name: 'Harvest',
              },
              inputs: ['main'],
              outputs: ['main'],
              credentials: [
                  {
                      name: 'harvestApi',
                      required: true,
                      displayOptions: {
                          show: {
                              authentication: ['accessToken'],
                          },
                      },
                  },
                  {
                      name: 'harvestOAuth2Api',
                      required: true,
                      displayOptions: {
                          show: {
                              authentication: ['oAuth2'],
                          },
                      },
                  },
              ],
              properties: [
                  {
                      displayName: 'Authentication',
                      name: 'authentication',
                      type: 'options',
                      options: [
                          {
                              name: 'Access Token',
                              value: 'accessToken',
                          },
                          {
                              name: 'OAuth2',
                              value: 'oAuth2',
                          },
                      ],
                      default: 'accessToken',
                  },
                  {
                      displayName: 'Resource',
                      name: 'resource',
                      type: 'options',
                      noDataExpression: true,
                      options: [
                          {
                              name: 'Client',
                              value: 'client',
                          },
                          {
                              name: 'Company',
                              value: 'company',
                          },
                          {
                              name: 'Contact',
                              value: 'contact',
                          },
                          {
                              name: 'Estimate',
                              value: 'estimate',
                          },
                          {
                              name: 'Expense',
                              value: 'expense',
                          },
                          {
                              name: 'Invoice',
                              value: 'invoice',
                          },
                          {
                              name: 'Project',
                              value: 'project',
                          },
                          {
                              name: 'Task',
                              value: 'task',
                          },
                          {
                              name: 'Time Entry',
                              value: 'timeEntry',
                          },
                          {
                              name: 'User',
                              value: 'user',
                          },
                      ],
                      default: 'task',
                  },
                  ...ClientDescription_1.clientOperations,
                  ...CompanyDescription_1.companyOperations,
                  ...ContactDescription_1.contactOperations,
                  ...EstimateDescription_1.estimateOperations,
                  ...ExpenseDescription_1.expenseOperations,
                  ...InvoiceDescription_1.invoiceOperations,
                  ...ProjectDescription_1.projectOperations,
                  ...TaskDescription_1.taskOperations,
                  ...TimeEntryDescription_1.timeEntryOperations,
                  ...UserDescription_1.userOperations,
                  {
                      displayName: 'Account Name or ID',
                      name: 'accountId',
                      type: 'options',
                      description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>',
                      required: true,
                      typeOptions: {
                          loadOptionsMethod: 'getAccounts',
                      },
                      default: '',
                  },
                  ...ClientDescription_1.clientFields,
                  ...ContactDescription_1.contactFields,
                  ...EstimateDescription_1.estimateFields,
                  ...ExpenseDescription_1.expenseFields,
                  ...InvoiceDescription_1.invoiceFields,
                  ...ProjectDescription_1.projectFields,
                  ...TaskDescription_1.taskFields,
                  ...TimeEntryDescription_1.timeEntryFields,
                  ...UserDescription_1.userFields,
              ],
          };
          this.methods = {
              loadOptions: {
                  async getAccounts() {
                      const returnData = [];
                      const { accounts } = await GenericFunctions_1.harvestApiRequest.call(this, 'GET', {}, '', {}, {}, 'https://id.getharvest.com/api/v2/accounts');
                      for (const account of accounts) {
                          const accountName = account.name;
                          const accountId = account.id;
                          returnData.push({
                              name: accountName,
                              value: accountId,
                          });
                      }
                      return returnData;
                  },
              },
          };
      }
      async execute() {
          const items = this.getInputData();
          const returnData = [];
          const resource = this.getNodeParameter('resource', 0);
          const operation = this.getNodeParameter('operation', 0);
          let endpoint = '';
          let requestMethod = '';
          let body;
          let qs;
          for (let i = 0; i < items.length; i++) {
              try {
                  body = {};
                  qs = {};
                  if (resource === 'timeEntry') {
                      if (operation === 'get') {
                          requestMethod = 'GET';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `time_entries/${id}`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'getAll') {
                          const responseData = await GenericFunctions_1.getAllResource.call(this, 'time_entries', i);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'createByStartEnd') {
                          requestMethod = 'POST';
                          endpoint = 'time_entries';
                          body.project_id = this.getNodeParameter('projectId', i);
                          body.task_id = this.getNodeParameter('taskId', i);
                          body.spent_date = this.getNodeParameter('spentDate', i);
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          Object.assign(body, additionalFields);
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint, body);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'createByDuration') {
                          requestMethod = 'POST';
                          endpoint = 'time_entries';
                          body.project_id = this.getNodeParameter('projectId', i);
                          body.task_id = this.getNodeParameter('taskId', i);
                          body.spent_date = this.getNodeParameter('spentDate', i);
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          Object.assign(body, additionalFields);
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint, body);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'delete') {
                          requestMethod = 'DELETE';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `time_entries/${id}`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'deleteExternal') {
                          requestMethod = 'DELETE';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `time_entries/${id}/external_reference`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'restartTime') {
                          requestMethod = 'PATCH';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `time_entries/${id}/restart`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'stopTime') {
                          requestMethod = 'PATCH';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `time_entries/${id}/stop`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'update') {
                          requestMethod = 'PATCH';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `time_entries/${id}`;
                          const updateFields = this.getNodeParameter('updateFields', i);
                          Object.assign(body, updateFields);
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint, body);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else {
                          throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The operation "${operation}" is not known!`, { itemIndex: i });
                      }
                  }
                  else if (resource === 'client') {
                      if (operation === 'get') {
                          requestMethod = 'GET';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `clients/${id}`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'getAll') {
                          const responseData = await GenericFunctions_1.getAllResource.call(this, 'clients', i);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'create') {
                          requestMethod = 'POST';
                          endpoint = 'clients';
                          body.name = this.getNodeParameter('name', i);
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          Object.assign(body, additionalFields);
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint, body);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'update') {
                          requestMethod = 'PATCH';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `clients/${id}`;
                          const updateFields = this.getNodeParameter('updateFields', i);
                          Object.assign(qs, updateFields);
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint, body);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'delete') {
                          requestMethod = 'DELETE';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `clients/${id}`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else {
                          throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`, { itemIndex: i });
                      }
                  }
                  else if (resource === 'project') {
                      if (operation === 'get') {
                          requestMethod = 'GET';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `projects/${id}`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'getAll') {
                          const responseData = await GenericFunctions_1.getAllResource.call(this, 'projects', i);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'create') {
                          requestMethod = 'POST';
                          endpoint = 'projects';
                          body.client_id = this.getNodeParameter('clientId', i);
                          body.name = this.getNodeParameter('name', i);
                          body.is_billable = this.getNodeParameter('isBillable', i);
                          body.bill_by = this.getNodeParameter('billBy', i);
                          body.budget_by = this.getNodeParameter('budgetBy', i);
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          Object.assign(body, additionalFields);
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint, body);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'update') {
                          requestMethod = 'PATCH';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `projects/${id}`;
                          const updateFields = this.getNodeParameter('updateFields', i);
                          Object.assign(body, updateFields);
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint, body);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'delete') {
                          requestMethod = 'DELETE';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `projects/${id}`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else {
                          throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`, { itemIndex: i });
                      }
                  }
                  else if (resource === 'user') {
                      if (operation === 'get') {
                          requestMethod = 'GET';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `users/${id}`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'getAll') {
                          const responseData = await GenericFunctions_1.getAllResource.call(this, 'users', i);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'me') {
                          requestMethod = 'GET';
                          endpoint = 'users/me';
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'create') {
                          requestMethod = 'POST';
                          endpoint = 'users';
                          body.first_name = this.getNodeParameter('firstName', i);
                          body.last_name = this.getNodeParameter('lastName', i);
                          body.email = this.getNodeParameter('email', i);
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          Object.assign(body, additionalFields);
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint, body);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'update') {
                          requestMethod = 'PATCH';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `users/${id}`;
                          const updateFields = this.getNodeParameter('updateFields', i);
                          Object.assign(qs, updateFields);
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint, body);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'delete') {
                          requestMethod = 'DELETE';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `users/${id}`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else {
                          throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`, { itemIndex: i });
                      }
                  }
                  else if (resource === 'contact') {
                      if (operation === 'get') {
                          requestMethod = 'GET';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `contacts/${id}`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'getAll') {
                          const responseData = await GenericFunctions_1.getAllResource.call(this, 'contacts', i);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'create') {
                          requestMethod = 'POST';
                          endpoint = 'contacts';
                          body.client_id = this.getNodeParameter('clientId', i);
                          body.first_name = this.getNodeParameter('firstName', i);
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          Object.assign(body, additionalFields);
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint, body);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'update') {
                          requestMethod = 'PATCH';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `contacts/${id}`;
                          const updateFields = this.getNodeParameter('updateFields', i);
                          Object.assign(qs, updateFields);
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint, body);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'delete') {
                          requestMethod = 'DELETE';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `contacts/${id}`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else {
                          throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`, { itemIndex: i });
                      }
                  }
                  else if (resource === 'company') {
                      if (operation === 'get') {
                          requestMethod = 'GET';
                          endpoint = 'company';
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else {
                          throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`, { itemIndex: i });
                      }
                  }
                  else if (resource === 'task') {
                      if (operation === 'get') {
                          requestMethod = 'GET';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `tasks/${id}`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'getAll') {
                          const responseData = await GenericFunctions_1.getAllResource.call(this, 'tasks', i);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'create') {
                          requestMethod = 'POST';
                          endpoint = 'tasks';
                          body.name = this.getNodeParameter('name', i);
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          Object.assign(body, additionalFields);
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint, body);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'update') {
                          requestMethod = 'PATCH';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `tasks/${id}`;
                          const updateFields = this.getNodeParameter('updateFields', i);
                          Object.assign(qs, updateFields);
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint, body);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'delete') {
                          requestMethod = 'DELETE';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `tasks/${id}`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else {
                          throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`, { itemIndex: i });
                      }
                  }
                  else if (resource === 'invoice') {
                      if (operation === 'get') {
                          requestMethod = 'GET';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `invoices/${id}`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'getAll') {
                          const responseData = await GenericFunctions_1.getAllResource.call(this, 'invoices', i);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'create') {
                          requestMethod = 'POST';
                          endpoint = 'invoices';
                          body.client_id = this.getNodeParameter('clientId', i);
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          Object.assign(body, additionalFields);
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint, body);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'update') {
                          requestMethod = 'PATCH';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `invoices/${id}`;
                          const updateFields = this.getNodeParameter('updateFields', i);
                          Object.assign(qs, updateFields);
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint, body);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'delete') {
                          requestMethod = 'DELETE';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `invoices/${id}`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else {
                          throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`, { itemIndex: i });
                      }
                  }
                  else if (resource === 'expense') {
                      if (operation === 'get') {
                          requestMethod = 'GET';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `expenses/${id}`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'getAll') {
                          const responseData = await GenericFunctions_1.getAllResource.call(this, 'expenses', i);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'create') {
                          requestMethod = 'POST';
                          endpoint = 'expenses';
                          body.project_id = this.getNodeParameter('projectId', i);
                          body.expense_category_id = this.getNodeParameter('expenseCategoryId', i);
                          body.spent_date = this.getNodeParameter('spentDate', i);
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          Object.assign(body, additionalFields);
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint, body);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'update') {
                          requestMethod = 'PATCH';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `expenses/${id}`;
                          const updateFields = this.getNodeParameter('updateFields', i);
                          Object.assign(qs, updateFields);
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint, body);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'delete') {
                          requestMethod = 'DELETE';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `expenses/${id}`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else {
                          throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`, { itemIndex: i });
                      }
                  }
                  else if (resource === 'estimate') {
                      if (operation === 'get') {
                          requestMethod = 'GET';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `estimates/${id}`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'getAll') {
                          const responseData = await GenericFunctions_1.getAllResource.call(this, 'estimates', i);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'create') {
                          requestMethod = 'POST';
                          endpoint = 'estimates';
                          body.client_id = this.getNodeParameter('clientId', i);
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          Object.assign(body, additionalFields);
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint, body);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'update') {
                          requestMethod = 'PATCH';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `estimates/${id}`;
                          const updateFields = this.getNodeParameter('updateFields', i);
                          Object.assign(qs, updateFields);
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint, body);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else if (operation === 'delete') {
                          requestMethod = 'DELETE';
                          const id = this.getNodeParameter('id', i);
                          endpoint = `estimates/${id}`;
                          const responseData = await GenericFunctions_1.harvestApiRequest.call(this, requestMethod, qs, endpoint);
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      else {
                          throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`, { itemIndex: i });
                      }
                  }
                  else {
                      throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`, {
                          itemIndex: i,
                      });
                  }
              }
              catch (error) {
                  if (this.continueOnFail()) {
                      const executionErrorData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray({ error: error.message }), { itemData: { item: i } });
                      returnData.push(...executionErrorData);
                      continue;
                  }
                  throw error;
              }
          }
          return [returnData];
      }
  }
  exports.Harvest = Harvest;
  //# sourceMappingURL=Harvest.node.js.map

documentation_markdown:
  ---
  #https://www.notion.so/n8n/Frontmatter-432c2b8dff1f43d4b1c8d20075510fe4
  title: Harvest credentials
  description: Documentation for Harvest credentials. Use these credentials to authenticate Harvest in n8n, a workflow automation platform.
  contentType: [integration, reference]
  ---

  # Harvest credentials

  You can use these credentials to authenticate the following nodes:

  - [Harvest](/integrations/builtin/app-nodes/n8n-nodes-base.harvest.md)

  ## Prerequisites

  Create a [Harvest](https://www.getharvest.com/) account.

  ## Supported authentication methods

  - API access token
  - OAuth2

  ## Related resources

  Refer to [Harvest's API documentation](https://help.getharvest.com/api-v2/){:target=_blank .external-link} for more information about the service.

  ## Using API Access Token

  To configure this credential, you'll need:

  - A Personal **Access Token**: Refer to the [Harvest Personal Access Token Authentication documentation](https://help.getharvest.com/api-v2/authentication-api/authentication/authentication/#personal-access-tokens){:target=_blank .external-link} for instructions on creating a personal access token.


  ## Using OAuth2

  --8<-- "_snippets/integrations/builtin/credentials/cloud-oauth-button.md"

  If you need to configure OAuth2 from scratch or need more detail on what's happening in the OAuth web flow, refer to the instructions in the [Harvest OAuth2 documentation](https://help.getharvest.com/api-v2/authentication-api/authentication/authentication/#oauth2-application){:target=_blank .external-link} to set up OAuth.

example_workflow:
  {"nodes":[{"parameters":{},"type":"n8n-nodes-base.node","typeVersion":1,"position":[220,120],"id":"1db096d8-5d32-4003-89d7-f0b514147dfc","name":"Node"}],"connections":{"Node":{"main":[[]]}},"pinData":{},"meta":{"templateCredsSetupCompleted":true,"instanceId":"7a46809418c2b68260fe7963289d8c63834666fa8224508f5454c865b9d3eab7"}}


node_type: n8n-nodes-base.HelpScout
name: HelpScout
display_name: HelpScout
description: Consume HelpScout API
category: Other
code_hash: ed850f3e789d21697c107e859b43364714ce661c3158cea1742fa42285f570d5
documentation_url: https://docs.n8n.io/integrations/builtin/credentials/helpscout
example_parameters: {}
properties_schema: []
package_name: n8n-nodes-base
extracted_at: 2025-06-08 08:05:23
updated_at: 2025-06-08 08:05:23
source_code:
  "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.HelpScout = void 0;
  const n8n_workflow_1 = require("n8n-workflow");
  const CountriesCodes_1 = require("./CountriesCodes");
  const ConversationDescription_1 = require("./ConversationDescription");
  const CustomerDescription_1 = require("./CustomerDescription");
  const GenericFunctions_1 = require("./GenericFunctions");
  const MailboxDescription_1 = require("./MailboxDescription");
  const ThreadDescription_1 = require("./ThreadDescription");
  class HelpScout {
      constructor() {
          this.description = {
              displayName: 'HelpScout',
              name: 'helpScout',
              icon: 'file:helpScout.svg',
              group: ['input'],
              version: 1,
              subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
              description: 'Consume HelpScout API',
              defaults: {
                  name: 'HelpScout',
              },
              inputs: ['main'],
              outputs: ['main'],
              credentials: [
                  {
                      name: 'helpScoutOAuth2Api',
                      required: true,
                  },
              ],
              properties: [
                  {
                      displayName: 'Resource',
                      name: 'resource',
                      type: 'options',
                      noDataExpression: true,
                      options: [
                          {
                              name: 'Conversation',
                              value: 'conversation',
                          },
                          {
                              name: 'Customer',
                              value: 'customer',
                          },
                          {
                              name: 'Mailbox',
                              value: 'mailbox',
                          },
                          {
                              name: 'Thread',
                              value: 'thread',
                          },
                      ],
                      default: 'conversation',
                  },
                  ...ConversationDescription_1.conversationOperations,
                  ...ConversationDescription_1.conversationFields,
                  ...CustomerDescription_1.customerOperations,
                  ...CustomerDescription_1.customerFields,
                  ...MailboxDescription_1.mailboxOperations,
                  ...MailboxDescription_1.mailboxFields,
                  ...ThreadDescription_1.threadOperations,
                  ...ThreadDescription_1.threadFields,
              ],
          };
          this.methods = {
              loadOptions: {
                  async getCountriesCodes() {
                      const returnData = [];
                      for (const countryCode of CountriesCodes_1.countriesCodes) {
                          const countryCodeName = `${countryCode.name} - ${countryCode.alpha2}`;
                          const countryCodeId = countryCode.alpha2;
                          returnData.push({
                              name: countryCodeName,
                              value: countryCodeId,
                          });
                      }
                      return returnData;
                  },
                  async getTags() {
                      const returnData = [];
                      const tags = await GenericFunctions_1.helpscoutApiRequestAllItems.call(this, '_embedded.tags', 'GET', '/v2/tags');
                      for (const tag of tags) {
                          const tagName = tag.name;
                          returnData.push({
                              name: tagName,
                              value: tagName,
                          });
                      }
                      return returnData;
                  },
                  async getMailboxes() {
                      const returnData = [];
                      const mailboxes = await GenericFunctions_1.helpscoutApiRequestAllItems.call(this, '_embedded.mailboxes', 'GET', '/v2/mailboxes');
                      for (const mailbox of mailboxes) {
                          const mailboxName = mailbox.name;
                          const mailboxId = mailbox.id;
                          returnData.push({
                              name: mailboxName,
                              value: mailboxId,
                          });
                      }
                      return returnData;
                  },
              },
          };
      }
      async execute() {
          var _a, _b;
          const items = this.getInputData();
          const returnData = [];
          const length = items.length;
          const qs = {};
          let responseData;
          const resource = this.getNodeParameter('resource', 0);
          const operation = this.getNodeParameter('operation', 0);
          for (let i = 0; i < length; i++) {
              try {
                  if (resource === 'conversation') {
                      if (operation === 'create') {
                          const mailboxId = this.getNodeParameter('mailboxId', i);
                          const status = this.getNodeParameter('status', i);
                          const subject = this.getNodeParameter('subject', i);
                          const type = this.getNodeParameter('type', i);
                          const resolveData = this.getNodeParameter('resolveData', i);
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          const threads = this.getNodeParameter('threadsUi', i)
                              .threadsValues;
                          const body = {
                              mailboxId,
                              status,
                              subject,
                              type,
                          };
                          Object.assign(body, additionalFields);
                          if (additionalFields.customerId) {
                              body.customer = {
                                  id: additionalFields.customerId,
                              };
                              delete body.customerId;
                          }
                          if (additionalFields.customerEmail) {
                              body.customer = {
                                  email: additionalFields.customerEmail,
                              };
                              delete body.customerEmail;
                          }
                          if (body.customer === undefined) {
                              throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Either customer email or customer ID must be set', { itemIndex: i });
                          }
                          if (threads) {
                              for (let index = 0; index < threads.length; index++) {
                                  if (threads[index].type === '' || threads[index].text === '') {
                                      throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Chat Threads cannot be empty');
                                  }
                                  if (threads[index].type !== 'note') {
                                      threads[index].customer = body.customer;
                                  }
                              }
                              body.threads = threads;
                          }
                          responseData = await GenericFunctions_1.helpscoutApiRequest.call(this, 'POST', '/v2/conversations', body, qs, undefined, { resolveWithFullResponse: true });
                          const id = responseData.headers['resource-id'];
                          const uri = responseData.headers.location;
                          if (resolveData) {
                              responseData = await GenericFunctions_1.helpscoutApiRequest.call(this, 'GET', '', {}, {}, uri);
                          }
                          else {
                              responseData = {
                                  id,
                                  uri,
                              };
                          }
                      }
                      if (operation === 'delete') {
                          const conversationId = this.getNodeParameter('conversationId', i);
                          responseData = await GenericFunctions_1.helpscoutApiRequest.call(this, 'DELETE', `/v2/conversations/${conversationId}`);
                          responseData = { success: true };
                      }
                      if (operation === 'get') {
                          const conversationId = this.getNodeParameter('conversationId', i);
                          responseData = await GenericFunctions_1.helpscoutApiRequest.call(this, 'GET', `/v2/conversations/${conversationId}`);
                      }
                      if (operation === 'getAll') {
                          const returnAll = this.getNodeParameter('returnAll', i);
                          const options = this.getNodeParameter('options', i);
                          if (options.tags) {
                              qs.tag = options.tags.toString();
                          }
                          Object.assign(qs, options);
                          delete qs.tags;
                          if (returnAll) {
                              responseData = await GenericFunctions_1.helpscoutApiRequestAllItems.call(this, '_embedded.conversations', 'GET', '/v2/conversations', {}, qs);
                          }
                          else {
                              qs.limit = this.getNodeParameter('limit', i);
                              responseData = await GenericFunctions_1.helpscoutApiRequestAllItems.call(this, '_embedded.conversations', 'GET', '/v2/conversations', {}, qs);
                              responseData = responseData.splice(0, qs.limit);
                          }
                      }
                  }
                  if (resource === 'customer') {
                      if (operation === 'create') {
                          const resolveData = this.getNodeParameter('resolveData', i);
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          const chats = this.getNodeParameter('chatsUi', i)
                              .chatsValues;
                          const address = this.getNodeParameter('addressUi', i)
                              .addressValue;
                          const emails = this.getNodeParameter('emailsUi', i)
                              .emailsValues;
                          const phones = this.getNodeParameter('phonesUi', i)
                              .phonesValues;
                          const socialProfiles = this.getNodeParameter('socialProfilesUi', i)
                              .socialProfilesValues;
                          const websites = this.getNodeParameter('websitesUi', i)
                              .websitesValues;
                          let body = {};
                          body = Object.assign({}, additionalFields);
                          if (body.age) {
                              body.age = body.age.toString();
                          }
                          if (chats) {
                              body.chats = chats;
                          }
                          if (address) {
                              body.address = address;
                              body.address.lines = [address.line1, address.line2];
                          }
                          if (emails) {
                              body.emails = emails;
                          }
                          if (phones) {
                              body.phones = phones;
                          }
                          if (socialProfiles) {
                              body.socialProfiles = socialProfiles;
                          }
                          if (websites) {
                              body.websites = websites;
                          }
                          if (Object.keys(body).length === 0) {
                              throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'You have to set at least one field', {
                                  itemIndex: i,
                              });
                          }
                          responseData = await GenericFunctions_1.helpscoutApiRequest.call(this, 'POST', '/v2/customers', body, qs, undefined, { resolveWithFullResponse: true });
                          const id = responseData.headers['resource-id'];
                          const uri = responseData.headers.location;
                          if (resolveData) {
                              responseData = await GenericFunctions_1.helpscoutApiRequest.call(this, 'GET', '', {}, {}, uri);
                          }
                          else {
                              responseData = {
                                  id,
                                  uri,
                              };
                          }
                      }
                      if (operation === 'properties') {
                          responseData = await GenericFunctions_1.helpscoutApiRequestAllItems.call(this, '_embedded.customer-properties', 'GET', '/v2/customer-properties', {}, qs);
                      }
                      if (operation === 'get') {
                          const customerId = this.getNodeParameter('customerId', i);
                          responseData = await GenericFunctions_1.helpscoutApiRequest.call(this, 'GET', `/v2/customers/${customerId}`);
                      }
                      if (operation === 'getAll') {
                          const returnAll = this.getNodeParameter('returnAll', i);
                          const options = this.getNodeParameter('options', i);
                          Object.assign(qs, options);
                          if (returnAll) {
                              responseData = await GenericFunctions_1.helpscoutApiRequestAllItems.call(this, '_embedded.customers', 'GET', '/v2/customers', {}, qs);
                          }
                          else {
                              qs.limit = this.getNodeParameter('limit', i);
                              responseData = await GenericFunctions_1.helpscoutApiRequestAllItems.call(this, '_embedded.customers', 'GET', '/v2/customers', {}, qs);
                              responseData = responseData.splice(0, qs.limit);
                          }
                      }
                      if (operation === 'update') {
                          const customerId = this.getNodeParameter('customerId', i);
                          const updateFields = this.getNodeParameter('updateFields', i);
                          let body = {};
                          body = Object.assign({}, updateFields);
                          if (body.age) {
                              body.age = body.age.toString();
                          }
                          if (Object.keys(body).length === 0) {
                              throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'You have to set at least one field', {
                                  itemIndex: i,
                              });
                          }
                          responseData = await GenericFunctions_1.helpscoutApiRequest.call(this, 'PUT', `/v2/customers/${customerId}`, body, qs, undefined, { resolveWithFullResponse: true });
                          responseData = { success: true };
                      }
                  }
                  if (resource === 'mailbox') {
                      if (operation === 'get') {
                          const mailboxId = this.getNodeParameter('mailboxId', i);
                          responseData = await GenericFunctions_1.helpscoutApiRequest.call(this, 'GET', `/v2/mailboxes/${mailboxId}`, {}, qs);
                      }
                      if (operation === 'getAll') {
                          const returnAll = this.getNodeParameter('returnAll', i);
                          if (returnAll) {
                              responseData = await GenericFunctions_1.helpscoutApiRequestAllItems.call(this, '_embedded.mailboxes', 'GET', '/v2/mailboxes', {}, qs);
                          }
                          else {
                              qs.limit = this.getNodeParameter('limit', i);
                              responseData = await GenericFunctions_1.helpscoutApiRequestAllItems.call(this, '_embedded.mailboxes', 'GET', '/v2/mailboxes', {}, qs);
                              responseData = responseData.splice(0, qs.limit);
                          }
                      }
                  }
                  if (resource === 'thread') {
                      if (operation === 'create') {
                          const conversationId = this.getNodeParameter('conversationId', i);
                          const text = this.getNodeParameter('text', i);
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          const attachments = this.getNodeParameter('attachmentsUi', i);
                          const body = {
                              text,
                              attachments: [],
                          };
                          Object.assign(body, additionalFields);
                          if (additionalFields.customerId) {
                              body.customer = {
                                  id: additionalFields.customerId,
                              };
                              delete body.customerId;
                          }
                          if (additionalFields.customerEmail) {
                              body.customer = {
                                  email: additionalFields.customerEmail,
                              };
                              delete body.customerEmail;
                          }
                          if (body.customer === undefined) {
                              throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Either customer email or customer ID must be set', { itemIndex: i });
                          }
                          if (attachments) {
                              if (attachments.attachmentsValues &&
                                  attachments.attachmentsValues.length !== 0) {
                                  (_a = body.attachments) === null || _a === void 0 ? void 0 : _a.push.apply(body.attachments, attachments.attachmentsValues);
                              }
                              if (attachments.attachmentsBinary &&
                                  attachments.attachmentsBinary.length !== 0 &&
                                  items[i].binary) {
                                  const mapFunction = (value) => {
                                      const binaryProperty = items[i].binary[value.property];
                                      if (binaryProperty) {
                                          return {
                                              fileName: binaryProperty.fileName || 'unknown',
                                              data: binaryProperty.data,
                                              mimeType: binaryProperty.mimeType,
                                          };
                                      }
                                      else {
                                          throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Binary property ${value.property} does not exist on input`, { itemIndex: i });
                                      }
                                  };
                                  (_b = body.attachments) === null || _b === void 0 ? void 0 : _b.push.apply(body.attachments, attachments.attachmentsBinary.map(mapFunction));
                              }
                          }
                          responseData = await GenericFunctions_1.helpscoutApiRequest.call(this, 'POST', `/v2/conversations/${conversationId}/chats`, body);
                          responseData = { success: true };
                      }
                      if (operation === 'getAll') {
                          const returnAll = this.getNodeParameter('returnAll', i);
                          const conversationId = this.getNodeParameter('conversationId', i);
                          if (returnAll) {
                              responseData = await GenericFunctions_1.helpscoutApiRequestAllItems.call(this, '_embedded.threads', 'GET', `/v2/conversations/${conversationId}/threads`);
                          }
                          else {
                              qs.limit = this.getNodeParameter('limit', i);
                              responseData = await GenericFunctions_1.helpscoutApiRequestAllItems.call(this, '_embedded.threads', 'GET', `/v2/conversations/${conversationId}/threads`, {}, qs);
                              responseData = responseData.splice(0, qs.limit);
                          }
                      }
                  }
              }
              catch (error) {
                  if (this.continueOnFail()) {
                      const executionErrorData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray({ error: error.message }), { itemData: { item: i } });
                      returnData.push(...executionErrorData);
                      continue;
                  }
                  throw error;
              }
              const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
              returnData.push(...executionData);
          }
          return [returnData];
      }
  }
  exports.HelpScout = HelpScout;
  //# sourceMappingURL=HelpScout.node.js.map

documentation_markdown:
  ---
  #https://www.notion.so/n8n/Frontmatter-432c2b8dff1f43d4b1c8d20075510fe4
  title: Help Scout credentials
  description: Documentation for Help Scout credentials. Use these credentials to authenticate Help Scout in n8n, a workflow automation platform.
  contentType: [integration, reference]
  ---

  # Help Scout credentials

  You can use these credentials to authenticate the following nodes:

  - [Help Scout](/integrations/builtin/app-nodes/n8n-nodes-base.helpscout.md)
  - [Help Scout Trigger](/integrations/builtin/trigger-nodes/n8n-nodes-base.helpscouttrigger.md)

  ## Prerequisites

  Create a [Help Scout](https://www.helpscout.com/) account.

  ## Supported authentication methods

  - OAuth2

  ## Related resources

  Refer to [Help Scout's API documentation](https://developer.helpscout.com/){:target=_blank .external-link} for more information about the service.

  ## Using OAuth2

  --8<-- "_snippets/integrations/builtin/credentials/cloud-oauth-button.md"

  If you need to configure OAuth2 from scratch or need more detail on what's happening in the OAuth web flow, you'll need to create a Help Scout app. Refer to the instructions in the [Help Scout OAuth documentation](https://developer.helpscout.com/mailbox-api/overview/authentication/#oauth2-application){:target=_blank .external-link} for more information.

example_workflow:
  {"nodes":[{"parameters":{},"type":"n8n-nodes-base.node","typeVersion":1,"position":[220,120],"id":"c0ccbc9f-e811-4946-b4a5-b902d871e9f6","name":"Node"}],"connections":{"Node":{"main":[[]]}},"pinData":{},"meta":{"templateCredsSetupCompleted":true,"instanceId":"8cb1496f5f6794e58444a24564eef99a5bcf458fa95696bac55fffc0de6610c2"}}


node_type: n8n-nodes-base.HighLevel
name: HighLevel
display_name: Resource
description: Consume HighLevel API
category: Other
code_hash: 325f12d22df387974941ce8e51c7dc1941ad49317ca47cd4916fde393a1635d0
documentation_url: https://docs.n8n.io/integrations/builtin/credentials/highlevel
example_parameters: {}
properties_schema: []
package_name: n8n-nodes-base
extracted_at: 2025-06-08 08:05:23
updated_at: 2025-06-08 08:05:23
source_code:
  "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.HighLevel = void 0;
  const ContactDescription_1 = require("./description/ContactDescription");
  const OpportunityDescription_1 = require("./description/OpportunityDescription");
  const TaskDescription_1 = require("./description/TaskDescription");
  const GenericFunctions_1 = require("./GenericFunctions");
  const ressources = [
      {
          displayName: 'Resource',
          name: 'resource',
          type: 'options',
          noDataExpression: true,
          options: [
              {
                  name: 'Contact',
                  value: 'contact',
              },
              {
                  name: 'Opportunity',
                  value: 'opportunity',
              },
              {
                  name: 'Task',
                  value: 'task',
              },
          ],
          default: 'contact',
          required: true,
      },
  ];
  class HighLevel {
      constructor() {
          this.description = {
              displayName: 'HighLevel',
              name: 'highLevel',
              icon: 'file:highLevel.svg',
              group: ['transform'],
              version: 1,
              description: 'Consume HighLevel API',
              subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
              defaults: {
                  name: 'HighLevel',
              },
              inputs: ['main'],
              outputs: ['main'],
              credentials: [
                  {
                      name: 'highLevelApi',
                      required: true,
                  },
              ],
              requestDefaults: {
                  baseURL: 'https://rest.gohighlevel.com/v1',
                  headers: {
                      Accept: 'application/json',
                      'Content-Type': 'application/json',
                  },
              },
              requestOperations: {
                  pagination: GenericFunctions_1.highLevelApiPagination,
              },
              properties: [
                  ...ressources,
                  ...ContactDescription_1.contactOperations,
                  ...ContactDescription_1.contactNotes,
                  ...ContactDescription_1.contactFields,
                  ...OpportunityDescription_1.opportunityOperations,
                  ...OpportunityDescription_1.opportunityFields,
                  ...TaskDescription_1.taskOperations,
                  ...TaskDescription_1.taskFields,
              ],
          };
          this.methods = {
              loadOptions: {
                  getPipelineStages: GenericFunctions_1.getPipelineStages,
                  getUsers: GenericFunctions_1.getUsers,
                  getTimezones: GenericFunctions_1.getTimezones,
              },
          };
      }
  }
  exports.HighLevel = HighLevel;
  //# sourceMappingURL=HighLevel.node.js.map

documentation_markdown:
  ---
  #https://www.notion.so/n8n/Frontmatter-432c2b8dff1f43d4b1c8d20075510fe4
  title: HighLevel credentials
  description: Documentation for HighLevel credentials. Use these credentials to authenticate HighLevel in n8n, a workflow automation platform.
  contentType: [integration, reference]
  ---

  # HighLevel credentials

  You can use these credentials to authenticate the following nodes:

  * [HighLevel node](/integrations/builtin/app-nodes/n8n-nodes-base.highlevel.md)

  ## Prerequisites

  Create a [HighLevel developer](https://marketplace.gohighlevel.com/){:target=_blank .external-link} account.

  ## Supported authentication methods

  - API key: Use with API v1
  - OAuth2: Use with API v2

  /// note | API 1.0 deprecation
  HighLevel deprecated API v1.0 and no longer maintains it. Use OAuth2 to set up new credentials.
  ///

  ## Related resources

  Refer to [HighLevel's API 2.0 documentation](https://highlevel.stoplight.io/docs/integrations/0443d7d1a4bd0-overview){:target=_blank .external-link} for more information about the service.

  For existing integrations with the API v1.0, refer to [HighLevel's API 1.0 documentation](https://public-api.gohighlevel.com/){:target=_blank .external-link}.

  ## Using API key

  To configure this credential, you'll need:

  - An **API Key**: Refer to the [HighLevel API 1.0 Welcome documentation](https://public-api.gohighlevel.com/){:target=_blank .external-link} for instructions on getting your API key.

  ## Using OAuth2

  To configure this credential, you'll need:

  - A **Client ID**
  - A **Client Secret**

  To generate both, create an app in **My Apps > Create App**. Use these settings:

  1. Set **Distribution Type** to **Sub-Account**.
  2. Add these **Scopes**:
      - `locations.readonly`
      - `contacts.readonly`
      - `contacts.write`
      - `opportunities.readonly`
      - `opportunities.write`
      - `users.readonly`
  3. Copy the **OAuth Redirect URL** from n8n and add it as a **Redirect URL** in your HighLevel app.
  4. Copy the **Client ID** and **Client Secret** from HighLevel and add them to your n8n credential.
  5. Add the same scopes added above to your n8n credential in a space-separated list. For example:

      ```locations.readonly contacts.readonly contacts.write opportunities.readonly opportunities.write users.readonly```

  Refer to HighLevel's [API Authorization documentation](https://highlevel.stoplight.io/docs/integrations/a04191c0fabf9-authorization){:target=_blank .external-link} for more details. Refer to HighLevel's [API Scopes documentation](https://highlevel.stoplight.io/docs/integrations/vcctp9t1w8hja-scopes){:target=_blank .external-link} for more information about available scopes.

example_workflow:
  {"nodes":[{"parameters":{},"type":"n8n-nodes-base.node","typeVersion":1,"position":[220,120],"id":"8e0e1ac4-71d2-4534-8b27-54b1674e50d1","name":"Node"}],"connections":{"Node":{"main":[[]]}},"pinData":{},"meta":{"templateCredsSetupCompleted":true,"instanceId":"5b3faa039393efc2144476ee9338be5f500d13c0ec16d2753ad24118569511af"}}


node_type: n8n-nodes-base.HomeAssistant
name: HomeAssistant
display_name: Home Assistant
description: Consume Home Assistant API
category: Other
code_hash: db530f5f43a4c0a938e63f71c6392dc711b44a2ecca9f17bc16c60b9b2d5896a
documentation_url: https://docs.n8n.io/integrations/builtin/credentials/homeassistant
example_parameters: {}
properties_schema: []
package_name: n8n-nodes-base
extracted_at: 2025-06-08 08:05:23
updated_at: 2025-06-08 08:05:23
source_code:
  "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.HomeAssistant = void 0;
  const ConfigDescription_1 = require("./ConfigDescription");
  const ServiceDescription_1 = require("./ServiceDescription");
  const StateDescription_1 = require("./StateDescription");
  const EventDescription_1 = require("./EventDescription");
  const LogDescription_1 = require("./LogDescription");
  const TemplateDescription_1 = require("./TemplateDescription");
  const HistoryDescription_1 = require("./HistoryDescription");
  const CameraProxyDescription_1 = require("./CameraProxyDescription");
  const GenericFunctions_1 = require("./GenericFunctions");
  class HomeAssistant {
      constructor() {
          this.description = {
              displayName: 'Home Assistant',
              name: 'homeAssistant',
              icon: 'file:homeAssistant.svg',
              group: ['output'],
              version: 1,
              subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
              description: 'Consume Home Assistant API',
              defaults: {
                  name: 'Home Assistant',
              },
              inputs: ['main'],
              outputs: ['main'],
              credentials: [
                  {
                      name: 'homeAssistantApi',
                      required: true,
                      testedBy: 'homeAssistantApiTest',
                  },
              ],
              properties: [
                  {
                      displayName: 'Resource',
                      name: 'resource',
                      type: 'options',
                      noDataExpression: true,
                      options: [
                          {
                              name: 'Camera Proxy',
                              value: 'cameraProxy',
                          },
                          {
                              name: 'Config',
                              value: 'config',
                          },
                          {
                              name: 'Event',
                              value: 'event',
                          },
                          {
                              name: 'Log',
                              value: 'log',
                          },
                          {
                              name: 'Service',
                              value: 'service',
                          },
                          {
                              name: 'State',
                              value: 'state',
                          },
                          {
                              name: 'Template',
                              value: 'template',
                          },
                      ],
                      default: 'config',
                  },
                  ...CameraProxyDescription_1.cameraProxyOperations,
                  ...CameraProxyDescription_1.cameraProxyFields,
                  ...ConfigDescription_1.configOperations,
                  ...EventDescription_1.eventOperations,
                  ...EventDescription_1.eventFields,
                  ...HistoryDescription_1.historyOperations,
                  ...HistoryDescription_1.historyFields,
                  ...LogDescription_1.logOperations,
                  ...LogDescription_1.logFields,
                  ...ServiceDescription_1.serviceOperations,
                  ...ServiceDescription_1.serviceFields,
                  ...StateDescription_1.stateOperations,
                  ...StateDescription_1.stateFields,
                  ...TemplateDescription_1.templateOperations,
                  ...TemplateDescription_1.templateFields,
              ],
          };
          this.methods = {
              credentialTest: {
                  async homeAssistantApiTest(credential) {
                      const credentials = credential.data;
                      const options = {
                          method: 'GET',
                          headers: {
                              Authorization: `Bearer ${credentials.accessToken}`,
                          },
                          uri: `${credentials.ssl === true ? 'https' : 'http'}://${credentials.host}:${credentials.port || '8123'}/api/`,
                          json: true,
                          timeout: 5000,
                      };
                      try {
                          const response = await this.helpers.request(options);
                          if (!response.message) {
                              return {
                                  status: 'Error',
                                  message: `Token is not valid: ${response.error}`,
                              };
                          }
                      }
                      catch (error) {
                          return {
                              status: 'Error',
                              message: `${error.statusCode === 401 ? 'Token is' : 'Settings are'} not valid: ${error}`,
                          };
                      }
                      return {
                          status: 'OK',
                          message: 'Authentication successful!',
                      };
                  },
              },
              loadOptions: {
                  async getAllEntities() {
                      return GenericFunctions_1.getHomeAssistantEntities.call(this);
                  },
                  async getCameraEntities() {
                      return GenericFunctions_1.getHomeAssistantEntities.call(this, 'camera');
                  },
                  async getDomains() {
                      return GenericFunctions_1.getHomeAssistantServices.call(this);
                  },
                  async getDomainServices() {
                      const currentDomain = this.getCurrentNodeParameter('domain');
                      if (currentDomain) {
                          return GenericFunctions_1.getHomeAssistantServices.call(this, currentDomain);
                      }
                      else {
                          return [];
                      }
                  },
              },
          };
      }
      async execute() {
          const items = this.getInputData();
          const returnData = [];
          const length = items.length;
          const resource = this.getNodeParameter('resource', 0);
          const operation = this.getNodeParameter('operation', 0);
          const qs = {};
          let responseData;
          for (let i = 0; i < length; i++) {
              try {
                  if (resource === 'config') {
                      if (operation === 'get') {
                          responseData = await GenericFunctions_1.homeAssistantApiRequest.call(this, 'GET', '/config');
                      }
                      else if (operation === 'check') {
                          responseData = await GenericFunctions_1.homeAssistantApiRequest.call(this, 'POST', '/config/core/check_config');
                      }
                  }
                  else if (resource === 'service') {
                      if (operation === 'getAll') {
                          const returnAll = this.getNodeParameter('returnAll', i);
                          responseData = (await GenericFunctions_1.homeAssistantApiRequest.call(this, 'GET', '/services'));
                          if (!returnAll) {
                              const limit = this.getNodeParameter('limit', i);
                              responseData = responseData.slice(0, limit);
                          }
                      }
                      else if (operation === 'call') {
                          const domain = this.getNodeParameter('domain', i);
                          const service = this.getNodeParameter('service', i);
                          const serviceAttributes = this.getNodeParameter('serviceAttributes', i);
                          const body = {};
                          if (Object.entries(serviceAttributes).length) {
                              if (serviceAttributes.attributes !== undefined) {
                                  serviceAttributes.attributes.map((attribute) => {
                                      body[attribute.name] = attribute.value;
                                  });
                              }
                          }
                          responseData = await GenericFunctions_1.homeAssistantApiRequest.call(this, 'POST', `/services/${domain}/${service}`, body);
                          if (Array.isArray(responseData) && responseData.length === 0) {
                              responseData = {};
                          }
                      }
                  }
                  else if (resource === 'state') {
                      if (operation === 'getAll') {
                          const returnAll = this.getNodeParameter('returnAll', i);
                          responseData = (await GenericFunctions_1.homeAssistantApiRequest.call(this, 'GET', '/states'));
                          if (!returnAll) {
                              const limit = this.getNodeParameter('limit', i);
                              responseData = responseData.slice(0, limit);
                          }
                      }
                      else if (operation === 'get') {
                          const entityId = this.getNodeParameter('entityId', i);
                          responseData = await GenericFunctions_1.homeAssistantApiRequest.call(this, 'GET', `/states/${entityId}`);
                      }
                      else if (operation === 'upsert') {
                          const entityId = this.getNodeParameter('entityId', i);
                          const state = this.getNodeParameter('state', i);
                          const stateAttributes = this.getNodeParameter('stateAttributes', i);
                          const body = {
                              state,
                              attributes: {},
                          };
                          if (Object.entries(stateAttributes).length) {
                              if (stateAttributes.attributes !== undefined) {
                                  stateAttributes.attributes.map((attribute) => {
                                      body.attributes[attribute.name] = attribute.value;
                                  });
                              }
                          }
                          responseData = await GenericFunctions_1.homeAssistantApiRequest.call(this, 'POST', `/states/${entityId}`, body);
                      }
                  }
                  else if (resource === 'event') {
                      if (operation === 'getAll') {
                          const returnAll = this.getNodeParameter('returnAll', i);
                          responseData = (await GenericFunctions_1.homeAssistantApiRequest.call(this, 'GET', '/events'));
                          if (!returnAll) {
                              const limit = this.getNodeParameter('limit', i);
                              responseData = responseData.slice(0, limit);
                          }
                      }
                      else if (operation === 'create') {
                          const eventType = this.getNodeParameter('eventType', i);
                          const eventAttributes = this.getNodeParameter('eventAttributes', i);
                          const body = {};
                          if (Object.entries(eventAttributes).length) {
                              if (eventAttributes.attributes !== undefined) {
                                  eventAttributes.attributes.map((attribute) => {
                                      body[attribute.name] = attribute.value;
                                  });
                              }
                          }
                          responseData = await GenericFunctions_1.homeAssistantApiRequest.call(this, 'POST', `/events/${eventType}`, body);
                      }
                  }
                  else if (resource === 'log') {
                      if (operation === 'getErroLogs') {
                          responseData = await GenericFunctions_1.homeAssistantApiRequest.call(this, 'GET', '/error_log');
                          if (responseData) {
                              responseData = {
                                  errorLog: responseData,
                              };
                          }
                      }
                      else if (operation === 'getLogbookEntries') {
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          let endpoint = '/logbook';
                          if (Object.entries(additionalFields).length) {
                              if (additionalFields.startTime) {
                                  endpoint = `/logbook/${additionalFields.startTime}`;
                              }
                              if (additionalFields.endTime) {
                                  qs.end_time = additionalFields.endTime;
                              }
                              if (additionalFields.entityId) {
                                  qs.entity = additionalFields.entityId;
                              }
                          }
                          responseData = await GenericFunctions_1.homeAssistantApiRequest.call(this, 'GET', endpoint, {}, qs);
                      }
                  }
                  else if (resource === 'template') {
                      if (operation === 'create') {
                          const body = {
                              template: this.getNodeParameter('template', i),
                          };
                          responseData = await GenericFunctions_1.homeAssistantApiRequest.call(this, 'POST', '/template', body);
                          if (responseData) {
                              responseData = { renderedTemplate: responseData };
                          }
                      }
                  }
                  else if (resource === 'history') {
                      if (operation === 'getAll') {
                          const returnAll = this.getNodeParameter('returnAll', i);
                          const additionalFields = this.getNodeParameter('additionalFields', i);
                          let endpoint = '/history/period';
                          if (Object.entries(additionalFields).length) {
                              if (additionalFields.startTime) {
                                  endpoint = `/history/period/${additionalFields.startTime}`;
                              }
                              if (additionalFields.endTime) {
                                  qs.end_time = additionalFields.endTime;
                              }
                              if (additionalFields.entityIds) {
                                  qs.filter_entity_id = additionalFields.entityIds;
                              }
                              if (additionalFields.minimalResponse === true) {
                                  qs.minimal_response = additionalFields.minimalResponse;
                              }
                              if (additionalFields.significantChangesOnly === true) {
                                  qs.significant_changes_only = additionalFields.significantChangesOnly;
                              }
                          }
                          responseData = (await GenericFunctions_1.homeAssistantApiRequest.call(this, 'GET', endpoint, {}, qs));
                          if (!returnAll) {
                              const limit = this.getNodeParameter('limit', i);
                              responseData = responseData.slice(0, limit);
                          }
                      }
                  }
                  else if (resource === 'cameraProxy') {
                      if (operation === 'getScreenshot') {
                          const cameraEntityId = this.getNodeParameter('cameraEntityId', i);
                          const dataPropertyNameDownload = this.getNodeParameter('binaryPropertyName', i);
                          const endpoint = `/camera_proxy/${cameraEntityId}`;
                          let mimeType;
                          responseData = await GenericFunctions_1.homeAssistantApiRequest.call(this, 'GET', endpoint, {}, {}, undefined, {
                              encoding: null,
                              resolveWithFullResponse: true,
                          });
                          const newItem = {
                              json: items[i].json,
                              binary: {},
                          };
                          if (mimeType === undefined && responseData.headers['content-type']) {
                              mimeType = responseData.headers['content-type'];
                          }
                          if (items[i].binary !== undefined && newItem.binary) {
                              Object.assign(newItem.binary, items[i].binary);
                          }
                          items[i] = newItem;
                          const data = Buffer.from(responseData.body);
                          items[i].binary[dataPropertyNameDownload] = await this.helpers.prepareBinaryData(data, 'screenshot.jpg', mimeType);
                      }
                  }
              }
              catch (error) {
                  if (this.continueOnFail()) {
                      if (resource === 'cameraProxy' && operation === 'get') {
                          items[i].json = { error: error.message };
                      }
                      else {
                          const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray({ error: error.message }), { itemData: { item: i } });
                          returnData.push(...executionData);
                      }
                      continue;
                  }
                  throw error;
              }
              const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
              returnData.push(...executionData);
          }
          if (resource === 'cameraProxy' && operation === 'getScreenshot') {
              return [items];
          }
          else {
              return [returnData];
          }
      }
  }
  exports.HomeAssistant = HomeAssistant;
  //# sourceMappingURL=HomeAssistant.node.js.map

documentation_markdown:
  ---
  #https://www.notion.so/n8n/Frontmatter-432c2b8dff1f43d4b1c8d20075510fe4
  title: Home Assistant credentials
  description: Documentation for Home Assistant credentials. Use these credentials to authenticate Home Assistant in n8n, a workflow automation platform.
  contentType: [integration, reference]
  priority: medium
  ---

  # Home Assistant credentials

  You can use these credentials to authenticate the following nodes:

  - [Home Assistant](/integrations/builtin/app-nodes/n8n-nodes-base.homeassistant.md)

  ## Supported authentication methods

  - API access token

  ## Related resources

  Refer to [Home Assistant's API documentation](https://developers.home-assistant.io/docs/api/rest){:target=_blank .external-link} for more information about the service.

  ## Using API access token

  To configure this credential, you'll need to [Install](https://www.home-assistant.io/installation/) Home Assistant, create a [Home Assistant](https://www.home-assistant.io/getting-started/onboarding) account, and have:

  - Your **Host**
  - The **Port**
  - A Long-Lived **Access Token**

  To generate an access token and set up the credential:

  1. To generate your **Access Token**, log in to Home Assistant and open your [User profile](https://my.home-assistant.io/redirect/profile){:target=_blank .external-link}.
  2. In the **Long-Lived Access Tokens** section, generate a new token.
  3. Copy this token and enter it in n8n as your **Access Token**.
  4. Enter the URL or IP address of your Home Assistant **Host**, without the `http://` or `https://` protocol, for example `your.awesome.home`.
  5. For the **Port**, enter the appropriate port:
  	- If you've made no port changes and access Home Assistant at `http://`, keep the default of `8123`.
  	- If you've made no port changes and access Home Assistant at `https://`, enter `443`.
  	- If you've configured Home Assistant to use a specific port, enter that port.
  6. If you've enabled SSL in Home Assistant in the [config.yml map key](https://developers.home-assistant.io/docs/add-ons/configuration/?_highlight=ssl#add-on-configuration){:target=_blank .external-link}, turn on the **SSL** toggle in n8n. If you're not sure, it's best to turn this setting on if you access your home assistant UI using `https://` instead of `http://`.

example_workflow:
  {"nodes":[{"parameters":{},"type":"n8n-nodes-base.node","typeVersion":1,"position":[220,120],"id":"4d2f194b-1dd4-45cb-8296-c98c27f670fe","name":"Node"}],"connections":{"Node":{"main":[[]]}},"pinData":{},"meta":{"templateCredsSetupCompleted":true,"instanceId":"847066e40263b5b6a8f888185d8e2d49b450b7b0829e866185d4e83f94c3c5e5"}}


node_type: n8n-nodes-base.HtmlExtract
name: HtmlExtract
display_name: HTML Extract
description: Extracts data from HTML
category: Other
code_hash: a9275186152c41bb3aea3d6c84c440e8b975b5b1e218d2bd3eafd12cc172cb7c
example_parameters: {}
properties_schema: []
package_name: n8n-nodes-base
extracted_at: 2025-06-08 08:05:23
updated_at: 2025-06-08 08:05:23
source_code:
  "use strict";
  var __importDefault = (this && this.__importDefault) || function (mod) {
      return (mod && mod.__esModule) ? mod : { "default": mod };
  };
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.HtmlExtract = void 0;
  const cheerio_1 = __importDefault(require("cheerio"));
  const n8n_workflow_1 = require("n8n-workflow");
  const get_1 = __importDefault(require("lodash/get"));
  const extractFunctions = {
      attribute: ($, valueData) => $.attr(valueData.attribute),
      html: ($, _valueData) => $.html() || undefined,
      text: ($, _valueData) => $.text(),
      value: ($, _valueData) => $.val(),
  };
  function getValue($, valueData, options) {
      const value = extractFunctions[valueData.returnValue]($, valueData);
      if (options.trimValues === false || value === undefined) {
          return value;
      }
      return value.trim();
  }
  class HtmlExtract {
      constructor() {
          this.description = {
              displayName: 'HTML Extract',
              name: 'htmlExtract',
              icon: 'fa:cut',
              group: ['transform'],
              version: 1,
              hidden: true,
              subtitle: '={{$parameter["sourceData"] + ": " + $parameter["dataPropertyName"]}}',
              description: 'Extracts data from HTML',
              defaults: {
                  name: 'HTML Extract',
                  color: '#333377',
              },
              inputs: ['main'],
              outputs: ['main'],
              properties: [
                  {
                      displayName: 'Source Data',
                      name: 'sourceData',
                      type: 'options',
                      options: [
                          {
                              name: 'Binary',
                              value: 'binary',
                          },
                          {
                              name: 'JSON',
                              value: 'json',
                          },
                      ],
                      default: 'json',
                      description: 'If HTML should be read from binary or JSON data',
                  },
                  {
                      displayName: 'Binary Property',
                      name: 'dataPropertyName',
                      type: 'string',
                      displayOptions: {
                          show: {
                              sourceData: ['binary'],
                          },
                      },
                      default: 'data',
                      required: true,
                      description: 'Name of the binary property in which the HTML to extract the data from can be found',
                  },
                  {
                      displayName: 'JSON Property',
                      name: 'dataPropertyName',
                      type: 'string',
                      displayOptions: {
                          show: {
                              sourceData: ['json'],
                          },
                      },
                      default: 'data',
                      required: true,
                      description: 'Name of the JSON property in which the HTML to extract the data from can be found. The property can either contain a string or an array of strings.',
                  },
                  {
                      displayName: 'Extraction Values',
                      name: 'extractionValues',
                      placeholder: 'Add Value',
                      type: 'fixedCollection',
                      typeOptions: {
                          multipleValues: true,
                      },
                      default: {},
                      options: [
                          {
                              name: 'values',
                              displayName: 'Values',
                              values: [
                                  {
                                      displayName: 'Key',
                                      name: 'key',
                                      type: 'string',
                                      default: '',
                                      description: 'The key under which the extracted value should be saved',
                                  },
                                  {
                                      displayName: 'CSS Selector',
                                      name: 'cssSelector',
                                      type: 'string',
                                      default: '',
                                      placeholder: '.price',
                                      description: 'The CSS selector to use',
                                  },
                                  {
                                      displayName: 'Return Value',
                                      name: 'returnValue',
                                      type: 'options',
                                      options: [
                                          {
                                              name: 'Attribute',
                                              value: 'attribute',
                                              description: 'Get an attribute value like "class" from an element',
                                          },
                                          {
                                              name: 'HTML',
                                              value: 'html',
                                              description: 'Get the HTML the element contains',
                                          },
                                          {
                                              name: 'Text',
                                              value: 'text',
                                              description: 'Get only the text content of the element',
                                          },
                                          {
                                              name: 'Value',
                                              value: 'value',
                                              description: 'Get value of an input, select or textarea',
                                          },
                                      ],
                                      default: 'text',
                                      description: 'What kind of data should be returned',
                                  },
                                  {
                                      displayName: 'Attribute',
                                      name: 'attribute',
                                      type: 'string',
                                      displayOptions: {
                                          show: {
                                              returnValue: ['attribute'],
                                          },
                                      },
                                      default: '',
                                      placeholder: 'class',
                                      description: 'The name of the attribute to return the value off',
                                  },
                                  {
                                      displayName: 'Return Array',
                                      name: 'returnArray',
                                      type: 'boolean',
                                      default: false,
                                      description: 'Whether to return the values as an array so if multiple ones get found they also get returned separately. If not set all will be returned as a single string.',
                                  },
                              ],
                          },
                      ],
                  },
                  {
                      displayName: 'Options',
                      name: 'options',
                      type: 'collection',
                      placeholder: 'Add Option',
                      default: {},
                      options: [
                          {
                              displayName: 'Trim Values',
                              name: 'trimValues',
                              type: 'boolean',
                              default: true,
                              description: 'Whether to remove automatically all spaces and newlines from the beginning and end of the values',
                          },
                      ],
                  },
              ],
          };
      }
      async execute() {
          const items = this.getInputData();
          const returnData = [];
          let item;
          for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
              try {
                  const dataPropertyName = this.getNodeParameter('dataPropertyName', itemIndex);
                  const extractionValues = this.getNodeParameter('extractionValues', itemIndex);
                  const options = this.getNodeParameter('options', itemIndex, {});
                  const sourceData = this.getNodeParameter('sourceData', itemIndex);
                  item = items[itemIndex];
                  let htmlArray = [];
                  if (sourceData === 'json') {
                      const data = (0, get_1.default)(item.json, dataPropertyName, undefined);
                      if (data === undefined) {
                          throw new n8n_workflow_1.NodeOperationError(this.getNode(), `No property named "${dataPropertyName}" exists!`, { itemIndex });
                      }
                      htmlArray = data;
                  }
                  else {
                      this.helpers.assertBinaryData(itemIndex, dataPropertyName);
                      const binaryDataBuffer = await this.helpers.getBinaryDataBuffer(itemIndex, dataPropertyName);
                      htmlArray = binaryDataBuffer.toString('utf-8');
                  }
                  if (!Array.isArray(htmlArray)) {
                      htmlArray = [htmlArray];
                  }
                  for (const html of htmlArray) {
                      const $ = cheerio_1.default.load(html);
                      const newItem = {
                          json: {},
                          pairedItem: {
                              item: itemIndex,
                          },
                      };
                      let htmlElement;
                      for (const valueData of extractionValues.values) {
                          htmlElement = $(valueData.cssSelector);
                          if (valueData.returnArray) {
                              newItem.json[valueData.key] = [];
                              htmlElement.each((i, el) => {
                                  newItem.json[valueData.key].push(getValue($(el), valueData, options));
                              });
                          }
                          else {
                              newItem.json[valueData.key] = getValue(htmlElement, valueData, options);
                          }
                      }
                      returnData.push(newItem);
                  }
              }
              catch (error) {
                  if (this.continueOnFail()) {
                      returnData.push({
                          json: {
                              error: error.message,
                          },
                          pairedItem: {
                              item: itemIndex,
                          },
                      });
                      continue;
                  }
                  throw error;
              }
          }
          return [returnData];
      }
  }
  exports.HtmlExtract = HtmlExtract;
  //# sourceMappingURL=HtmlExtract.node.js.map

example_workflow:
  {"nodes":[{"parameters":{},"type":"n8n-nodes-base.node","typeVersion":1,"position":[220,120],"id":"2b1bf01c-f447-4fba-86db-0a56e752a530","name":"Node"}],"connections":{"Node":{"main":[[]]}},"pinData":{},"meta":{"templateCredsSetupCompleted":true,"instanceId":"f696c79e131c0c096d1687442b429e7e34d7d59053575753520aa0266cea0c88"}}


node_type: n8n-nodes-base.Html
name: Html
display_name: HTML
description: Work with HTML
category: Other
code_hash: 9531d0a56d4f238a5c8fd64ea0b1c85308c7aa09d60d54033bd0365cbf8ebbe4
documentation_url: https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.html
example_parameters: {}
properties_schema: []
package_name: n8n-nodes-base
extracted_at: 2025-06-08 08:05:23
updated_at: 2025-06-08 08:05:23
source_code:
  "use strict";
  var __importDefault = (this && this.__importDefault) || function (mod) {
      return (mod && mod.__esModule) ? mod : { "default": mod };
  };
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.Html = exports.capitalizeHeader = void 0;
  const cheerio_1 = __importDefault(require("cheerio"));
  const n8n_workflow_1 = require("n8n-workflow");
  const placeholder_1 = require("./placeholder");
  const utils_1 = require("./utils");
  const utilities_1 = require("../../utils/utilities");
  const capitalizeHeader = (header, capitalize) => {
      if (!capitalize)
          return header;
      return header
          .split('_')
          .filter((word) => word)
          .map((word) => word[0].toUpperCase() + word.slice(1))
          .join(' ');
  };
  exports.capitalizeHeader = capitalizeHeader;
  class Html {
      constructor() {
          this.description = {
              displayName: 'HTML',
              name: 'html',
              icon: 'file:html.svg',
              group: ['transform'],
              version: 1,
              subtitle: '={{ $parameter["operation"] }}',
              description: 'Work with HTML',
              defaults: {
                  name: 'HTML',
              },
              inputs: ['main'],
              outputs: ['main'],
              parameterPane: 'wide',
              properties: [
                  {
                      displayName: 'Operation',
                      name: 'operation',
                      type: 'options',
                      noDataExpression: true,
                      options: [
                          {
                              name: 'Generate HTML Template',
                              value: 'generateHtmlTemplate',
                              action: 'Generate HTML template',
                          },
                          {
                              name: 'Extract HTML Content',
                              value: 'extractHtmlContent',
                              action: 'Extract HTML Content',
                          },
                          {
                              name: 'Convert to HTML Table',
                              value: 'convertToHtmlTable',
                              action: 'Convert to HTML Table',
                          },
                      ],
                      default: 'generateHtmlTemplate',
                  },
                  {
                      displayName: 'HTML Template',
                      name: 'html',
                      typeOptions: {
                          editor: 'htmlEditor',
                      },
                      type: 'string',
                      default: placeholder_1.placeholder,
                      noDataExpression: true,
                      description: 'HTML template to render',
                      displayOptions: {
                          show: {
                              operation: ['generateHtmlTemplate'],
                          },
                      },
                  },
                  {
                      displayName: '<b>Tips</b>: Type ctrl+space for completions. Use <code>{{ }}</code> for expressions and <code>&lt;style&gt;</code> tags for CSS. JS in <code>&lt;script&gt;</code> tags is included but not executed in n8n.',
                      name: 'notice',
                      type: 'notice',
                      default: '',
                      displayOptions: {
                          show: {
                              operation: ['generateHtmlTemplate'],
                          },
                      },
                  },
                  {
                      displayName: 'Source Data',
                      name: 'sourceData',
                      type: 'options',
                      options: [
                          {
                              name: 'Binary',
                              value: 'binary',
                          },
                          {
                              name: 'JSON',
                              value: 'json',
                          },
                      ],
                      default: 'json',
                      description: 'If HTML should be read from binary or JSON data',
                      displayOptions: {
                          show: {
                              operation: ['extractHtmlContent'],
                          },
                      },
                  },
                  {
                      displayName: 'Binary Property',
                      name: 'dataPropertyName',
                      type: 'string',
                      requiresDataPath: 'single',
                      displayOptions: {
                          show: {
                              operation: ['extractHtmlContent'],
                              sourceData: ['binary'],
                          },
                      },
                      default: 'data',
                      required: true,
                      description: 'Name of the binary property in which the HTML to extract the data from can be found',
                  },
                  {
                      displayName: 'JSON Property',
                      name: 'dataPropertyName',
                      type: 'string',
                      requiresDataPath: 'single',
                      displayOptions: {
                          show: {
                              operation: ['extractHtmlContent'],
                              sourceData: ['json'],
                          },
                      },
                      default: 'data',
                      required: true,
                      description: 'Name of the JSON property in which the HTML to extract the data from can be found. The property can either contain a string or an array of strings.',
                  },
                  {
                      displayName: 'Extraction Values',
                      name: 'extractionValues',
                      placeholder: 'Add Value',
                      type: 'fixedCollection',
                      typeOptions: {
                          multipleValues: true,
                      },
                      displayOptions: {
                          show: {
                              operation: ['extractHtmlContent'],
                          },
                      },
                      default: {},
                      options: [
                          {
                              name: 'values',
                              displayName: 'Values',
                              values: [
                                  {
                                      displayName: 'Key',
                                      name: 'key',
                                      type: 'string',
                                      default: '',
                                      description: 'The key under which the extracted value should be saved',
                                  },
                                  {
                                      displayName: 'CSS Selector',
                                      name: 'cssSelector',
                                      type: 'string',
                                      default: '',
                                      placeholder: '.price',
                                      description: 'The CSS selector to use',
                                  },
                                  {
                                      displayName: 'Return Value',
                                      name: 'returnValue',
                                      type: 'options',
                                      options: [
                                          {
                                              name: 'Attribute',
                                              value: 'attribute',
                                              description: 'Get an attribute value like "class" from an element',
                                          },
                                          {
                                              name: 'HTML',
                                              value: 'html',
                                              description: 'Get the HTML the element contains',
                                          },
                                          {
                                              name: 'Text',
                                              value: 'text',
                                              description: 'Get only the text content of the element',
                                          },
                                          {
                                              name: 'Value',
                                              value: 'value',
                                              description: 'Get value of an input, select or textarea',
                                          },
                                      ],
                                      default: 'text',
                                      description: 'What kind of data should be returned',
                                  },
                                  {
                                      displayName: 'Attribute',
                                      name: 'attribute',
                                      type: 'string',
                                      displayOptions: {
                                          show: {
                                              returnValue: ['attribute'],
                                          },
                                      },
                                      default: '',
                                      placeholder: 'class',
                                      description: 'The name of the attribute to return the value off',
                                  },
                                  {
                                      displayName: 'Return Array',
                                      name: 'returnArray',
                                      type: 'boolean',
                                      default: false,
                                      description: 'Whether to return the values as an array so if multiple ones get found they also get returned separately. If not set all will be returned as a single string.',
                                  },
                              ],
                          },
                      ],
                  },
                  {
                      displayName: 'Options',
                      name: 'options',
                      type: 'collection',
                      placeholder: 'Add Option',
                      default: {},
                      displayOptions: {
                          show: {
                              operation: ['extractHtmlContent'],
                          },
                      },
                      options: [
                          {
                              displayName: 'Trim Values',
                              name: 'trimValues',
                              type: 'boolean',
                              default: true,
                              description: 'Whether to remove automatically all spaces and newlines from the beginning and end of the values',
                          },
                      ],
                  },
                  {
                      displayName: 'Options',
                      name: 'options',
                      type: 'collection',
                      placeholder: 'Add Option',
                      default: {},
                      displayOptions: {
                          show: {
                              operation: ['convertToHtmlTable'],
                          },
                      },
                      options: [
                          {
                              displayName: 'Capitalize Headers',
                              name: 'capitalize',
                              type: 'boolean',
                              default: false,
                              description: 'Whether to capitalize the headers',
                          },
                          {
                              displayName: 'Custom Styling',
                              name: 'customStyling',
                              type: 'boolean',
                              default: false,
                              description: 'Whether to use custom styling',
                          },
                          {
                              displayName: 'Caption',
                              name: 'caption',
                              type: 'string',
                              default: '',
                              description: 'Caption to add to the table',
                          },
                          {
                              displayName: 'Table Attributes',
                              name: 'tableAttributes',
                              type: 'string',
                              default: '',
                              description: 'Attributes to attach to the table',
                              placeholder: 'e.g. style="padding:10px"',
                          },
                          {
                              displayName: 'Header Attributes',
                              name: 'headerAttributes',
                              type: 'string',
                              default: '',
                              description: 'Attributes to attach to the table header',
                              placeholder: 'e.g. style="padding:10px"',
                          },
                          {
                              displayName: 'Row Attributes',
                              name: 'rowAttributes',
                              type: 'string',
                              default: '',
                              description: 'Attributes to attach to the table row',
                              placeholder: 'e.g. style="padding:10px"',
                          },
                          {
                              displayName: 'Cell Attributes',
                              name: 'cellAttributes',
                              type: 'string',
                              default: '',
                              description: 'Attributes to attach to the table cell',
                              placeholder: 'e.g. style="padding:10px"',
                          },
                      ],
                  },
              ],
          };
      }
      async execute() {
          const items = this.getInputData();
          const operation = this.getNodeParameter('operation', 0);
          if (operation === 'convertToHtmlTable' && items.length) {
              let table = '';
              const options = this.getNodeParameter('options', 0);
              let tableStyle = '';
              let headerStyle = '';
              let cellStyle = '';
              if (!options.customStyling) {
                  tableStyle = "style='border-spacing:0; font-family:helvetica,arial,sans-serif'";
                  headerStyle =
                      "style='margin:0; padding:7px 20px 7px 0px; border-bottom:1px solid #eee; text-align:left; color:#888; font-weight:normal'";
                  cellStyle = "style='margin:0; padding:7px 20px 7px 0px; border-bottom:1px solid #eee'";
              }
              const tableAttributes = options.tableAttributes || '';
              const headerAttributes = options.headerAttributes || '';
              const itemsData = [];
              const itemsKeys = new Set();
              for (const entry of items) {
                  itemsData.push(entry.json);
                  for (const key of Object.keys(entry.json)) {
                      itemsKeys.add(key);
                  }
              }
              const headers = Array.from(itemsKeys);
              table += `<table ${tableStyle} ${tableAttributes}>`;
              if (options.caption) {
                  table += `<caption>${options.caption}</caption>`;
              }
              table += `<thead ${headerStyle} ${headerAttributes}>`;
              table += '<tr>';
              table += headers
                  .map((header) => '<th>' + (0, exports.capitalizeHeader)(header, options.capitalize) + '</th>')
                  .join('');
              table += '</tr>';
              table += '</thead>';
              table += '<tbody>';
              itemsData.forEach((entry, entryIndex) => {
                  const rowsAttributes = this.getNodeParameter('options.rowsAttributes', entryIndex, '');
                  table += `<tr  ${rowsAttributes}>`;
                  const cellsAttributes = this.getNodeParameter('options.cellAttributes', entryIndex, '');
                  table += headers
                      .map((header) => {
                      let td = `<td ${cellStyle} ${cellsAttributes}>`;
                      if (typeof entry[header] === 'boolean') {
                          const isChecked = entry[header] ? 'checked="checked"' : '';
                          td += `<input type="checkbox" ${isChecked}/>`;
                      }
                      else {
                          td += entry[header];
                      }
                      td += '</td>';
                      return td;
                  })
                      .join('');
                  table += '</tr>';
              });
              table += '</tbody>';
              table += '</table>';
              return [
                  [
                      {
                          json: { table },
                          pairedItem: items.map((_item, index) => ({
                              item: index,
                          })),
                      },
                  ],
              ];
          }
          let item;
          const returnData = [];
          for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
              try {
                  if (operation === 'generateHtmlTemplate') {
                      let html = this.getNodeParameter('html', itemIndex);
                      for (const resolvable of (0, utilities_1.getResolvables)(html)) {
                          html = html.replace(resolvable, this.evaluateExpression(resolvable, itemIndex));
                      }
                      const result = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray({ html }), {
                          itemData: { item: itemIndex },
                      });
                      returnData.push(...result);
                  }
                  else if (operation === 'extractHtmlContent') {
                      const dataPropertyName = this.getNodeParameter('dataPropertyName', itemIndex);
                      const extractionValues = this.getNodeParameter('extractionValues', itemIndex);
                      const options = this.getNodeParameter('options', itemIndex, {});
                      const sourceData = this.getNodeParameter('sourceData', itemIndex);
                      item = items[itemIndex];
                      let htmlArray = [];
                      if (sourceData === 'json') {
                          if (item.json[dataPropertyName] === undefined) {
                              throw new n8n_workflow_1.NodeOperationError(this.getNode(), `No property named "${dataPropertyName}" exists!`, { itemIndex });
                          }
                          htmlArray = item.json[dataPropertyName];
                      }
                      else {
                          this.helpers.assertBinaryData(itemIndex, dataPropertyName);
                          const binaryDataBuffer = await this.helpers.getBinaryDataBuffer(itemIndex, dataPropertyName);
                          htmlArray = binaryDataBuffer.toString('utf-8');
                      }
                      if (!Array.isArray(htmlArray)) {
                          htmlArray = [htmlArray];
                      }
                      for (const html of htmlArray) {
                          const $ = cheerio_1.default.load(html);
                          const newItem = {
                              json: {},
                              pairedItem: {
                                  item: itemIndex,
                              },
                          };
                          let htmlElement;
                          for (const valueData of extractionValues.values) {
                              htmlElement = $(valueData.cssSelector);
                              if (valueData.returnArray) {
                                  newItem.json[valueData.key] = [];
                                  htmlElement.each((i, el) => {
                                      newItem.json[valueData.key].push((0, utils_1.getValue)($(el), valueData, options));
                                  });
                              }
                              else {
                                  newItem.json[valueData.key] = (0, utils_1.getValue)(htmlElement, valueData, options);
                              }
                          }
                          returnData.push(newItem);
                      }
                  }
              }
              catch (error) {
                  if (this.continueOnFail()) {
                      returnData.push({
                          json: {
                              error: error.message,
                          },
                          pairedItem: {
                              item: itemIndex,
                          },
                      });
                      continue;
                  }
                  throw error;
              }
          }
          return [returnData];
      }
  }
  exports.Html = Html;
  //# sourceMappingURL=Html.node.js.map

documentation_markdown:
  ---
  #https://www.notion.so/n8n/Frontmatter-432c2b8dff1f43d4b1c8d20075510fe4
  title: HTML
  description: Documentation for the HTML node in n8n, a workflow automation platform. Includes guidance on usage, and links to examples.
  contentType: [integration, reference]
  priority: high
  ---

  # HTML

  The HTML node provides operations to help you work with HTML in n8n.

  /// note | HTML Extract node
  The HTML node replaces the HTML Extract node from version 0.213.0 on. If you're using an older version of n8n, you can still view the [HTML Extract node documentation](https://github.com/n8n-io/n8n-docs/blob/86fe33b681621e618e3adcab9a27e8605dbc23ad/docs/integrations/builtin/core-nodes/n8n-nodes-base.htmlextract.md){:target=_blank .external-link}.
  ///
  /// warning | Cross-site scripting
  When using the HTML node to generate an HTML template you can introduce [XSS (cross-site scripting)](https://owasp.org/www-community/attacks/xss/){:target=_blank .external-link}. This is a security risk. Be careful with un-trusted inputs.
  ///

  ## Operations

  * [**Generate HTML template**](#generate-html-template): Use this operation to create an HTML template. This allows you to take data from your workflow and output it as HTML.
  * [**Extract HTML content**](#extract-html-content): Extract contents from an HTML-formatted source. The source can be in JSON or a binary file (`.html`).
  * [**Convert to HTML Table**](#convert-to-html-table): Convert content to an HTML table.

  The node parameters and options depend on the operation you select. Refer to the sections below for more details on configuring each operation.

  ## Generate HTML template

  Create an HTML template. This allows you to take data from your workflow and output it as HTML. 

  You can include:

  * Standard HTML
  * CSS in `<style>` tags.
  * JavaScript in `<script>` tags. n8n doesn't execute the JavaScript.
  * Expressions, wrapped in `{{}}`.

  You can use [Expressions](/code/expressions.md) in the template, including n8n's [Built-in methods and variables](/code/builtin/overview.md). 

  ## Extract HTML Content

  Extract contents from an HTML-formatted source. The source can be in JSON or a binary file (`.html`).

  Use these parameters:

  ### Source Data

  Select the source type for your HTML content. Choose between:

  * **JSON**: If you select this source data, enter the **JSON Property**: the name of the input containing the HTML you want to extract. The property can contain a string or an array of strings.
  * **Binary**: If you select this source data, enter the **Input Binary Field**: the name of the input containing the HTML you want to extract. The property can contain a string or an array of strings.

  ### Extraction Values

  - **Key**: Enter the key to save the extracted value under.
  - **CSS Selector**: Enter the CSS selector to search for.
  - **Return Value**: Select the type of data to return. Choose from:
  	- **Attribute**: Return an attribute value like `class` from an element.
  		- If you select this option, enter the name of the **Attribute** to return the value of.
  	- **HTML**: Return the HTML that the element contains.
  	- **Text**: Return the text content of the element.
  		- If you choose this option, you can also enter a comma-separated list of selectors to skip in the **Skip Selectors**.
  	- **Value**: Return the value of an input, select, or text area.
  - **Return Array**: Choose whether to return multiple extraction values as an array (turned on) or as a single string (turned off).

  ### Extract HTML Content options

  You can also configure this operation with these options:

  * **Trim Values**: Controls whether to remove all spaces and newlines from the beginning and end of the values (turned on) or leaves them (turned off).
  * **Clean Up Text**: Controls whether to remove leading whitespaces, trailing whitespaces, and line breaks (newlines) and condense multiple consecutive whitespaces into a single space (turned on) or to leave them as-is (turned off).

  ## Convert to HTML Table

  This operation expects data from another node. It has no parameters. It includes these options:

  * **Capitalize Headers**: Controls whether to capitalize the table's headers (turned on) or not (turned off).
  * **Custom Styling**: Controls whether to use custom styling (turned on) or not (turned off).
  * **Caption**: Enter a caption to add to the table.
  * **Table Attributes**: Enter any attributes to apply to the `<table>`, such as style attributes.
  * **Header Attributes**: Enter any attributes to apply to the table's headers `<th>`.
  * **Row Attributes**: Enter any attributes to apply to the table's rows `<tr>`.
  * **Cell Attributes**: Enter any attributes to apply to the table's cells `<td>`.

  ## Templates and examples

  <!-- see https://www.notion.so/n8n/Pull-in-templates-for-the-integrations-pages-37c716837b804d30a33b47475f6e3780 -->
  [[ templatesWidget(page.title, 'html') ]]

example_workflow:
  {"nodes":[{"parameters":{},"type":"n8n-nodes-base.node","typeVersion":1,"position":[220,120],"id":"623f1ce2-f576-492b-9d8d-1741c608d5cb","name":"Node"}],"connections":{"Node":{"main":[[]]}},"pinData":{},"meta":{"templateCredsSetupCompleted":true,"instanceId":"9c0f10ec064c664867d4511cdfd0ef80a18007af9e6d6af2d96dcca0b6a5c189"}}


