static async createCron (req, res) {
    if (!ArkimeUtil.isString(req.body.name)) {
      return res.serverError(403, 'Missing query name');
    }
    if (!ArkimeUtil.isString(req.body.query)) {
      return res.serverError(403, 'Missing query expression');
    }
    if (!ArkimeUtil.isString(req.body.action)) {
      return res.serverError(403, 'Missing query action');
    }
    if (!ArkimeUtil.isString(req.body.tags)) {
      return res.serverError(403, 'Missing query tag(s)');
    }

    if (req.body.roles !== undefined && !ArkimeUtil.isStringArray(req.body.roles)) {
      return res.serverError(403, 'Roles field must be an array of strings');
    }

    if (req.body.editRoles !== undefined && !ArkimeUtil.isStringArray(req.body.editRoles)) {
      return res.serverError(403, 'Edit roles field must be an array of strings');
    }

    if (req.body.users !== undefined && !ArkimeUtil.isString(req.body.users, 0)) {
      return res.serverError(403, 'Users field must be a string');
    }

    // comma/newline separated value -> array of values
    let users = ArkimeUtil.commaOrNewlineStringToArray(req.body.users || '');
    users = await User.validateUserIds(users);
    req.body.users = users.validUsers;

    const doc = {
      doc: {
        enabled: true,
        name: req.body.name,
        tags: req.body.tags,
        users: req.body.users,
        roles: req.body.roles,
        query: req.body.query,
        action: req.body.action,
        editRoles: req.body.editRoles,
        created: Math.floor(Date.now() / 1000)
      }
    };

    if (ArkimeUtil.isString(req.body.description)) {
      doc.doc.description = req.body.description;
    }

    if (ArkimeUtil.isString(req.body.notifier)) {
      doc.doc.notifier = req.body.notifier;
    }

    const userId = req.settingUser.userId;

    let minTimestamp;
    try {
      const { body: data } = await Db.getMinValue(Db.getSessionIndices(true), '@timestamp');
      minTimestamp = Math.floor(data.aggregations.min.value / 1000);
    } catch (err) {
      minTimestamp = Math.floor(Date.now() / 1000);
    }

    if (+req.body.since === -1) {
      doc.doc.lpValue = doc.doc.lastRun = minTimestamp;
    } else {
      doc.doc.lpValue = doc.doc.lastRun =
         Math.max(minTimestamp, Math.floor(Date.now() / 1000) - 60 * 60 * parseInt(req.body.since || '0', 10));
    }

    doc.doc.count = 0;
    doc.doc.creator = userId || 'anonymous';

    try {
      const { body: info } = await Db.indexNow('queries', 'query', null, doc.doc);

      if (CronAPIs.#primaryViewer) { CronAPIs.processCronQueries(); }

      doc.doc.key = info._id;
      if (doc.doc.users) {
        doc.doc.users = doc.doc.users.join(',');
      }

      return res.send(JSON.stringify({
        success: true,
        query: doc.doc,
        text: 'Created query!',
        invalidUsers: users.invalidUsers
      }));
    } catch (err) {
      console.log(`ERROR - ${req.method} /api/cron`, util.inspect(err, false, 50));
      return res.serverError(500, 'Create query failed');
    }
  }
POST - /api/cron

Create a new periodic query.
@name /cron
@returns {boolean} success - Whether the create operation was successful.
@returns {string} text - The success/error message to (optionally) display to the user.
@returns {ArkimeQuery} query - The new query