<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>echo3.co</title>
  <subtitle>Freelance technologist for small businesses: bespoke systems, retained support, cloud infrastructure, and security compliance, without the ticket queue.</subtitle>
  <link href="https://echo3.co/feed.xml" rel="self"/>
  <link href="https://echo3.co/"/>
  <updated>2026-07-19T00:00:00Z</updated>
  <id>https://echo3.co/</id>
  <author>
    <name>Jude Sudbury</name>
  </author>
  <entry>
    <title>ADHD, generalisation, and why I&#39;ve never wanted to specialise</title>
    <link href="https://echo3.co/posts/adhd/"/>
    <updated>2026-07-19T00:00:00Z</updated>
    <id>https://echo3.co/posts/adhd/</id>
    <content type="html">&lt;blockquote class=&quot;tldr&quot;&gt;
&lt;strong&gt;TLDR:&lt;/strong&gt; diagnosed with ADHD at 51, after decades of suspecting it myself. This is the story of what that&#39;s actually like day to day, why it pushed me toward being a generalist instead of a specialist, and why I&#39;ve stopped treating that as a failure. If you just want the professional payoff, it&#39;s in the last section.
&lt;/blockquote&gt;
&lt;p&gt;I was diagnosed with ADHD two years ago, at 51. I’m writing this at 53, which should tell you something about how long it took me to actually sit down and write it.&lt;/p&gt;
&lt;p&gt;I didn’t get diagnosed because I finally noticed something was wrong; I suspected ever since ADHD started being discussed openly that I had it. I got diagnosed because at some point I decided that noticing wasn’t the same as knowing, and if I was going to build my working life around this trait, I wanted a qualified psychiatrist to actually confirm it rather than me diagnosing myself off the back of an online screening questionnaire.&lt;/p&gt;
&lt;p&gt;That distinction matters more than it sounds. Self-recognition is usually right, in my experience and from what I hear from other adults who go through this. The pattern-matching part of noticing “this describes me” is not the hard part. The hard part, and the useful part, is what a formal assessment gives you that self-diagnosis can’t: certainty you can actually build on, and access to medication if you decide you want it as one tool among several. I do, sometimes. Not daily, not as a personality transplant, but situationally, month-end bookkeeping being the reliable example I always reach for. There is no earthly reason my brain finds reconciling invoices harder than untangling a genuinely difficult problem, which is basically my raison d’être, and yet here we are. Medication helps on the days that particular mismatch needs help.&lt;/p&gt;
&lt;h2&gt;What the trait actually looks like, thirty-plus years in&lt;/h2&gt;
&lt;p&gt;I’m not going to pretend this is all upside dressed up as a personality quirk, because that does a disservice to anyone reading this who’s tired of ADHD being marketed as a secret superpower with none of the difficult bits mentioned.&lt;/p&gt;
&lt;p&gt;The difficult bits are real. Tasks that are boring but important, the invoicing, the admin, the licence renewal that’s been sitting in an email for three weeks, get avoided in a way that has nothing to do with laziness and everything to do with a brain that treats “important but uninteresting” as barely worth the fuel. Multi-step tasks with no obvious payoff until the very end are hard to start and harder to finish. And there’s a particular flavour of shame that comes from knowing exactly what you should be doing, wanting to do it, and still not doing it, that took me a long time to stop internalising as a character flaw.&lt;/p&gt;
&lt;p&gt;The coping mechanisms accumulate over decades whether you’ve got a name for what you’re coping with or not. External structure where my own doesn’t hold: calendars, reminders, breaking big vague tasks into small concrete ones I can actually start. Knowing which of my own moods are “just get started and it’ll click” versus “genuinely not today, don’t fight it.” None of that came from a diagnosis. The diagnosis just explained why I’d needed to build all of it in the first place.&lt;/p&gt;
&lt;p&gt;And then there’s the other side, which is where this stops being a list of coping strategies and starts being relevant to why you’re reading this on an IT professional’s website rather than a mental health blog. I chase the next interesting thing, constantly. I see the big picture before I see the detail. I generate ideas at a rate that occasionally outpaces my ability to execute on all of them. And when something is either genuinely fascinating or the deadline is real and close, I can hyperfocus in a way that gets a disproportionate amount done in a short window, the flip side of the same trait that makes me useless at starting the boring thing three weeks before it’s due.&lt;/p&gt;
&lt;h2&gt;Why that produces a generalist, not a specialist&lt;/h2&gt;
&lt;p&gt;Twenty-five years in IT, and I’ve never wanted to go deep and narrow in any one direction. Plenty of very good, very successful IT people build a career on exactly that, ten years becoming the best in the world at one specific thing. I looked at that path more than once and knew, with total certainty, that it would slowly kill something in me. Not because depth is bad. Because staying interested in one narrow thing for a decade is exactly the kind of task my brain treats as “important but uninteresting” once the initial novelty wears off, and I’d have been fighting my own wiring the entire way.&lt;/p&gt;
&lt;p&gt;My wife of thirty years is a specialist. She’s excellent at one thing, and she’s the best in her game at it. My brother-in-law is the same, top of his field. I could never be either of those people, but the world is built to expect specialists, or at least that’s how it felt for years, and against that expectation (real or imagined) I spent a long time quietly filing myself under F for failure. Twenty-five-plus years into a career, and where had it got me? Not the best in a field. Not a six-figure salary at the top of a large company. Just someone working for himself in a niche, doing interesting things, keeping his clients happy, trusting he’d always give them the best advice, no BS, and fantastic value for money. It took me a long time to see that as the actual result rather than the consolation prize. I spent 25 years measuring myself against a definition of success I now think was wrong for me, and it hurt.&lt;/p&gt;
&lt;p&gt;I’ve made peace with it now. I’ll never specialise, and I’ll always be good at a lot of different things instead. My wife still rolls her eyes at me sometimes: “well, of course you’re excellent at that thing you just started.”&lt;/p&gt;
&lt;p&gt;Generalising isn’t a consolation prize for not being able to specialise. It’s the actual shape of how this brain works well. New problem, new domain, new interesting puzzle, every single week, sometimes every single day. A bespoke Power Automate flow one morning, an ISO 27001 control gap the next afternoon, a stalled cloud app deployment that’s sat there waiting for someone to actually make it go live, the day after that. That’s not scattered. That’s the exact operating conditions this trait actually thrives under.&lt;/p&gt;
&lt;h2&gt;How this actually helps the people I work for&lt;/h2&gt;
&lt;p&gt;I’ll keep this part short, because the story above is the evidence, not a preamble to it.&lt;/p&gt;
&lt;p&gt;Pattern recognition across domains that specialists often don’t cross is a direct product of never staying in one lane long enough to forget what the other lanes look like. Spotting that a client’s problem doesn’t need the expensive enterprise platform, it needs a small, right-sized thing built from parts most consultants wouldn’t think to combine, that’s the generalist’s move, not the specialist’s. Hyperfocus, the same trait that makes me useless at starting my own admin early, means that when I’m in the middle of solving something genuinely knotty for a client, I don’t want to stop until it’s actually solved. And a lower tolerance for boring, bloated process than most people have is, frankly, why “the smallest thing that solves it” isn’t just a pricing philosophy on this site. It’s the only way I’ve ever been able to work.&lt;/p&gt;
&lt;p&gt;I’m not telling you this so you’ll feel sorry for me, or so you’ll be impressed. I’m telling you because if you’re going to trust someone with your systems, you might as well know what’s actually driving how they think.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Building a GDPR-Compliant Patient System on Microsoft 365 for a Genetic Counselling Practice</title>
    <link href="https://echo3.co/posts/genecare-patient-system/"/>
    <updated>2026-07-18T00:00:00Z</updated>
    <id>https://echo3.co/posts/genecare-patient-system/</id>
    <content type="html">&lt;p&gt;A solo genetic counsellor came to me needing a proper patient management
