Issue verifying eager notification

markking Member Posts: 2
edited January 29 in Developer APIs

Hello, I'm having issues verifying eager notifications.

Here is the following eager notification code from my API (using Directus CMS backend):, async (req, res) => {
       * @type {import('../../event-auditions-endpoint/node_modules/@directus/api/dist/services').ItemsService<Directus.Videos>}
      const videosService = new ItemsService('videos', {
        schema: req.schema,
        accountability: { admin: true },
      });`body: ${JSON.stringify(req.body)} `);

      try {
        if (!isValidNotificationSignature(req, logger)) {
          return res
            .send({ message: 'Invalid notification signature' });

        await videosService.updateByQuery(
          { filter: { public_id: { _eq: req.body.public_id } } },
          { encoded_time: new Date().toISOString() },
      } catch (err) {
        logger.error(err, 'Error handling notification');
        res.status(500).send({ message: 'Internal server error' });

function isValidNotificationSignature(req, logger) {
  try {
    const timestamp = parseInt(req.header('X-Cld-Timestamp'));
    const signature = req.header('X-Cld-Signature');`timestamp: ${timestamp} signature: ${signature}`)

    const isValid = cloudinary.utils.verifyNotificationSignature(
    if (!isValid) {
      logger.error(`notification signature is not valid`);
      return false;
    return true;
  } catch (error) {
    logger.error(error, 'Unable to verify signature');
  return false;

Here is also code used to generate signed URLS:

router.get('/:fileName', async (req, res) => {
  try {
    const { fileName } = req.params;

    const { name } = path.parse(fileName);

    const timestamp = Math.round(new Date().getTime() / 1000);
    const signature = cloudinary.utils.api_sign_request(
        public_id: name,
        upload_preset: 'hls-encode',
        eager_notification_url: eagerNotificationURL,

    const signedUrl = new URL(
    signedUrl.searchParams.set('timestamp', timestamp.toString());
    signedUrl.searchParams.set('signature', signature);
    signedUrl.searchParams.set('public_id', name);
    signedUrl.searchParams.set('upload_preset', 'hls-encode');
    signedUrl.searchParams.set('folder', STORAGE_CLOUDINARY_ROOT);
    signedUrl.searchParams.set('api_key', STORAGE_CLOUDINARY_API_KEY);
    );`signedUrl: ${signedUrl}`);

      message: 'success',
      data: { signedURL: signedUrl },
  } catch (e) {
      message: 'error generating signedUrl',
      data: {},

I've logged the body received from the eager notifcation here:


I've confirmed the timestamps are valid within the default valid_for so it must be an issue comparing the hash values. I've tried setting the hashing algorithm to both 'sha1' and 'sha256' with no success.

I've confirmed I am receiving these values from the headers as well:

const timestamp = parseInt(req.header('X-Cld-Timestamp'));
const signature = req.header('X-Cld-Signature');

Any tips on why this verification might be failing?

I can provide more info if necessary.

Thank you.



  • aleksandar
    aleksandar Member, Cloudinary Staff Posts: 14

    Hi @markking,

    Thanks for your message.

    I checked internally and I see you submitted a ticket with our Support team directly and they shared details on why you could be encountering the error. That response from our side was sent on January 28th at 01:05 UTC. I'm not sharing that response here since it contains account-specific details.

    May I please ask you to check if you received that response from us and if not, please reply back in that support ticket and we can resend our response.



  • markking
    markking Member Posts: 2

    Yes I received a response from the support team this discussion can be deleted thanks!