Query works in Sandbox but not live

A query to find recurring invoices for a specified client is proving problematic - and just when everything else was proceeding so well. The query works in the sandbox, but when run from our application I get the following message.

Client error: POST https://api.quickfile.co.uk/Invoice/Search resulted in a 400 Bad Request response: {“Errors”:{“Error”:["19The element ‘SearchParameters’ in namespace ‘https://api.quickfile.co.uk’ has invalid child eleme (truncated…)

By way of diagnosis I put a breakpoint in the code to display the json code on the screen which I could then cut and paste into the sandbox. Sure enough, the pasted code in the sandbox works.

Also for diagnostics, I used a known ClientID that would return a result

The code works from the application. I know that there is something really obvious that I have missed which is laughing at me - but I cannot see it at the moment. Any advice would be appreciated.

The code that creates the calling parameters is as follows:

    function getRecurrringInvoice($credentials, $ClientID) {
        $request['payload']['Header'] = [
            'MessageType' => "Request",
            'SubmissionNumber' => $credentials['SubmissionNumber']
        ];
        $request['payload']['Header']['Authentication'] = [
            'AccNumber' => $credentials['AccNumber'],
            'MD5Value' => $credentials['MD5Value'],
            'ApplicationID' => $credentials['ApplicationID']
        ];
            $request['payload']['Body']['SearchParameters'] = [
            'ReturnCount' => 200,
            'Offset' => 0,
            'OrderResultsBy' => 'InvoiceNumber',
            'OrderDirection' => 'ASC',
            'InvoiceType' => 'RECURRING',
            'ShowDeleted' => false
        ];

The above code works fine in the application, but fails when I add this section below. However, when I paste the json code into the sandbox from the 'echo statement, the sandbox returns the expected result

        $request['payload']['Body']['SearchParameters']['ClientDetails'] = [
    //          'ClientID' => $ClientID
                'ClientID' =>    known good account number for testing
        ];
        echo json_encode($request, JSON_PRETTY_PRINT); DIE(); // only for debugging
        return $request;
    }

That endpoint URL looks suspect - you should be posting to https://api.quickfile.co.uk/1_2/invoice/search including the 1_2 version number. I suspect the URL you’re using without a version number is an earlier version of the API spec with a slightly different schema.

Hi Ian
Thank you for the response.
That is the URL that I am posting to. The query works successfully without the additional following element:

    $request['payload']['Body']['SearchParameters']['ClientDetails'] = [
      'ClientID' => $ClientID
];

added to the array, where client ID is a validated client number.

With all the API scripts that I have, requests are passed to a function, along with the method required ‘invoice/search’ in this case in a parameter $searchType. An extract of that function is :

        public function callAPI($request, $searchType) {
    $guzzleClient = new GuzzleHttp\Client(["base_uri" => "https://api.quickfile.co.uk/1_2"]);

    try {
        $result = $guzzleClient->post( $searchType, ["json" => $request]);
`....etc`

What’s got me scratching my head is that if I put breakpoint in the code and convert the array to JSON, I can paste this into the sandbox and all works well.

I’m not entirely sure how guzzle (or php in general) handles URLs but according to the official URI specification, if you start from a base URI of

https://api.quickfile.co.uk/1_2

and resolve a relative path of

invoice/search

then the resulting absolute URI is

https://api.quickfile.co.uk/invoice/search

without the 1_2, and that is what your original error message suggests you’re posting to. To make it include the 1_2 in the resolved result the base URI needs a trailing slash

https://api.quickfile.co.uk/1_2/

This has caught me out many times in other programming languages. Without the slash the spec treats 1_2 as a file name in the root directory / of api.quickfile.co.uk, and resolves relative paths against that directory. With the slash, 1_2 is the base directory.

1 Like

Hi @Mike

As @ian_roberts mentions, with Guzzle you would need to set the base path with the trailing slash. Like Ian, this has caught me out before now too.

There’s a bit more details in the Guzzle docs:
http://docs.guzzlephp.org/en/stable/quickstart.html#creating-a-client

Well I’ll be a monkeys uncle!

Given that all requests go to exactly the same handler on my system, and that all existing calls so far have worked, I was not expecting putting in the trailing slash to make the least difference and even to possibly break it.

BUT it now works. Many thanks @ian_roberts and @QFMathew

2 Likes

Great. I guess everything you’ve tried so far has been things that were allowed by the original v1 schema, and this is the first case where the version number was critical.

This topic was automatically closed after 14 days. New replies are no longer allowed.