<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: v3 Signature Mismatch - Public UIE (Local Dev + Proxy) in APIs &amp; Integrations</title>
    <link>https://community.hubspot.com/t5/APIs-Integrations/v3-Signature-Mismatch-Public-UIE-Local-Dev-Proxy/m-p/1152036#M82120</link>
    <description>&lt;P&gt;&lt;SPAN class=""&gt;Thanks so much for sharing your code, &lt;a href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/173949"&gt;@KKauper&lt;/a&gt;! It's very helpful to see a working manual implementation. &lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;SPAN class=""&gt;We've also been down the manual calculation path (Node.js/Express) and found, like you, that **bleep** is in the details of that base string, especially the exact&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;uri&lt;/SPAN&gt;&lt;SPAN class=""&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;component.&lt;BR /&gt;&lt;BR /&gt;Our manual Node.js&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;crypto&lt;/SPAN&gt;&lt;SPAN class=""&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;calculations actually match standard online HMAC tools for a given base string and our&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;CLIENT_SECRET&lt;/SPAN&gt;&lt;SPAN class=""&gt;. However, this "standard" signature still doesn't match the&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;X-HubSpot-Signature-V3&lt;/SPAN&gt;&lt;SPAN class=""&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;header sent by the&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;hs project dev&lt;/SPAN&gt;&lt;SPAN class=""&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;proxy when using&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;hubspot.fetch()&lt;/SPAN&gt;&lt;SPAN class=""&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;from our UI extension. &lt;/SPAN&gt;&lt;SPAN class=""&gt;This suggests the proxy's string-to-sign has a nuance we haven't yet replicated. &lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;SPAN class=""&gt;We're also finding that&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;@hubspot/api-client&lt;/SPAN&gt;&lt;SPAN class=""&gt;'s&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;Signature.isValid()&lt;/SPAN&gt;&lt;SPAN class=""&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;is similarly failing for us in this proxied dev scenario. Your example reinforces that a precise manual approach&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;can&lt;/SPAN&gt;&lt;SPAN class=""&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;work, so we're continuing to investigate the exact base string formation by the local dev proxy. Appreciate you posting your solution!&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;SPAN class=""&gt;&lt;a href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/177184"&gt;@DianaGomez&lt;/a&gt;&amp;nbsp;- Would love to keep this thread / conversation open to everyone while we continue working through a solution, as we will report back with an update when we do in case it helps anyone else out now or in the future.&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;</description>
    <pubDate>Tue, 13 May 2025 17:57:21 GMT</pubDate>
    <dc:creator>Milest</dc:creator>
    <dc:date>2025-05-13T17:57:21Z</dc:date>
    <item>
      <title>v3 Signature Mismatch - Public UIE (Local Dev + Proxy)</title>
      <link>https://community.hubspot.com/t5/APIs-Integrations/v3-Signature-Mismatch-Public-UIE-Local-Dev-Proxy/m-p/1151592#M82096</link>
      <description>&lt;P&gt;Hey Devs! Stuck on a persistent v3 signature mismatch for our public UI Extension that we're looking for some guidance on:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;`hubspot.fetch()`&amp;nbsp;calls to our local Node.js backend (proxied via&amp;nbsp;`local.json`&amp;nbsp;+ Cloudflare tunnel, with&amp;nbsp;`CLIENT_SECRET`&amp;nbsp;injected into&amp;nbsp;`hs project dev`) consistently result in a &lt;STRONG&gt;403 "Invalid HubSpot signature"&lt;/STRONG&gt; from our middleware.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Key Findings:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;`CLIENT_SECRET`&amp;nbsp;is confirmed identical everywhere.&lt;/LI&gt;&lt;LI&gt;`@hubspot/api-client`'s&amp;nbsp;`Signature.isValid()`&amp;nbsp;returns&amp;nbsp;`false`, even when passed the full URL (from&amp;nbsp;`req.originalUrl`&amp;nbsp;with documented URI decoding), method, empty raw body (for GET), numeric timestamp, and our client secret.&lt;/LI&gt;&lt;LI&gt;Our manual Node.js&amp;nbsp;`crypto`&amp;nbsp;calculation for the&amp;nbsp;_same base string_&amp;nbsp;matches standard online HMAC tools, but this "standard" signature does **not** match the signature header sent by the&amp;nbsp;`hs project dev`&amp;nbsp;proxy.&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;&lt;BR /&gt;If I understand correctly, this suggests the base string signed by the&amp;nbsp;`hs project dev`&amp;nbsp;proxy differs from our reconstruction (and likely from what&amp;nbsp;`Signature.isValid()`&amp;nbsp;expects in this proxied scenario).&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Question:&lt;/STRONG&gt; Are there any known specific nuances to how&amp;nbsp;`hs project dev`&amp;nbsp;proxy constructs its string-to-sign for v3 (e.g., query param order, specific URL encoding details beyond the documented list) that we might be missing?&lt;BR /&gt;&lt;BR /&gt;Happy to provide more detailed logs/code if anyone has encountered this, and might be willing to provide some direction. Thanks in advance for any insight here!&lt;/P&gt;</description>
      <pubDate>Mon, 12 May 2025 22:44:56 GMT</pubDate>
      <guid>https://community.hubspot.com/t5/APIs-Integrations/v3-Signature-Mismatch-Public-UIE-Local-Dev-Proxy/m-p/1151592#M82096</guid>
      <dc:creator>Milest</dc:creator>
      <dc:date>2025-05-12T22:44:56Z</dc:date>
    </item>
    <item>
      <title>Re: v3 Signature Mismatch - Public UIE (Local Dev + Proxy)</title>
      <link>https://community.hubspot.com/t5/APIs-Integrations/v3-Signature-Mismatch-Public-UIE-Local-Dev-Proxy/m-p/1151718#M82101</link>
      <description>&lt;P&gt;Hi &lt;SPAN style="background: var(--ck-color-mention-background); color: var(--ck-color-mention-text);"&gt;&lt;a href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/941232"&gt;@Milest&lt;/a&gt;&lt;/SPAN&gt;,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thanks for reaching out to the Community!&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I would like to invite some members of our community who may offer valuable insights.— hey &lt;SPAN style="background: var(--ck-color-mention-background); color: var(--ck-color-mention-text);"&gt;&lt;a href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/863028"&gt;@EMalueg&lt;/a&gt;&lt;/SPAN&gt;, &lt;STRONG&gt;&lt;SPAN style="background: var(--ck-color-mention-background); color: var(--ck-color-mention-text);"&gt;&lt;a href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/173949"&gt;@KKauper&lt;/a&gt;&lt;/SPAN&gt;, &lt;SPAN style="background: var(--ck-color-mention-background); color: var(--ck-color-mention-text);"&gt;&lt;a href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/589350"&gt;@09156&lt;/a&gt;&lt;/SPAN&gt;, &lt;SPAN style="background: var(--ck-color-mention-background); color: var(--ck-color-mention-text);"&gt;&lt;a href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/324811"&gt;@zach_threadint&lt;/a&gt;&lt;/SPAN&gt;&lt;/STRONG&gt; - Could you share your advice with &lt;SPAN style="background: var(--ck-color-mention-background); color: var(--ck-color-mention-text);"&gt;&lt;a href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/941232"&gt;@Milest&lt;/a&gt;&lt;/SPAN&gt;?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thanks for taking a look!&lt;/P&gt;
