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.
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:
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.
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?
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.
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.
The whole webhook custom body treatment is suspect.
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!)
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.