Power Automate and Business Central

Power Automate has Business Central connectors, however, they are very limited. What Power Automate does not have are connectors to Business Central for the Web Services. You can locate these web services in Business Central under Web Services.

Services listed under Web Services in Business Central

So how can you get access to the Web Services in Power Automate? Not that easy. But I figured it out with some sleuthing and piecing things together. This is a multi-step process and if you do not have admin rights to Azure/Business Central, you may need to contact your IT department to get them.

So the steps (read difficulties) I ran into getting this to work are the following:

  1. You need to authenticate against Business Central (Microsoft) using oAuth2.0 and get a bearer token
  2. You use the bearer token to call the web service that you need
  3. You get a JSON response
  4. You need to fiddle with the response and the Parse JSON did not work properly for me so I did need to MacGyver some of it
  5. You get variables and you can use them anywhere, in my case, I just wanted to populate an Excel table

Here is what I did:

  1. oAuth2.0 and Power Automate
  • Now click on API permissions and make sure these permissions are added. So click on Add a permission and on the next screen select Microsoft APIs and look for Business Central. Select Business Central and then select DELEGATED PERMISSIONS. I selected app_access/Automation.ReadWrite.All/user_impersonation. I do not believe that you need to Financials.ReadWrite.All.
  • After you are done that, you need to add another permission but this time, you need to choose Microsoft Graph. The select Delegated Permission and then add USER.READ.
  • After you have done all that Don’t forget to GRANT ADMIN CONSENT after you add it!
  • Click on the Overview tab, and make a note of the Client ID and Tenant ID. We will need those in a bit.

