Error 403 trying to create new notification

I am trying to create a new notification, and I am able to call the validate endpoint no problem, but I am getting a 403:

403 {‘statusCode’: 403, ‘message’: ‘Forbidden’}

when calling the create notification endpoint:

<CIMultiDict(‘content-type’: ‘application/json’, ‘x-api-key’: ‘QN_xxxxredactedxxxx’, ‘accept’: ‘application/json’)>
RequestInfo(url=URL(‘’), method=‘POST’, headers=<CIMultiDictProxy(‘Host’: ‘’, ‘content-type’: ‘application/json’, ‘x-api-key’: ‘QN_xxxxredactedxxxx’, ‘accept’: ‘application/json’, ‘Accept-Encoding’: ‘gzip, deflate’, ‘User-Agent’: ‘Python/3.10 aiohttp/3.8.4’, ‘Content-Length’: ‘61560’)>)
403 {‘statusCode’: 403, ‘message’: ‘Forbidden’}

And i cannot figure out why …

Hello Chev_Y,

This is an issue we are currently experiencing and should be fixed today. We appreciate you bringing this up and your patience!


Hey Chev_Y,

This issue has been resolved!


Thank you, I can confirm that it works on my end. Quick question I am confused about … So, there is a limit to the payload size of the expression I can submit when creating a notification. Does the patch update method actually allow me to get around that? I have an alert for erc20 token transfers to or from a list of addresses. I am calling update on that notification with another expression of exactly the same syntax but with a different list of addresses. My question is does the update method actually allow me to extend the original notification, or will it simply overwrite it with the new expression (and thus not actually add additional addresses to monitor for events)?

I believe your documentation says there is no limit to the amount of addresses you can monitor events for, so I would hope that the update method is appending the additional addresses to the expression, but I am not so sure that’s what happening.

Would you mind clarifying this for me? Thanks.

Hey Chev_Y,

Can you please link us to the documentation you are referring to?

Patch method with a new expression overwrites the old expression, it does not append. There is a maximum size limit for expressions. It will return an error if the expression is too large. We recommend breaking the addresses into smaller groups and creating multiple notifications. We don’t explicitly limit the number of addresses in the expression, but at a certain point, the expression is too large and will return an error.


Gotcha, thank you for clarifying that. You know what would be a cool feature? You should create another endpoint, so you have destinations, notifications, and then “targets”, or “address_lists”, or something. Basically, it would awesome if i could upload a list of addresses, and then that list would be assigned a unique ID, and then if i could use that unique id as a variable in my expressions, that would be amazing. Especially if there was no limit (I suppose there would have to be some limit, because otherwise you may get some script kiddie trying to monitor every active account on chain clogging up your resources, but let’s say, up to a million accounts, would be reasonable) to the number of addresses i could have in that list, and then if there was an endpoint for appending to that list … well, if you implement that, I would never use any of your competitors again. I would be the most loyal customer on earth.

I would even be willing to help you implement it. I am a software engineer with ten years of experience writing Python and doing Linux administration, and I’ve been writing Solidity for about a couple of years. Feel free to PM me if you happen to be hiring or like my idea and want help :slight_smile:

1 Like

Hey Chev_Y,

We appreciate the feedback, and I have relayed it over to our internal team. We’re always hiring and opening up new positions here at QuickNode, so I would recommend taking a look at Jobs at QuickNode for any availabilities.


Is it possible to shorten an expression and use something like:

((tx_to || tx_from||tx_logs_topic1||tx_logs_topic2) in [0xF04114B3c207582f689aa8e528d3F02E915537d3,0xcBA424203b52cDe6eEd992a307f265D7ce02D79, 0xaF0a299c42d4Ad3656240866B554e8e3895F28Dc])

Instead of what am I doing now which is basically:

 >  def create_expression(self, addresses: list[ChecksumAddress]) -> str:
 >           """
 >           :return:
 >           """
 >           _addresses = ', '.join(["'%s'" % a for a in addresses])
 >           return """(tx_to in (%s)) || (tx_from in (%s)) || (tx_logs_topic1 in (%s)) || (tx_logs_topic2 in (%s))""" % (
 >           _addresses, _addresses, _addresses, _addresses)

As you can see, the expression becomes rather large when you are searching for multiple fields because afaik, I must specify the same list of addresses again and again for each condition. This is not exactly any better than what I was doing previously and will probably go back to doing manually, which was checking each transaction in every block to see if the sender or recipient is one of my accounts I am monitoring, expanding that to also check to see if there were logs emitted during the transaction, if any of the topics match any of my target accounts, or perhaps I could just search the tx calldata (if any) for the accounts. I had this running on several different chains without issue, except I was only looking at and tx.from, but i think i could easily add I thought that qn_alerts would make this easier, but it has not. So I will probably go back to the previous, manual method. Unless I can shorten those expressions in a way like in my example?