Outbound REST GET Suddenly Returns 400 From An Unencoded Value In A Built URL
What does "from returned HTTP status: 400 <!DOCTYPE html>" mean in Workday REST API?
An outbound REST call that has run cleanly for months starts returning a 400 with a generic HTML error page instead of a normal API response. Nothing changed in your integration and the vendor says nothing changed on their side. The usual cause is that a value being substituted into the URL has started containing a character that needs percent-encoding, and the code building that URL never encoded it.
Quick fix
Log the resolved URL for one failing record, paste it into a REST client to confirm it reproduces the 400, then URL-encode every value substituted into the URL and retry.
Permanent fix
URL-encode substituted values as the default when building any URL dynamically, rather than adding encoding only after a character breaks a call. Log the resolved URL whenever an outbound call fails, because an integration that has run for months will eventually meet a record whose data has a shape earlier records did not, and without that log the failure looks like an unexplained vendor outage.
Troubleshooting
- Notice that the body is an HTML page, not JSON or XML. That means a web server or proxy rejected the request before the API ever saw it, which points at the request line rather than at your payload or credentials.
- Establish whether it fails for every record or only some. Failing on a subset is the strongest possible signal that the data, not the configuration, is what changed.
- Take one failing record and one succeeding record and diff the values that get substituted into the URL. Look for spaces, ampersands, plus signs, hashes, percent signs, commas, and accented characters.
- Log the fully resolved URL for a failing record. If the URL is built from an expression, the configured expression tells you nothing useful on its own.
- Paste that exact resolved URL into a REST client. If it reproduces the 400 there, you have confirmed the URL itself is the problem and can stop investigating your integration's plumbing.
- Wrap every substituted value in URL encoding at the point the URL is built, then retry the same record.
- Do not spend time overriding Host, Accept, or Content-Type headers by hand. These are set from the URL and from the message being sent, and forcing them rarely changes anything while hiding the real cause.