&lt;P&gt;Diana&lt;/P&gt;</description>
      <pubDate>Tue, 13 May 2025 07:22:15 GMT</pubDate>
      <guid>https://community.hubspot.com/t5/APIs-Integrations/v3-Signature-Mismatch-Public-UIE-Local-Dev-Proxy/m-p/1151718#M82101</guid>
      <dc:creator>DianaGomez</dc:creator>
      <dc:date>2025-05-13T07:22:15Z</dc:date>
    </item>
    <item>
      <title>Re: v3 Signature Mismatch - Public UIE (Local Dev + Proxy)</title>
      <link>https://community.hubspot.com/t5/APIs-Integrations/v3-Signature-Mismatch-Public-UIE-Local-Dev-Proxy/m-p/1151752#M82106</link>
      <description>&lt;P&gt;Unfortunately, I can't help here. I do not use this new UI extensions framework, and I don't use `Signature.isValid()` from the Hubspot API client. Instead I use `crypto.timingSafeEqual()` after building the signature. Happy to share my code, however, if it would help.&lt;/P&gt;</description>
      <pubDate>Tue, 13 May 2025 08:48:05 GMT</pubDate>
      <guid>https://community.hubspot.com/t5/APIs-Integrations/v3-Signature-Mismatch-Public-UIE-Local-Dev-Proxy/m-p/1151752#M82106</guid>
      <dc:creator>KKauper</dc:creator>
      <dc:date>2025-05-13T08:48:05Z</dc:date>
    </item>
    <item>
      <title>Re: v3 Signature Mismatch - Public UIE (Local Dev + Proxy)</title>
      <link>https://community.hubspot.com/t5/APIs-Integrations/v3-Signature-Mismatch-Public-UIE-Local-Dev-Proxy/m-p/1151853#M82110</link>
      <description>&lt;P&gt;Thank you,&amp;nbsp;&lt;a href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/177184"&gt;@DianaGomez&lt;/a&gt;&amp;nbsp;- I look forward to connecting with more of the community!&lt;BR /&gt;&lt;BR /&gt;&lt;a href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/173949"&gt;@KKauper&lt;/a&gt;&amp;nbsp;- I appreciate your quick response and insight. I'm definitely open to trying alternative approaches. Anything that you're able to share would be highly appreciated. Thanks so much again for your help!&lt;/P&gt;</description>
      <pubDate>Tue, 13 May 2025 12:30:44 GMT</pubDate>
      <guid>https://community.hubspot.com/t5/APIs-Integrations/v3-Signature-Mismatch-Public-UIE-Local-Dev-Proxy/m-p/1151853#M82110</guid>
      <dc:creator>Milest</dc:creator>
      <dc:date>2025-05-13T12:30:44Z</dc:date>
    </item>
    <item>
      <title>Re: v3 Signature Mismatch - Public UIE (Local Dev + Proxy)</title>
      <link>https://community.hubspot.com/t5/APIs-Integrations/v3-Signature-Mismatch-Public-UIE-Local-Dev-Proxy/m-p/1151892#M82111</link>
      <description>&lt;P&gt;No problem. Here is our code:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="javascript"&gt;    // Get incoming request signature
    const requestSignature = params?.headers?.['x-hubspot-signature-v3']
    const requestTimestamp = params?.headers?.['x-hubspot-request-timestamp']

    if (!requestSignature) {
      throw new GeneralError('Did not receive Hubspot signature v3')
    }

    if (!requestTimestamp) {
      throw new GeneralError('Did not receive Hubspot signature v3 timestamp')
    }

    // Validate timestamp
    const MAX_ALLOWED_TIMESTAMP = 300000 // 5 minutes in milliseconds
    const currentTime = Date.now()
    if (currentTime - requestTimestamp &amp;gt; MAX_ALLOWED_TIMESTAMP) {
      throw new GeneralError('Hubspot signature v3 timestamp is invalid')
    }

    // Calculate signature
    const clientSecret = &amp;lt;your secret&amp;gt;
    const body = !['GET', 'DELETE'].includes(params.method) ? JSON.stringify(params.originalBody) : ''
    const source = params.method + params.uri + body + requestTimestamp
    const signature = crypto.createHmac('sha256', clientSecret).update(source).digest('base64')

    // Validate signature
    if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(requestSignature)))      
    {
      throw new NotAuthenticated('Hubspot signature v3 mismatch')
    }

    // Successfully validated&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I hope it helps.&lt;/P&gt;</description>
      <pubDate>Tue, 13 May 2025 13:24:14 GMT</pubDate>
      <guid>https://community.hubspot.com/t5/APIs-Integrations/v3-Signature-Mismatch-Public-UIE-Local-Dev-Proxy/m-p/1151892#M82111</guid>
      <dc:creator>KKauper</dc:creator>
      <dc:date>2025-05-13T13:24:14Z</dc:date>
    </item>
    <item>
      <title>Re: v3 Signature Mismatch - Public UIE (Local Dev + Proxy)</title>
      <link>https://community.hubspot.com/t5/APIs-Integrations/v3-Signature-Mismatch-Public-UIE-Local-Dev-Proxy/m-p/1152036#M82120</link>
      <description>&lt;P&gt;&lt;SPAN class=""&gt;Thanks so much for sharing your code, &lt;a href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/173949"&gt;@KKauper&lt;/a&gt;! It's very helpful to see a working manual implementation. &lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;SPAN class=""&gt;We've also been down the manual calculation path (Node.js/Express) and found, like you, that **bleep** is in the details of that base string, especially the exact&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;uri&lt;/SPAN&gt;&lt;SPAN class=""&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;component.&lt;BR /&gt;&lt;BR /&gt;Our manual Node.js&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;crypto&lt;/SPAN&gt;&lt;SPAN class=""&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;calculations actually match standard online HMAC tools for a given base string and our&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;CLIENT_SECRET&lt;/SPAN&gt;&lt;SPAN class=""&gt;. However, this "standard" signature still doesn't match the&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;X-HubSpot-Signature-V3&lt;/SPAN&gt;&lt;SPAN class=""&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;header sent by the&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;hs project dev&lt;/SPAN&gt;&lt;SPAN class=""&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;proxy when using&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;hubspot.fetch()&lt;/SPAN&gt;&lt;SPAN class=""&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;from our UI extension. &lt;/SPAN&gt;&lt;SPAN class=""&gt;This suggests the proxy's string-to-sign has a nuance we haven't yet replicated. &lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;SPAN class=""&gt;We're also finding that&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;@hubspot/api-client&lt;/SPAN&gt;&lt;SPAN class=""&gt;'s&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;Signature.isValid()&lt;/SPAN&gt;&lt;SPAN class=""&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;is similarly failing for us in this proxied dev scenario. Your example reinforces that a precise manual approach&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class=""&gt;can&lt;/SPAN&gt;&lt;SPAN class=""&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;work, so we're continuing to investigate the exact base string formation by the local dev proxy. Appreciate you posting your solution!&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;SPAN class=""&gt;&lt;a href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/177184"&gt;@DianaGomez&lt;/a&gt;&amp;nbsp;- Would love to keep this thread / conversation open to everyone while we continue working through a solution, as we will report back with an update when we do in case it helps anyone else out now or in the future.&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Tue, 13 May 2025 17:57:21 GMT</pubDate>
      <guid>https://community.hubspot.com/t5/APIs-Integrations/v3-Signature-Mismatch-Public-UIE-Local-Dev-Proxy/m-p/1152036#M82120</guid>
      <dc:creator>Milest</dc:creator>
      <dc:date>2025-05-13T17:57:21Z</dc:date>
    </item>
    <item>
      <title>Re: v3 Signature Mismatch - Public UIE (Local Dev + Proxy)</title>
      <link>https://community.hubspot.com/t5/APIs-Integrations/v3-Signature-Mismatch-Public-UIE-Local-Dev-Proxy/m-p/1262000#M87264</link>
      <description>&lt;DIV&gt;&lt;SPAN&gt;Hey &lt;a href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/941232"&gt;@Milest&lt;/a&gt;, we ran into the exact same issue and spent a while debugging it. Here's what we found — hopefully this saves someone else the trouble.&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;&lt;SPAN&gt;Root cause&lt;/SPAN&gt;&lt;/H2&gt;
