A large part of the reason that many APIs fail at content negotiation has to do with the fact that many clients don't support it properly. Chrome in particular completely ignores the Vary header (and its devs have marked the issue as "won't fix"), so it's not practical to have the same URL respond with different media types based on the Accepts header (it overwrites the cached item, so the back button doesn't work properly). Many APIs compensate for this by putting the format in a query parameter.