system. Booking, notes, documents, all of it currently scattered across
inboxes and a spreadsheet. The market had two options: dedicated clinic
software, priced and featured for a multi-clinician practice, or generic
CRM tools that would need almost as much bespoke work as building from
scratch, minus the fit. Neither made sense for one practitioner.&lt;/p&gt;
&lt;p&gt;She was already paying for Microsoft 365, and as the sole controller of
other people’s genetic health data, she was already bound by GDPR, no
industry-specific certification required. So instead of adding a vendor,
I built the system inside the tenant she already owned and already had to
secure.&lt;/p&gt;
&lt;h2&gt;Architecture&lt;/h2&gt;
&lt;p&gt;SharePoint does the data layer: a Patients list, an Appointments list, a
Notes list, and a Patient Documents library, linked together with lookup
columns rather than duplicated fields. Nothing exotic, but it means every
record lives somewhere she can audit, back up, and permission without
learning a new admin console.&lt;/p&gt;
&lt;p&gt;Microsoft Bookings handles the actual scheduling, because it’s the thing
clients see and it already worked. A Power Automate flow bridges Bookings
to SharePoint: every new booking becomes a patient record (or updates an
existing one) and an appointment record, without anyone re-typing details
into a second system.&lt;/p&gt;
&lt;p&gt;Power Apps is the planned front end, a canvas app for the day-to-day work
of looking up a patient, adding notes, and pulling up documents, so the
practice doesn’t need to touch SharePoint’s native UI at all.&lt;/p&gt;
&lt;p&gt;Auth runs through Entra ID, same as the rest of the tenant. That’s most of
the GDPR case in one sentence: no new identity provider, no new place for
access control to drift out of sync, no personal data leaving
infrastructure that’s already covered by the client’s existing data
processing arrangements. The whole thing costs the price of the Microsoft
365 licences she was paying for anyway.&lt;/p&gt;
&lt;h2&gt;Gotchas&lt;/h2&gt;
&lt;p&gt;A few things that cost more time than they should have, in case they save
someone else the afternoon:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Bookings connector’s calendar dropdown in Power Automate fails with
&lt;code&gt;AADSTS50013&lt;/code&gt;. Don’t fight it: type the booking mailbox address directly
into the trigger field instead of selecting from the list.&lt;/li&gt;
&lt;li&gt;Inline &lt;code&gt;filter()&lt;/code&gt; expressions in Power Automate are flaky when pulling
values out of &lt;code&gt;CustomQuestionAnswers&lt;/code&gt;. The Filter array action does the
same job and actually works.&lt;/li&gt;
&lt;li&gt;The Bookings trigger returns &lt;code&gt;StartTime&lt;/code&gt; as a plain string, not an
object. No &lt;code&gt;?[&#39;DateTime&#39;]&lt;/code&gt; needed, and adding it just breaks the
expression.&lt;/li&gt;
&lt;li&gt;Array length checks on the dedup branch need “is greater than”, not “is
equal to”. Equal to zero silently skips cases it shouldn’t.&lt;/li&gt;
&lt;li&gt;Patient deduplication matches on email address only. That’s a
simplification, not an oversight: at this practice’s patient volume, it’s
reliable enough, and anything more elaborate would be solving a problem
she doesn’t have.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Where it stands&lt;/h2&gt;
&lt;p&gt;The data layer and the Bookings-to-SharePoint integration are built and
tested: bookings flow in, patient and appointment records get created or
matched correctly, nothing needs manual re-entry. The Power Apps front end
is next.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Building a Real-Time AI Bridge for a Tabletop RPG</title>
    <link href="https://echo3.co/posts/fgu-claude-bridge/"/>
    <updated>2026-04-25T00:00:00Z</updated>
    <id>https://echo3.co/posts/fgu-claude-bridge/</id>
    <content type="html">&lt;p&gt;I play Dungeons and Dragons. Specifically, I run it: I’m the Dungeon Master, which means I’m responsible for the world, the story, the NPCs, the rules, the pacing, and the improvised dialogue. It’s a lot of overhead, and prep time is always limited.&lt;/p&gt;
&lt;p&gt;I’ve been using AI heavily for prep: developing characters, writing descriptions, planning encounters. But during live sessions, keeping the AI contextually aware of the game state while running the session is difficult. I was either neglecting the AI or breaking the flow of the game to type updates.&lt;/p&gt;
&lt;p&gt;The solution was to connect them directly.&lt;/p&gt;
&lt;h2&gt;The Setup: Virtual Tabletops&lt;/h2&gt;
&lt;p&gt;Fantasy Grounds Unity (FGU) is a leading Virtual Tabletop (VTT) that replicates the tabletop experience online. It has a rich extension system and a large library of licensed content. We play online, keeping a Discord open for voice chat while the game’s mechanics and narrative play out in the FGU chat window.&lt;/p&gt;
&lt;h2&gt;FGU Has No Native AI Integration&lt;/h2&gt;
&lt;p&gt;To use AI during a session, you normally have to manually copy chat logs or summarize events in a separate browser window, then copy responses back. That workflow falls apart at a live table. I needed the AI to watch the session alongside me, building its own awareness of events, so I could query it with minimal friction.&lt;/p&gt;
&lt;h2&gt;The Architecture&lt;/h2&gt;
&lt;p&gt;The bridge consists of three components:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;A Lua extension inside FGU:&lt;/strong&gt; This registers custom GM slash commands. When typed, the extension writes a JSON request directly to FGU’s console log.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A Python server running locally:&lt;/strong&gt; This monitors FGU’s &lt;code&gt;chatlog.html&lt;/code&gt; for new entries, parsing them in real time to accumulate session history in memory. When a GM command is written to the console log, the Python server packages the history, the command, and the campaign notes, and sends them to the Anthropic API.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Anthropic API (Claude):&lt;/strong&gt; Receives the full context, generates the response, and returns it to the Python server, which automatically copies it to the system clipboard for the GM to paste.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;language-diagram&quot;&gt;&lt;code class=&quot;language-diagram&quot;&gt;FGU chatlog.html  →  Python monitors continuously
                      Session events accumulate in memory (no API call, no cost)

GM types /npctalk  →  console.log  →  Python detects it
                       Full context sent to Anthropic API
                       Response copied to clipboard
                       GM: Ctrl+V into FGU chat → Enter&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;How the Live Context Works&lt;/h2&gt;
&lt;p&gt;FGU writes everything—dialogue, attack rolls, damage, turn markers—to &lt;code&gt;chatlog.html&lt;/code&gt;. The Python server polls this file every 0.4 seconds. New lines are parsed, stripped of HTML, and appended to an in-memory list. Mechanical events (like dice rolls) are prefixed with &lt;code&gt;[ROLL]&lt;/code&gt; so Claude understands they are game mechanics rather than narrative text.&lt;/p&gt;
&lt;p&gt;Every few seconds, pending events are flushed into the conversation history as a &lt;code&gt;[TABLE]&lt;/code&gt; message. Claude is instructed via the system prompt to absorb these silently without generating a response.&lt;/p&gt;
&lt;p&gt;When a slash command is sent, the entire conversation history is dispatched to the API. Claude has seen the full context of the session and can respond instantly in character.&lt;/p&gt;
&lt;h2&gt;The Campaign Notes&lt;/h2&gt;
&lt;p&gt;Two markdown files provide Claude’s background knowledge:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;campaign_history.md&lt;/code&gt;: The accumulated campaign record (world details, character backstories, session recaps).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;session_notes.md&lt;/code&gt;: Pre-written descriptions for locations, NPC profiles (personality, voice, mannerisms), and GM secrets.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are loaded at server startup and injected into the system prompt of every API call.&lt;/p&gt;
&lt;h2&gt;The GM Commands&lt;/h2&gt;
&lt;p&gt;All commands are slash commands typed in the FGU chat box:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/describe&lt;/code&gt;: Generates sensory scene descriptions based on notes.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/npctalk (Name)&lt;/code&gt;: Generates character dialogue ready to paste.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/npcaction (Name)&lt;/code&gt;: Generates physical character actions.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/combatsummary&lt;/code&gt;: Translates recent dice rolls into a narrative description of the battle.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/claude&lt;/code&gt;: Freeform private query whispered to the GM.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/claudereset&lt;/code&gt;: Clears the conversation history buffer.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Cost &amp;amp; Performance&lt;/h2&gt;
&lt;p&gt;API calls are only made when a GM command is sent; monitoring the logs is free. A full session typically costs less than a dollar using Claude Haiku, depending on the size of the note files and query frequency.&lt;/p&gt;
&lt;p&gt;The full project, including the Lua extension and Python server templates, is available on &lt;strong&gt;&lt;a href=&quot;https://github.com/heyjudeuk/fgu-claude-bridge&quot;&gt;GitHub (heyjudeuk/fgu-claude-bridge)&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note for developers: FGU Unity 5.x uses &lt;code&gt;Comm.registerSlashHandler&lt;/code&gt; for slash commands. Older documentations reference &lt;code&gt;ChatManager.registerSlashCommand&lt;/code&gt;, which has been deprecated.&lt;/em&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Fixing the Microsoft 365 Room Finder Nobody Could See</title>
    <link href="https://echo3.co/posts/m365-room-finder/"/>
    <updated>2026-01-25T00:00:00Z</updated>
    <id>https://echo3.co/posts/m365-room-finder/</id>
    <content type="html">&lt;p&gt;You create a room resource in Exchange Online. Maybe it’s just a single meeting room for a small office, but you want bookings managed properly rather than relying on calendar etiquette and guesswork. Everything appears to be set up correctly, yet users report they cannot find the room in Outlook’s Room Finder. They can add it by manually typing the room name, but the automated search is an empty void.&lt;/p&gt;
&lt;p&gt;When a user clicks “Add room” and selects “Browse all rooms”, Room Finder prompts them to select a building, only to return zero results.&lt;/p&gt;
&lt;p&gt;This behavior shows up consistently across Outlook desktop, Outlook on the web, and Teams. In most cases, nothing is actually broken—Microsoft’s default configurations simply assume you are a multinational corporation.&lt;/p&gt;
&lt;h2&gt;The Missing Metadata Trap&lt;/h2&gt;
&lt;p&gt;Microsoft’s official troubleshooting guidance tells you to create a Room List using PowerShell and add the rooms to it (documented in &lt;a href=&quot;https://learn.microsoft.com/en-us/troubleshoot/exchange/calendars/conference-rooms-not-displayed&quot;&gt;Microsoft’s Troubleshooting Guide&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;You can follow those instructions exactly, create the list, add the room, and wait 48 hours for replication, only to find the Room Finder is still completely empty.&lt;/p&gt;
&lt;p&gt;The reason is that modern Room Finder is driven by Microsoft’s &lt;em&gt;Places&lt;/em&gt; service. If a room is missing basic location metadata—specifically &lt;strong&gt;street, city, postcode, and country&lt;/strong&gt;—it will fail to appear even when the building field is populated. The UI doesn’t throw an error or warn you; it just silently fails to display the resource.&lt;/p&gt;
&lt;p&gt;This design makes sense if you assume every tenant has dozens of offices spread across regions, each managed by a dedicated facilities team. For a small office with one meeting room and a kettle in the corner, it is absurd. There is no fallback, no “show all rooms” button, and no hint explaining that missing metadata is the blocker.&lt;/p&gt;
&lt;h2&gt;The Fix&lt;/h2&gt;
&lt;p&gt;The fix requires PowerShell. You cannot configure these location attributes in the Microsoft 365 Admin Center or the Exchange Admin Center UI.&lt;/p&gt;
&lt;p&gt;First, connect to Exchange Online PowerShell and run this to inspect what Exchange actually sees:&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Get-Place&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Where-Object&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Type&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-eq&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Room&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Format-Table&lt;/span&gt; Identity&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;Building&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;City&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;Street&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;PostalCode&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If your rooms show empty location fields, Room Finder will ignore them. To fix it, assign both the building and the core location metadata:&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Set-Place&lt;/span&gt; `
  &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;Identity &lt;span class=&quot;token string&quot;&gt;&quot;Meeting Room 1&quot;&lt;/span&gt; `
  &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;Building &lt;span class=&quot;token string&quot;&gt;&quot;ABC Company HQ&quot;&lt;/span&gt; `
  &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;Street &lt;span class=&quot;token string&quot;&gt;&quot;Alphabet Street&quot;&lt;/span&gt; `
  &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;City &lt;span class=&quot;token string&quot;&gt;&quot;London&quot;&lt;/span&gt; `
  &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;PostalCode &lt;span class=&quot;token string&quot;&gt;&quot;ABC DEF&quot;&lt;/span&gt; `
  &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;CountryOrRegion &lt;span class=&quot;token string&quot;&gt;&quot;United Kingdom&quot;&lt;/span&gt; `
  &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;Floor 1 `
  &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;Capacity 8&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After running &lt;code&gt;Set-Place&lt;/code&gt; and ensuring the room is in a valid Room List, wait a few hours for the directory changes to propagate.&lt;/p&gt;
&lt;p&gt;Microsoft’s choice to require enterprise-grade metadata before displaying a single office meeting room is a classic example of corporate over-engineering. But once you populate the Place fields, the Room Finder finally works.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Entra ID Joined, But Not an Admin? Fixing the &quot;SID With a Question Mark&quot; Issue on Windows 11</title>
    <link href="https://echo3.co/posts/entra-id-joined-not-admin/"/>
    <updated>2025-06-20T00:00:00Z</updated>
    <id>https://echo3.co/posts/entra-id-joined-not-admin/</id>
    <content type="html">&lt;p&gt;You unbox a new Windows 11 Pro laptop, run through the out-of-box experience, sign in with a work account, and the device joins Entra ID without complaint. Then you find the user has no local admin rights.&lt;/p&gt;
&lt;p&gt;Worse, if you open the local Administrators group you’ll see a SID starting &lt;code&gt;S-1-12-1...&lt;/code&gt; with a greyed-out question mark where a name should be. No name, no permissions, no way to elevate. Fully joined, fully unusable.&lt;/p&gt;
&lt;h2&gt;The problem&lt;/h2&gt;
&lt;p&gt;The first user to join a device to Entra ID used to be added to the local Administrators group automatically. Microsoft changed that default in newer tenants. The join itself still succeeds, but the admin assignment doesn’t happen, and what’s left behind is a SID Windows can’t resolve. The account clearly exists, since the user can sign in, but there’s nothing to elevate it with: no admin password, no way to install software, update drivers, or reset Windows from within the OS.&lt;/p&gt;
&lt;h2&gt;What causes it&lt;/h2&gt;
&lt;p&gt;Almost always, it’s the device settings in Entra ID (or an Intune policy) not assigning local admin rights during join. Check it here:&lt;/p&gt;
&lt;p&gt;Entra admin centre → Devices → Device settings → Local administrator settings&lt;/p&gt;
&lt;p&gt;Set “Registering user is added as local administrator on the device during Microsoft Entra join” to &lt;strong&gt;All&lt;/strong&gt;, and “Global administrator role is added as local administrator on the device during Microsoft Entra join” to &lt;strong&gt;Yes&lt;/strong&gt; (handy as a fallback if the first setting ever gets misconfigured again).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20250620/entra-id-join-as-admin.png&quot; alt=&quot;Screen shot of EntraID Entra join settings under devices&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Fixing a device already in this state&lt;/h2&gt;
&lt;p&gt;If a device has already joined with no admin user, there are two ways out.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reset and rejoin.&lt;/strong&gt; If you’re still early in deployment, &lt;code&gt;Shift + Restart&lt;/code&gt; at the login screen → Troubleshoot → Reset this PC. Keep the device online throughout OOBE, and fix the tenant setting above first so the rejoin doesn’t repeat the problem. If BitLocker is on, confirm the recovery key is already in Entra ID before you wipe.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix it remotely via Intune&lt;/strong&gt;, if wiping isn’t an option. Push a script through Endpoint Manager → Devices → Scripts:&lt;/p&gt;
&lt;pre class=&quot;language-powershell&quot;&gt;&lt;code class=&quot;language-powershell&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Add-LocalGroupMember&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Group&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Administrators&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;Member &lt;span class=&quot;token string&quot;&gt;&quot;AzureAD&#92;user@domain.com&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;The takeaway&lt;/h2&gt;
&lt;p&gt;Nothing here is broken so much as reconfigured: Microsoft tightened the default, and a device that looks fully provisioned can still be missing the one thing that makes it usable. Worth checking the device settings before you roll out a new deployment profile, rather than after the first support call.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Why MFA Isn&#39;t Enough (And How to Actually Fix It)</title>
    <link href="https://echo3.co/posts/why-mfa-isnt-enough/"/>
    <updated>2024-09-03T00:00:00Z</updated>
    <id>https://echo3.co/posts/why-mfa-isnt-enough/</id>
    <content type="html">&lt;p&gt;Multi-Factor Authentication (MFA) is the standard baseline for securing Microsoft 365 accounts. By requiring a second factor—like an authenticator app approval or a code—it stops bulk credential-stuffing attacks. However, relying on MFA as a standalone defense creates a false sense of security. Modern phishing techniques bypass standard MFA entirely by targeting session cookies rather than just passwords.&lt;/p&gt;
&lt;h2&gt;The Mechanics of Session Hijacking&lt;/h2&gt;
&lt;p&gt;Phishing frameworks like Evilginx do not just steal credentials; they steal the authenticated session.&lt;/p&gt;
&lt;p&gt;Evilginx operates as a reverse proxy, acting as a man-in-the-middle between the user and the legitimate Microsoft 365 login portal. The workflow operates in six stages:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Proxy Setup:&lt;/strong&gt; The attacker deploys a server running the reverse proxy, cloning the styling of the target login page.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Link Generation:&lt;/strong&gt; The proxy generates a custom URL pointing to the proxy server, designed to mimic a legitimate domain.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Delivery:&lt;/strong&gt; The link is sent to the user via a targeted email, disguised as a standard document review or password prompt.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Interception:&lt;/strong&gt; When the user clicks the link, they see the actual, live Microsoft login page served through the proxy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Capture:&lt;/strong&gt; As the user enters their password and completes the MFA prompt, the proxy intercepts both the credentials and the resulting session cookie.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hijack:&lt;/strong&gt; The legitimate portal issues a session cookie to the user’s browser to keep them logged in. The proxy intercepts this cookie and copies it. The attacker can then load this cookie into their own browser, bypassing MFA entirely and gaining direct access to the mailbox.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once inside, attackers typically set up silent inbox rules to delete sent mail or redirect invoices, playing a quiet “long game” to intercept financial transactions.&lt;/p&gt;
&lt;h2&gt;Moving Beyond User Training&lt;/h2&gt;
&lt;p&gt;Many organizations treat user training as their primary defense against these attacks. While training helps, humans are fallible. Under pressure or distraction, even trained users will click a well-crafted link.&lt;/p&gt;
&lt;p&gt;Relying on users to spot sophisticated proxy domains is a weak security model. Instead, you need hard, system-enforced technical controls.&lt;/p&gt;
&lt;h2&gt;Hard Controls: Conditional Access and Intune&lt;/h2&gt;
&lt;p&gt;To secure Microsoft 365 against session theft, you must implement Conditional Access policies that restrict access to verified, compliant devices.&lt;/p&gt;
&lt;p&gt;Instead of asking “who is logging in?”, your security policies must ask “what device are they logging in from?”.&lt;/p&gt;
&lt;p&gt;By integrating Microsoft Intune and enforcing device compliance, you ensure that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Only corporate-managed or registered compliant devices can access company data.&lt;/li&gt;
&lt;li&gt;An attacker in possession of a stolen session cookie still cannot log in, because their machine is not registered in your directory as a compliant device.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For personal devices (like mobiles used for email), you can enforce selective compliance policies through Mobile Application Management (MAM) to protect corporate data without violating personal privacy.&lt;/p&gt;
&lt;p&gt;MFA is a necessary baseline, but it is not a complete security strategy. True security means deploying controls that are actually real—hardening the identity boundary so that stolen session cookies are useless without a verified, managed device.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Windows 10 Remote Desktop Fix: &quot;The system administrator has restricted the types of logon (network or interactive) that you may use&quot;</title>
    <link href="https://echo3.co/posts/rdp-restricted-logon/"/>
    <updated>2024-05-23T00:00:00Z</updated>
    <id>https://echo3.co/posts/rdp-restricted-logon/</id>
    <content type="html">&lt;p&gt;A client was trying to reach a Windows 10 Enterprise workstation over RDP from a laptop and hit this:&lt;/p&gt;
&lt;p&gt;“The system administrator has restricted the types of logon (network or interactive) that you may use. For assistance, contact your system administrator or technical support.”&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240523/rdp-error.png&quot; alt=&quot;Screen shot of this error: The system administrator has restricted the types of logon (network or interactive) that you may use. For assistance, contact your system administrator or technical support&quot;&gt;&lt;/p&gt;
&lt;h2&gt;What I checked first&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Remote access was enabled.&lt;/li&gt;
&lt;li&gt;The account used for the connection was local and a member of the local Administrators group.&lt;/li&gt;
&lt;li&gt;NLA and the firewall were both switched off, purely to rule them out.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of that was fine, which meant the problem was somewhere less obvious.&lt;/p&gt;
&lt;h2&gt;The actual cause&lt;/h2&gt;
&lt;p&gt;I opened Local Security Policy (&lt;code&gt;secpol.msc&lt;/code&gt;, or search “local security policy” from the Start menu) to confirm the Administrators group was listed under “Allow log on through Remote Desktop Services.” It was. While I was in there, though, I noticed “&lt;strong&gt;Deny&lt;/strong&gt; log on through Remote Desktop Services” had an entry for &lt;strong&gt;Local account&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Open Local Security Policy:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240523/search-for-local-security-policy.png&quot; alt=&quot;Find/ open local security policy app.&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Find “Deny log on through Remote Desktop Services”:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240523/local-sec-policy.png&quot; alt=&quot;Find Deny log on through Remote Desktop Services.&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Remove “Local account”:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240523/local-sec-policy-2.png&quot; alt=&quot;Remove &amp;quot;Local account&amp;quot;.&quot;&gt;&lt;/p&gt;
&lt;p&gt;That was it. Problem solved.&lt;/p&gt;
&lt;p&gt;This policy appears to be a default on Enterprise editions, on the assumption that the machine is domain-joined and RDP access should come through domain accounts rather than local ones. This particular workstation was standalone, so the default was actively working against the client rather than protecting anything.&lt;/p&gt;
&lt;p&gt;Worth noting: “Deny access to this computer from the network” had the same &lt;strong&gt;Local account&lt;/strong&gt; entry, and will bite you the same way if you’re troubleshooting network logons rather than RDP specifically.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Handling Null Properties in JSON Payloads in Power Automate</title>
    <link href="https://echo3.co/posts/power-automate-null-properties-json/"/>
    <updated>2024-03-08T00:00:00Z</updated>
    <id>https://echo3.co/posts/power-automate-null-properties-json/</id>
    <content type="html">&lt;p&gt;Following on from my previous article on querying the Companies House API in Microsoft Power Automate, in this article I’ll explore an option for handling missing JSON properties in a given payload that are necessary for subsequent actions in your flow.&lt;/p&gt;
&lt;h2&gt;The Problem&lt;/h2&gt;
&lt;p&gt;As an overview, this is what my flow does:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;From a source Excel spreadsheet, iterate through a list of company registration numbers that I’m interested in finding charge information for.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In this loop, there is an HTTP GET action that constructs a URI from the current row of the Excel spreadsheet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Following this is a Parse JSON action, the contents of which are used to set up another (nested) loop which iterates through all ‘charges’ listed against that company&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There is then a 3rd nested loop (a loop within a loop within a loop) that iterates through ‘persons entitled’, which is an array associated with each charge.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The data is written to a SQL database using an Insert Row action.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;However, during the course of testing my flow, I noticed that some of the JSON payloads were causing the flow to fail. Why? Because some charges (very old ones) registered on Companies House have no persons entitled listed. This means the JSON property ‘persons_entitled’ was completely missing. Without this, the 3rd loop, which required this property to exist, would fail.&lt;/p&gt;
&lt;p&gt;Power Automate doesn’t have a failsafe mechanism for dealing with null entities, so we have to be a little creative.&lt;/p&gt;
&lt;h2&gt;The Solution&lt;/h2&gt;
&lt;p&gt;The solution I used was to create a condition action:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240308/condition.png&quot; alt=&quot;The condition action in Power Automate&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here you can see my flow. The condition action sits directly below the loop which iterates through the list of charges in the Companies House JSON payload. Its job is to check the existence of the ‘persons_entitled’ property. If it exists, then continue with the inner most loop (IteratePersonsEntitled), if not, then effectively do nothing (I have a compose action here that simply concatinates a string; it’s merely there so &lt;em&gt;something&lt;/em&gt; happens in the false branch).&lt;/p&gt;
&lt;p&gt;The condition contains the following expression:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;contains&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;IterateCharges&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;persons_entitled&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The contains function inspects items from the IterateCharges loop, looking for the existence of the persons_entitled array. If this property was missing entirely from the JSON payload (for a given charge) then that array will be absent and the function will return false.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240308/function.png&quot; alt=&quot;Condition expression configuration&quot;&gt;&lt;/p&gt;
&lt;p&gt;So you can see the logic. If the persons_entitled array is present, the contains function returns true. The condition expression states that if the expression = true then proceed with the actions in the true branch, else follow the false branch.&lt;/p&gt;
&lt;p&gt;Now my flow can continue without falling over in the event of a missing property!&lt;/p&gt;
&lt;h2&gt;Other Tweaks&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;I had to amend the JSON schema I posted in my &lt;a href=&quot;/posts/companies-house-api-power-automate/&quot;&gt;previous article&lt;/a&gt;, removing several required properties, notably ‘links’ and ‘persons_entitled’ since this was also causing my flow to fail when these were not included in the JSON payload.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Some companies queried via the API do not have any charges listed, so the API returns a 404 not found error. To handle this in Power Automate, you must configure the ‘run after’ setting for the action directly following the HTTP action:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240308/runafter.png&quot; alt=&quot;Configuring run after in Power Automate&quot;&gt;&lt;/p&gt;
&lt;p&gt;In my flow, I have a delay action that I added to avoid the 600 queries per 5 minutes imposed by the Companies House API. Here I ticked the ‘Has failed’ option under Run After under the HTTP action.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Using Power Automate with the Companies House API</title>
    <link href="https://echo3.co/posts/companies-house-api-power-automate/"/>
    <updated>2024-02-09T00:00:00Z</updated>
    <id>https://echo3.co/posts/companies-house-api-power-automate/</id>
    <content type="html">&lt;p&gt;A client asked whether I could investigate pulling data from Companies House using their API. This is still work in progress since ultimately the data harvested will be dumped into a database for later reporting using PowerBI. However, I thought it might be useful to document the process of using Microsoft Power Automate (my chosen tool for this task) to perform HTML GET operations via the Companies House API and parsing the subsequent JSON payload.&lt;/p&gt;
&lt;h2&gt;Step 1: Create an application &amp;amp; API key&lt;/h2&gt;
&lt;p&gt;Visit: &lt;a href=&quot;https://developer.company-information.service.gov.uk/manage-applications/add&quot;&gt;this link&lt;/a&gt; to create an application in your Companies House ‘Developer Hub’. If you don’t have an account, you will need to register first (it’s free). You can’t use your webfiling account (if you have one).&lt;/p&gt;
&lt;p&gt;Fill in the new application form. It’s fine to choose ‘Live’ under ‘Choose an environment for your application’. Click the application name you’ve just created. In my example, it’s called GCF:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240209/step01.webp&quot; alt=&quot;Create an application in Companies House&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you can’t find this page, here’s &lt;a href=&quot;https://developer.company-information.service.gov.uk/manage-applications&quot;&gt;a handy link&lt;/a&gt;. On the next page, there should be a green &lt;strong&gt;Create new key&lt;/strong&gt; button under the heading &lt;strong&gt;‘Keys for this application’&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Give the key a name, a description and select &lt;strong&gt;REST&lt;/strong&gt; as the API type and leave the remaining fields blank:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240209/step01b.webp&quot; alt=&quot;Create an API key in Companies House&quot;&gt;&lt;/p&gt;
&lt;p&gt;Then click the green &lt;strong&gt;Create Key&lt;/strong&gt; button. On the next page, copy the API key. There is a ‘Copy’ link, but this didn’t work for me at the time of writing, so I had to highlight and copy the key manually:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240209/step01c.webp&quot; alt=&quot;Copy API key&quot;&gt;&lt;/p&gt;
&lt;p&gt;You must now convert this key into base64 which will be used to authorise the GET request in Power Automate later.&lt;/p&gt;
&lt;p&gt;Head over to &lt;a href=&quot;https://www.base64encode.org/&quot;&gt;base64encode.org&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And paste your API key &lt;strong&gt;plus a colon&lt;/strong&gt; (:). This is important because the API uses Basic Authentication without a password. The trailing colon is important because it adheres to the Basic Authentication standard, ensuring that the server can correctly parse the base64 encoded string and identify the username (or API key in this case) without expecting a password. Without the colon, the server might interpret the entire base64 encoded string as the username, leading to authentication errors.&lt;/p&gt;
&lt;p&gt;Click the &lt;strong&gt;ENCODE&lt;/strong&gt; button and you should end up with something that looks like this: OTExNWVjNTQtYTA5NC00MDQ2LTlmYmMtMDcwNDg4YjhkOWZmOg==
Don’t try and use this key as it will be deleted by the time you read this article!&lt;/p&gt;
&lt;h2&gt;Step 2: Create a new flow in Power Automate&lt;/h2&gt;
&lt;p&gt;Note that to use HTTP GET (required for this task), you will need a premium license. In my example, I’m going to use a simple manually triggered flow to see who holds charges for a given company on Companies House. In the future I will develop this flow to iterate through a spreadsheet of companies that my client is interested in, dumping out the retrieved data into an Azure SQL database for later reporting. But for now, we’ll keep it simple.&lt;/p&gt;
&lt;p&gt;From your &lt;a href=&quot;https://make.powerautomate.com/&quot;&gt;Power Automate homepage&lt;/a&gt; create a flow, using a manual trigger. Start from a blank ‘Instant cloud flow’:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240209/step02.webp&quot; alt=&quot;Create a flow&quot;&gt;&lt;/p&gt;
&lt;p&gt;Name your flow and select ‘Manually trigger a flow’, then click &lt;strong&gt;Create&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240209/step02b.webp&quot; alt=&quot;Create a flow step 2&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Step 3: Create an HTML GET action&lt;/h2&gt;
&lt;p&gt;First, click on the ‘Manually trigger a flow’ action and in the flyout on the left, click ‘add an input’. Select &lt;strong&gt;Number&lt;/strong&gt;, and type RegNo in the Number field, leaving ‘Please enter a number’ as the default. We will use this company registration number to query Companies House via their API to get the data we want:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240209/step03.webp&quot; alt=&quot;Configure the manual trigger&quot;&gt;&lt;/p&gt;
&lt;p&gt;Next, add an action in your flow by clicking the + button under the manual trigger. In the flyout, search for HTTP and select the HTTP action:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240209/step03b.webp&quot; alt=&quot;Add the HTTP action&quot;&gt;&lt;/p&gt;
&lt;p&gt;We are going to use the ‘charges’ ‘list’ API request to return a list of charges for a company:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://developer-specs.company-information.service.gov.uk/companies-house-public-data-api/reference/charges/list?v=latest&quot;&gt;https://developer-specs.company-information.service.gov.uk/companies-house-public-data-api/reference/charges/list&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Click the newly added HTTP action in the Flow designer and paste this URL into the URI field:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;https://api.company-information.service.gov.uk/company//charges&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We need to supply the company registration number in our request, so click the space inbetween the forward slashes after company and before charges and select &lt;strong&gt;insert dynamic content&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240209/step03c.webp&quot; alt=&quot;Configure the GET request&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the pop up menu, click &lt;strong&gt;See More&lt;/strong&gt; next ‘Manually trigger a flow’, then select &lt;strong&gt;RegNo&lt;/strong&gt; in the list.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240209/step03d.webp&quot; alt=&quot;Insert a dynamic field&quot;&gt;&lt;/p&gt;
&lt;p&gt;Select &lt;strong&gt;GET&lt;/strong&gt; in the Method dropdown and type &lt;strong&gt;Authorization&lt;/strong&gt; in the first Headers box where it says ‘Enter Key’. In the box next to it, type &lt;strong&gt;Basic&lt;/strong&gt; then a space and then paste your base64 API key where is says ‘Enter Value’. You should end up with something like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240209/step03e.webp&quot; alt=&quot;Fully configured HTTP GET request&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Step 4: Parse JSON&lt;/h2&gt;
&lt;p&gt;Add another step directly below your HTTP action, search for and add the &lt;strong&gt;Parse JSON&lt;/strong&gt; action. In the configuration box on the left, click into ‘Content’ and click the lightning bolt icon to open the dynamic picker menu. Under HTTP select &lt;strong&gt;Body&lt;/strong&gt;. The JSON schema we need to provide is a little tricky since Companies House don’t provide a JSON schema and the JSON chargeList resource they give cannot be used to generate one (you &lt;em&gt;can&lt;/em&gt; generate a schema from it, but your flow will fail!). In the end I had to run my flow with just the manual trigger and HTTP action, examine the raw output from the HTTP action (the JSON payload sent by Companies House) and use that to generate the JSON schema. Once I had the JSON output, I added the Parse JSON action back and then clicked the ‘Use sample payload to generate schema’ in the Parse JSON action properties and it gave me this:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;etag&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;total_count&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;integer&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;unfiltered_count&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;integer&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;satisfied_count&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;integer&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;part_satisfied_count&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;integer&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;items&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;array&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;items&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token property&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;etag&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;charge_code&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;classification&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                            &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;charge_number&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;integer&quot;&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;delivered_on&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;created_on&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;satisfied_on&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;particulars&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                            &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;token property&quot;&gt;&quot;contains_floating_charge&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;boolean&quot;&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;token property&quot;&gt;&quot;contains_fixed_charge&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;boolean&quot;&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;token property&quot;&gt;&quot;floating_charge_covers_all&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;boolean&quot;&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;token property&quot;&gt;&quot;contains_negative_pledge&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;boolean&quot;&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;persons_entitled&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;array&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;items&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                            &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;token property&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;
                                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;token property&quot;&gt;&quot;required&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
                                &lt;span class=&quot;token string&quot;&gt;&quot;name&quot;&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;transactions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;array&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;items&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                            &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;token property&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                &lt;span class=&quot;token property&quot;&gt;&quot;filing_type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;
                                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                &lt;span class=&quot;token property&quot;&gt;&quot;delivered_on&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;
                                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                &lt;span class=&quot;token property&quot;&gt;&quot;links&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                    &lt;span class=&quot;token property&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                        &lt;span class=&quot;token property&quot;&gt;&quot;filing&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                            &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;
                                        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;token property&quot;&gt;&quot;required&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
                                &lt;span class=&quot;token string&quot;&gt;&quot;filing_type&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                &lt;span class=&quot;token string&quot;&gt;&quot;delivered_on&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                &lt;span class=&quot;token string&quot;&gt;&quot;links&quot;&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;links&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                            &lt;span class=&quot;token property&quot;&gt;&quot;self&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;more_than_four_persons_entitled&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;boolean&quot;&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token property&quot;&gt;&quot;required&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
                    &lt;span class=&quot;token string&quot;&gt;&quot;etag&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token string&quot;&gt;&quot;charge_code&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token string&quot;&gt;&quot;classification&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token string&quot;&gt;&quot;charge_number&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token string&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token string&quot;&gt;&quot;delivered_on&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token string&quot;&gt;&quot;created_on&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token string&quot;&gt;&quot;particulars&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token string&quot;&gt;&quot;persons_entitled&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token string&quot;&gt;&quot;transactions&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token string&quot;&gt;&quot;links&quot;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your configured Parse JSON action should look like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240209/step04.webp&quot; alt=&quot;Fully configured Parse JSON&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Step 5: Setting up the loops&lt;/h2&gt;
&lt;p&gt;The JSON we are parsing has several nested arrays. We want to iterate through the list of charges for the company specified and then iterate through each charge to get the ‘persons entitled’. We are therefore going to have to set up two loops, one nested within the other.&lt;/p&gt;
&lt;p&gt;Under the Parse JSON action, click the plus button and add an &lt;strong&gt;Apply to each&lt;/strong&gt; action. The usual configuration box pops up from the left. First, rename the action (click on Apply to each) to &lt;strong&gt;Outer&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Now click in ‘Select An Output From Previous Steps’ and click the &lt;em&gt;fx&lt;/em&gt; icon to the right. In the function box type:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;outputs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Parse_JSON&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;body&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;items&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then click &lt;strong&gt;Add&lt;/strong&gt;. Your final config should look like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240209/step05b.webp&quot; alt=&quot;Configuring the outer loop&quot;&gt;&lt;/p&gt;
&lt;p&gt;Next, click the plus button inside the grey box under the ‘Outer’ action&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240209/step05c.webp&quot; alt=&quot;Adding the inner loop&quot;&gt;&lt;/p&gt;
&lt;p&gt;Add another &lt;strong&gt;Apply to each&lt;/strong&gt; action and name this one &lt;strong&gt;Inner&lt;/strong&gt;. Click in ‘Select An Output From Previous Steps’ and click the &lt;em&gt;fx&lt;/em&gt; icon to the right. In the function box type:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Outer&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;persons_entitled&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Step 6: Create an add row to an Excel table action&lt;/h2&gt;
&lt;p&gt;Create an Excel spreadsheet in OneDrive and create a table within this spreadsheet with the following headers: Reg_no, charge_ID and Persons_entitled_name. Now in your flow, click the plus button directly below the Inner loop, search for and add the &lt;strong&gt;Add a row into a table&lt;/strong&gt; (Excel) action.&lt;/p&gt;
&lt;p&gt;In the configuration box, select your spreadsheet (you may be prompted to authenticate to OneDrive) and select your table within your spreadsheet. Under ‘Advanced parameters’, use the checkboxes to show the three headers above (Reg_no, charge_ID and Persons_entitled_name).&lt;/p&gt;
&lt;p&gt;In ‘Reg_no’, click the lightning icon, scroll down through the picker and select &lt;strong&gt;RegNo&lt;/strong&gt; under ‘Manually trigger a flow’&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240209/step06.webp&quot; alt=&quot;Configuring the add row action step 1&quot;&gt;&lt;/p&gt;
&lt;p&gt;In ‘Charge_ID’ click the &lt;em&gt;fx&lt;/em&gt; button and enter the following:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Outer&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;charge_code&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In ‘Persons_entitled_name’ click the &lt;em&gt;fx&lt;/em&gt; button and enter:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Inner&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;name&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The final config should look like this for the ‘Add a row into a table’ action:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240209/step06b.webp&quot; alt=&quot;Configuring the add row action final config&quot;&gt;&lt;/p&gt;
&lt;p&gt;And the final flow should look like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240209/finalflow.webp&quot; alt=&quot;What the final flow looks like&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Step 7: Save and run your flow!&lt;/h2&gt;
&lt;p&gt;Click the Save button. Your flow will be validated and saved. Now click Test. Select ‘Manually’, enter a valid company registration number and then click the blue &lt;strong&gt;Run flow&lt;/strong&gt; button. If there are any charges for that company, the charge code will be written to the Excel table along with the ‘entitled persons’.&lt;/p&gt;
&lt;h2&gt;Further considerations&lt;/h2&gt;
&lt;p&gt;Future development of this flow will involve iterating through a list of companies my client is interested in, rather than having to manually enter a company registration number each time. Some error handling will need to be added to account for 404 ‘not found’ returns by the API and some consideration will be needed for the default API limit of 600 requests within a five minute period.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Fixing the Buffer Time Problem in Microsoft Bookings</title>
    <link href="https://echo3.co/posts/fixing-the-buffer-time-problem-in-microsoft-bookings/"/>
    <updated>2024-01-31T00:00:00Z</updated>
    <id>https://echo3.co/posts/fixing-the-buffer-time-problem-in-microsoft-bookings/</id>
    <content type="html">&lt;p&gt;As I write this post I have just started using Microsoft Bookings. As an IT professional, having the ability for a client to visit my Bookings page and put an appointment in my diary is a great way of avoiding the usual back and forth via email to pin down a mutually convenient time. Out of the box, Bookings offers a good deal of flexibility, including the option of adding &lt;strong&gt;‘buffer time’&lt;/strong&gt; to allow for preparation, travel between appointments, avoiding back to back appointments etc. However, as noted by many here &lt;a href=&quot;https://techcommunity.microsoft.com/t5/microsoft-bookings-ideas/calendar-time-vs-buffer-time/idi-p/2469887&quot;&gt;Calendar time vs Buffer time - Microsoft Community Hub&lt;/a&gt;, this feature is flawed: The first appointment that was created by the system resulted in me ringing my client 30 minutes early, because the buffer time set simply &lt;em&gt;extends&lt;/em&gt; the event in the calendar; the reminder pops up and then I must remember to ring my client 30 minutes later. The ‘time with client’ is buried in the event notes. Not great …&lt;/p&gt;
&lt;h2&gt;A workaround using Microsoft Power Automate&lt;/h2&gt;
&lt;p&gt;By leveraging Power Automate, we can create a flow that automatically adds a ‘buffer time’ event around the booking, ensuring that reminders and scheduling reflect the actual appointment times, not the buffer periods. Here’s how:&lt;/p&gt;
&lt;h3&gt;Step 1: Add the Power Automate integration to Microsoft Bookings&lt;/h3&gt;
&lt;p&gt;Turn off your buffer time for all services in Microsoft Bookings and click the Integrations button in the sidebar:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240131/step_01.webp&quot; alt=&quot;Selecting the &#39;Create a flow&#39; option in Power Automate to begin fixing the buffer time issue in Microsoft Bookings&quot;&gt;&lt;/p&gt;
&lt;p&gt;As of writing, this is the only integration offered:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240131/step_02.webp&quot; alt=&quot;Select Power Automate as a connector for Microsoft Bookings&quot;&gt;&lt;/p&gt;
&lt;p&gt;then click ‘Go to Setup’:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240131/step_03.webp&quot; alt=&quot;Select Go to setup&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Step 2: Create the trigger&lt;/h3&gt;
&lt;p&gt;We want our flow to trigger when a new appointment is created:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240131/step_04.webp&quot; alt=&quot;Create a Flow trigger when an appointment is created in Microsoft Bookings&quot;&gt;&lt;/p&gt;
&lt;p&gt;You should then be presented with Power Automate’s design grid with a sole trigger event ‘When a appointment is Created’ (spot the grammatical errors!). There will be an alarming &lt;em&gt;‘Invalid parameters’&lt;/em&gt; warning. Just click it:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240131/step_05.webp&quot; alt=&quot;The trigger shows an invalid parameters warning&quot;&gt;&lt;/p&gt;
&lt;p&gt;Using the dropdown, select the appropriate booking page. When an appointment is made using this Bookings page, it will trigger your flow automation. I only have one setup in this example.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240131/step_06.webp&quot; alt=&quot;In the trigger properties, select the appropriate bookings page&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Step 3: Calculate buffer times&lt;/h3&gt;
&lt;p&gt;In this step we are going to create two calculated variables that will define the start and end time of our buffer appointment. In my example, I am using a pre and post meeting buffer time of 30 minutes.&lt;/p&gt;
&lt;p&gt;First, click the plus button directly below your trigger in the flow grid:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240131/step_07.webp&quot; alt=&quot;Add the first variable after the event trigger&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the left hand flyout, search for &lt;strong&gt;‘initialize variable’&lt;/strong&gt; and click it:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240131/step_08.webp&quot; alt=&quot;Find and select initialize variable&quot;&gt;&lt;/p&gt;
&lt;p&gt;Under the parameters tab, enter &lt;strong&gt;PreMeetingBuffer&lt;/strong&gt; under Name, use the dropdown to select &lt;strong&gt;String&lt;/strong&gt; under Type and next to Value, click the fx button:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240131/step_09.webp&quot; alt=&quot;Fill in the variable parameters&quot;&gt;&lt;/p&gt;
&lt;p&gt;And copy and paste the following code. We are using the addMinutes function to subtract 30 minutes from the start time of the appointment that triggered the flow:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;addMinutes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;triggerOutputs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;body/StartTime&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now click &lt;strong&gt;Add&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240131/step_10.webp&quot; alt=&quot;Commit the variable by clicking Add&quot;&gt;&lt;/p&gt;
&lt;p&gt;You now need to add another variable, following the steps above, this time clicking the plus sign under the newly appeared &lt;strong&gt;‘Initialize variable’&lt;/strong&gt; action. Call this new variable &lt;strong&gt;PostMeetingBuffer&lt;/strong&gt; and use the following function to calculate the end of our buffer appointment:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;addMinutes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;triggerOutputs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;body/EndTime&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In my example, the buffer appointment will be 30 minutes longer than the triggering event booking.&lt;/p&gt;
&lt;p&gt;You should now have three objects in your Flow: A trigger and &lt;strong&gt;two variables&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;Step 4: Create a buffer calendar event&lt;/h3&gt;
&lt;p&gt;Click the plus sign below the last action you created (the second variable, which should be called &lt;strong&gt;Initialize variable 1&lt;/strong&gt; by default). In the flyout on the left, search for &lt;strong&gt;create event&lt;/strong&gt; and add it:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240131/step_11.webp&quot; alt=&quot;Add the create event action in Microsoft Power Automate&quot;&gt;&lt;/p&gt;
&lt;p&gt;Under the parameters tab, select your calendar from the dropdown (normally just called &lt;strong&gt;Calendar&lt;/strong&gt;) and give it a name under Subject (I’m calling mine &lt;strong&gt;Booking Buffer&lt;/strong&gt;). Click the lightning bolt symbol next to the Start Time:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240131/step_12.webp&quot; alt=&quot;Click the lightning bolt symbol next to Start Time&quot;&gt;&lt;/p&gt;
&lt;p&gt;And select the &lt;strong&gt;PreMeetingBuffer&lt;/strong&gt; variable we created earlier:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240131/step_13.webp&quot; alt=&quot;Select the PreMeetingBuffer variable&quot;&gt;&lt;/p&gt;
&lt;p&gt;For the End time, select the &lt;strong&gt;PostMeetingBuffer&lt;/strong&gt; variable. Under advanced parameters I’ve also done the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Turned reminders OFF&lt;/li&gt;
&lt;li&gt;Show as Busy (by default any event created using this action would show as available)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240131/step_14.webp&quot; alt=&quot;Configure the create event action&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the end, your flow should look like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240131/flow_overview.webp&quot; alt=&quot;Final flow overview&quot;&gt;&lt;/p&gt;
&lt;p&gt;Save your flow and then test it by creating a booking via your Bookings page. You should end up with something like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/20240131/final_step.webp&quot; alt=&quot;A calendar with a buffer appointment around it&quot;&gt;&lt;/p&gt;
&lt;p&gt;The buffer appointment won’t trigger a reminder (if you configured the advanced parameters above) but it will prevent back to back bookings (make sure you configure the ‘busy’ parameter above) and you will only receive calendar notifications for the actual events generated by your Bookings page.&lt;/p&gt;
&lt;p&gt;I haven’t looked at creating flows for deleting or amending these automatically generated buffer events if the original booking is cancelled or amended. Something for another day!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;NB: I did try the Copilot AI to help create the flow, but it wasn’t helpful, so I ended up having to use my brain! 🧠&lt;/p&gt;
&lt;/blockquote&gt;
</content>
  </entry>
</feed>
