Getting 400 (Bad Request) API

Hi,
I am currently moving away from XML to be using the JSON endpoints on your api and I found an issue.

When I try to create a new client I have a (400) Bad Request returned from your endpoint.
I’ve tried to use the API sandbox which seems to work with the same Json request I have.

Can you help?
This is the Json I am sending on the request. (Obscured personal details)

{
"payload": {
    "Header": {
        "MessageType": "Request",
        "SubmissionNumber": "subnumber",
        "Authentication": {
            "AccNumber": "accountnumber",
            "MD5Value": "generatedmd5",
            "ApplicationID": "appID"
        }
    },
    "Body": {
        "ClientDetails": {
            "CompanyName": "TESTING"
        },
        "ClientContacts": {
            "DefaultContact": {
                "FirstName": "firstname",
                "Surname": "lastname",
                "TelephoneNumbers": {
                    "Telephone": []
                },
                "Email": "email@emai.com",
                "Password": "password"
            }
        }
    }
}

}

Is there anything in the 400 response body giving a more detailed error message?

No, just have a 400 error.

Without seeing the code that you’re using to send the request it could be a number of things, e.g. the wrong Content-Type header, reusing the same SubmissionNumber from a previous request, a problem in exactly how you’ve computed the MD5 signature, etc. etc. There should be some sort of body to the 400 response giving more details but how you access the body in error cases is another thing that varies depending on which HTTP request library you’re using.

Hi @APereira

I’ve tested the code above and it works fine on my end. It may be, as @ian_roberts suggested, one of the values that you’ve blocked out relating to the authentication.

@ian_roberts @QFMathew
Thanks for your responses.

As it posts the value I do not see it, I just know the code generated is that one.

Would it be possible for you to have a look at my account requests log?

When I tested by sending it through the sandbox it worked fine as well.

if I have any kind of authentication failure it will give me a 400 error?

Again, if you want us to be able to help you debug you will have to share the code you are using to call the API, in whatever language that is written. There should be some way to extract the error message from the 400 response, or at the very least a way to enable wire-level logging so you can see what your code is sending and receiving, but exactly how you do that depends what language and library you’re using.

Sorry I read it in a rush and for some reason thought you were asking me for the submission number.

here we go.

        private string EndPoint(string QfEndPoint) { return "https://api.quickfile.co.uk/1_2/" + QfEndPoint; }

    private string RequestHeader(string PartnerUID)
    {
        var _context = new MearHelpdeskContext();
        var PartnerDetails = _context.MtPartners.Where(s => s.PartnerUid == PartnerUID).FirstOrDefault();
        string SubmitionID = Guid.NewGuid().ToString();
        string result = "{\"payload\": { \"Header\": { \"MessageType\": \"Request\", \"SubmissionNumber\": \"[IDSUBMITION]\",\"Authentication\": {\"AccNumber\": \"[ACCOUNTNUMBER]\",\"MD5Value\": \"[MD5]\",\"ApplicationID\": \"[APPID]\"}},";
        result = result.Replace("[ACCOUNTNUMBER]", PartnerDetails.QuickfileAccountno);
        result = result.Replace("[APPID]", PartnerDetails.QuickfileapiAppId);

        result = result.Replace("[IDSUBMITION]", SubmitionID);
        result = result.Replace("[MD5]", MD5Key(PartnerUID, SubmitionID));
        return result;
    }

    private string MD5Key(string PartnerUID, string SubmitionID)
    {
        var _context = new MearHelpdeskContext();
        var PartnerDetails = _context.MtPartners.Where(s => s.PartnerUid == PartnerUID).FirstOrDefault();

        string ConnectedData = PartnerDetails.QuickfileAccountno + PartnerDetails.QuickfileapiKey + SubmitionID;
        MD5 md5 = MD5.Create();
        byte[] inputBytes = Encoding.ASCII.GetBytes(ConnectedData); byte[] hash = md5.ComputeHash(inputBytes);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < hash.Length; i++) { sb.Append(hash[i].ToString("X2")); }
        return sb.ToString().ToLower();
    }

    private string CommonRequest(string PartnerUID, string JsonRequest, string QfEndPoint)
    {
        // Get PartnerDetails
        var _context = new MearHelpdeskContext();
        var PartnerDetails = _context.MtPartners.Where(s => s.PartnerUid == PartnerUID).FirstOrDefault();

        var request = (HttpWebRequest)WebRequest.Create(new Uri(EndPoint(QfEndPoint)));
        request.Method = "POST";
        request.ContentType = "application/json";
        request.KeepAlive = false;
        request.Accept = "application/json";
        StreamWriter writer = new StreamWriter(request.GetRequestStream());

        writer.WriteLine(JsonRequest);
        writer.Close();
        WebResponse response = default(WebResponse);
        response = request.GetResponse();
        StreamReader sr = new StreamReader(response.GetResponseStream());
        string JsonStringResponse = sr.ReadToEnd();
        return JsonStringResponse;
    }

calling function as

CommonRequest(PartnerUID, QuickfileJsonRequest, “client/create”)

OK, so you need to wrap everything from the WebRequest.create to the end of the CommonRequest method in a try block as you will get a WebException thrown when the server responds with 400. If you catch that exception then the exception itself provides access to the response body, which should include the actual error message.

A bit of additional advice though - it’s far too easy to introduce syntax errors when you construct JSON by hand with string concatenation, I strongly recommend you use System.Text.Json or similar.

1 Like

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