0

I am trying to call an external API (https://api.fortnox.se/3/customers/2) from an Excel on web.

The Web API I am calling returns a jason data structure such as the "Response" under "Retrieve a customer" session here: https://developer.fortnox.se/documentation/resources/customers/

Response data structure:

{
    "Customer": {
        "@url": "https://api.fortnox.se/3/customers/102",
        "Active": true,
        "Address1": "Halltorpsgatan",
        "Address2": null,
        "City": "KLIPPAN",
        "Comments": null,
        "CostCenter": null,
        "Country": "Sverige",
        "CountryCode": "SE",
        "Currency": "SEK",
        "CustomerNumber": "102",
        "DefaultDeliveryTypes": {
            "Invoice": "PRINT",
            "Offer": "PRINT",
            "Order": "PRINT"
        },
        "DefaultTemplates": {
            "CashInvoice": "DEFAULTTEMPLATE",
            "Invoice": "DEFAULTTEMPLATE",
            "Offer": "DEFAULTTEMPLATE",
            "Order": "DEFAULTTEMPLATE"
        },
        "DeliveryAddress1": null,
        "DeliveryAddress2": null,
        "DeliveryCity": null,
        "DeliveryCountry": null,
        "DeliveryCountryCode": null,
        "DeliveryFax": null,
        "DeliveryName": null,
        "DeliveryPhone1": null,
        "DeliveryPhone2": null,
        "DeliveryZipCode": null,
        "Email": "a.s@example.com",
        "EmailInvoice": "a.s@example.com",
        "EmailInvoiceBCC": "",
        "EmailInvoiceCC": "",
        "EmailOffer": "a.s@example.com",
        "EmailOfferBCC": "",
        "EmailOfferCC": "",
        "EmailOrder": "a.s@example.com",
        "EmailOrderBCC": "",
        "EmailOrderCC": "",
        "Fax": null,
        "GLN": null,
        "GLNDelivery": null,
        "InvoiceAdministrationFee": null,
        "InvoiceDiscount": null,
        "InvoiceFreight": null,
        "InvoiceRemark": "",
        "Name": "Anders Svensson",
        "OrganisationNumber": "",
        "OurReference": "",
        "Phone1": "0435-9249236",
        "Phone2": null,
        "PriceList": "A",
        "Project": "",
        "SalesAccount": null,
        "ShowPriceVATIncluded": false,
        "TermsOfDelivery": "",
        "TermsOfPayment": "",
        "Type": "PRIVATE",
        "VATNumber": "",
        "VATType": "SEVAT",
        "VisitingAddress": null,
        "VisitingCity": null,
        "VisitingCountry": null,
        "VisitingCountryCode": null,
        "VisitingZipCode": null,
        "WWW": "",
        "WayOfDelivery": "",
        "YourReference": "",
        "ZipCode": "264 32"
    }
}

Inspired by the Stackoverflow post here: Fetch error on Office Script (Excel on web) I wrote the following code:

interface aCustomer {
  Customer: CustomerClass;
}

interface CustomerClass {
  Address1: string;
  Country: string;
}

async function main(workbook: ExcelScript.Workbook): Promise<void> {
  let response = await fetch("https://api.fortnox.se/3/customers/2", {
    method: "GET",
    mode: "no-cors",
    headers: {
      "Access-Token": "XXXX",
      "Client-Secret": "XXXX",
      "Content-Type": "application/json",
      "Accept": "application/json"
    }
  });
  let customer2: aCustomer = await response.json();
  console.log(customer2);
}

But when I ran it kept throwing the error: "Line 21: Unexpected end of input"

Line 21: let customer2: Customer = await response.json()

I guess I have defined a wrong interface, or otherwise any idea what the problem might be? Thanks!

Max
  • 1
  • 1
  • 1
    Does this answer your question? [fetch() unexpected end of input](https://stackoverflow.com/questions/45696999/fetch-unexpected-end-of-input) – Nishant Apr 05 '21 at 07:24
  • Type definitions are not yet a problem. I guess your data fetching has problem. Have a look at the link I mentioned – Nishant Apr 05 '21 at 07:25
  • Thanks @Nishant. Do you mean that I should not use 'no-cors' mode in the fetch() method? Though when I tried without "mode: 'no-cors' ", then it "Failed to fetch" on Line 11 "let response = await fetch("https://api.fortnox.se/3/customers/"... Any ideas how I could solve it? Thanks! – Max Apr 05 '21 at 11:48
  • @Max - did you ever get an example working? I'm struggling with this as well – swv Aug 28 '21 at 18:36

2 Answers2

1

It seems the API you're trying to use is most likely provided to be consumed by either a desktop client application or server application, but not directly from client side JavaScript within a browser (where CORS might become an issue).

A possible workaround is to use a "Fetch Proxy". In short, it is a simple web server that passes along your original requests to the target API and sends back the responses to your client side JavaScript. This could work since there won't be CORS problem between this Fetch Proxy server and the target API (server-to-server communication) and at the same time this Fetch Proxy server is configured to allow CORS from your client side JavaScript.

You can build and host your own Fetch Proxy server or you can try some existing ones. But if you care about data privacy or performance, you probably want to build and host your own. This Stack Overflow post was particularly talking about one of the existing popular Fetch Proxy server implementation ("CORS Anywhere").

And this article also has some good explanation on this CORS issue and the Fetch Proxy idea.

Yutao Huang
  • 1,503
  • 1
  • 13
  • 25
0

Referring to the example code in https://learn.microsoft.com/en-us/office/dev/scripts/resources/samples/external-fetch-calls I think all you need to do is add a question mark symbol like this to your aCustomer interface:

interface aCustomer {
  Customer?: CustomerClass;
}
  • Please summarize links you share in order to avoid link rot. – robere2 Jul 10 '22 at 17:09
  • What do you mean? You are asking me to write a short summary of the contents of the URL? If so, the context of the URL, in this post, already makes it clear that the URL is referring to the problem being addressed/resolved here. That is, in this case, it is in response to and about "Interface error on Office Script (Excel on Web)". My reply is specific to using "interfaces". That means the URL is about that. So, there is ample information, here, that not only gives context to the URL but explains it. By "rot" do you mean "a broken link"? It is not a technical term I recognise. – MrAnalyticals Jul 11 '22 at 17:53