Javascript: Getting Started

Hi I’m very new to this and as part of my learning process I’m starting from the ground up in order to give myself the best understanding of connecting to this API.

I’ve trawled through Google but have hit a wall.

I found this post in the forum with a really helpful snippet of JS using fetch which I feel is a good starting point:

var url = 'https://api.companieshouse.gov.uk/company/12345678';
var key = 'MyAPIKey';
var headers = new Headers ({
  'Authorization': 'Basic ' + btoa(key),
  'Content-Type': 'text/json'
});
var obj = {
  mode: 'no-cors',
  method: 'GET',
  headers: headers
};
fetch(url, obj)
.then((resp) => resp.json())
.then(data => console.log(data))
.then(function(res) {
  return res.json();
})
.then(function(res) {
  console.log(res);
})
.catch(function(err) {
  console.log(err);
});

I’m this with my API key trying both CORS and NO-CORS but returning only this error:

GET https://api.companieshouse.gov.uk/company net::ERR_ABORTED 401
  (anonymous) @ VM15:12
SyntaxError: Unexpected end of input
  at <anonymous>:13:22

I’ve also tried embedding into my page ensuring that I have registered the appropriate JS domains but get a similar 401 error.

Any assistance or advice would be appreciated.

EDIT: Added company number to code snippet

Welcome. The lines you show:

GET https://api.companieshouse.gov.uk/company net::ERR_ABORTED 401

(That’s a 401 unauthorized error) … which suggests that either there was something wrong with your API key (or the whole of the Authorization header) OR you were calling the API from a IP address you haven’t registered with them. (You might get a 403 response in that case though.)

If you’ve registered an IP address when you signed up but were using localhost as a development server you should check the following workaround:

SyntaxError: Unexpected end of input

…is obviously because your code is trying to parse a stream as json but there is no (JSON) body in this case - you might want to trap that.

After you’ve resolved that part, probably the next place to start would be the documentation of the API:

You’re calling the company profile endpoint. The documentation for company profile shows you that you need to send in a company number. (The documentation could possibly be improved with a worked example - but it has a live “try it out” feature…).

So try the following at the start of your code:

var compprofile = 'https://api.companieshouse.gov.uk/company/';
// Company "numbers" are strings, currently always 8 characters.  Leading zeros are significant. 
var company = '00048839'; // barclays bank
var url = compprofile + company;
//  Your API key goes below
// (as per the example thread post you mentioned you need a colon after that
// e.g. 'MyAPIKey2843298:')
var key = '.........'; 
...

You should get something like the json below:

{
    "jurisdiction": "england-wales",
    "undeliverable_registered_office_address": false,
    "last_full_members_list_date": "2012-08-31",
    "accounts": {
        "next_made_up_to": "2020-12-31",
        "overdue": false,
        "next_due": "2021-06-30",
        "last_accounts": {
            "made_up_to": "2019-12-31",
            "period_end_on": "2019-12-31",
            "type": "group",
            "period_start_on": "2019-01-01"
        },
        "accounting_reference_date": {
            "month": "12",
            "day": "31"
        },
        "next_accounts": {
            "period_start_on": "2020-01-01",
            "overdue": false,
            "period_end_on": "2020-12-31",
            "due_on": "2021-06-30"
        }
    },
    "registered_office_address": {
        "postal_code": "E14 5HP",
        "locality": "London",
        "address_line_1": "1 Churchill Place"
    },
    "company_number": "00048839",
    "company_name": "BARCLAYS PLC",
    "type": "plc",
    "has_been_liquidated": false,
    "date_of_creation": "1896-07-20",
    "sic_codes": [
        "64110",
        "70100"
    ],
    "etag": "48a27160106b9459983d0a1473726bd7e3028b53",
    "company_status": "active",
    "has_insolvency_history": false,
    "previous_company_names": [
        {
            "effective_from": "1896-07-20",
            "name": "BARCLAYS BANK PLC",
            "ceased_on": "1985-01-01"
        }
    ],
    "has_charges": false,
    "confirmation_statement": {
        "next_due": "2021-04-15",
        "next_made_up_to": "2021-04-01",
        "last_made_up_to": "2020-04-01",
        "overdue": false
    },
    "links": {
        "self": "/company/00048839",
        "filing_history": "/company/00048839/filing-history",
        "officers": "/company/00048839/officers",
        "exemptions": "/company/00048839/exemptions"
    },
    "registered_office_is_in_dispute": false,
    "can_file": true
}

