How to determine whether to use query parameters or body in GET requests when integrating with different APIs?

I am working with two different APIs, both using GET requests but handling request data differently:

  1. API 1 requires the data to be sent in the request body, even though the HTTP method is GET.
    Example:

    $config = [
        'method' => 'GET',
        'url' => 'http://example.com/api/endpoint',
        'headers' => [
            'Content-Type' => 'application/json',
        ],
        'body' => [
            'key1' => 'value1',
            'key2' => 'value2',
        ],
    ];
    
  2. API 2 requires the data to be sent as query parameters in the URL.
    Example:

    $config = [
        'method' => 'GET',
        'url' => 'http://example.com/api/endpoint',
        'headers' => [
            'Content-Type' => 'application/json',
        ],
        'query' => [
            'key1' => 'value1',
            'key2' => 'value2',
        ],
    ];
    

Both APIs work with the GET method, but their requirements for passing data are different. This makes it challenging to decide when to use query parameters and when to use the request body for a GET request.

Questions:

  1. How can I determine whether to use query parameters (query) or the request body (body) for a GET request?
  2. Is it common or correct for a GET request to accept data in the body, even though the HTTP specification discourages it?
  3. How can I design a generic HTTP client (e.g., using Guzzle) to handle these differences dynamically based on the API’s requirements?

Any guidance, best practices, or examples would be appreciated!

 $options = ['headers' => $request['headers']];

        if ($request['method'] === 'GET') {
            if ($request['isRequestRawBody']) {
                $options['body'] = json_encode($request['body']);
            } else {
                $options['query'] = $request['body'];
            }
        } else {
            $contentType = $request['headers']['Content-Type'] ?? '';

            switch ($contentType) {
                case 'application/x-www-form-urlencoded':
                    $options['form_params'] = $request['body'];
                    break;
                case 'application/json':
                    $options['json'] = $request['body'];
                    break;
                case 'multipart/form-data':
                    $options['multipart'] = array_map(function ($key, $value) {
                        return ['name' => $key, 'contents' => $value];
                    }, array_keys($request['body']), $request['body']);
                    break;
                default:
                    $options['body'] = $request['body'];
            }
        }

        return $options;