If someone recommends “Request Token Encoding: None” in a webhook, always push back
A client recently asked about connecting Marketo to Clay and we were dismayed at Clay’s official docs:
See how they recommend Request Token Encoding: None? That’s totally wrong, since:
- There are
{{lead.tokens}}
in the body, i.e. request tokens. - The body uses URL encoding, indicated by the
&
and=
delimiters. - You must URL-encode tokens in a URL-encoded body.
This webhook setup instantly breaks with a Company like Jack & Jill Construction
. It’s kind of inconceivable that they tested it at all.
Moreover, when you actually set up a webhook receiver in the Clay app, it says the payload is supposed to be JSON-encoded, not URL-encoded! So their doc feels like a hallucination. You should actually be using a payload like this:
{
"first_name" : {{lead.First Name}},
"last_name" : {{lead.Last Name}}
}
And of course set Request Token Encoding: JSON.
Why would you ever use Request Token Encoding: None?
In 2 rare cases, None is correct:
- When all fields in your payload — can’t just be a subset — are already JSON- or URL-encoded. In practice, this usually means the payload is a single field written via API, designed for sending as-is.
For example, you might store a complete JSON object with properties and child objects in a Textarea, and the data is intended to have that same shape on the remote server. If you let Marketo encode{{lead.Big JSON Object}}
again, that won’t work: it’ll be one giant string. - Even more rare is when the remote service expects text/plain payloads. Usually these are old internal services to which you send values like
1;NOT PROVIDED;TRUE
(that's the entire payload!).
You don't want to encode the 3 tokens that comprise that payload: it either becomes1;NOT+PROVIDED;TRUE
(URL) or1;"NOT PROVIDED";"TRUE"
(JSON) which aren't the same.
In both of these cases, something non-standard is happening and you should push back on the requester to explain the reason.
P.S. Tokens in the URL are always URL-encoded, even with None (but pretend you don’t know that)
An undocumented quirk is when the URL, not the request body, contains tokens:
https://hooks.example.com/123?first_name={{lead.First Name}}&last_name={{lead.Last Name]}
Those tokens are always URL-encoded, regardless of the Request Token Encoding setting. This is fine! But it’s confusing because the URL is undoubtedly part of the request: Request Token Encoding should be read as Request Body Token Encoding.
So be careful not to rest on whether a webhook “works” using GET. When the service switches to POST in a few months and you move those tokens to the body, it’ll break unless you have Request Token Encoding: Form/URL.