Workflow API is missing webhook custom body properties

Workflows v4 API: GET doesn’t return a webhook action’s custom request body, and PUT erases it.

When a workflow’s “Send a webhook” action uses Customize request body, GET /automation/v4/flows/{flowId} returns that action with no trace of the body. It has method, webhookUrl, authSettings, queryParams, connection and type, and nothing else. The docs say a PUT replaces the whole workflow. So a client that reads the flow, changes something unrelated (here, a custom code action’s sourceCode) and PUTs it back erases the custom body without warning. The webhook then falls back to sending all of the enrolled object’s properties.

The PUT returns success, and reading the flow back looks identical to what was sent, because the body was never visible. The client has no way to detect the loss.

Hey @darveesh,

Thanks for bringing this to the community! :glowing_star:

Looks like you’re dealing with a tough combo there. I don’t have a definitive answer on whether the custom request body is intentionally excluded or if this is just a gap, but it could be worth reviewing these docs while we wait for some peer input:

Would love to hear if others have experienced this/ how they’re dealing with it!

Hey @Alex_Boissonneault, @evaldas, @remingtonbegg have you across this before? If so, do you have any suggestions for @darveesh on this?

Thank you!!

Sam, Community Manager

I’d treat this as a real gotcha. The v4 workflows API is still in beta, and the PUT is a full replace. HubSpot’s own docs say anything from the GET that you leave out of the PUT gets dropped. I haven’t seen the docs mention the webhook custom body at all, so I can’t tell you it’s by design. What I’d do in the meantime:

  • Don’t round-trip the whole flow for small edits if it contains webhook actions with custom bodies
  • Make the edit in the workflow editor instead, or test on a cloned workflow first
  • If you must use the API, keep your own copy of the custom body and compare it after each PUT, in the UI
  • Remember the PUT needs the current revisionId, so always GET right before you PUT
  • Post it in the Ideas forum and raise it with HubSpot Support or your developer contact, with your example flow

Please check this against your own portal, since this is what I’d expect from the docs, not something I’ve confirmed.

Help article (has screenshots): Workflows API - HubSpot docs

I’d avoid round-tripping that workflow through PUT until the missing body is addressed. A safer pattern could be to send only a record ID to an external endpoint and build the outbound payload there, with an explicit allowlist of fields. Prostir.build is one way to keep that processing outside the HubSpot workflow, if you’re already using agents or API flows there. That won’t fix the API issue, but it can reduce the risk of silently sending extra CRM properties. Have you tested a minimal webhook payload?

For visibility, another post today in the same genre (and more): Workflows API: let us read and write the settings that are currently UI-only.

Appreciate the input re workaround. I am having to resort to manual workflow management for now, but the issue needs to be addressed. A GET that doesn’t return all the actions settings and a PUT that acts like a POST is dangerous stuff.

Hey @darveesh, thanks for the loop-in @stassey!

I looked around and couldn’t find anyone reporting the webhook body specifically, but the root cause has come up before. Back in Aug 2025, someone reported a v4 PUT wiping the workflow name, description and all actions (Bug report: Workflow API v4 update is not working as expected). There’s also a separate thread about PUT silently clearing re-enrollment trigger settings. Neither has a fix. Your case is the same pattern with one extra twist: the field doesn’t even show up in the GET, so there’s nothing you could send back to keep it.

Even the new 2027-03-beta guide says anything from the GET that’s left out of the PUT gets removed. So a hidden field is always going to get wiped, and you can’t work around it from the API side.

The fix that’s held up for me is replacing “Send a webhook” with a custom code action that makes the call itself (fetch/axios with your exact body). sourceCode round-trips fully, so nothing gets dropped on PUT, and you get retries and logging as a bonus. If the native webhook has to stay, have your client skip or flag any flow with a webhook action before it PUTs. That way nobody loses the body without knowing.

I’d also file it through the Developer Feedback form (that’s where HubSpot pointed the earlier thread) and link both threads, so they can see it’s a pattern and not a one-off.

I am going to go on a limb and say this is also related (causing?) another bug in Husbpot’s own UI. Try this:

  • Create a workflow with a webhook action and a custom body. Save it and exit.
  • Go back into the workflow and add/edit the webhook custom body. Add a dummy test property for instance. Save it and exit.
  • Go Back into the workflow, view its version history. Go to the initial version. Look at the webhook custom body. That dummy test property you added to the latest version shows up in that original version. :slight_smile:

The whole webhook custom body treatment is suspect.

Hey @darveesh,

Thanks for digging deeper into this! If you believe there may be a bug, flagging this with Support, as they could look into your examples and escalate this internally if need be. (Live chat/ or phone support may be your quickest options!)

Hope this helps point you in the right direction!

Sam, Community Manager

Hi Stassey. Yes, I have created a support ticket for the version history bug that appears in the UI. I just wanted to post here for possible relevance to this topic of the Workflow API not working properly.

Support just got back to me on the UI bug I reported. The product team was able to verify the bug, and pushed in a fix today for that issue. At least in the UI now the revision history properly displays the webhook custom body data for past workflow versions.

I received an update from support that product has fixed this issue with the API. I tested it and it works now.

Thank you for testing this so thoroughly, and you’re right on both counts: the fix is live, and the custom request body is returned in a field named body, not jsonSchema as an earlier note in this case described.

To confirm from my side: the engineering team successfully merged and deployed the fix, and they confirmed it just yesterday afternoon when I was already off my shift. Your round-trip tests on the scratch workflow, both the unchanged PUT and the one that modified the custom code step, along with the production workflow now showing the bodies of both webhook steps, all match what we’d expect from the fix.

On your question about whether body is now a documented part of the v4 flow schema: as of today, the public API reference hasn’t been updated to list the body field on webhook actions, so I can’t point you to published documentation for it yet. What I can confirm is that the behavior is intentional and deployed, and I’ve raised the documentation question with the team. One practical suggestion while the documentation catches up: consider keeping a light validation step in your deploy script, for example asserting that each webhook action’s body is present in the GET response before you PUT. It’s inexpensive insurance while the field is new.