There are a couple ways to get around issues like this, if you want two slightly different requests to return the same response (i.e. the requests differ only by an API key GET param) the quickest and easiest solution is to customize varnish's definition of uniqueness using the hash_data function in vcl_hash. You just strip out all url elements that don't contribute toward making the response distinct and hash that. For example, if the url contains "access_token", strip all GET params out of the hash key:
sub vcl_hash {
if (req.url ~ "access_token"){
set req.url = regsub(req.url, "^https?://(.*)\?access_token=.*$","\1");
}
hash_data(req.url);
}
In other words this would cache mydomain.com/some/restful/request?access_token=abc and mydomain.com/some/restful/request?access_token=def as a match.
If the response is mostly the same with small areas that should be unique (i.e. one value in a large JSON response, or a div in the header that says "Welcome Username!"), you can use edge side includes. The catch, of course, is that this requires customization to what the backend returns.