Now, go to Power Automate where we will create the create the steps required to access Business Central

  • This is a fairly simple process and here is the Power Automate steps that we will require:
  • Initialize a variable and assign it a name Username or UN. It is a STRING variable and paste the CLIENT ID that you got from Azure into the value field.
  • Initialize another variable and assign it a name Password or PW. It is also a STRING variable and paste the SECRET (password) that you got from Azure into the value field
  • Add a new step using COMPOSE. Add this line into the Expression (with all the quotes, but replace XXXX with the Client ID from above and YYYY with the Secret (password) from above:
  • Now add an HTTP step
    • Under HEADERS add Content-Type as a key and assign this to the value: application/x-www-form-urlencoded
    • Under QUERIES add client_id and client_secret as keys, and assign the values we got from above into them
    • Under BODY put in the output from the COMPOSE step
    • Now click on ADVANCED OPTIONS and use Authentication: BASIC and put in the username and password variables into username and password
  • Add a new step and choose PARSE JSON. Use the Body from the previous step and use this as the schema:
{
    "type": "object",
    "properties": {
        "token_type": {
            "type": "string"
        },
        "expires_in": {
            "type": "integer"
        },
        "ext_expires_in": {
            "type": "integer"
        },
        "access_token": {
            "type": "string"
        }
    }
}
  • Add a new step HTTP again
    • This time use GET as the Method
    • the URI comes from the Business Central Web Services APIv2.0. Generally, the calls look like this (where xxxx is your tenant ID / cccc is your company name from business central / dddd is the webservice name that you gave: https://api.businesscentral.dynamics.com/v2.0/xxxx/Production/ODataV4/Company(‘cccc’)/dddd
    • Under HEADERS add 3 keys and assign these values:
      • Content-Type value to assign application/json
      • Authorization value to assign Bearer and choose the variable “access token” from our previous step
      • Accept: value to assign odata=nometadata
    • Under ADVANCED OPTIONS, choose None for authentication
  • The step above will return the information to you in a JSON format. In my case, I got the CUSTOMER CARD information from Business Central (this is Page 21)
  • Add another step and use the Parse JSON function. Use the Body from the HTTP request above under CONTENT. Use this as the schema (note you may have additional fields for your customization):
{
    "body": {
        "type": "object",
        "properties": {
            "@@odata.context": {
                "type": "string"
            },
            "value": {
                "type": "array",
                "items": {
                    "type": "object",
                    "properties": {
                        "@@odata.etag": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "No": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Name": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Name_2": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Search_Name": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "IC_Partner_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Balance_LCY": {
                            "type": "integer"
                        },
                        "Balance_Due_LCY": {
                            "type": "integer"
                        },
                        "Credit_Limit_LCY": {
                            "type": "integer"
                        },
                        "Blocked": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Privacy_Blocked": {
                            "type": "boolean"
                        },
                        "Salesperson_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Responsibility_Center": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Service_Zone_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Document_Sending_Profile": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "TotalSales2": {
                            "type": "integer"
                        },
                        "CustSalesLCY_CustProfit_AdjmtCostLCY": {
                            "type": "integer"
                        },
                        "AdjCustProfit": {
                            "type": "integer"
                        },
                        "AdjProfitPct": {
                            "type": "integer"
                        },
                        "CFDI_Purpose": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "CFDI_Relation": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "CFDI_Export_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "SAT_Tax_Regime_Classification": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Last_Date_Modified": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Disable_Search_by_Name": {
                            "type": "boolean"
                        },
                        "Address": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Address_2": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Country_Region_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "City": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "County": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Post_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "ShowMap": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Phone_No": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "MobilePhoneNo": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "E_Mail": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Fax_No": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Home_Page": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Language_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Primary_Contact_No": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "ContactName": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Bill_to_Customer_No": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "VAT_Registration_No": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "EORI_Number": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "GLN": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Use_GLN_in_Electronic_Document": {
                            "type": "boolean"
                        },
                        "Copy_Sell_to_Addr_to_Qte_From": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Tax_Liable": {
                            "type": "boolean"
                        },
                        "Tax_Area_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Tax_Identification_Type": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Tax_Exemption_No": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "RFC_No": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "CURP_No": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "State_Inscription": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Gen_Bus_Posting_Group": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "VAT_Bus_Posting_Group": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Customer_Posting_Group": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Currency_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Price_Calculation_Method": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Customer_Price_Group": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Customer_Disc_Group": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Allow_Line_Disc": {
                            "type": "boolean"
                        },
                        "Invoice_Disc_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Prices_Including_VAT": {
                            "type": "boolean"
                        },
                        "Prepayment_Percent": {
                            "type": "integer"
                        },
                        "Application_Method": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Partner_Type": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Payment_Terms_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Payment_Method_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Reminder_Terms_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Fin_Charge_Terms_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Cash_Flow_Payment_Terms_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Print_Statements": {
                            "type": "boolean"
                        },
                        "Last_Statement_No": {
                            "type": "integer"
                        },
                        "Block_Payment_Tolerance": {
                            "type": "boolean"
                        },
                        "Preferred_Bank_Account_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Bank_Communication": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Check_Date_Format": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Check_Date_Separator": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Ship_to_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Location_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Combine_Shipments": {
                            "type": "boolean"
                        },
                        "Reserve": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Shipping_Advice": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Shipment_Method_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Shipping_Agent_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Shipping_Agent_Service_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Shipping_Time": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Base_Calendar_Code": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Customized_Calendar": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "ExpectedCustMoneyOwed": {
                            "type": "integer"
                        },
                        "TotalMoneyOwed": {
                            "type": "integer"
                        },
                        "CalcCreditLimitLCYExpendedPct": {
                            "type": "integer"
                        },
                        "Balance_Due": {
                            "type": "integer"
                        },
                        "Payments_LCY": {
                            "type": "integer"
                        },
                        "CustomerMgt_AvgDaysToPay_No": {
                            "type": "integer"
                        },
                        "DaysPaidPastDueDate": {
                            "type": "integer"
                        },
                        "AmountOnPostedInvoices": {
                            "type": "integer"
                        },
                        "AmountOnCrMemo": {
                            "type": "integer"
                        },
                        "AmountOnOutstandingInvoices": {
                            "type": "integer"
                        },
                        "AmountOnOutstandingCrMemos": {
                            "type": "integer"
                        },
                        "CustInvDiscAmountLCY": {
                            "type": "integer"
                        },
                        "Global_Dimension_1_Filter": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Global_Dimension_2_Filter": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Currency_Filter": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "Date_Filter": {
                            "type": [
                                "string",
                                "null"
                            ]
                        }
                    },
                    "required": []
                }
            }
        }
    }
}
  • Add a new step and initialize 1 variable for each field that you will require data for. In this case, we will just obtain the Name of the client. So initialize 1 variable and call it Name, type is STRING, and assign it any value for now
  • Add an Apply to Each step under SELECT AN OUTPUT FROM PREVIOUS STEPS I added this expression: outputs(‘Parse_JSON_DetailCustomer’)?[‘body’]?[‘value’]
  • Note that I called my Parse JSON step Parse JSON DetailCustomer so remember to add an underscore for all the spaces. You might have named that step something else, so replace the title of that step with yours. If you are at a loss, you can get the title just by looking at the Parse JSON step
  • Now assign the value to the variable by using the set variable step and using this expression: items(‘Apply_to_each’)?[‘Name’] Note that the Apply_to_each is the title for this step
  • Once you have assigned the variable, you can use it anywhere!