Good luck.

1 Like

Thank you so much for the detailed response. I did include the company number with my test but omitted it from the snippet (have edited my post with a dummy number to avoid further misdirection).

Reading through the information you’ve provided now. Thanks again.

@voracityemail So as mentioned I have updated my hosts file with:

127.0.0.1	application.com

and added https://application.com & http://application.com to my JS domains in my API settings. I’ve also added a couple of extra options to my fetch:

cache: "no-cache",
credentials: "include",

My error has changed slightly.

Error with mode: 'cors’

Access to fetch at 'https://api.companieshouse.gov.uk/company/12345678' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
VM39:14 GET https://api.companieshouse.gov.uk/company/12345678 net::ERR_FAILED
(anonymous) @ VM39:14
VM39:24 TypeError: Failed to fetch

Error with mode: 'no-cors’

GET https://api.companieshouse.gov.uk/company/12345678 net::ERR_ABORTED 401
(anonymous) @ VM45:14
VM45:24 SyntaxError: Unexpected end of input
    at <anonymous>:15:22

Are you able to assist further?

I’m not 100% sure as I don’t personally use javascript to access this - all I can do is point to the other stuff on the forum:

  • I think you need use CORS (not the ‘no-cors’ - I believe CORS is the default mode but check that).
  • If you’re getting a 403 I think the issue is the domain (server) you’re making the request from is not being seen as matching one of the “Javascript domain” entries you set up in your registration. As mentioned before, if you’re on localhost there’s a hack to get around that. If not check what ports your server uses. If you’re not using 80 (for http) or 443 (for https) I think you need to specify the port somehow. Looking around the forum it seems it’s possible to add this to the JavaScript domains.
  • A good thread on this - and helpful comment - was this:

You could try using one of the jQuery examples around the forum to check if that works, then go back and make fetch() work.

Most browsers will allow you to debug this sort of thing in detail by logging network requests. This is certainly possible with Opera and Firefox out of the box and presumably Chrome too. If you switch logging on (generally in a “developer tools” section) you should be able to see the CORS process in detail. (You shouldn’t need to delve too deep since javascript / the browser should now handle all of this complexity for you in a routine manner but you might spot something here.) First you should see the browser making an http OPTIONS request. It should be possible - normally a context menu - to view or copy request or response headers, the request or response (body) or the whole lot (“copy all as HAR”). As mentioned above, what you’re looking for in your request is the “Origin” parameter. The response from the Companies House server will contain an “Access-Control-Allow-Origin” entry. If this is “*” (for everything) I think this indicates that the next step will fail for you e.g. where the browser sends the actual GET request with the Authorization header with your API key. You should see your actual specific domain there.

If you can get past that, if things are still not working again check the details, but if you’ve got a 401 error then that points to an issue with the http basic authorisation, normally due to not putting a ‘:’ after your api key, failing to run that whole string through a base64 encoding step (e.g. btoa() in javascript) or just getting the API key wrong.

1 Like

@voracityemail I want to thank you for your help, patience and time invested in your responses. I was panicking because of time pressure hence the lazy requests but once I slowed down and did some reading I managed to find the solution. I needed to add an origin in the header. This snippet now returns the company information I need:

var url = 'https://api.companieshouse.gov.uk/company/12345678';
var key = 'MyApiKey';
var headers = new Headers ({
  'Authorization': 'Basic ' + btoa(key),
  'Content-Type': 'text/json',
  'Origin': 'MyOriginUrl'
});
var obj = {
  mode: 'cors',
  method: 'GET',
  cache: 'no-cache',
  headers: headers
};
fetch(url, obj)
.then((resp) => resp.json())
.then(data => console.log(data))
.catch(function(err) {
  console.log(err);
});

Thanks again! I could not have done it without you! :blush:

1 Like

You’re welcome - we may need to use this in the future so it’s useful to have a simple correct example.

Just one thing I’m not sure about. I’m not sure why manually setting the Origin header makes the difference. From the docs - which as far as I can see apply to both basic javascript xhr and the fetch interface (the latter isn’t spelled out though):

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#The_HTTP_request_headers

Note that these headers are set for you when making invocations to servers. Developers using cross-site XMLHttpRequest capability do not have to set any cross-origin sharing request headers programmatically.

… and later:

Note that in any access control request, the Origin header is always sent.

Glad it’s working for you anyway.

1 Like