&lt;DIV&gt;&lt;SPAN&gt;The &lt;/SPAN&gt;&lt;SPAN&gt;&lt;EM&gt;hs project dev&lt;/EM&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&amp;nbsp;proxy signs requests with the &lt;/SPAN&gt;&lt;SPAN&gt;&lt;STRONG&gt;local URL&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&amp;nbsp;(after &lt;/SPAN&gt;&lt;EM&gt;local.json&lt;/EM&gt;&lt;SPAN&gt;&amp;nbsp;mapping), not the original public URL.&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV&gt;&lt;SPAN&gt;For example, if your &lt;/SPAN&gt;&lt;SPAN&gt;&lt;EM&gt;local.json&lt;/EM&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&amp;nbsp;maps &lt;/SPAN&gt;&lt;SPAN&gt;&lt;EM&gt;&lt;A href="https://your-backend.com" target="_blank"&gt;https://your-backend.com&lt;/A&gt;&lt;/EM&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&amp;nbsp;to &lt;/SPAN&gt;&lt;SPAN&gt;&lt;EM&gt;&lt;A href="http://localhost:3000" target="_blank"&gt;http://localhost:3000&lt;/A&gt;&lt;/EM&gt;&lt;/SPAN&gt;&lt;SPAN&gt;, the CLI:&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;SPAN&gt;Receives a &lt;/SPAN&gt;&lt;SPAN&gt;`hubspot.fetch()`&lt;/SPAN&gt;&lt;SPAN&gt; call targeting &lt;/SPAN&gt;&lt;SPAN&gt;`&lt;A href="https://your-backend.com/api/endpoint?portalId=123" target="_blank"&gt;https://your-backend.com/api/endpoint?portalId=123&lt;/A&gt;`&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;Maps the URL to &lt;SPAN&gt;`&lt;A href="http://localhost:3000/api/endpoint?portalId=123" target="_blank"&gt;http://localhost:3000/api/endpoint?portalId=123&lt;/A&gt;`&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Signs with the mapped URL&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;(&lt;/SPAN&gt;&lt;SPAN&gt;&lt;EM&gt;&lt;A href="http://localhost:3000/" target="_blank"&gt;http://localhost:3000/&lt;/A&gt;...&lt;/EM&gt;&lt;/SPAN&gt;&lt;SPAN&gt;)&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;Sends the request to &lt;SPAN&gt;&lt;EM&gt;&lt;A href="http://localhost:3000/" target="_blank"&gt;http://localhost:3000/&lt;/A&gt;...&lt;/EM&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV&gt;&lt;SPAN&gt;We confirmed this by reading the CLI source code at &lt;/SPAN&gt;&lt;SPAN&gt;&lt;EM&gt;&lt;a href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/63720"&gt;@hubspot&lt;/a&gt;/app-functions-dev-server/dist/signing.js&lt;/EM&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&amp;nbsp;and &lt;/SPAN&gt;&lt;SPAN&gt;&lt;EM&gt;AppProxyService.js&lt;/EM&gt;&lt;/SPAN&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;&lt;SPAN&gt;The fix&lt;/SPAN&gt;&lt;/H2&gt;
&lt;DIV&gt;&lt;SPAN&gt;Reconstruct the URL from what Express actually receives — not from a hardcoded public URL:&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;PRE&gt;&lt;SPAN&gt;// JS&lt;BR /&gt;const&lt;/SPAN&gt; &lt;SPAN&gt;uri&lt;/SPAN&gt; &lt;SPAN&gt;=&lt;/SPAN&gt; &lt;SPAN&gt;`&lt;/SPAN&gt;&lt;SPAN&gt;${&lt;/SPAN&gt;&lt;SPAN&gt;req.&lt;/SPAN&gt;&lt;SPAN&gt;protocol&lt;/SPAN&gt;&lt;SPAN&gt;}&lt;/SPAN&gt;&lt;SPAN&gt;://&lt;/SPAN&gt;&lt;SPAN&gt;${&lt;/SPAN&gt;&lt;SPAN&gt;req.&lt;/SPAN&gt;&lt;SPAN&gt;get&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;'host'&lt;/SPAN&gt;&lt;SPAN&gt;)&lt;/SPAN&gt;&lt;SPAN&gt;}${&lt;/SPAN&gt;&lt;SPAN&gt;req.&lt;/SPAN&gt;&lt;SPAN&gt;originalUrl&lt;/SPAN&gt;&lt;SPAN&gt;}&lt;/SPAN&gt;&lt;SPAN&gt;`&lt;/SPAN&gt;&lt;SPAN&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV&gt;&lt;SPAN&gt;This works in both local dev and production because in both cases it's the URL the request was actually sent to.&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;&lt;SPAN&gt;Other gotchas we found&lt;/SPAN&gt;&lt;/H2&gt;
&lt;DIV&gt;&lt;STRONG&gt;1. `CLIENT_SECRET`&lt;/STRONG&gt;&lt;SPAN&gt;&lt;STRONG&gt; is required&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&amp;nbsp;— without it, requests fail silently (500 from the proxy, no backend logs at all). The CLI gives no warning. Launch with:&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;PRE&gt;&lt;SPAN&gt;// shell&lt;BR /&gt;CLIENT_SECRET=&lt;/SPAN&gt;&lt;SPAN&gt;"your-app-secret"&lt;/SPAN&gt; &lt;SPAN&gt;hs&lt;/SPAN&gt; &lt;SPAN&gt;project&lt;/SPAN&gt; &lt;SPAN&gt;dev&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV&gt;&lt;SPAN&gt;&lt;STRONG&gt;2. GET body mismatch&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&amp;nbsp;— the CLI sends &lt;/SPAN&gt;&lt;SPAN&gt;&lt;EM&gt;""&lt;/EM&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&amp;nbsp;(2 bytes, &lt;/SPAN&gt;&lt;SPAN&gt;&lt;EM&gt;content-length: 2&lt;/EM&gt;&lt;/SPAN&gt;&lt;SPAN&gt;) as the HTTP body for GET requests, but signs with an empty string &lt;/SPAN&gt;&lt;SPAN&gt;&lt;EM&gt;''&lt;/EM&gt;&lt;/SPAN&gt;&lt;SPAN&gt;. Use &lt;/SPAN&gt;&lt;SPAN&gt;&lt;EM&gt;''&lt;/EM&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&amp;nbsp;for GET/DELETE in your signature calculation.&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;&lt;SPAN&gt;Working middleware (Node.js/Express)&lt;/SPAN&gt;&lt;/H2&gt;
&lt;PRE&gt;&lt;SPAN&gt;// JS&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;const&lt;/SPAN&gt; &lt;SPAN&gt;crypto&lt;/SPAN&gt; &lt;SPAN&gt;=&lt;/SPAN&gt; &lt;SPAN&gt;require&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;'crypto'&lt;/SPAN&gt;&lt;SPAN&gt;);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;function&lt;/SPAN&gt; &lt;SPAN&gt;verifyHubspotSignature&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;req&lt;/SPAN&gt;&lt;SPAN&gt;, &lt;/SPAN&gt;&lt;SPAN&gt;res&lt;/SPAN&gt;&lt;SPAN&gt;, &lt;/SPAN&gt;&lt;SPAN&gt;next&lt;/SPAN&gt;&lt;SPAN&gt;) {&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;const&lt;/SPAN&gt; &lt;SPAN&gt;signature&lt;/SPAN&gt; &lt;SPAN&gt;=&lt;/SPAN&gt; &lt;SPAN&gt;req&lt;/SPAN&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;SPAN&gt;header&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;'X-HubSpot-Signature-v3'&lt;/SPAN&gt;&lt;SPAN&gt;);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;const&lt;/SPAN&gt; &lt;SPAN&gt;timestamp&lt;/SPAN&gt; &lt;SPAN&gt;=&lt;/SPAN&gt; &lt;SPAN&gt;req&lt;/SPAN&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;SPAN&gt;header&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;'X-HubSpot-Request-Timestamp'&lt;/SPAN&gt;&lt;SPAN&gt;);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;if&lt;/SPAN&gt;&lt;SPAN&gt; (&lt;/SPAN&gt;&lt;SPAN&gt;!&lt;/SPAN&gt;&lt;SPAN&gt;signature&lt;/SPAN&gt; &lt;SPAN&gt;||&lt;/SPAN&gt; &lt;SPAN&gt;!&lt;/SPAN&gt;&lt;SPAN&gt;timestamp&lt;/SPAN&gt;&lt;SPAN&gt;) {&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;return&lt;/SPAN&gt; &lt;SPAN&gt;res&lt;/SPAN&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;SPAN&gt;status&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;401&lt;/SPAN&gt;&lt;SPAN&gt;).&lt;/SPAN&gt;&lt;SPAN&gt;json&lt;/SPAN&gt;&lt;SPAN&gt;({ &lt;/SPAN&gt;&lt;SPAN&gt;error:&lt;/SPAN&gt; &lt;SPAN&gt;'Missing signature headers'&lt;/SPAN&gt;&lt;SPAN&gt; });&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; }&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;if&lt;/SPAN&gt;&lt;SPAN&gt; (&lt;/SPAN&gt;&lt;SPAN&gt;Date&lt;/SPAN&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;SPAN&gt;now&lt;/SPAN&gt;&lt;SPAN&gt;() &lt;/SPAN&gt;&lt;SPAN&gt;-&lt;/SPAN&gt; &lt;SPAN&gt;Number&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;timestamp&lt;/SPAN&gt;&lt;SPAN&gt;) &lt;/SPAN&gt;&lt;SPAN&gt;&amp;gt;&lt;/SPAN&gt; &lt;SPAN&gt;300000&lt;/SPAN&gt;&lt;SPAN&gt;) {&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;return&lt;/SPAN&gt; &lt;SPAN&gt;res&lt;/SPAN&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;SPAN&gt;status&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;401&lt;/SPAN&gt;&lt;SPAN&gt;).&lt;/SPAN&gt;&lt;SPAN&gt;json&lt;/SPAN&gt;&lt;SPAN&gt;({ &lt;/SPAN&gt;&lt;SPAN&gt;error:&lt;/SPAN&gt; &lt;SPAN&gt;'Timestamp too old'&lt;/SPAN&gt;&lt;SPAN&gt; });&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; }&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;const&lt;/SPAN&gt; &lt;SPAN&gt;body&lt;/SPAN&gt; &lt;SPAN&gt;=&lt;/SPAN&gt; &lt;SPAN&gt;[&lt;/SPAN&gt;&lt;SPAN&gt;'GET'&lt;/SPAN&gt;&lt;SPAN&gt;, &lt;/SPAN&gt;&lt;SPAN&gt;'DELETE'&lt;/SPAN&gt;&lt;SPAN&gt;]&lt;/SPAN&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;SPAN&gt;includes&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;req&lt;/SPAN&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;SPAN&gt;method&lt;/SPAN&gt;&lt;SPAN&gt;) &lt;/SPAN&gt;&lt;SPAN&gt;?&lt;/SPAN&gt; &lt;SPAN&gt;''&lt;/SPAN&gt; &lt;SPAN&gt;:&lt;/SPAN&gt; &lt;SPAN&gt;JSON&lt;/SPAN&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;SPAN&gt;stringify&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;req&lt;/SPAN&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;SPAN&gt;body&lt;/SPAN&gt; &lt;SPAN&gt;??&lt;/SPAN&gt; &lt;SPAN&gt;''&lt;/SPAN&gt;&lt;SPAN&gt;);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;const&lt;/SPAN&gt; &lt;SPAN&gt;uri&lt;/SPAN&gt; &lt;SPAN&gt;=&lt;/SPAN&gt; &lt;SPAN&gt;`&lt;/SPAN&gt;&lt;SPAN&gt;${&lt;/SPAN&gt;&lt;SPAN&gt;req.&lt;/SPAN&gt;&lt;SPAN&gt;protocol&lt;/SPAN&gt;&lt;SPAN&gt;}&lt;/SPAN&gt;&lt;SPAN&gt;://&lt;/SPAN&gt;&lt;SPAN&gt;${&lt;/SPAN&gt;&lt;SPAN&gt;req.&lt;/SPAN&gt;&lt;SPAN&gt;get&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;'host'&lt;/SPAN&gt;&lt;SPAN&gt;)&lt;/SPAN&gt;&lt;SPAN&gt;}${&lt;/SPAN&gt;&lt;SPAN&gt;req.&lt;/SPAN&gt;&lt;SPAN&gt;originalUrl&lt;/SPAN&gt;&lt;SPAN&gt;}&lt;/SPAN&gt;&lt;SPAN&gt;`&lt;/SPAN&gt;&lt;SPAN&gt;;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;const&lt;/SPAN&gt; &lt;SPAN&gt;source&lt;/SPAN&gt; &lt;SPAN&gt;=&lt;/SPAN&gt; &lt;SPAN&gt;req&lt;/SPAN&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;SPAN&gt;method&lt;/SPAN&gt; &lt;SPAN&gt;+&lt;/SPAN&gt; &lt;SPAN&gt;uri&lt;/SPAN&gt; &lt;SPAN&gt;+&lt;/SPAN&gt; &lt;SPAN&gt;body&lt;/SPAN&gt; &lt;SPAN&gt;+&lt;/SPAN&gt; &lt;SPAN&gt;timestamp&lt;/SPAN&gt;&lt;SPAN&gt;;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;const&lt;/SPAN&gt; &lt;SPAN&gt;expected&lt;/SPAN&gt; &lt;SPAN&gt;=&lt;/SPAN&gt; &lt;SPAN&gt;crypto&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .&lt;/SPAN&gt;&lt;SPAN&gt;createHmac&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;'sha256'&lt;/SPAN&gt;&lt;SPAN&gt;, &lt;/SPAN&gt;&lt;SPAN&gt;process&lt;/SPAN&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;SPAN&gt;env&lt;/SPAN&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;SPAN&gt;CLIENT_SECRET&lt;/SPAN&gt;&lt;SPAN&gt;)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .&lt;/SPAN&gt;&lt;SPAN&gt;update&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;source&lt;/SPAN&gt;&lt;SPAN&gt;)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .&lt;/SPAN&gt;&lt;SPAN&gt;digest&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;'base64'&lt;/SPAN&gt;&lt;SPAN&gt;);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;const&lt;/SPAN&gt; &lt;SPAN&gt;sigBuffer&lt;/SPAN&gt; &lt;SPAN&gt;=&lt;/SPAN&gt; &lt;SPAN&gt;Buffer&lt;/SPAN&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;SPAN&gt;from&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;signature&lt;/SPAN&gt;&lt;SPAN&gt;);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;const&lt;/SPAN&gt; &lt;SPAN&gt;expectedBuffer&lt;/SPAN&gt; &lt;SPAN&gt;=&lt;/SPAN&gt; &lt;SPAN&gt;Buffer&lt;/SPAN&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;SPAN&gt;from&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;expected&lt;/SPAN&gt;&lt;SPAN&gt;);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;if&lt;/SPAN&gt;&lt;SPAN&gt; (&lt;/SPAN&gt;&lt;SPAN&gt;sigBuffer&lt;/SPAN&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;SPAN&gt;length&lt;/SPAN&gt; &lt;SPAN&gt;!==&lt;/SPAN&gt; &lt;SPAN&gt;expectedBuffer&lt;/SPAN&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;SPAN&gt;length&lt;/SPAN&gt; &lt;SPAN&gt;||&lt;/SPAN&gt; &lt;SPAN&gt;!crypto&lt;/SPAN&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;SPAN&gt;timingSafeEqual&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;sigBuffer&lt;/SPAN&gt;&lt;SPAN&gt;, &lt;/SPAN&gt;&lt;SPAN&gt;expectedBuffer&lt;/SPAN&gt;&lt;SPAN&gt;)) {&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;return&lt;/SPAN&gt; &lt;SPAN&gt;res&lt;/SPAN&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;SPAN&gt;status&lt;/SPAN&gt;&lt;SPAN&gt;(&lt;/SPAN&gt;&lt;SPAN&gt;401&lt;/SPAN&gt;&lt;SPAN&gt;).&lt;/SPAN&gt;&lt;SPAN&gt;json&lt;/SPAN&gt;&lt;SPAN&gt;({ &lt;/SPAN&gt;&lt;SPAN&gt;error:&lt;/SPAN&gt; &lt;SPAN&gt;'Invalid signature'&lt;/SPAN&gt;&lt;SPAN&gt; });&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; }&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;next&lt;/SPAN&gt;&lt;SPAN&gt;();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;}&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV&gt;&lt;SPAN&gt;Note: this follows the same approach as the &lt;/SPAN&gt;&lt;A href="https://developers.hubspot.com/docs/apps/developer-platform/build-apps/authentication/request-validation" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;official Node.js example&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN&gt;in the HubSpot docs. &lt;/SPAN&gt;&lt;SPAN&gt;&lt;EM&gt;Signature.isValid()&lt;/EM&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&amp;nbsp;from&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;EM&gt;&lt;a href="https://community.hubspot.com/t5/user/viewprofilepage/user-id/63720"&gt;@hubspot&lt;/a&gt;/api-client&lt;/EM&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&amp;nbsp;does the exact same HMAC calculation internally (&lt;/SPAN&gt;&lt;A href="https://github.com/HubSpot/hubspot-api-nodejs/blob/master/src/utils/signature.ts" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;https://github.com/HubSpot/hubspot-api-nodejs/blob/master/src/utils/signature.ts&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt;) but doesn't solve the URL reconstruction issue — you still need to pass it the correct URL yourself.&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV&gt;&lt;SPAN&gt;Hope this helps!&lt;BR /&gt;&lt;/SPAN&gt;&lt;/DIV&gt;</description>
      <pubDate>Wed, 25 Mar 2026 12:28:35 GMT</pubDate>
      <guid>https://community.hubspot.com/t5/APIs-Integrations/v3-Signature-Mismatch-Public-UIE-Local-Dev-Proxy/m-p/1262000#M87264</guid>
      <dc:creator>EDoyen</dc:creator>
      <dc:date>2026-03-25T12:28:35Z</dc:date>
    </item>
  </channel>
</rss>