This entire process was frustrating on many levels. Microsoft documentation is about as good if it were written in an alien language (why is that?). There is great information about oAuth2.0 authentication (but only after spending hours looking) and not a great deal on Parse JSON. I ran into days of frustration when I kept on getting object not array errors, or null errors. In any event, this worked for me, and I hope it works for you.

Using Power Automate Service to Access Business Central Tables

If you are like me and do a lot of importing and sorting and just want data at your fingertips without having to go through Business Central, you like to have data either in SQL or in Excel. Why? Because you can do xlookups or other necessary evils when creating import tables with configuration packages or other automation.

So how do you go about getting the data into Excel? You can use PowerAutomate with Business Central.

I will show you the steps that I had to take to do this.

Step 1: Use the Business Central Connector in PowerAutomate and use the FIND RECORDS (V3). You will need to input the Environment Name (usually Production) and then the company name. Use the API v2.0, and for my case, I used the customers table.

Step 2: Add another step, APPLY TO EACH and use the output from the previous step. Choose the one that says VALUE (List of items). Then select EXCEL ONLINE BUSINESS > ADD A ROW INTO A TABLE and work your way through to the Excel file that you created for this. Remember, your data MUST sit in a table in Excel, so you have to formulate this first. Your flow should look like this, but your table may look different from mine.

Simply go through the different headers in your excel file and simply plop down the the data that you need for each one. You will have an excel file that looks like this in the end (I have obfuscated the confidential data)

Yet another Master Calendar Script for PowerBI

The Master Calendar is super important in PowerBI, especially if you want to run reports using relative dates or a series in time. Essentially all tables, should be linked to your master calendar via the date field.

This is what PowerBI looks like when the dates are all joined. You should use the date field to connect to other date fields. It is usually a 1 to many relationship.

Master Calendar

The Master Calendar is important, especially for financial reporting because you can create columns that indicate fiscal year, fiscal period, week number, year, year to date flags, next month, last twelve months and so forth. Here is a Master Calendar that I created:

This Master Calendar includes the day relative to today, month relative to today, day of the week in words, fiscal year (which is different from the calendar year), fiscal quarter, accounting period (as a number), week number (relative to the calendar), weekday or weekend and so forth.

The Master Calendar allows you to use slicers to filter out data automatically. This is very important when creating financial reports that are a point in time, such as the balance sheet vs income statement which is a period of time. It is exceptionally useful when running trial balance data. If you are short on time, you can just use the steps below to create the Master Calendar in PowerBI:

  • Click on NEW TABLE (name the table Master_Calendar)
  • Make sure you mark the table as a date table by clicking on DATE TABLE
  • Then start by adding this column
    • Your first column is a column of dates automatically generated by PowerBI:
