def composite_request(self, data):
        """Call a 'composite' request with subrequests, error handling

        A fake object for request/response is created for a subrequest in case
        of error, to be possible to use the same error hanler with a clear
        message as with an individual request.
        """
        post_data = {'compositeRequest': data, 'allOrNone': True}
        resp = self.handle_api_exceptions('POST', 'composite', json=post_data)
        comp_resp = resp.json()['compositeResponse']
        is_ok = all(x['httpStatusCode'] < 400 for x in comp_resp)
        if is_ok:
            return resp

        # construct an equivalent of individual bad request/response
        bad_responses = {
            i: x for i, x in enumerate(comp_resp)
            if not (x['httpStatusCode'] == 400
                    and x['body'][0]['errorCode'] in ('PROCESSING_HALTED', 'ALL_OR_NONE_OPERATION_ROLLED_BACK'))
        }
        if len(bad_responses) != 1:
            raise InternalError("Too much or too many subrequests with an individual error")
        bad_i, bad_response = bad_responses.popitem()
        bad_request = data[bad_i]

        bad_req = FakeReq(bad_request['method'], bad_request['url'], bad_request.get('body'),
                          bad_request.get('httpHeaders', {}), context={bad_i: bad_request['referenceId']})

        body = [merge_dict(x, referenceId=bad_response['referenceId'])
                for x in bad_response['body']]
        bad_resp_headers = bad_response['httpHeaders'].copy()
        bad_resp_headers.update({'Content-Type': resp.headers['Content-Type']})

        bad_resp = FakeResp(bad_response['httpStatusCode'], json.dumps(body), bad_req, bad_resp_headers)

        self.raise_errors(bad_resp)
Call a 'composite' request with subrequests, error handling

        A fake object for request/response is created for a subrequest in case
        of error, to be possible to use the same error hanler with a clear
        message as with an individual request.