DATE=(CALENDAR(START DATE,TODAY())
  • Note, you can add to the number of days beyond today() by simply putting a + and the number of days you want to go beyond today. Like this:
    • DATE=(CALENDAR(START DATE,TODAY()+30)
  • Then add the following each as a new column:

	1. DATE=(CALENDAR(START DATE,TODAY())

	2. Day_of_week = 

	3. Date relative to today = 1*([Date]-today())

	4. Day_of_week_name = IF('Date'[Day_of_week]=1,"Monday",IF('Date'[Day_of_week]=2,"Tuesday",IF('Date'[Day_of_week]=3,"Wednesday",IF('Date'[Day_of_week]=4,"Thursday",IF('Date'[Day_of_week]=5,"Friday",IF('Date'[Day_of_week]=6,"Saturday","Sunday"))))))

	5. Fiscal_Year = IF(MONTH([Date])>=8,YEAR([Date])+1,YEAR([Date]))

	6. Fiscal_Quarter = IF(AND(MONTH([Date])>=8,MONTH([Date])<=10),"Q1",IF(OR(MONTH([Date])>=11,MONTH([Date])<=1),"Q2",IF(AND(MONTH([Date])>=2,MONTH([Date])<=4),"Q3",IF(AND(MONTH([Date])>=5,MONTH([Date])<=7),"Q4"))))

	7. Accounting_Period = IF(MONTH([Date])=8,1,IF(MONTH([Date])=9,2,IF(MONTH([Date])=10,3,IF(MONTH([Date])=11,4,IF(MONTH([Date])=12,5,IF(MONTH([Date])=1,6,IF(MONTH([Date])=2,7,IF(MONTH([Date])=3,8,IF(MONTH([Date])=4,9,IF(MONTH([Date])=5,10,IF(MONTH([Date])=6,11,IF(MONTH([Date])=7,12))))))))))))

	8. Week_number = WEEKNUM([Date],2)

	9. Weekday_or_weekend = IF(AND([Day_of_week]>=1,'Date'[Day_of_week]<=5),"Weekday","Weekend")

	10. Month_relative = 12 * Year([Date])+Month([Date])-12*Year(today())-Month(today())

	11. Last_12_Months = IF(AND('Date'[Month_relative]>=-12,'Date'[Month_relative]<=-1),"LTM","")

	12. Fiscal_Year_Presentation = CONCATENATE("FY",[Fiscal_Year])

	13. Fiscal_Year_Quarter = CONCATENATE([Fiscal_Year_Presentation],[Fiscal_Quarter])

	14. Month = IF(MONTH([Date])=1,"January",IF(MONTH([Date])=2,"February",IF(MONTH([Date])=3,"March",IF(MONTH([Date])=4,"April",IF(MONTH([Date])=5,"May",IF(MONTH([Date])=6,"June",IF(MONTH([Date])=7,"July",IF(MONTH([Date])=8,"August",IF(MONTH([Date])=9,"September",IF(MONTH([Date])=10,"October",IF(MONTH([Date])=11,"November","December")))))))))))

	15. End_Of_Month = (EOMONTH([DATE],0))

	16. Start_Of_Month = STARTOFMONTH('Date'[Date])

	17. Month_Number = MONTH('Date'[Date])

	18. Fiscal_Year_Period = CONCATENATE("FY",CONCATENATE('Date'[Fiscal_Year],CONCATENATE(" - P ",'Date'[Accounting_Period])))

	19. Short_week_name = left('Date'[Day_of_week_name],3)

	20. Calendar_Year = year('Date'[Date])


You should have a Master_Calendar table similar to the one I have. This is a very important step to creating financial reporting (or other time based reporting in PowerBI.

Please note that the fiscal year in this examples starts on Aug 1. If you want to change the fiscal year start date simply change items 5, 6 and 7 to your corresponding fiscal year to the period.

Foreign Exchange Tables / API in Business Central

We wanted to see all of the foreign exchange rates in Power BI from Business Central for various reasons: 1) To make sure the exchange rates were being updated daily and, 2) to run reports on the exchange rates

Business Central stores the FX rates in table

To create the API, go to WEB SERVICES in Business Central and select NEW. The object type is page, and use Object ID 483 and publish. The URL will be produced and you use that as the oData source in PowerBI.

Coffee table from a rotting piece of wood circa WW2 that a friend got from another friend.

This piece of wood was in pretty bad shape. I managed to stabilize it with PC Wood Hardener and epoxy. The rotting portion was very much a sponge. It sucked up about 3 bottles of wood hardener and lots of epoxy and varnish.

Here is an over exposed picture of the piece of wood.

I used a hand plane to plane the surface of the table flat. I then realized the right side of the wood was going to fall off due to the rot.

After planing over several days

I don’t typically like the epoxy effects that some people do, so I strictly wanted the epoxy to be structural and not a feature. I mixed in some deep red dye so that it would not be entirely noticeable.

I had to make legs for this thing. I noticed some cool joins that welders do, so I tried one myself.

Because the bottom of the wood was not planed to the same thickness, I had to improvise on the legs. I made one of the legs adjustable for level.

Using PowerShell to access the tables in Business Central

I wanted a really simply way to access the tables in Business Central and to write the information of those tables into SQL database so that my team could access them directly from SQL.

Since I am just an accountant, I always find it very difficult when I find snippets of code but nothing is explained. So I will try my best to break everything down for other fellow accountants so that they can follow through.

Sure, there are many ways to do this, but I just wanted to try this. So here is my script. You can copy this script directly, and there are just a few things for you to change. Any thing that is underlined you will need to change.

#  References.
#  https://docs.microsoft.com/en-us/azure/active-directory/develop/v1-protocols-oauth-code
#  https://www.reddit.com/r/PowerShell/comments/9clts3/powershell_automation_with_oauth2/
#

#
# https://login.windows.net/2383c526-aef3-47e9-8487-37712e689168/oauth2/token?resource=https://api.businesscentral.dynamics.com

# Class to get an OAuth 2.0 authentication token from BC using a Password Grant.
#
class AADPasswordGrant {
    [string]$token                  #Token that we need to get to Authenticate with later
    [string]$tenantId               #BC Tenant ID
    [string]$clientId               #The ApplicationId that was registed for BC in AAD.   
    [string]$username               #BC username
    [string]$password               #BC Password 
    [System.Security.SecureString]$securePasswordStr #BC Password we will convert to a secure string later
    [string]$securePasswordBStr     #BSTR version of the secure password  
    [string]$clientSecret           #Key that was generated when registring BC in AAD
    [string]$grantType      = "password"  #This must be password so we are not challenged or have to use a form.  
    [string]$callbackUrl    = "https://127.0.0.1/auth-response"              #The same callback registered for BC in AAD
    [string]$accessTokenUrl = "https://login.windows.net/{tenantId}/oauth2/token"  #Url to request the token from
    [string]$resourceUrl    = "https://api.businesscentral.dynamics.com"           #The resource we want to talk to
    [string]$scopeUrl       = "https://api.businesscentral.dynamics.com"           #The resource we want to talk to
   
    AADPasswordGrant([string]$tenandId, [string]$clientId, [string]$clientSecret, [string]$userName, [string]$password) {
        $this.tenantId     = $tenandId
        $this.clientId     = $clientId
        $this.clientSecret = $clientSecret
        $this.userName     = $userName
        $this.securePasswordStr  = (ConvertTo-SecureString -String $password -AsPlainText -Force)
        $this.securePasswordBStr = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($this.securePasswordStr))
        $this.accessTokenUrl     = $this.accessTokenUrl.Replace('{tenantId}', $tenandId)
    }

    [void]TryGetAuthorisationToken () {
        $body = @{
            grant_type    = $this.grantType
            username      = $this.userName
            password      = $this.securePasswordBStr
            client_id     = $this.clientId
            client_secret = $this.clientSecret
            scope         = $this.scopeUrl
            redirect_uri  = $this.callbackUrl
            resource      = $this.resourceUrl
        }
        $authResult = Invoke-RestMethod -Method Post -Uri $this.accessTokenUrl -Body $body
        $this.token =$authResult.access_token
    }
}

#
# Test the Class Here
#
$tenantId     = '1447d526-aee2-47e9-8418-27732e6848546'      #Your BC tennantID
$clientId     = 'af912c1d-d67c-407a-8f5f-2bd8dbb1cda9'      #The id that BC is registered with in AAD  
$clientSecret = 'ETZ9Nqy--Wi9-zjF9B97-.oeCLyA0.AEfd' #The secret key that was created when registering BC for AAD Auth
$username     = 'xx@xxx.com'            #Username for the password grant -- this is usually your Office365 credentials
$password     = 'your office365 password'                       #Password in plain text note.. this is not advised and there are ways of producing a key in PowerShell so your password is not stored in plain text

[AADPasswordGrant]$aadPasswordGrant = [AADPasswordGrant]::new($tenantId, $clientId, $clientSecret, $username, $password)
$aadPasswordGrant.TryGetAuthorisationToken()

$companiesUrl = "https://api.businesscentral.dynamics.com/v2.0/Production/api/v2.0"
$requestHeaders = @{ 'Authorization' = 'Bearer ' + $aadPasswordGrant.token }
$result = Invoke-RestMethod -Uri $companiesUrl -Headers $requestHeaders -Method Get
$result.value | Export-Csv -Path c:\output\bc-environment.csv

A few things to note about our environment:

  1. We are running Business Central (SAAS/Online – it’s in Office365 not our own servers
  2. We use AAD (Azure Active Directory) to authenticate – that is we use our Office365 credentials to login to Business Central (I am using the OAuth2.0 token to gain access to Business Central
  3. The code above is accessing the PRODUCTION platform.

Most of the code above is just to get the OAuth 2.0 token to get access to Business Central. Why is it not simply a username and password? I’m not sure, and this is what Microsoft requires to access Business Central. Like I said, I’m not a coder, just an accountant.

There are 5 pieces of information that you need to change in the above code (and you might not be able to get all of them yourself):

  1. Tenant ID – You can get this by going to Business Central with your browser and clicking on Help and Support. You will find your Tenant ID. If you don’t see it, you can always get it from your URL.
The red underline is the Tenant ID

2.