Files Migration - GUI frontend, Safe Article Syncing/Conversion, the Easy Way!
Files migration is a powerful article conversion and sync tool that can work for any drive mapped network shares, sharepoint folders, or local files- And now it's even easier and more powerful than ever with safe article conversion/syncing, and an easy-to-use GUI- (download) We've included file and article content hashing so that syncing docs that live in files only updates what has changed and can be ran as many times as desired, it's no longer just a one-time job and your articles can follow your files over their lifespan. This update also includes some less-obvious features that are really handy. Files-Migration utility now checks each file's 'Magic Bytes' to determine migration strategy, in addition to file extension. This is mostly due to the fact that not every file is what it claims to be. Sometimes you might have a docx file masquerading as a doc file. Another neat item to note is that you can place migrated files in any folder structure you want in Hudu, and they will stay in their respective locations, even after re-syncing. 0Introducing Hudu-Magic Python Client for the Hudu API
Finally, an official Python client for Hudu's API For users on Windows, Linux, or Mac! What even is Python? I dislike snakes! python is a high-level, interpreted programming language known for its simple, English-like syntax. It's very readable and intuitive. hudu-magic is a Python package that wraps the Hudu API in a small, class-based client so you can stay in one language, with types and structure that match how Hudu thinks about resources. we also have an examples section that make starting out as easy as possible! Why another client? Thin stack — basically requests and the standard library (plus typing-extensions on older Pythons). No heavy framework tax. You'll find it's quite fast. Pleasant to use — a HuduClient with resources like companies, assets, articles, and models you can save(), delete(), and refresh() Honest to the API — the surface is driven from OpenAPI, so everything sent is exactly as Hudu's API defines. How do I get it? First, make sure you have python installed. If you want a handy oneliner for this to happen with your Windows, Mac or Linux machine, look no further than install-python help page in community Once you have python installed and your virtual environment is created (installer above does this for you), you can simply run: python -m pip install hudu-magic or to upgrade your hudu-magic package python -m pip install hudu-magic --upgrade --no-cache How do I use it? It's easy - first, you make sure your script imports hudu_magic and the HuduClient class. Then, define your client using your instance URL and API key from hudu_magic import HuduClient client = HuduClient( api_key="your_api_key", instance_url="https://yourinstance.huducloud.com" ) Then? Whatever you want. to create a company, you might mycompany = client.companies.create(name="Test Company") to create an asset, you might myasset = client.assets.create(payload={"name": "Router", "company_id": 1, "asset_layout_id": 10}) And Once you have an object (via create or get), you can interact with or modify it directly. For Example. mycompany.list_assets() or mycompany.list_articles() or myasset.update(name="New Name") or myasset.relate_to(myotherasset) These methods and more are also allowed on collections or lists of objects - just be careful! Collection methods are powerful, so ALWAYS make sure to have a current backup. The following would delete all assets for a given company. mycompany.list_assets().delete() If you want specific help with a specific class, endpoint, or resource, you can call describe() or help() methods, such as: client.assets.describe() or myasset.describe() or for more detailed information: client.passwords.help() or myarticle.help() depending on what you're doing, you may need to wrap help/describe methods in a print() statement. For detailed instructions, see community README or pypi (python package index) page It's still a pretty new project, so any ideas, questions, or issues are encouraged! You can submit new issues on the community scripts issues section if you have trouble! 0Moving Assets Between Layouts using GUI - Doing things the Easier Way!
Move assets from one Hudu asset layout to another with a guided GUI workflow. The tool helps you map fields, fill required values, combine multiple source fields with `Smoosh`, handle merge-on-match behavior, and relink supported related objects. https://github.com/Hudu-Technologies-Inc/Community-Scripts/tree/main/Migrations/Migrating-Assets-Between-Layouts Quick summary Run HuduAssetLayoutTransfer.exe Choose the source and destination layouts Pick merge behavior for matching assets Review each destination field in the mapping wizard Confirm the final plan and run the transfer What This Tool Does - Transfers asset data from one Hudu layout into another - Supports field-by-field mapping through the GUI - Lets you use constant values for required destination fields - Supports SMOOSH to combine multiple source fields into one destination field - Can normalize or strip HTML from rich text when needed - Supports structured AddressData destination mapping - Supports ListSelect destination mapping, including optional creation of missing list items - Can merge or skip when a likely matching asset already exists in the destination - Relinks supported related records such as passwords, uploads, articles, and photos What Gets Carried Over - Any source asset fields you choose to map - AssetTag relations, converted into direct relations where applicable - Related passwords - Related procedures - Related articles - Attached uploads - Public photos - Related photos * *Photo relinking requires Hudu 2.41.0 or later. Requirements - PowerShell 7.5.1 or later on Windows PC - A Hudu base URL - A Hudu API key - An existing source layout and destination layout Quick Start 1. Launch the tool Run HuduAssetLayoutTransfer.exe. The tool opens a GUI window and a terminal window. The terminal is mainly there for logging and troubleshooting. 2. Enter your Hudu connection details Provide your Hudu URL and API key. 3. Choose the source and destination layouts Pick the layout you are moving from and the layout you are moving to. You will then get a confirmation step to review or change the selection. 4. Choose merge behavior for matches If an incoming source asset appears to match an existing destination asset, you can choose how the tool should behave. You can also optionally rename the source layout after the transfer is complete. 5. Decide whether to archive the original source assets This is usually recommended once you are confident the transfer plan is correct. 6. Review field mappings If the source and destination layouts already line up closely, the tool may offer a direct transfer path. Otherwise, you will work through the field mapping wizard one destination field at a time. Merge Modes When a source asset appears to match a destination asset, choose one of these behaviors: Merge-FillBlanks: destination wins; source only fills missing values Merge-PreferSource: source wins; destination acts as fallback Merge-Concat: keeps both values for text-like fields and chooses a winner for non-text fields Skip: do not transfer the source asset if a match is found Use Merge-Concat when you want to preserve both sets of notes or descriptive text. Use Merge-FillBlanks when the destination is already your source of truth. Field Mapping Workflow Each destination field is reviewed in the GUI. For every field, choose one mapping mode: Source Field: map from one source field Constant Value: always write the same literal value SMOOSH: combine multiple source fields into one destination field Skip: leave the destination field unmapped The mapping editor also shows a live snapshot of: Configured destination fields Pending destination fields Skipped destination fields Mapped source fields Unmapped source fields Use Back and Next to move through the review loop. Back discards any in-progress edits for the current field unless that field was already saved earlier. Standard Source Mapping This is the most common path: pick a source field and optionally enable Strip HTML. Use Strip HTML when moving from rich text or embed-like source fields into plain text destination fields. Constant Mapping Use this when a destination field should always receive the same value. This is especially useful for required destination fields that have no good source equivalent. ListSelect Mapping For ListSelect destination fields, choose a source field and define which source values should map to which destination list items. This is helpful when the source data is inconsistent and needs to be normalized into one controlled list. Example: Source values like floor, ground, or dirt can map to destination option ground stuff Source values like sunny or sunshine can map to solar stuff Matching is case-insensitive and uses first-match-wins behavior. If the destination list may be missing values, enabling Add missing list items is usually the right choice. AddressData Mapping AddressData fields can be mapped by parts: address_line_1 address_line_2 city state zip country_name The tool builds the destination address object only when at least one address component is present. SMOOSH Mapping SMOOSH lets you combine multiple source fields into one destination field. It is usually most useful for RichText, Heading, or other notes-style destinations. Example rich text output: Serial Number: 9JD2NLAL4 Notes: This is a good computer (link) Example plain text output: 9JD2NLAL4; This is a good computer; John https://huduurl.huducloud.com/a/computerslug Per-Job Settings After field mapping, the tool asks a few follow-up questions depending on how your plan is configured. $includeblanksduringsmoosh (default - $false) - Includes empty values when building SMOOSH output. $includeLabelInSmooshedValues (default - $true)- Prepends the source field label before each SMOOSHed value. $excludeHTMLinSMOOSH (default - $false)- Strips HTML and flattens SMOOSH output into cleaner plain text. $includeRelationsForArchived (default - $true) Preserves relations even when the related object is archived. How Matching Works Before creating a destination asset, the tool checks whether a likely match already exists. A source asset is treated as a likely match when: It belongs to the same company as a destination asset, and The names are the same, or the destination name starts with or ends with the source name Very short names are intentionally not matched too aggressively. This matching logic helps prevent accidental duplicates while still allowing flexible merge behavior. Review, Outputs, and Logs Before the transfer runs, the tool shows a final summary of the mapping plan, including: Direct mappings Constants SMOOSH target and source count Skipped fields Merge behavior Archive preference After the transfer, the tool writes a timestamped JSON results file such as: transferresults_YYYYMMDD_HHMMSS.json The console output also includes field-level and relation-level progress messages to help with troubleshooting. Troubleshooting Tips Plain text fields showing HTML Enable Strip HTML on the specific field mapping, especially when the source field is RichText, Heading, or Embed-like content. ListSelect values not landing where expected Double-check the whenvalues mapping and remember that matching is case-insensitive and uses the first matching destination option. Email fields look messy Make sure the destination field is typed or labeled as an email field so the email cleanup logic can normalize the value correctly. Address casing looks odd The helper logic normalizes common US state names and country variants such as US, USA, and United States. Tips Prefer matching destination field types when possible Use constants to satisfy required destination fields that have no good source value Use SMOOSH for notes-style destinations rather than trying to cram several inputs into a single normal field For plain text destinations, consider both Strip HTML and excludeHTMLinSMOOSH=$true Start with a small test layout or a small company subset before running a large migration --- Changelog - v0.3 - Initial public draft of the layout-switching documentation, November 19, 2025 - v0.5 - Added merge-on-match options, February 23, 2026 - v0.6 - Added constant fallback values and combined relation handling on match, March 3, 2026 - v0.8 - Added password, photo, public photo, and upload reattribution, March 4, 2026 - v1.0 - Finalized GUI, added forward,back buttons, and field indicator panel. 1Self-Hosters: Consider Migrating your old AssetTags to the new AssetTag format-Here's How:
Hey there, self-hosters, DIY fanatics, and fellow linux penguins- I wanted to post a guide for our self-hosters for migrating from the old AssetTag format- While many of you have likely already made the switch, there's likely a few that haven't yet. Thankfully, doing this is super-easy. it is always a good idea to kick off a backup first First, you'll need to access your container host, which is most likely a linux host. It doesn't matter whether you access a headless box via ssh or a fancy desktop environment. You'll just need to start a new terminal session (with a user in the docker group or root), and run the below command to start the process- docker exec -it -u 0 $(docker ps --filter "name=app" --format "{{.ID}}") bin/rake convert_asset_tags:to_new_format If you're nervous or have a large instance, you can tee the output to a file for later review with the below one-liner. This just results in everything being logged to a file named something like- tags_result_1775068117.txt docker exec -it -u 0 $(docker ps --filter "name=app" --format "{{.ID}}") bin/rake convert_asset_tags:to_new_format 2>&1 | tee "tags_result_$(date +%s).txt" You'll see a stream of text while this is working through the process. It's quite fast, but you'll see exactly how many fields have been converted to the new AssetTag format (and how many already were in this format) It's always good to have the latest + greatest! Let us know if you have any questions! 0Central Hudu Audit Report
HUDU CENTRAL AUDIT REPORT SCRIPT INSTRUCTIONS See link in Community Repo ========================================================= WHAT THIS SCRIPT DOES --------------------- The script signs in to Microsoft Azure, reads your Hudu API key and Hudu site URL from Azure Key Vault, calls the Hudu API, and builds one Central Knowledge Base article with inventory counts. Each run refreshes that article's HTML content. The KB article includes: - Executive Global Summary: fixed list of resource types (companies, assets, layouts, KB articles, passwords, expirations, folders, password folders, procedures, networks, websites, IP addresses, rack storages/items, VLANs, VLAN zones) with Active / Archived / Total where the API supports it. - Per-company totals and a full Company Resource Breakdown (every company, every listed resource type, zeros included), plus per-company archived sum and grand total rows. - Asset detail sections (by layout globally, by company, by layout per company). - Data Retrieval Errors: any API/list failures and notes (for example duplicate KB article titles). - Article selection: the script looks up the KB article whose title exactly matches $CentralReportArticleName (default "Central Audit Report"). If found, it updates that article. If several articles share the title, it updates the one with the latest updated_at timestamp (tie-break: higher article id) and records a warning in Data Retrieval Errors listing the other ids. If not found, it creates a new article with that title. - Documentation, that lives in the comment block at the top of: hudu_central_audit_report.ps1 REQUIREMENTS (READ CAREFULLY PLEASE) ----------------------------- 1) PowerShell 7 or newer is required. Do not use Windows PowerShell 5.1 for this script. The script file includes #Requires -Version 7.0 so it will refuse to run on 5.1. 2) Run PowerShell 7 "As Administrator" for the session where you will execute the script. Some environments need this for module installs or policy; use an elevated window for consistency. 3) Entra ID + Azure Key Vault secrets. This script does not embed your Hudu API key or URL in plain text. You sign in with the Azure Az PowerShell modules; the script then calls Get-AzKeyVaultSecret. Note: "Entra ID" (Azure AD) is only how your admin may sign you into Azure. The script itself reads named secrets from a Key Vault. In Entra you can create secrets under: Azure Portal(Entra ID) → Key vaults → your vault → Objects → Secrets. 4) Your Azure account (or the account you use with Connect-AzAccount) needs at least Get and List on the secrets used for Hudu URL and Hudu API key. The script does not write any Key Vault secrets for the report. CONFIGURATION YOU MUST EDIT (IN THE SCRIPT) -------------------------------------------- Open hudu_central_audit_report.ps1 and find the section: CONFIGURATION - EDIT THESE VALUES Set these to match your Key Vault and secret names: $AzVault_Name = "your-key-vault-name" $AzVault_HuduApiKeySecretName = "AUDITAPI" (Secret value = your Hudu x-api-key. ~ You can get this in your Hudu instance as a Super-Admin from Admin > API Key.) $AzVault_HuduBaseDomainSecretName = "AUDITURL" (Secret value = your Hudu base URL or hostname. Examples that all work after normalization: hudu.com | https://hudu.com | https://hudu.com/ ) $CentralReportArticleName = "Central Audit Report" (Exact KB article title the script creates or updates. Must match the article name you want in Hudu.) -ReportDetailLevel Controls how much data the script includes in the KB article. You can choose from: Executive (default) Includes global summary and data retrieval errors only. Smallest payload. Use if the KB article fails to render (500 error) due to size. Full Includes all tables: global summary, company totals, company resource breakdown, assets by layout, assets by company, assets by layout per company. Best for complete auditing. May hit Hudu HTML size limits on very large instances (500+ companies). Compact Includes global summary, company grand totals, assets by layout (global), and assets by company. Skips heavy per-company breakdown tables. Good balance of detail and size. Example usage: -ReportDetailLevel Compact Full audit example: -ReportDetailLevel Full CREATING KEY VAULT SECRETS (ENTRA ID STEPS) ------------------------------------------ 1) Azure Portal → Key vaults → select your vault. 2) Objects → Secrets → Generate/Import. 3) Name: use the same name as in the script (e.g. AUDITAPI, AUDITURL). 4) Secret value: paste the Hudu API key or URL/domain as appropriate. 5) Save. DUPLICATE KB ARTICLE TITLES ---------------------------- Avoid duplicate titles. If more than one article uses $CentralReportArticleName, the script updates the most recently updated article (see Article selection above) and logs a warning with the other article ids. Consolidate or rename duplicates in Hudu so only one central report article remains. OPTIONAL SWITCHES ----------------- -DryRun Connects and gathers data but does not POST or PUT the KB article. Prints what it would do. -VerifyEndpoints After validating Hudu credentials, calls each API path the report uses and prints row counts. Does not update the KB article. Use this to confirm API access and pagination behavior. -ReportDetailLevel Controls how much data the script includes in the KB article. Choose from: Executive (default): Smallest payload. Use if the KB article fails to render (500 error) due to size. Includes global summary and data retrieval errors only. Full: Includes all tables: global summary, company totals, company resource breakdown, assets by layout, assets by company, assets by layout per company. Best for complete auditing. May hit Hudu HTML size limits on very large instances (500+ companies). Compact: Includes global summary, company grand totals, assets by layout (global), and assets by company. Skips heavy per-company breakdown tables. Good balance of detail and size. Examples -ReportDetailLevel Compact Full audit: -ReportDetailLevel Full NORMAL RUN (UPDATE OR CREATE THE ARTICLE) ----------------------------------------- 1) Install PowerShell 7+. 2) Open PowerShell 7 as Administrator. 3) Install Az modules if prompted (script may install Az.Accounts and Az.KeyVault for the current user). 4) Edit the CONFIGURATION section in hudu_central_audit_report.ps1. 5) Run: pwsh -File "C:\path\to\hudu_central_audit_report.ps1" For a full (largest) report in one run: pwsh -File "C:\path\to\hudu_central_audit_report.ps1" -ReportDetailLevel Full (Use your actual path to the script folder.) 6) Sign in to Azure if Connect-AzAccount appears. 7) Wait for "Updated central KB article" or "Created central KB article" action in Hudu. EDGE CASES AND TROUBLESHOOTING ------------------------------ - Empty or wrong AUDITURL: fix the secret value; the script normalizes scheme and trailing slashes but must end with a resolvable host. - Empty AUDITAPI: validation fails with a clear error. - Access denied on Key Vault: grant your identity Secret Get and List on the vault (or on those secrets via RBAC). - "Endpoint verification" failures: run with -VerifyEndpoints and read which path failed; often, pagination or permissions on a specific resource type. - If you rename the central article in Hudu but not in the script, the script will create a new article using $CentralReportArticleName. - If the KB article fails to render (500 error) on very large instances, try -ReportDetailLevel Compact or Executive to reduce payload size. Try increasing your rate limit if you run into this issue. Additional resources may be required if the API rate limit change does not address your issues. 2Want a way to migrate your data from IT Glue easily?
Migrating from IT Glue is the biggest new-customer request we get. We have amazing scripts that handle this, so we thought: how about an easy-to-run tool?! Here's what it looks like: You can find the latest copy of the executable (Windows 10+ | x86_64 only) in our main GitHub repository here: ITGlue-Hudu-Migration (file calledITGlue-Hudu-Migration-GUI.exe) Or directly download the executable: https://github.com/Hudu-Technologies-Inc/ITGlue-Hudu-Migration/raw/refs/heads/main/ITGlue-Hudu-Migration-GUI.exe 2Hudu n8n node v1.9.2 released - improved ai tools
Max Soukhomlinov has just released version 1.9.2 of the Hudu n8n community node - and this one’s a big upgrade for AI workflows. What's new: You can now add the Hudu node directly as a tool inside your n8n workflows. Just: Specify the target entity Define the allowed operations Everything else is handled by the node. You can install n8n-nodes-hudu here: https://www.npmjs.com/package/n8n-nodes-hudu For more information, see this Reddit Post! 0Activity Log Drilldown Helper
Interactive Filter + Human‑Readable Formatter This script is a small activity log explorer for Hudu. Instead of writing individual Where-Object filters every time you want to answer questions like: “Show me everything where record_type is Article” “Which user did update actions?” “What activity happened from this IP?” “What details were included in those events?” …it pulls a sample of activity logs, lets you pick an attribute, then pick a value, and prints the matching logs back out in a readable, story‑like format. Why This Exists Hudu activity logs are powerful — but digging through them manually gets old fast. This helper turns raw activity data into an interactive, explorable audit tool that’s fast, readable, and human‑friendly. How to Run Open a new pwsh7 session on your windows device and perform one of the following: the Oneliner [Ninja-Style] irm 'https://raw.githubusercontent.com/Hudu-Technologies-Inc/Community-Scripts/refs/heads/main/Administration/Auditing-Activity-Logs/Audit-ActivityLogs.ps1' | iex Clone+Start [Samurai-Style] (requires git scm installed) git clone https://github.com/Hudu-Technologies-Inc/Community-Scripts; cd .\Community-Scripts\Administration\Auditing-Activity-Logs; . .\Audit-ActivityLogs.ps1; Download-Extract-Run [Ashigaru-Warrior-Style] Invoke-WebRequest https://codeload.github.com/Hudu-Technologies-Inc/Community-Scripts/zip/refs/heads/main -OutFile Community-Scripts.zip; Expand-Archive -Path .\Community-Scripts.zip; cd .\Community-Scripts\Community-Scripts-main\Administration\Auditing-Activity-Logs; . .\Audit-ActivityLogs.ps1; After submitting required infos, You’ll see: A numbered list of attributes → pick one A numbered list of values → pick one Matching activity entries printed in green Common Use Cases Audit a single action type “Show me all delete actions” Track changes to a specific record type “Only Passwords activity” Investigate suspicious behavior “Everything from IP x.x.x.x” User troubleshooting “What did this user do around that time?” Client / company review “What activity happened under company X?” How It Works 1. Pulls Activity Logs You start with a set of activity log records (whatever Get-HuduActivityLogs returns in your environment). 2. Builds Drilldown Attributes + Values The script scans all properties present across the returned objects and builds a lookup table like: action → { create, update, delete, … } record_type → { Article, Asset, Password, … } user_name → { Mason, Cameron, … } company_name → { Acme Inc, Contoso, … } ip_address → { 10.0.0.5, 203.0.113.42, … } This lets you browse the dataset without memorizing field names. 3. Interactive Selection You are prompted to choose: An attribute to filter by A value for that attribute No manual filtering required. 4. Human‑Readable Output For each matching activity log entry, the script prints a friendly summary including: Who did it (name → email fallback logic) What action occurred Which record (type + name) Company context Source (browser / app + OS) IP address Details (if present) Timestamp (formatted_datetime) The result reads more like an audit trail than raw JSON. Menu Reference Attribute Selection This answers the question: “Which field do you want to filter on?” Common examples: record_type — Article vs Asset vs Password action — create / update / delete user_email / user_name company_name ip_address app_type 0Flags and Flagtypes - Handling Data Quality, Ownership, and Special Cases, the EZ Way
Flagging items can help identify critical items, high-sensitivity areas, items that need attention, or other conditions that require a second thought. Here are some ways you can easily add such flags and apply them to suit your organizations needs- Flags and FlagTypes can help tighten focus around items in Hudu that need special care, more attention, review or revision. Being a powerful feature set for organization and notation, it's a good capability to have a handle on as a Hudu user, administrator or power-user. Notes on FlagTypes FlagTypes can be applied to a variety of objects in Hudu Articles Networks Ip Addresses VLAN Zones Assets Companies Procedures Rack Storages Passwords While these are general categories that something might fit in, how you use them is up to you. The best part? You can pick from a variety of colors to represent any of your FlagTypes You might have a FlagType named 'Needs Attention' or 'Under Review' for quality assurance purposes with the color Orange You might have a FlagType named 'Handle With Care' or 'Special Case' for special cases or edge cases with the color Pink You might have a FlagType named 'Mason' or 'Cameron' to define ownership of article or object with the color Green You might have a FlagType named 'Invoices' or 'Cash on Delivery' to define characteristics of a company with the color Purple You might have a FlagType named 'Deprecated' or 'EOL' to flag objects that aren't going to be in use much longer with the color Blue You might have a FlagType named 'In-Service', 'Checked-Out' or 'Not-In-Service' to flag objects that are in a special state with the color Grey Notes on Flags Flags represent the individual attribution of a flagtype to an object For example, if you have a FlagType named 'Needs Attention' or 'Under Review' for quality assurance purposes with the color Orange, you might apply that to 6 passwords, 2 companies, and an asset. This would result in 9 new Flag objects. Flag objects can be revoked or changed at any time and any single object can have one, none, or several distinct/unique flagtypes attributed to them. Firstly, you'll need to load the prerequisite helper functions with this one-liner (using pwsh7+), then you're ready to roll. Start a new pwsh session and run: irm 'https://raw.githubusercontent.com/Hudu-Technologies-Inc/Community-Scripts/refs/heads/main/Administration/Flags-And-Flagtypes/Prerequisites.ps1' | iex You can run this command from an existing powershell session start a new one Run-Command Dialog (Start+R / ❖+R) and typing 'pwsh' If all the prerequisites are met (updated HuduAPI module and Hudu 2.40.0 or newer), you'll get a nice green message indicating that you're ready to go- If not, you might try with elevated permissions or after upgrading your hudu instance. Let's go through some scenarios. Of course, you can and are encouraged to modify these scenarios to better suit your needs Scenario 1: we want to flag all assets that haven't been updated since $flagDate First, you'll need to set your $flagDate variable. This can be any date that you think any given asset should have been updated since. Most date formats are valid to set here, but to keep the day and month sections from being conflated with one another, the below formats are good. We give preference to international formats here. $flagDate = '26 Jan 2026 15:56' # $flagdate = '26-01-2026 15:56' # $flagdate = '26/01/2026 15:56' with your flagdate variable set, we can compare the dates, assign some flags, and take a closer look at these stale assets as a team- $allAssets = Get-HuduAssets | Where-Object {Compare-DateStrings -a $_.updated_at -b $flagDate} $staleAssetesFlag = Select-OrCreateFlagType -description "Flag all assets not updated since $flagDate" $allassets | ForEach-Object {New-HuduFlag -flagTypeId $staleAssetesFlag.id -flagableType "asset" -flaggableId $_.id} Scenario 2: we want to flag all articles that have less than 100 characters in Length For this snippet, we'll want to set what we think is an acceptable minimum length (in characters) for articles. Any articles shorter than this, we will flag for review- $minimumAcceptableLength = 100 $shortArticles = Get-HuduArticles | Where-Object {"$($_.content)".length -lt $minimumAcceptableLength} $shortArticlesFlag = Select-OrCreateFlagType -description "Flag all articles with less than 100 characters" $shortArticles | ForEach-Object {New-HuduFlag -flagTypeId $shortArticlesFlag.id -flagableType "article" -flaggableId $_.id} Scenario 3: lets get a handle on weak passwords! Weak passwords should be under a magnifying glass, since they can create a major security gap. In this example, we'll set a variable for minimum password length and for minimum unique characters used. $minimumpasswordLength=8 $minimumCharsUsed=6 Once you've defined what you think are acceptable minimum values for passwords, you can 'flag away' $weakPasswords = get-hudupasswords | Where-Object {"$($_.asset_password.password ?? $_.password)".length -lt $minimumpasswordLength -or ("$($_.asset_password.password ?? $_.password)".ToCharArray() | Select-Object -Unique).Count -lt $minimumCharsUsed} $weakPasswordsFlag = Select-OrCreateFlagType -description "Flag all weak passwords with either less than $minimumpasswordLength chars, or fewer than $minimumCharsUsed different chars" $weakPasswords | ForEach-Object {New-HuduFlag -flagTypeId $weakPasswordsFlag.id -flagableType "password" -flaggableId $_.id} Scenario 4: we want to flag all procedures that have too-few tasks/steps If your organization has some procedures that might need to be evaluated, this can be a great starting point Firstly, we'll define what we think is an acceptable minimum number of steps or tasks a procedure should have $minimumAllowedSteps=2 And we can then apply that to all the procedures in Hudu with the snippet below $weakProcedures = Get-HuduProcedures | Where-Object {$_.total -le $minimumAllowedSteps} $proceduresFlag = Select-OrCreateFlagType -description "Flag all procedures that have $minimumAllowedSteps or fewer tasks/steps" $weakProcedures | ForEach-Object {New-HuduFlag -flagTypeId $proceduresFlag.id -flagableType "procedure" -flaggableId $_.id} Scenario 5: we want to flag all rack storages that are underutilized (less than X% capacity) First, we'll need to define what we consider to be underutilized (as percent utilization). In this example, we'll suppose 10% or lower constitutes an underutilized rack storage, but you can change this as best suits your needs $minimumUtilization=10 Then, we're ready to flag some rack storages $underutilizedRacks = Get-HuduRackStorages | Where-Object {[int]($_.utilization) -le $minimumUtilization} $racksFlag = Select-OrCreateFlagType -description "Flag all rack storages that are underutilized (less than $minimumUtilization% capacity)" $underutilizedRacks | ForEach-Object {New-HuduFlag -flagTypeId $racksFlag.id -flagableType "rack" -flaggableId $_.id} Scenario 6: we want to flag external networks so that they will be recognized and handled with care This one is pretty straightforward and doesn't require any user-defined variables. We're just selecting for external networks. It can help to make these external networks easily identifiable so they may be handled with extra care $externalNetworks = Get-HuduNetworks | Where-Object {[int]($_.network_type) -eq 1} $externalNetworksFlag = Select-OrCreateFlagType -description "Flag all external networks" $externalNetworks | ForEach-Object {New-HuduFlag -flagTypeId $externalNetworksFlag.id -flagableType "network" -flaggableId $_.id} Scenario 7: lets flag all publicly shared articles so that we don't update them with sensitive info by mistake This is a pretty big one, especially if you have many internal and external articles to differentiate. $publicArticles = Get-HuduArticles | Where-Object {$_.enable_sharing -or $_.share_url} $publicArticlesFlag = Select-OrCreateFlagType -description "Flag all publicly shared articles" $publicArticles | ForEach-Object {New-HuduFlag -flagTypeId $publicArticlesFlag.id -flagableType "article" -flaggableId $_.id} 0Custom Microsoft Graph user imports
Import ms365 users into Hudu without creating hudu cards. I'm personally not a fan of the cards integrations in Hudu, so I created a script that: Pulls users from ms365 graph based on specific distribution groups such as "All company employees" or whatever you use. Allowing you to add any graph data to the user asset in Hudu. Currently includes name, email, Phone number, Teams number, Title, Department. Adds a list of all collaboration groups, security groups, mail-enabled security groups and distribution groups to the user asset. Can easily be built upon the n8n flow to add more elements to the user asset. 0Converting from TextFields to ListSelect (DropDown) Fields
Have you ever had a text field that you wish was.... More consistent? Maybe like a listselect field? It's something that comes up now and again and is easier than ever. This helpful little snippet is in our Community Repo, or can be invoked with this oneliner, below. pwsh -NoProfile -ExecutionPolicy Bypass -Command "irm 'https://raw.githubusercontent.com/Hudu-Technologies-Inc/Community-Scripts/main/Administration/Listifying-Text-Fields/Listify-Text-Field.ps1' | iex" First, you can select any layout that has a TextField Then, you can simply select the field you would like to make a new ListSelect field for as a replacement. All of your data will be carried over to this new field and all unique values will be available in a new list assigned to it! After you select the desired field you'd like to change over, you'll be asked to confirm-- and if something doesn't seem right, you can exit with CTL+C key combination After you confirm by hitting enter, it will get to work. The script will: grab all unique values for this field in your selected layout create (or update) a new list containing unique values add this field to your chosen layout copy over values from source field to new list field for all assets in layout And that's it! You may want to confirm things are looking as-expected, and then wrap up by removing the original field. Conveniently, this script opens up the administrative page for your chosen layout and the global asset view for your chosen layout. Happy Listifying! 0Create Standardized Folder Structure Across KBs
Want a way to create a standardized folder structure across all of your Client's KB sections? Maybe you want a standard structure something like: SOPs Adminstrative New User Setup Network Request Forms Troubleshooting Network Servers Printers Using Script to create a templated KB Folder Structure Across Companies This guide shows what you will need: How to create the Key Vault How to create the two secrets How to use them in your script A minimal working example ============================================================ This script utilizes Azure Key Vault keys for security so it's not storing your actual API key information. Create Azure Key Vault 1. Create the Azure Key Vault Step 1 — Open Azure Portal Go to: https://portal.azure.com Search for Key Vaults → click Create. Step 2 — Required fields Project details: Subscription: your subscription Resource group: choose or create one Instance details: Key Vault name: must be unique (example: Hudu-Automation-Vault) Region: pick your region Pricing tier: Standard Access Configuration: Permission model: Role-based access control (RBAC) (Required for PowerShell scripts) Networking: Public access: Enabled Allow all networks (for now) Click Review + Create → Create. 2. Give Yourself Permission In your new Key Vault → left menu → Access Control (IAM) Click Add → Add role assignment Select role: Key Vault Secrets User (read secrets only, recommended) OR Key Vault Administrator (full access — only for setup) Add your Azure user Save You now have permission to read secrets from PowerShell. 3. Create the Two Required Secrets Inside your Key Vault → Secrets → Generate/Import. Secret #1 — Hudu API Key Name: HuduAPIKey Value: paste the API key from Hudu Path in Hudu: Admin → API Keys Click Create. Secret #2 — HuduBaseURL Name: HuduBaseURL Value example: https://docs.yourcompany.com OR: docs.yourcompany.com (Both work — the script normalizes it.) Click Create. Run the Script 4. Use the Script (Clean Version) Enter your Azure Vault Key and Hudu URL at the top of the script before running. Select either options 1 or 2 after company listings. Option 1 will apply your folder creation to all companies. Option 2 will apply your folder creation to the company IDs you enter. If you select option to please format your IDs as follow: 1,2,4,5,etc How to create folders: Here's an example of what you would type: testing 0 testing 1 testing 2 testing 3 testing 4 testing 5 testing 6 testing 7 testing 8 testing 9 testing 10 testing 11 This creates the following structure: testing 0 (root) testing 1 testing 2 testing 3 testing 4 testing 5 testing 6 testing 7 testing 8 When done follow confirmation messages, and accept the creation. The script will then create the folders, and silently remove any credentials used(API, Domain, Azure Secrets, etc). You can view the script here: 0Advanced CSS - Customize It All
Hudu is highly customizable, not only with regards to asset layouts and data organization, but also presentation. As many folks are likely already aware, custom CSS can be placed for all-users by a user with sufficient permissions to do so. At face value, this might seem like just fonts, colors, decoration, it can tune your experience to make Hudu uniquely yours. We've added a compendium of CSS tweaks over in the Community Scripts Github Repo It includes these topics to start with, but any submissions are welcome, either directly or by-message! Topics: Articles And Contents MagicDashes Assets and Fields Search and Navigation Companies and Logos FontAwesome Icons 0Audit Company Assets by Leveraging the HuduAPI PowerShell Module
Did you know that there's a PowerShell Module for the HuduAPI created by the community? You can find details on the PowerShell Module here: https://github.com/Hudu-Technologies-Inc/HuduAPI Partners have asked us for a way to audit their companies to determine which companies have little to no assets within them. Attached is an example script for doing just that. What it does Prompts you for your API Key and URL Generates a CSV file with the following data: Company ID Company Name Number of Assets Number of Passwords Number of Articles Running the Script Download the .ps1 file Run it, that's it! The script will prompt you for your API key and Hudu URL Once the script finishes, it will clear your API Key and URL information from your PowerShell session Considerations The PowerShell module does require PowerShell 7+ (pwsh.exe) to run properly, so the script will attempt to install/use PowerShell 7 if it can, it will error-out otherwise. If you have a lot of companies (1000+), it may take a while for the script to run and generate the CSV file, it's likely not stuck! 0Proper asset export to excel
n8n Automated webhook that retrieves all data of an asset type based on asset layout ID. Exports in excel file with list item names instead of ID, as you would expect an export to do. Maps [list id] to the actual name, useful for further data processing in excel. Works dynamically with all forms of asset layouts. To make it work, enter your Hudu api key in all HTTP nodes. Create an asset layout, for example call it "Export". Add "</> Embed" field. When creating the asset enter the webhook link from n8n. The n8n automation must be "active" and the webhook URL must be production instead of test. To make things more user friendly in Hudu, I made the embedded webhook button more pretty: <div style="padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 10px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); margin-bottom: 30px;"> <h2 style="margin-top: 0; color: white; font-size: 24px;">💻 Export Computer</h2> <p style="color: white; margin-bottom: 20px;">Download all computer assets with readable data</p> <a href="<Your webhook production link>?layout_id=1&company_id=1" style="display: inline-block; padding: 15px 30px; background: white; color: #667eea; text-decoration: none; border-radius: 8px; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.2);">📥 Export Now</a> <p style="color: white; font-size: 12px; margin-top: 20px; margin-bottom: 0;">ℹ️ Excel file will download automatically</p> </div> 1Magic Dash Management via CLI
This one is courtesy of David Kniskern, the one, the only. Also available in the Community Meta-Repo Overview The Hudu Magic Dash Manager is a powerful PowerShell script designed to provide comprehensive management of Magic Dash tiles within your Hudu instance. This tool offers an intuitive, menu-driven interface for creating, updating, deleting, and managing Magic Dash tiles across all companies in your Hudu environment. Prerequisites System Requirements PowerShell 7.5.1 or higher Windows 10/11 (or compatible PowerShell environment) Internet connectivity to your Hudu instance Azure Key Vault access (for credential management) Required Access Hudu API Key (24-character key from your Hudu instance) Hudu Instance URL (your Hudu domain without trailing slash) Azure Key Vault with stored credentials Magic Dash functionality enabled in your Hudu instance Installation & Setup Step 1: Download the Script A. clone the community repo git clone https://github.com/Hudu-Technologies-Inc/Community-Scripts B. download just this script from Github $(Invoke-WebRequest -uri "https://raw.githubusercontent.com/Hudu-Technologies-Inc/Community-Scripts/refs/heads/main/Information-and-Visualization/Managing-MagicDashes/Managing-MagicDashes.ps1").content | Out-File .\Managing-MagicDashes.ps1 Step 2: Azure Key Vault Setup If you haven't set up keyvault or fetching your secret fails, you will be asked to type in your Hudu API key, which is removed from memory when script completes Create Azure Key Vault (if not already created): Add Hudu API key as a new secret in this vault Change the $VaultName variable in this script to the name of your vault Change the $ApiKeySecretName variable in this script to the name of your secret which has your Hudu API key Step 3: Verify Installation Invoke the script- (if you cloned Community repo) . .\Information-and-Visualization\Managing-MagicDashes\Managing-MagicDashes.ps1 (if you downloaded directly) . .\Managing-MagicDashes.ps1 Configuration Azure Key Vault Configuration The script expects the following secrets in your Azure Key Vault: Secret Name Description Example Value HuduAPIKey Your 24-character Hudu API key abc123def456ghi789jkl012 VaultName Your Key Vault Name Rickys-Vault Usage Guide Starting the Script Open PowerShell as Administrator Navigate to the script directory Run the script: .\interactive_magic_dash_manager.ps1 Main Menu Navigation Upon startup, you'll see the main menu: 🎯 WELCOME TO THE MAGIC DASH MANAGER🎯. ┌─ 1. Select a company with existing Magic Dash tiles ├─ 2. Create a new Magic Dash tile for any company └─ 0. Exit Option 1: Managing Existing Tiles Select a company from the list of companies with Magic Dash tiles Choose management option: Mass Delete - Delete all tiles for the company Individual Delete - Select specific tiles to delete Update Tiles - Modify existing tile properties Create New - Add a new tile to the company Option 2: Creating New Tiles Enter company name (case-sensitive) Provide tile details: Title - Name of the Magic Dash tile URL - Link destination (must include https://) Description - Optional description text Navigation Tips Type '0' at any input prompt to return to the previous menu Type 'No' at any Yes/No prompt to go back to the previous page Press Enter to keep current values when updating tiles Use '0' to exit any menu and return to the main menu 1Expiration Report -> Email
Here is a script that mimics the Alert Expiration Report that can be tweaked and scheduled to your liking using the Hudu API to pull the Asset and Website expiration information It requires PowerShell 7 Thank you ChatGPT 1All-Files Hudu Article Migration
Get it Here or from Community Scripts / Meta Repo Do you have a stack of files, possibly not well-organized, possibly of different filetypes that you need to move into Hudu? Don't want to waste time converting them to a searchable/editable format? This script is a lifesaver and can help you achieve high quality documentation without the headache. It's designed to be easy-to-use, have defaults, and flexibility for any directory structure. Any accessible mapped drive containing documents is your oyster. All files are left completely intact and conversion operations only use temporary copies of source files. Original source files are by-default attached to article for reference and posterity. What it can do Generates Hudu articles from many different types of source material (directories, files, PDFs, Office docs, HTML pages). Converts hundreds of document formats on-the-fly, extracts and places images, and keeps the original. Allows for use with any existing Sharepoint, OneDrive, or Network share as-is--Just filter-in or filter-out the types of files you want in Hudu. Non-Document files can be uploaded as-is and attributed to an article, so long as you don't explicitly omit that filetype. Getting Started You'll need these prerequisites Hudu Instance and API key (version 2.39.5 or newer) Powershell 7.5.1 or newer (Windows) Libreoffice (if you don't have LibreOffice, you'll be prompted to install the newest stable version when running the script) A Directory containing documents that you want in Hudu Running Running is easy. Once you've downloaded your script and navigated to this project's directory in Powershell, you can run it! There is one required parameter, /TargetDocumentDir, but like all the other parameters, if we need to know, we'll prompt! Parameter Description TargetDocumentDir Directory containing the articles to process. DocConversionTempDir Temporary directory for PDF/HTML/LibreOffice conversions. filter Case-insensitive file or directory filter. Supports wildcards (e.g., *.pdf, keep*). DestinationStrategy Determines how articles are added to Hudu: GlobalKb, SameCompany, or VariousCompanies. Optional; prompts if omitted. SourceStrategy Controls recursion: use Recurse to search subdirectories; omit to stay at a single level (will prompt if missing). IncludeDirectories Whether to treat directories as a resource. Recommended when not using recursive source strategy. IncludeOriginals Include original documents in the article along with converted versions. Default: true. MaxItems Maximum number of files/directories allowed in a batch. Default: 500. MaxTotalBytes Maximum allowed total size of incoming documents. Default: 5 GB. MaxDepth Maximum recursion depth when using Recurse. Default: 5 levels. *NOTE- If you elect to include directories as source-objects with includeDirectories, SourceStrategy will be set to 'TopLevel' to prevent duplication. Here are some handy usage examples: Say I have some mission-critical .docx files on our Sharepoint Drive that we need to add to hudu, they are in various folders, sometimes pretty deeply-nested. . .\Files-For-Hudu.ps1 -TargetDocumentDir V:\2025\Q1 -SourceStrategy Recurse -Filter "*.docx" -MaxDepth 10 We have a bunch of various files on our Drive-Mapped Azure Blob storage that were never well-organized. There are in less-common formats like "csv",".rtf", ".txt", ".md", ".wpd",".xls", ".xlsx", and we want them in Hudu! . .\Files-For-Hudu.ps1 -TargetDocumentDir B:\Company\Billing-Exceptions But what can I expect to see in Hudu when uploading and converting these documents? PDF, Richtext, Document formats convert pretty nicely into native HTML Hudu KBs. Sometimes there are minor changes to the way they look, especially if those documents had embedded fonts. Largely, they should look pretty good and will be fully searchable and editable if any adjustments are needed. What about plaintext files, Markdown, CSV, what do those look like? CSV and TSV files are rendered into an HTML table. If you need to, you can easily edit the article to adjust row / column spacings. Plaintext and Markdown are pretty basic after converting. Often times, they will be placed into a codeblock What about document formats that cannot be converted? If they are less than 100mb in size, they can be uploaded as an attachment and a placeholder article is created for reference and searching for said filename. Is there a way to check the results after a Sync/Migration? Indeed there is! You'll have a json object in your project directory that includes a timestamp and all the details of your batch conversion / upload job. Advanced Usage - Configuring Filetype Preferences To configure your preferred filetypes to target for conversion, to ignore, or to otherwise upload as attachment, you can add to or edit the extension lists/arrays in files-config.ps1. Embeddable images, the first array includes possible image types that could be included in an article or extracted from a document. All of these are pretty safe to leave alone, though you are not likely to encounter some of the less-common ones. DisallowedForConvert array includes the stuff that WE KNOW is not a readable document. These can, however, be attached to articles and included as uploads SkipEntirely is self-explanatory - we don't want to touch these! That's it! If you have any issues, suggestions, or questions, feel free to drop us a comment! We're always looking for ways to make documentation better for everyone! If you need help with migrations, you can email our team at [email protected]. 0Auditing RBAC, Password Folder Access, and Public Articles
See Also: Github Community Repo for RBAC and Access Info It's always important to audit access levels and public data, especially when dealing with large swaths of client data or new access control features. There are several angles to consider - user permissions, group permissions, public articles, password folders, but this handy script can be a useful way to visualize some of these potential areas of improvement. If you are a 'Totally Tabular' kind of user, this is just the tool for you- the results export to a few handy csv's for any drilldown or analysis needed (no actual passwords included in these tables). RBAC Passwords / Folders Section tables included: Per-user password/folder access and membership details Group-accessibility counts RBAC passwords per-company/per-folder Per-user accessible passwords count group associations for all RBAC-enabled passwords All Passwords / Scope Section Tables included: All Password Details scope, RBAC, name and company password / scope / company comparison Which companies have more passwords with/without RBAC Articles Section Public Articles overview - just a simple table of article name, public url, and company. (if no company is present, it is a Central/Global Knowledge Base article). Generally, it's good to ensure that these article names should reflect its contents. Too-general of article names could lead to confusion during management. Viewing CSV Results If you wish to use these files, you can open them in a folder named 'hudu-audit' with a timestamp. 0Converting Dropdowns into ListSelect
'why DropDown when you can ListSelect?' Well, now you don't have to! See Also: Github Community Repo - Converting Dropdowns into ListSelect If you have some pesky "legacy" dropdown fields in your layouts, this will help you switch them over to newer ListSelect fields in no time. Selecting your best course of action will vary, depending on where your instance is hosted. Self-Hosters are reccomended to use this guide, since they have direct access to rails console. 💾 Step 1: Make sure you have a backup For our cloud-hosted comrades, we recommend that you have a recent backup before proceeding. Automatic backups complete for cloud-hosted persons at the below times every day (with a little extra time sprinkled in for the larger instances to finish.) 00:03 UTC 06:03 UTC 12:03 UTC 18:03 UTC If you find yourself trapped between these backup windows, you can reach out to support to have them initiate a backup and/or restore. ⚙️ Step 2: Setup Questions Once you're confident that you have a point in time that you can go back to if needed, you can simply start the attached script. Since it isn't something that you run continuously, you can simply enter your Hudu URL and Hudu API key when prompted. You'll also be asked just a few questions. Firstly will be 'Which layouts to replace ListSelect for'. Like anything major, it's likely best to start slow and elect to changeover an individual layout. The layouts you have available as options here are strictly layouts that include at least 1 Dropdown Field. ⌛️ Step 3 - Waiting for process to complete After making your selection and indicating that you have a recent backup- the process will begin and you will see output similar to the example, below. For those technically inclined, the entire process is as follows: create list for each of the dropdown fields in layout create a new, replica layout that is identical to source layout, but contains ListSelect fields create new replica assets for each asset in original layout re-attach same relations, passwords to new assets, remove original assets set source layout inactive, rename source layout with suffix of '-OLD' set new layout as active, rename new layout with original layout name It will complete fairly quickly and will generate a log file. This log file will potentially contain sensitive information, so be sure to securely remove after viewing! It will contain the following messages / items in the order that they were processed: assets, relationships, lists, layouts, passwords that have been created or reattributed any assets, relationships, lists, layouts, passwords that encountered an issue during processing And that's it! As simple as one would hope. 🧹 Wrap-Up Wrapping up, you'll be left with some of your original asset layouts (which are now renamed with suffix '-OLD'). You'll need to manually remove these, as we can't remove these via Hudu API at present. 0Hudu Health Report and Statistics
Easily Keep Tabs on Important Key Hudu Health Metrics Tracking health information of your Hudu instance can be helpful for even those who aren't self-hosted. What gets Tracked Basic/Overall Info Current Version / Latest Version Is an Update Available? If you're self-hosted Links for Self-Hosted Upgrades Docs are present, otherwise Help Information / Action item regarding Version is made available Link to new Docker image are provided Links to Release notes are provided Hudu Reported Date - Date, as reported by Hudu. Can be useful for self-hosted information or just to see when this article was last updated Web Redirects for HTTP - this is important to make sure no data can be sent to/from Hudu over insecure / Non-TLS channels. Uploads / Photos Statistics Uploads By MIMEtype / Filetype - a breakdown of how many of which files are most prominent Space Used for each MimeType / Filetype - how much is used where? Newest Files per MimeType - Which files are contributing to these numbers as of late? Uploads Per Month - Over Time, how many uploads does your instance add ever month? Uploads per Relationship Type - What are all these uploads related to? Top-Ten largest Uploads by Size Duplicated Upload Names - Top 10 Most-Frequent Filenames for Uploads - How many of them are duplicates that can be removed? Photos by Relationship Type - What are all these photos related to? Articles Statistics Word Count, Largest - What article in my instance has the most words? Word Count, Smallest - Are there any articles that are empty or nearly empty? Text Length Longest - If there are any base64-embedded images, those can increase wait times when making database requests. This is a reliable way to find these Shortest Text Length - Great for finding empty or near-empty articles (Mime-Type is an identifier that specifies the format of a file or document) Setting Up Setting Up is easy, All you need to do is: Enter your Hudu Base URL in this variable, below $HuduBaseUrl = "https://yourhuduURL.huducloud.com" If you want a custom name for your global kb article, you can set this to anything you'd like, as long as it makes sens $PreferredArticleTitle = "Hudu Health Report" If you are self-hosted, some alternative information is given to you, so you'll want to set $selfhosted to $true here: $HuduSetup = @{ SelfHosted=$false HuduImage="hududocker/hudu" #for beta, use hududocker/hudubeta } If you are on beta, you can switch the channel that you are checking as well. The only downside is that there are less tags available for beta and thus somewhat limited tag differentiation. If running continuously, you'll want to fill out your AZ keystore information for safe and continuous secrets management. We only need one secret for this one, $huduAPIKey. Set up the script to run on a schedule in Task Scheduler to runAs a user that can authenticate to AZ keystore. $UseAZVault = $true $AzVault_HuduSecretName = "HuduAPIKeySecretName" # Name of your secret $AzVault_Name = "MyVaultName" # Name of your vault That's It! The script should only take a few seconds to run and will generate a KB article with all of the selected information. 0Auto-Creating Articles From Anything
See Also: Community Github Repo - Articles From Anything Client Library Did you know there is a way to create articles in Hudu from just about any source with a single command? This can be a handy way to sync almost anything to an article in Hudu with little effort and maximum capability. With this, you can bulk-convert a folder of pdf's to articles, sync a status page to Hudu every 30 minutes, sync and make a directory listing for a shared folder available as an article, and more. Article From Local Directory Listing What it does: This script has all the helpers you could want for creating / updating a new article from: PDF File (converts to html, extracts images, does it all) Local Directory will use HTML file if present in this dir (with an html file present) if no html file is present, it will generate a webage image gallery of images present and/or files found in dir Remote Webpage (authenticated or public) you can add additional request headers as you'd like Article Made from PDF File -Note: Articles and associated files are searched for by same-name, so articles will be updated if they already exist, existing photos/files will be used if they already exist so that you don't have any dupes from running multiple times. This means that you could sync your Desktop on a schedule 100x and you'd still just have one article, with directory listing! This script doesn;t do anything out of the gate, however. It's intended to inspire your own creativity. It does, however, generate some boilerplate commands for you on start. # from a web page Set-HuduArticleFromWebPage -uri "https://en.wikipedia.org/wiki/Special:Random" -companyname "Administrator's company" -title "website synced from EC2AMAZ-1ARNI6V" # from a PDF file Set-HuduArticleFromPDF -pdfPath "c:\tmp\somepdf.pdf" -companyname "Administrator's company" -title "new article from pdf" # From a folder containing any type of files Set-HuduArticleFromResourceFolder -resourcesFolder "C:\Users\Administrator\Desktop " -companyname "Administrator's company" -title "Administrator's Desktop Contents" # From a local folder containing a webpage and images Set-HuduArticleFromResourceFolder -resourcesFolder "C:\Users\Administrator\Pictures" -companyname "Administrator's company" -title "local pictures in C:\Users\Administrator\Pictures" Advanced - Authenticated Webpages You can pass in any JWT, session-token, access token, into the Set-HuduArticleFromWebPage function, in the form of hashtable / KeyValue map $headers = @{ Authorization = "Bearer <TOKEN>"; Cookie = "sessionid=..." } Set-HuduArticleFromWebPage -Uri "https://internal.example.com/page" -AddtlHeaders $headers Advanced Usage - Avoiding Ratelimits If a certain webpage that you are syncing to an article in Hudu keeps ratelimiting you, refusing connection, or sending other 40x http errors, you might try Controlling throttling and retries for web scraping (-DelayMs, -Retry) params 3Interactive Network Maps from IPam/Networks/Vlans/Zones
Have you ever wanted to visualize all your networks in Hudu as an interactive network map? Well, this makes doing so easy, customizable, and effortless! While fairly basic in design, it can make things much easier for our friends to conceptualize a network's topography. An article is either created or updated (if it already exists) for each network described in each company. A Highest-Level / overview network will also be created, if applicable. ⚙ Setup Setup is pretty easy. You have various customization options, but the meat and bones of what is needed is pretty simple. 1️⃣ Run Once To run once or to test it out, you'll want to make sure that your $HuduBaseURL is set. Interactive use doesn't need a secrets provider, so you will be asked for your Hudu API key when running in this fashion. 📆 Run on a schedule If you'd prefer that this runs on a schedule or non-interactively to always give you the most up-to-date network maps, it's recommended that you use an Azure KeyVault for storing your Hudu API key. To enable this, you'll need to make sure $UseAZVault is set to $true, as well as setting your KeyVault name and Hudu API Key secret name. Also, you'll still want to make sure your $HuduBaseURL value is set. Each entity in a given network matrix is clickable and drills into the Hudu record for that item. Main Entities Mapped: VLANs and Zones are in the leftmost two columns (Blue/Orange) Networks are in the center column (Green) Linked/Associated assets are pulled in (Yellow) IP Addresses are rightmost, tied to asset, or directly linked to network (Grey) WAN Networks and Public IP Ranges/Blocks are supported here. Really, anything that is IPV4 is supported! The colors used for both entity types and status indicators can be changed. For example, if you have a lot of asset assignments and you want to see the lines/Bézier curves that are behind entities, you can assign transparency to that object type. 📝 Customizations ℹ️ Customization + Options - Info to Display In addition to customizing colors for certain entity types or status types, there are some items that can be changed to show or not show certain information based on entity type. Generally speaking, there's plenty of room for details, however. $OpenLinksInNewWindow = $false # Open links to assets, networks, vlans, zones, or addresses in new window or same window $IncludeExtendedNetworkMeta = $true #Show 'Type','LocationId','Description','VLAN ID' in Networks $IncludeExtendedAssetMeta = $true # Show 'Name','Manufacturer','Model','Serial' Properties in Assets $IncludeAddressMeta = $true # Show 'Status','FQDN','Description' properties in Address $ShowDetails = $true # Add additional relationships and entity details during page generation $CurvyEdges = $true # Use Bézier curves or straight lines when drawing relationship lines $SaveHTML=$false # Save a copy of network HTML to local directory 🎨 Customization + Options - Palette & Colors To customize your color palette/scheme, you can simply replace any of the reference colors in this section. Some of these may be subsequently referenced in the $ColorByStatus or $ColorByType lookup tables, just something to take note of. ✳️ Customization + Options - Icons To change your icon set or to assign other entity types an icon, you can modify this list, below, $AvailableIcons. It comes preloaded with some basic icons from Lucide.dev (MIT Liscense). It's recommended to use SVG data URI for these for more flexible scaling, but you can also use PNG, JPG images if you change the 'type' to the correct extension (omit the dot). Alternatively, if you have an image/svg as an Upload object in Hudu, you can just set the UploadID to that object's ID, which might be easier. If you want to assign an icon to an entity type that doesn't currently have one, like $Address in above example, you can simply follow the same convention in $IconByType, above, and ensure the Name matches the icon already in Hudu or to-be-updated. To remove an icon from an entity type, you can set it to $null in the $IconByType array. Icons in this table are looked up in Hudu, so whether you specify existing uploaded images or new ones with data in Icon= section, they are only uploaded one time. 💬 Customization + Options - Alternative Status/Role Naming Conventions If you are using alternative list item names for your Network Roles or your Network/Address Statuses, you can simply update the name of each status type here (left-side in below example) You can reference a color from the colors definitions or just define a hexadecimal color directly. You can also change the card color for each individual entity in the same way, in this other map/hashtable, $ColorByType. 5Magic Dash - Integration Asset Tracking
Overview This script automatically creates Magic Dash tiles in Hudu based on your integration assets. It currently supports 11 different integrations and can count devices, locations, contacts, and assets from various RMM/PSA platforms. Now Available in Community GitHub Repo What You’ll Get: Once set up correctly, the script will: Automatically count integration assets. Create and update Magic Dash tiles. Support both automation and custom messages. Skip companies gracefully if something’s missing. Your Magic Dash will show live counts for all integrations with almost no manual work. You can choose not to use the automation part, and fill out custom data to be pushed to magic dash tiles via Hudu's API. Please note integration Asset are counted as a WHOLE, not the individual cards. Meaning that if you have 3 cards from one integration or more in one Asset, this will show up in the magic dash as one Asset counted. If you are using Connected Fields, please ensure these are setup properly as duplicate Assets may cause miscounting. 📋 What You Need Before You Start: PowerShell 7 or later Hudu Version 2.39.3 or later Azure PowerShell module (Install-Module Az) HuduAPI PowerShell module (Install-Module HuduAPI) Entra ID (Azure AD) account with access to Key Vault Hudu instance with API access 🔐 Step 1 – Set Up Azure Key Vault We use Azure Key Vault to securely store your Hudu API key and base domain. Create a Key Vault Go to Azure Portal Search for “Key Vaults” and click Create. Fill in the following: Subscription: Your Azure subscription Resource Group: Create new or use existing Key Vault name: Example My-Key-Vault-Name Region: Choose your region Pricing tier: Standard Click Review + Create → Create. Add Secrets Inside the Key Vault go to Secrets → Generate/Import and add two secrets: Secret 1: HuduAPIKey Name: HuduAPIKey Value: Your Hudu API key (Hudu → Admin → API Keys) Content Type: text/plain Choose an expiry date or leave it to never expire. Secret 2: HuduBaseDomain Name: HuduBaseDomain Value: Your Hudu base URL (e.g., https://yourcompany.hudu.io) No trailing slash! Content Type: text/plain Choose an expiry date or leave it to never expire. Give Yourself Permission Key Vault → Access policies → Add Access Policy. Pick your user account. Under Secret permissions select Get and List. Click Add then Save. ⚙️ Step 2 – Configure the Script Open test_magic_dash.ps1 in a text editor. On line 51 you’ll see: $VaultName = "My-Key-Vault-Name-Here" Replace "My-Key-Vault-Name-Here" with the name of your Key Vault. 🏗️ Step 3 – Create the Asset Layout in Hudu In Hudu go to Admin → Asset Layouts → New Asset Layout. Name it Company Details (this name is required). Pick any icon and color. Click Create. Step 4 – Add the Required Fields Every integration needs its own set of fields in the Company Details layout. You only have to add the fields for the integrations you actually use. Base Fields (all integrations need these): Custom Fields:ENABLED (CheckBox) – switches between custom and automation mode. IncludeArchivedAssets:ENABLED (CheckBox) – whether to include archived assets in the count. Field Types: CheckBox for any :ENABLED field. Text for :URL, :NOTE and all :Count fields. Field Naming: Use exactly the names below (case-sensitive). Format: ServiceName:FieldName. Field Reference by Integration (ENABLED → URL → NOTE → Counts) HaloPSA HaloPSA:ENABLED (CheckBox) HaloPSA:URL (Text) HaloPSA:NOTE (Text) HaloPSA:DeviceCount (Text) HaloPSA:ContactCount (Text) DattoRMM DattoRMM:ENABLED (CheckBox) DattoRMM:URL (Text) DattoRMM:NOTE (Text) DattoRMM:DeviceCount (Text) CW Manage CW Manage:ENABLED (CheckBox) CW Manage:URL (Text) CW Manage:NOTE (Text) CW Manage:ConfigurationCount (Text) CW Manage:LocationCount (Text) CW Manage:ContactCount (Text) AutoTask AutoTask:ENABLED (CheckBox) AutoTask:URL (Text) AutoTask:NOTE (Text) AutoTask:DeviceCount (Text) AutoTask:LocationCount (Text) AutoTask:ContactCount (Text) Atera Atera:ENABLED (CheckBox) Atera:URL (Text) Atera:NOTE (Text) Atera:DeviceCount (Text) Atera:ContactCount (Text) Addigy Addigy:ENABLED (CheckBox) Addigy:URL (Text) Addigy:NOTE (Text) Addigy:DeviceCount (Text) Syncro Syncro:ENABLED (CheckBox) Syncro:URL (Text) Syncro:NOTE (Text) Syncro:DeviceCount (Text) Syncro:ContactCount (Text) NinjaOne NinjaOne:ENABLED (CheckBox) NinjaOne:URL (Text) NinjaOne:NOTE (Text) NinjaOne:DeviceCount (Text) NinjaOne:LocationCount (Text) N-Central N-Central:ENABLED (CheckBox) N-Central:URL (Text) N-Central:NOTE (Text) N-Central:DeviceCount (Text) N-Central:LocationCount (Text) PulsewayRMM PulsewayRMM:ENABLED (CheckBox) PulsewayRMM:URL (Text) PulsewayRMM:NOTE (Text) PulsewayRMM:AssetCount (Text) Step 5 – Create a “Company Details” Asset for Each Company Open a company in Hudu. Add a new asset using the Company Details layout. For each integration you want to track: Tick ServiceName:ENABLED. Optionally: fill ServiceName:NOTE (custom message). Optionally: fill ServiceName:URL (link to integration portal). Save. Example of what Custom "Note" would look like: One “Company Details” asset per company is required. If you have zero or multiple, the script will skip that company. 🚀 Step 6 – Run the Script Open PowerShell 7 (pwsh): cd "C:\Path\To\Your\Script" . est_magic_dash.ps1 The script will: Validate your credentials (3 tries). Find companies with exactly one “Company Details” asset. Count assets from each integration. Update the count fields. Create Magic Dash tiles for enabled integrations. Handle custom vs automation mode. 🎛️ Step 7 – Modes Custom Mode: Custom Fields:ENABLED = True + fill NOTE fields → script uses your custom messages. Automation Mode: Custom Fields:ENABLED = False + leave NOTE fields empty → script generates messages automatically. Mixed Mode: Some services custom, others automated. 🔧 Troubleshooting “Credential validation failed” – Check Key Vault name and secret names; verify permissions. “No/multiple layout(s) found with name Company Details” – Check layout name and active status. “Skipping company” – Create exactly one Company Details asset per company. “Magic Dash tiles not appearing” – Ensure ENABLED fields are checked and integration has assets. The script prints debug info showing missing fields, counts, and errors. 📞 Need Help? Double-check field names (they are case-sensitive). Ensure permissions and integration configuration. Review debug output. 🎉 All done, you should now have an Automatically created integration dashboard. 6Automatic Interactive Location Articles with Mapbox
See Also: Community Github Repo - Mapbox Locations Maps For those of you that want to see all your locations at a glance in an interactive, multi-location map, here you go! This uses MapBox API for the geocoding data and for the Geographic Tiles, you just need to sign up and get a public access token. Everything you need for this is available with a Free account! What You’ll Get: This will generate a map with all locations as an article in each company, and then at the end, for all companies in Central KB. Every company is assigned a random color, so if you have many companies and many locations, it's easier to see them in the index and on the map. Each pin is clickable and will lead you right to that location (or if it's the company's main location, it will lead you to the company instead). 📋 What You Need Before You Start: PowerShell 7 or later Hudu version 2.39.3 or later. Hudu instance with API Access Mapbox Account / Public Access Token (its the one that starts with 'pk...') ⚙️ Step 2 – Configure/Run the Script Out of the box, you can simply just run the script and it will prompt you for your API Keys and Hudu URL. That's it! If you want to, you can also customize some things, below: $GeoArticleNaming = "#COMPANYNAME Locations" $DownloadTiles = $true $preferredStyle = "mapbox/dark-v11" $GeoArticleNaming - this is what you name your articles. The #COMPANYNAME delimiter is replaced with your company name (or global for the global article). So if I set it to "#COMPANYNAME is cool"then, for the company, Hudu, the geo article created will be named "Hudu is cool". $DownloadTiles - this determines whether or not we download the map image or if we reference it directly from mapbox. If you are short on disk space, you can set this to false, but you will use credits/usage allocation for every map you view in Hudu. If you leave this as $false, then your utilization only goes up at the time you generate these. $preferredStyle - can be set to any user-customized style or any of the default stylesx in Mapbox. If you select a dark style, it will use white text (*if dark is in the style name) There are many different map styles depending on how you choose to use them. NOTE - certain styles don't have all the same features, so some map styles may not work but most of the newer ones work fine 📆 Script Schedules or Single Run Since locations don't change often, it isn't anticipated that you'll need to run this very often, maybe when new clients are onboarded. As such, it will ask you for these items, above, on start, and unset those variables when finished. You can run as many times as you want in a row, and as long as you don't change your naming convention (with $GeoArticleNaming variable), then it will simply update all the existing articles instead of creating them. 🚀 That it's! This is what your new Article should look like: That's about it! Pretty easy to use and run. Advanced users will also find some CSS that is modifyable and changable in there- so if you are a wizard, cast some magic! You can simply run the script once or you can set it to run on a schedule if you'd like. 7Self/Auto-Documenting Machines with Powershell Script
See Also: Community Github Repo - Endpoint Self-Reporting What it does: This grabs and tracks information into a (new or existing) asset in Hudu! Including: system/hardware information, WAN ip, software stats, user info (or whatever else you add) It matches assets by both Company ID and Serial Number, as not to overlap. It can be a handy tool or starting point for auto-documenting internal or client assets While the provided 'blank slate' might be more than enough for some, It's pretty easy to add on to as well, if you find yourself in a position where you need to track more, or different, data you can do either of the following: Simply run this script to bring your plan to fruition. If a layout of the same name doesn't exist or has been removed, it will be created in Hudu as you describe in this script. Modify the associated Asset Layout in Hudu alongside the template's labels and field types in this script (be sure to match these) The metrics that are built-in / provided allow for checking HotFix/Update Status, Privilege/Access Creep, TPM or Bitlocker Status, Installed Software, and a few other handy items across a few machines or an entire fleet. These assets can be auto-updated with automation. The assets that get created are easy to work with and are searchable, relatable and easy to move if ever needed! If you want to automate this script running across a number of machines it's recommended to do so with Azure KeyVault. In doing this, you'll just need to make sure that they are Domain-Joined and can be logged in by a user-principal that has read access to secrets in your Azure KeyVault / Keystore. For details, see: 'How to Set Up Azure Key Vault' Article in the community To expand on this, you could utilize Hudu's company-scoped API keys to prevent any possibility of crosstalk. This would just require different secret names in several (or the same) KeyVault(s). When setting up on a Windows machine, you can just use task scheduler to schedule these. NOTE: be sure to RunAs the aforementioned user principal (in order to bypass any interactive password prompts) Getting Started: There's really just three things to enter if you have your Hudu API key set up in AZ keyvalult: You'll need to set two variables to enable Azure KeyVault authentication (for your secrets storage). $AZVault_HuduSecretName (the name for your Azure KeyVault Secret) $AZVault_Name (the name for your Azure KeyVault) $HuduBaseURL (the url to your hudu instance, of course) If you're just giving it a try or testing a new styling, you can bypass Azure KeyVault secrets fetching by placing your API key with the actual value. Not using a Secrets Storage provider Like Azure KeyVault or OnePassword CLI is not recommended for production, especially if designed for non-interactive use. New-HuduAPIKey "$(Get-AzKeyVaultSecret -VaultName "$AzVault_Name" -Name "$AzVault_HuduSecretName" -AsPlainText)" New-HuduAPIKey "urkeyhere" # DONT DO THIS IN PRODUCTION ;( As far as the rest, that's really up to your preferences and requirements: $HowOftenDays denotes how far back to fetch data. It's how-often because its meant to echo how often you run this script. If how often you run it and how far back it gets data is the same number, then you always have all the data, (even historical data in Hudu records). $CompanyName is the company that this script will be running for or matching into. If an asset for this company doesn't exist with the same serial number / name or company / name, it will be created. If a match is found, it will be updated. $HuduAssetLayoutName is the name of the asset layout we'll be searching for. You can name this anything, and if it doesn't exist, it will be created. If it does exist it will be updated into. If the default colors aren't for you, congratulations, because color is the zest of life. Fortunately, it's possible to set up certain colors or styles even just for certain assets or companies. Just add any table header, table body, or any other table-friendly css stylings/colors in your: $TableTheme and/or: $TableAttributes variables. These are injected into each html table / field except device name. Protip: If you want an added field that is specifically just for manually-entered notes you can simply add this one line to this script, and this field will be reserved for human documentation: (in the asset layout specification, simply paste a new field in there.) As in taking the provided/boilerplate layout: And adding a field in there, just for people- so that nothing we write gets overwritten. 0Bulk Import Websites for Customers
If you're needing to bulk-import websites for a specific customer, we've made a simple script to handle this, rather than having to add each one to the UI individually. ===================================================== Create a simple CSV with a list of all of websites you want to import (just the urls on each line, don't need any other data) and save it somewhere easy to call from PowerShell (eg. C:\temp\websites.csv) Download the script file Save it somewhere easy to run, such as C:\temp\HuduBulkWebsiteImporter.ps1 Open PowerShell as Administrator Depending on your computer's policies, you may have to set your ExecutionPolicy to allow the script Run this command and hit enter: Set-ExecutionPolicy RemoteSigned -Scope CurrentUser When asked, type Y and press Enter. Run the Script In PowerShell change directory to where you saved the script, then call the script: eg. cd C:\temp .\HuduBulkWebsiteImporter.ps1 Answer the Questions The script will prompt you with options one at a time: Hudu URL Example: https://yourcompany.huducloud.com CSV File Path (where your file is saved) eg. C:\temp\websites.csv Hudu API Key Paste in your API key (from Hudu settings). (yourcompany.huducloud.com/admin/api_keys) Company Name Type the company name exactly as shown in Hudu. Domain Features The script will prompt you about enabling or disabling features (DNS, SSL, WHOIS, DMARC, DKIM, SPF). You can choose to enable them all, disable them all, or choose each option. The script will tell you how many websites were created, skipped, or failed. Check in Hudu Log into Hudu, open the company, and look under Websites. If some failed, read the "Skip Report" the script shows. It explains why and how to fix. 0Migrating Assets Between Layouts With Ease
See Also: Community Github Repo - Migrating Assets Between Layouts One thing we've noticed that has come up over the years is that sometimes you just need to move assets to other layouts--which can be tricky as there isn't a way to do it within the UI. In needing to do this, we've come up with a fairly easy solution. Here's how it works: Launch the tool Run HuduAssetLayoutTransfer.exe. The tool opens a GUI window and a terminal window. The terminal is mainly there for logging and troubleshooting. 2. Enter your Hudu connection details Provide your Hudu URL and API key. 3. Choose the source and destination layouts Pick the layout you are moving from and the layout you are moving to. You will then get a confirmation step to review or change the selection. 4. Choose merge behavior for matches If an incoming source asset appears to match an existing destination asset, you can choose how the tool should behave. You can also optionally rename the source layout after the transfer is complete. 5. Decide whether to archive the original source assets This is usually recommended once you are confident the transfer plan is correct. 6. Review field mappings If the source and destination layouts already line up closely, the tool may offer a direct transfer path. Otherwise, you will work through the field mapping wizard one destination field at a time. It might not be perfect yet, but we've moved a few hundred thousand assets between layouts with it already for customers and test accounts. (i think we're probably over a million by now) Feel free to check this link to make sure you always have the latest and greatest version of the tool: https://github.com/Hudu-Technologies-Inc/Community-Scripts/tree/main/Migrations/Migrating-Assets-Between-Layouts It's fairly easy to use and we will continue to improve upon it, so any ideas or recommendations are welcome. For more-specific details and instructions, you can check the dedicated readme, here. *updated Apr, 2026 If you need help with migrations, you can email our team at [email protected]. 0Migrating Assets Between Layouts
For Partners looking to migrate assets from 1 Asset Layout to another, we've created a PowerShell script to make this process easy. In needing to do this, we've come up with a fairly easy solution. The flow works like this: Select source/destination for assets A template is generated for you to fill out what to place where Once template is filled out, it's bombs-away See our post in the Automation library for most information! If you have any comments or questions, feel free to reply to either thread. 0ITGlue to Hudu Migration
Hudu has built upon this amazing open-source project. The original project was started by Luke Whitelock and often being maintained by Mendy Green and community contributors. Our fork is tested for and intended to be used with the very newest Hudu versions. Our version of the script includes some features that may not (yet) be present in the community repo. It also includes a more rigid minimum Hudu version requirement. Update March 2026: We now offer an easy-to-use Windows application that'll guide you through the migration process (it runs the migration scripts but has a simple UI to guide you through setup). Here's what it looks like: You can find the latest copy of the executable (Windows 10+ | x86_64 only) in our main GitHub repository here: ITGlue-Hudu-Migration (file calledITGlue-Hudu-Migration-GUI.exe) The Script will automatically migrate: Companies Contacts Locations Configurations Domains Flexible Asset Layouts Flexible Assets Documents with folder structure Passwords (with OTP Codes)* Document Links The script currently cannot migrate: Checklists - Checklists can be migrated, but there is. secondary script to run afterwards. SSL Certificates Permissions (Folders, Companies, Passwords, KBs, etc.) *Password folders--a secondary script will need to be run to import password folders. See our ITGlue-Hudu-Migration GitHub Repository for more information and instructions for running the script! If you need help with migrations, you can email our team at [email protected]. 4PassPortal to Hudu Migration Scripts
Easily migrate your PassPortal Companies, Passwords, and Knowledge Base articles to Hudu with this script, preserving formatting and images, using the PassPortal API and exports. Features: Migrate Companies/Company names Migrate Passwords See our GitHub for more information and instructions for running the script! If you need help with migrations, you can email our team at [email protected]. 0Troubleshooting Guide (Hudini Prompt Example)
Context: You are creating a troubleshooting guide for an MSP technician. Instructions: Start with a brief summary of the issue. List possible causes in a bulleted or numbered format. Provide step-by-step solutions for each cause. Include preventative tips or ongoing monitoring suggestions at the end. Ensure formatting is clean and language is concise and instructional. Tips for Crafting Effective Prompts: Be Specific: Use clear, concise language and avoid unnecessary words. Provide Context: Include relevant background information to guide the AI. Set Boundaries: Define what should and shouldn’t be included in the response. Evaluate and Iterate: Refine your prompt based on the AI’s output. Focus and Relevance: Keep your prompt targeted to prevent confusion and off-topic responses. 0Scrub Sensitive Data (Hudini Prompt Example)
Context: Before proceeding with the request, identify and remove sensitive customer information. Replace these details with appropriate placeholders. Instructions: Search for and replace the following: Company names → [Company Name] Employee names and emails → [Full Name], [Email] Phone numbers → [Phone Number] Physical addresses → [Address] IP addresses → [IP Address] API keys or credentials → [Credential/Key] Unique customer identifiers → [Customer ID] Maintain overall clarity and integrity of the request. Output the sanitized version only. Tips for Crafting Effective Prompts: Be Specific: Use clear, concise language and avoid unnecessary words. Provide Context: Include relevant background information to guide the AI. Set Boundaries: Define what should and shouldn’t be included in the response. Evaluate and Iterate: Refine your prompt based on the AI’s output. Focus and Relevance: Keep your prompt targeted to prevent confusion and off-topic responses. 0KB Article Templates (Hudini Prompt Example)
Context: You are generating a structured knowledge base article for internal or client-facing use. Instructions: Begin with a short but descriptive introduction. Break down the procedure into clear steps with numbered or bulleted formatting. Use section headers where appropriate (e.g., Overview, Steps, Troubleshooting, Additional Notes). Include common issues or troubleshooting advice if relevant. Use language appropriate to the audience (technical or non-technical). Tips for Crafting Effective Prompts: Be Specific: Use clear, concise language and avoid unnecessary words. Provide Context: Include relevant background information to guide the AI. Set Boundaries: Define what should and shouldn’t be included in the response. Evaluate and Iterate: Refine your prompt based on the AI’s output. Focus and Relevance: Keep your prompt targeted to prevent confusion and off-topic responses. 0Summarize a Support Call or Ticket for Internal Handoff (Hudini Prompt Example)
Context: You are summarizing a recent support call or ticket for handoff to another technician or team. Instructions: Structure the summary with the following bolded labels: Issue: Describe the core problem. Actions Taken: Detail what has been attempted or resolved. Client Response: Note the client's reaction or instructions. Next Steps: Outline what still needs to be done, or who it's handed off to. Keep the format clean and consistent. Be factual and avoid assumptions unless noted as such. Tips for Crafting Effective Prompts: Be Specific: Use clear, concise language and avoid unnecessary words. Provide Context: Include relevant background information to guide the AI. Set Boundaries: Define what should and shouldn’t be included in the response. Evaluate and Iterate: Refine your prompt based on the AI’s output. Focus and Relevance: Keep your prompt targeted to prevent confusion and off-topic responses. 0Meeting Notes → Next Steps Summary (Hudini Prompt Example)
Context: You are provided with rough meeting notes. Convert these into a structured summary of action items. Instructions: List each action item clearly with the assigned person. Include due dates if mentioned. Identify and call out any blockers. Use clear, bullet point formatting for quick scanning. Ensure the tone remains professional and objective. Tips for Crafting Effective Prompts: Be Specific: Use clear, concise language and avoid unnecessary words. Provide Context: Include relevant background information to guide the AI. Set Boundaries: Define what should and shouldn’t be included in the response. Evaluate and Iterate: Refine your prompt based on the AI’s output. Focus and Relevance: Keep your prompt targeted to prevent confusion and off-topic responses. 0Convert Messy Technician Notes into Clean SOP (Hudini Prompt Example)
Context: You are provided with raw, unstructured technician notes. Convert them into a clear, concise, and easy-to-follow Standard Operating Procedure. This SOP should be suitable for a junior technician. Instructions: Begin with a brief, descriptive title that reflects the task. Structure the SOP using numbered steps. Clarify vague language and remove redundancies. Format for readability using spacing and consistent punctuation. Ensure terminology is accurate and internally consistent. If a step includes warnings or caveats, clearly highlight them. Tips for Crafting Effective Prompts: Be Specific: Use clear, concise language and avoid unnecessary words. Provide Context: Include relevant background information to guide the AI. Set Boundaries: Define what should and shouldn’t be included in the response. Evaluate and Iterate: Refine your prompt based on the AI’s output. Focus and Relevance: Keep your prompt targeted to prevent confusion and off-topic responses. 0Quick Notes Template (Hudini Prompt Example)
Context: You are assisting in structuring Quick Notes for a company’s dashboard. These notes are entered into a rich text WYSIWYG editor and should follow a standardized, easy-to-read format. Instructions: Format the note in a clear, structured layout for quick scanning. Use bold headers to clearly separate sections. Use bulleted lists or short, well-formatted lines for readability. Keep details concise and relevant to the client’s current state. If any information is missing, use [N/A] instead of leaving blank. If any content starts with "A side note:", format it as a Warning Callout. Tips for Crafting Effective Prompts: Be Specific: Use clear, concise language and avoid unnecessary words. Provide Context: Include relevant background information to guide the AI. Set Boundaries: Define what should and shouldn’t be included in the response. Evaluate and Iterate: Refine your prompt based on the AI’s output. Focus and Relevance: Keep your prompt targeted to prevent confusion and off-topic responses. 0Integrate Hudu Data into Microsoft Fabric
We know many of our partners appreciate metrics and analytics, so we've put together a simple collection of scripts to easily connect Hudu data points to Microsoft Fabric (allowing you to report with PowerBI) with great flexibility! Examples of data you can sync from Hudu: Article Stats Sum of articles ratings of articles Sum of draft articles Password Stats Sum of weak passwords Sum of old passwords Internal Stats Number of admins Number of super admins Top article author The possibilities are pretty limitless. 2[Rewst] GDAP Documentation Helper
Document and track your GDAP relationships at scale—with automation Built to streamline security and compliance, this workflow fetches GDAP agreements across all managed tenants and creates structured Hudu assets—automatically. ✅ 🔍 What It Does Maps Rewst orgs to Microsoft Tenants Pulls GDAP agreement data via Microsoft Graph Formats and uploads agreement details into Hudu Skips duplicates and logs every step Fully modular with robust error handling Whether you're documenting for compliance, audits, or visibility, this workflow handles the heavy lifting and keeps your GDAP data clean and up-to-date in Hudu. 🧰 Key Features 🔁 Reusable subworkflows for tenant mapping, agreement parsing, and Hudu asset creation ⚠️ Error-safe design with universal error routing and execution logging 🚀 Concurrent processing for speed and scale 🎯 Built for Rewst + Hudu—no extra setup required 👋 This release is part of our partnership with Hudu to bring real-world automation to the MSP community. Want more workflows like this? Need help customizing? Let’s talk. 📺 Don’t forget to join our webinar tomorrow as we showcase this workflow (and others) live! 0[Rewst] Hudu Expirations Tracker for CW PSA
We’re excited to share a free, ready-to-use Expirations Monitoring Workflow built for Hudu and powered by Rewst, available now for the community! This solution allows you to: Instantly trigger on all asset expirations in Hudu using webhooks Automatically create ConnectWise PSA tickets for upcoming expirations Eliminate missed renewals with proactive, ticket-driven alerts It’s fully documented, easy to implement, and designed to keep your team ahead of the curve. 🎯 🧠 Built by ZenTop Consulting, a partner to MSPs in automation strategy and Rewst workflow development. We're proud to be working with Hudu to help MSPs streamline documentation and alerts. 📺 Join us tomorrow, 7/23 at 2PM EST, for a live webinar where we’ll walk through the workflow! Check out the documentation for implementing this workflow here 💬 Questions? Feedback? Want to automate more? We’re here to help. Check us out at https://ZenTop.tech 0Company Creation from Form (n8n)
Workflow to create a company, generate a default KB folder/subfolder structure, and seed that structure with standard articles — all triggered from an incoming webhook. What It Does: Accepts webhook trigger (i.e. form submissions [Tally, Typeform, Jotform]) Creates a company record in Hudu using submitted fields (name, address, phone, etc.) Generates a default KB folder [Company Name] KB Standards, with subfolders: Documentation Guides Processes Adds templated articles into each subfolder These are AI-generated sample articles, recommend replacing. Ensures everything is auto-nested and formatted cleanly in your Hudu KB Use Case: Use this when onboarding new clients or standardizing documentation across companies. Trigger this from a simple form (i.e. "Client Onboarding form"), and the workflow will create the company in Hudu and generate a starting point for your KB. Prerequisites: Hudu Community Node installed in your n8n instance A form tool that can POST to a webhook (e.g. Tally or JotForm) Field names in your form should match the expected Hudu company fields Customization Ideas: Include conditional logic to skip article creation for certain types of clients Add alerts/Slack messages when a new company is onboarded Add additional articles to subfolders by chaining more 'Create Article' nodes Just playing around with n8n and seeing what I could automate. If you have suggestions for improving the workflow or ideas for additional steps to add, I'd love to hear them! 0SharePoint to Hudu KB Migration Scripts
Easily migrate your SharePoint Knowledge Base articles to Hudu with this script, preserving formatting and images. Features: Choose which SharePoint sites you want to migrate over. Choose what Company or Companies you want to import into Option to automatically link Hudu documents to the original SharePoint article. Automatically convert text-based documents (.pdf, .docx, .txt, etc.) into Hudu Articles. Optionally covert Spreadsheets and PowerPoints into Hudu Articles (or choose to have them imported as attachments). See our GitHub for more information and instructions for running the script! Note: The script does not currently support SharePoint Lists. If you need help with migrations, you can email our team at [email protected]. 2FortiOS Recommended Release Tracker Into KB
Automated workflow to sync FortiOS recommended releases from Fortinet Community to Hudu KB Scrapes the latest FortiOS recommended releases from Fortinet's community forum Processes and normalises the data (fixes missing product family values) Updates the existing Hudu knowledge base article with fresh data Automatically timestamps the update { "nodes": [ { "parameters": {}, "type": "n8n-nodes-base.manualTrigger", "typeVersion": 1, "position": [ -760, -360 ], "id": "b443427e-30aa-4087-a850-fd758f8d9ed0", "name": "Manual Trigger" }, { "parameters": { "url": "https://community.fortinet.com/t5/FortiGate/Technical-Tip-Recommended-Release-for-FortiOS/ta-p/227178", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "User-Agent", "value": "Mozilla/5.0" } ] }, "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ -540, -360 ], "id": "5a14482f-e92a-468e-b544-b8b227a0a12f", "name": "Fetch Fortinet Community Page" }, { "parameters": { "sourceFormat": "html", "targetFormat": "n8nObject", "inputData": "={{ $json.data }}", "selectorMode": "advanced", "elementSelector": "div.lia-message-body-content table:contains(\"Product Family\") tbody tr" }, "type": "n8n-nodes-csv-json-htmltable-converter.csvJsonHtmltableConverter", "typeVersion": 1, "position": [ -320, -360 ], "id": "2bdcfb4d-7780-40b0-bf1f-1bedb2b2b5bc", "name": "Parse HTML Table Data" }, { "parameters": { "jsCode": "// n8n JavaScript Code Node\n// This node processes all items and fills missing Product Family values\n\n// Get all input items\nconst items = $input.all();\nconst results = [];\nlet lastKnownProductFamily = '';\n\n// Process each item\nfor (let i = 0; i < items.length; i++) {\n const currentItem = items[i].json;\n \n // Check if this row has all 4 columns (indicating it's a product family row)\n const hasFourColumns = currentItem['Product Family'] && \n currentItem['Product Details'] && \n currentItem['Recommended Release'] && \n currentItem.hasOwnProperty('End of Engineering Support Passed (Y/N)');\n \n if (hasFourColumns) {\n // This row has all 4 columns - it's a product family row\n lastKnownProductFamily = currentItem['Product Family'];\n \n const outputItem = {\n 'Product Family': currentItem['Product Family'],\n 'Product Details': currentItem['Product Details'],\n 'Recommended Release': currentItem['Recommended Release'],\n 'End of Engineering Support Passed (Y/N)': currentItem['End of Engineering Support Passed (Y/N)']\n };\n results.push(outputItem);\n } else {\n // This row is missing the 4th column - data is shifted left\n // \"Product Family\" field contains the actual Product Details\n // \"Product Details\" field contains the actual Recommended Release\n // \"Recommended Release\" field contains the actual End of Engineering Support status\n // \"End of Engineering Support Passed (Y/N)\" field is missing\n \n const outputItem = {\n 'Product Family': lastKnownProductFamily,\n 'Product Details': currentItem['Product Family'] || '', // This is actually the product model\n 'Recommended Release': currentItem['Product Details'] || '', // This is actually the version\n 'End of Engineering Support Passed (Y/N)': currentItem['Recommended Release'] || '' // This is actually Y/N\n };\n results.push(outputItem);\n }\n}\n\nreturn results;" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -100, -360 ], "id": "85bce601-c053-4999-ad32-a1c0a97db712", "name": "Fix Data Alignment Issues" }, { "parameters": { "sourceFormat": "n8nObject", "targetFormat": "html", "inputData": "={{ $('Fix Data Alignment Issues').item.json }}", "prettyPrint": true }, "type": "n8n-nodes-csv-json-htmltable-converter.csvJsonHtmltableConverter", "typeVersion": 1, "position": [ 120, -360 ], "id": "d664c574-8613-45ef-9917-9080f63461b9", "name": "Generate HTML Table" }, { "parameters": { "resource": "articles", "limit": 1, "filters": { "name": "FortiOS Recommended Releases" } }, "type": "n8n-nodes-hudu.hudu", "typeVersion": 1, "position": [ 340, -360 ], "id": "50510321-b845-47a0-8515-8980db9dba27", "name": "Retrieve Hudu KB Article", "credentials": { "huduApi": { "id": "23pSojhjXIg9tX4l", "name": "Hudu Cloud" } } }, { "parameters": { "operation": "replace", "sourceHtml": "={{ $json.content }}", "replacementContent": "={{ $('Generate HTML Table').item.json.convertedData }}", "tablePreset": "table-under-heading", "headingText": "Recommended releases" }, "type": "n8n-nodes-csv-json-htmltable-converter.csvJsonHtmltableConverter", "typeVersion": 1, "position": [ 560, -360 ], "id": "d15e74c8-7d83-4408-b449-1fcfef4bd6c7", "name": "Replace Table Content" }, { "parameters": { "jsCode": "// n8n JavaScript Code Node\n// This node updates the \"Current as of\" date in HTML content\n\n// Get the HTML content from the previous node\nlet htmlContent = $input.first().json.convertedData;\n\n// Create current date in simplified format\nconst now = new Date();\nconst options = { \n weekday: 'short', \n day: 'numeric', \n month: 'short', \n year: 'numeric', \n hour: '2-digit', \n minute: '2-digit',\n timeZone: 'Australia/Sydney'\n};\n\n// Format: Mon 1 Sept 2025 17:01 GMT+10\nconst formattedDate = now.toLocaleDateString('en-AU', options).replace(',', '') + ' GMT+10';\n\n// Regular expression to find and replace the \"Current as of\" date\n// Matches: <p><strong>Current as of</strong>: [any content]</p>\nconst regex = /(<p><strong>Current as of<\\/strong>:\\s*)[^<]*(<\\/p>)/gi;\n\n// Replace with new date\nconst updatedHtml = htmlContent.replace(regex, `$1${formattedDate}$2`);\n\n// Return the updated HTML\nreturn {\n convertedData: updatedHtml\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 780, -360 ], "id": "363eae63-b386-4ffb-82d7-7c51aa41c941", "name": "Update Timestamp" }, { "parameters": { "resource": "articles", "operation": "update", "articleId": "={{ $('Retrieve Hudu KB Article').item.json.id }}", "updateFields": { "content": "={{ $json.convertedData }}" } }, "type": "n8n-nodes-hudu.hudu", "typeVersion": 1, "position": [ 1000, -360 ], "id": "83ae3d7e-51ed-41fc-8a25-28e5d40085f0", "name": "Save Updated Article", "credentials": { "huduApi": { "id": "23pSojhjXIg9tX4l", "name": "Hudu Cloud" } } }, { "parameters": { "content": "### WEB SCRAPING\nRetrieves the latest FortiOS recommended releases from Fortinet's community forum", "height": 320, "color": 7 }, "type": "n8n-nodes-base.stickyNote", "position": [ -620, -480 ], "typeVersion": 1, "id": "27fa0a90-800d-4d96-a2a1-b720a7a60bd4", "name": "Sticky Note" }, { "parameters": { "content": "### DATA PROCESSING\nExtracts table data and fixes formatting issues where product family names are missing from subsequent rows", "height": 320, "width": 420, "color": 7 }, "type": "n8n-nodes-base.stickyNote", "position": [ -360, -480 ], "typeVersion": 1, "id": "6c50c7a6-e2d2-4ff4-af53-085b73cb1adc", "name": "Sticky Note1" }, { "parameters": { "content": "### CONTENT PREPARATION\nConverts processed data back to HTML format, retrieves existing KB article, replaces table content, and updates the 'Current as of' timestamp", "height": 320, "width": 840, "color": 7 }, "type": "n8n-nodes-base.stickyNote", "position": [ 80, -480 ], "typeVersion": 1, "id": "e703e797-a5d4-4157-bc0e-f1a0d40287aa", "name": "Sticky Note2" }, { "parameters": { "content": "### FINAL UPDATE\nSaves the updated content back to the Hudu knowledge base article", "height": 320, "color": 7 }, "type": "n8n-nodes-base.stickyNote", "position": [ 940, -480 ], "typeVersion": 1, "id": "8418f283-b516-4bba-a291-c4c4db2aa391", "name": "Sticky Note3" }, { "parameters": { "content": "### FORTIOS RELEASE TRACKER\nAutomated workflow to sync FortiOS recommended releases from Fortinet Community to Hudu KB\n\n- Scrapes latest FortiOS recommended releases from Fortinet's community forum\n- Processes and normalises the data (fixes missing product family values)\n- Updates the existing Hudu knowledge base article with fresh data\n- Automatically timestamps the update", "height": 200, "width": 680 }, "type": "n8n-nodes-base.stickyNote", "position": [ -620, -720 ], "typeVersion": 1, "id": "d0534980-65cf-4ab2-8f0d-44edaf7170ed", "name": "Sticky Note4" } ], "connections": { "Manual Trigger": { "main": [ [ { "node": "Fetch Fortinet Community Page", "type": "main", "index": 0 } ] ] }, "Fetch Fortinet Community Page": { "main": [ [ { "node": "Parse HTML Table Data", "type": "main", "index": 0 } ] ] }, "Parse HTML Table Data": { "main": [ [ { "node": "Fix Data Alignment Issues", "type": "main", "index": 0 } ] ] }, "Fix Data Alignment Issues": { "main": [ [ { "node": "Generate HTML Table", "type": "main", "index": 0 } ] ] }, "Generate HTML Table": { "main": [ [ { "node": "Retrieve Hudu KB Article", "type": "main", "index": 0 } ] ] }, "Retrieve Hudu KB Article": { "main": [ [ { "node": "Replace Table Content", "type": "main", "index": 0 } ] ] }, "Replace Table Content": { "main": [ [ { "node": "Update Timestamp", "type": "main", "index": 0 } ] ] }, "Update Timestamp": { "main": [ [ { "node": "Save Updated Article", "type": "main", "index": 0 } ] ] } }, "pinData": {}, "meta": { "templateCredsSetupCompleted": true, "instanceId": "611ddd66d5de12500d1ef99054392712c274ebf5b09f9b60165457ca4792fd1c" } } 0Easy Script for setting up SSO/SAML/SCIM with Entra ID/Azure App Registration
If you're using Entra ID as your IdP for SSO/SAML/SCIM/JIT, we've created an easy-to-run script to automatically configure your Entra ID tenant with Hudu. Further Reading - SAML SSO with Microsoft Entra ID Further Reading - Just in Time (JIT) Provisioning Script is located at the bottom of this post and is also attached. Getting Started setup: If you want to configure specific user/service permission scopes, you can enter those in the arrays named $DelegatedPermissions and $ApplicationPermissions, respectively. If you aren't sure, you can just leave these alone. Running: Simply invoke this script to get started, you will be prompted for your Hudu Instance URL and desired App registration name (defaults to your Hudu instance URL). Then, Azure CLI will be installed (if not installed already) via winget (winget will be automatically installed if it's not already). Azure CLI is fairly large, so this part may take a while. Your default browser will open with a login page to sign in with AZ CLI if it cannot find a valid context to use. Complete sign-in with a user that has sufficient permissions to create a new app registration. You'll then be prompted to select your desired tenant. (hit enter for current or default) If an app registration by the same name already exists, it will simply add any user/service level permissions you've specified. Some values/secrets needed for setup on the Hudu-side will be printed one time. Be sure not to lose your application secret! Lastly, it will prompt you to open some browser window to complete your setup. If you select 1, for yes, it will open: the Hudu/Entra setup guide JIT Provisioning setup info (optional) your Hudu SAML setup page Your newly registered App's setup blade in Azure After setting up and securely recording the aforementioned values, press enter to clear your powershell session's sensitive variables. Script # Set variables for any added user/service principal permissions if going outside the box. $DelegatedPermissions=@("User.Read") $ApplicationPermissions=@("User.Read") # e.g. "myinstance.huducloud.com" $HuduBaseURL="yourinstance.hudu.com" # $DelegatedPermissions = @("User.Read","User.ReadBasic.All","GroupMember.Read.All","User.Read.All") # $ApplicationPermissions=@("User.Read.All,GroupMember.Read.All","Directory.Read.All") # Enter these variables in-script $HuduBaseURL = $HuduBaseURL ?? $((Read-Host -Prompt 'Set the base domain of your Hudu instance (e.g https://myinstance.huducloud.com)') -replace '[\\/]+$', '') -replace '^(?!https://)', 'https://' $HuduDomain = [uri]$HuduBaseURL $HuduHost = $HuduDomain.Host #Useful urls $usefulURLs = @( @{ name = "Microsoft Entra Setup"; url = "https://support.hudu.com/hc/en-us/articles/11311225368471-SAML-SSO-with-Microsoft-Entra-ID" }, @{ name = "JIT Provisioning"; url = "https://support.hudu.com/hc/en-us/articles/33096409741975-Just-in-Time-JIT-Provisioning-with-Microsoft-Entra-ID-Beta-Access-Required" }, @{ name = "Hudu Scim/SAML/SSO Config"; url = "$HuduBaseURL/saml" } ) # Prompt for SAM App Display Name with Hudu domain as default $SAMDisplayName = $SAMDisplayName ?? ( Read-Host -Prompt "Enter a name for your App Registration or leave blank to use '$HuduHost'" ) if ([string]::IsNullOrWhiteSpace($SAMDisplayName)) { $SAMDisplayName = "$HuduHost" } $SAM_Alt_Redirect="$HuduBaseURL/saml/consume" # Alt URL for redirects $DelegatedPermissions=@() $PermissionsToAssign=$ApplicationPermissions # instantiate some other variables $env:AZURE_CLI_ENCODING = "UTF-8" [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 $HorizontalRule="--------------------" # install/import az module, set initial AZ context foreach ($module in @('Az')) {if (Get-Module -ListAvailable -Name $module) { Write-Host "Importing module, $module"; Import-Module $module } else {Write-Host "Installing and importing module $module...... Please be patient, it can take a while."; Install-Module $module -Force -AllowClobber; Import-Module $module } } if (-not (Get-AzContext)) { try { Connect-AzAccount -UseDeviceAuthentication -ErrorAction Stop } catch { Write-Error "Failed to connect to Azure. Error: $_" exit 1 } } else { Write-Host "AZContext already set. Skipping Sign-on." } # Define a few useful methods function Select-ObjectFromList($objects, $message, $allowNull = $false) { $validated = $false while (-not $validated) { if ($allowNull -eq $true) { Write-Host "0: None/Skip/Custom" } for ($i = 0; $i -lt $objects.Count; $i++) { $object = $objects[$i] Write-Host "$($i + 1): $($object)" } $PermissionsProfile = Read-Host $message if ([string]::IsNullOrEmpty($PermissionsProfile) -or $PermissionsProfile -lt 0 -or $PermissionsProfile -gt $objects.Count) { Write-Host "Invalid selection. Please enter a number from above." } elseif ($PermissionsProfile -eq 0 -and $allowNull) { return $null } else { $validated = $true } } return $objects[$PermissionsProfile - 1] } # Checking for AZ CLI and installing Write-Host "Checking for AZ CLI..." $azCommand = Get-Command az -ErrorAction SilentlyContinue if (-not $azCommand) { Write-Host "AZ CLI command not found! If this script was ran as Administrator, we can install it, let's check." if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Write-Error "You will need AZ CLI to run this script. If you want to install AZ CLI with this script, run again as admin, otherwise install AZ CLI Manually before running..." exit 1 } try { Write-Host "Attempting WinGet install of AZ CLI via PowerShell module from PSGallery..." Write-Host "Setting up Nuget Provider for AZ CLI... $(Install-PackageProvider -Name NuGet -Force)" Write-Host "Setting up PSGallery for AZ CLI... $(Install-Module -Name Microsoft.WinGet.Client -Force -Repository PSGallery)" Write-Host "Ensuring Winget for AZ CLI... $(Repair-WinGetPackageManager)" Write-Host "Using Winget to install Azure CLI... $(winget install -e --id Microsoft.AzureCLI)" } catch { write-host "Couldnt install AZ CLI via Winget. Attempting install via MSI package." Write-Host "Downloading MSI Package to .\AzureCLI.msi... $(Invoke-WebRequest -Uri https://aka.ms/installazurecliwindowsx64 -OutFile .\AzureCLI.msi)" Write-Host "Installing AZ CLI via MSI Package in Background... $(Start-Process msiexec.exe -Wait -ArgumentList '/I AzureCLI.msi /quiet')" Write-Host "Clean up MSI Package file post-install... $(Remove-Item .\AzureCLI.msi -Force)" } } else { Write-Host "Azure CLI is available at: $($azCommand.Path)" } # Sign in with AZ CLI Write-Host "AZ CLI is present and available. Attempting login with AZ CLI if not already authenticated..." try { # Check if already logged in $account = az account show --output json | ConvertFrom-Json if ($account -and $account.id) { Write-Host "Already logged into Azure CLI as: $($account.user.name)" } else { throw "No active Azure account." } } catch { # If not logged in, log in Write-Host "Not logged into Azure CLI. Attempting to log in..." try { az login --use-device-code Write-Host "Successfully logged into Azure CLI." } catch { Write-Error "Failed to log in to Azure CLI. Exiting." exit 1 } } # Step 1: List Available Tenant IDs (Optional) Write-Host "Step 1: Select Tenants" $Tenants = az account list --query "[].{Name:name, TenantId:tenantId, SubscriptionId:id}" --output json | ConvertFrom-Json Write-Host "Available Tenants:" Write-Host $Tenants $TenantId = Read-Host "Enter the Tenant ID to use (leave blank for current)" if ($TenantId -ne "") { az account set --tenant $TenantId Write-Host "Switched to Tenant: $TenantId" } else { $TenantId = az account show --query tenantId --output tsv Write-Host "Using current Tenant: $TenantId" } # Step 2, find or create app Write-Host "Step 2: Find or Create App" $AppId = az ad app list --all --display-name "$SAMDisplayName" --query "[?displayName=='$SAMDisplayName'].appId" --output tsv if ($AppId) { Write-Host "App '$SAMDisplayName' already exists with ID: $AppId" } else { Write-Host "Creating new App Registration: $SAMDisplayName" $AppId = az ad app create ` --display-name "$SAMDisplayName" ` --web-redirect-uris "$HuduBaseURL" "$SAM_Alt_Redirect" ` --query appId --output tsv Write-Host "Created App with ID: $AppId" } # Step 3, find or create Service Principal Write-Host "Step 3: Find or Create Service Principal" $ServicePrincipalId = az ad sp list --all --query "[?appId=='$AppId'].id" --output tsv if (-not $ServicePrincipalId) { Write-Host "Creating Service Principal for App ID: $AppId" $ServicePrincipalId = az ad sp create --id "$AppId" --query id --output tsv Write-Host "Created Service Principal with ID: $ServicePrincipalId" } else { Write-Host "Service Principal already exists with ID: $ServicePrincipalId" } # Step 4: Get Service Principal Type(s) from user, desired permissions, scopes, roles Write-Host "Step 4: Get Service Principal Type(s) from user, desired permissions, scopes, roles" $GraphAppId = az ad sp list --filter "displayName eq 'Microsoft Graph'" --query "[].appId" --output tsv $PermissionsToAssign = @() $PermissionsToAssign = $DelegatedPermissions + $ApplicationPermissions Write-Host "Select which permissions to assign:" Write-Host "1. Delegated Permissions (User-level)" Write-Host "2. Application Permissions (Service-level)" Write-Host "3. Both (All permissions)" $PermissionsProfile = Read-Host "Enter your choice (1, 2, or 3)" switch ($PermissionsProfile) { "1" { Write-Host "Assigning Delegated Permissions..." $PermissionsToAssign = $DelegatedPermissions $PermissionType = "Delegated" } "2" { Write-Host "Assigning Application Permissions..." $PermissionsToAssign = $ApplicationPermissions $PermissionType = "Application" } "3" { Write-Host "Assigning Both Delegated and Application Permissions..." } Default { Write-Host "Falling Back to Use Both Delegated and Application Permissions..." } } $GraphAppId = az ad sp list --filter "displayName eq 'Microsoft Graph'" --query "[].appId" --output tsv # Step 5, Apply Desired AD Service Principal Permissions/Scopes Write-Host "Step 5, Apply Desired AD Service Principal Permissions/Scopes" $DelegatedScopes = @() $ApplicationRoles = @() foreach ($permission in $PermissionsToAssign) { Write-Host "Retrieving permission ID for '$permission'..." $PermissionId = az ad sp show --id $GraphAppId --query "appRoles[?value=='$permission'].id" --output tsv if (-not $PermissionId) { $PermissionId = az ad sp show --id $GraphAppId --query "oauth2PermissionScopes[?value=='$permission'].id" --output tsv if ($PermissionId) { Write-Host "Granting $permission ($PermissionId) as Scope (Delegated permission)..." $DelegatedScopes += "$PermissionId=Scope" } else { Write-Host "Warning: Permission '$permission' not found in Microsoft Graph API!" } } else { Write-Host "Granting $permission ($PermissionId) as Role (Application permission)..." $ApplicationRoles += "$PermissionId=Role" } } Write-Host "Step 5, Apply Desired AD Service Principal Permissions/Scopes" if ($DelegatedScopes.Count -gt 0) { Write-Host "Applying Delegated permissions..." foreach ($scope in $DelegatedScopes) { az ad app permission add --id $AppId --api $GraphAppId --api-permissions "$scope" } } if ($ApplicationRoles.Count -gt 0) { Write-Host "Applying Application permissions..." foreach ($role in $ApplicationRoles) { az ad app permission add --id $AppId --api $GraphAppId --api-permissions "$role" } } if ($DelegatedScopes.Count -gt 0) { Write-Host "Granting admin consent for Delegated permissions..." az ad app permission grant --id $AppId --api $GraphAppId --scope ($DelegatedScopes -replace "=Scope", "" -join " ") } if ($ApplicationRoles.Count -gt 0) { Write-Host "Granting admin consent for Application permissions..." az ad app permission admin-consent --id $AppId } $usefulURLs += @{ name = "Further Config for $SAMDisplayName Registration"; url = "https://portal.azure.com/#blade/Microsoft_AAD_IAM/StartboardApplicationsMenuBlade/overview/appId/$AppId" } $AppSecret = az ad app credential reset --id $AppId --query password --output tsv # Print final summary in a structured way Write-Host "${HorizontalRule}General App Registration Info${HorizontalRule}" Write-Host "**Application ID:** $AppId" Write-Host "**Tenant ID:** $TenantId" Write-Host "**Service Principal ID:** $ServicePrincipalId" Write-Host "**App Secret (CRITICAL - PROTECT THIS SERET, ONLY SHOWN ONCE)**: $AppSecret" -ForegroundColor Red Write-Host "${HorizontalRule}Additional Info${HorizontalRule}" Write-Host "**Graph App ID:** $GraphAppId" Write-Host "**Microsoft Subscription ID:** $($AzAccounts | Where-Object { $_.isDefault -eq $true })" Write-Host "**Delegated Scopes Added:** $($DelegatedScopes.Count)" Write-Host "**Application Roles Added:** $($ApplicationRoles.Count)" Write-Host "`nFinal Steps Required in Azure Portal:`n" -ForegroundColor Yellow Write-Host "1. We will now open the Enterprise App page in Azure where you must:" Write-Host " - Paste Values/Secrets and Configure SAML settings" Write-Host " - copy your certificate (PEM format) to Hudu setup page" Write-Host " - Set the NameID to 'user.userprincipalname'" Write-Host "`nReference Guide:" Write-Host " https://support.hudu.com/hc/en-us/articles/11311225368471-SAML-SSO-with-Microsoft-Entra-ID" -ForegroundColor Green # Prompt user if ($(Select-ObjectFromList -objects @("yes","no") -message "Open Browser to Complete Setup?") -eq "yes"){ foreach ($item in $usefulURLs) { Write-Host "🌐 Opening $($item.name): $($item.url)" -ForegroundColor Magenta Start-Process $item.url } } Read-Host "${HorizontalRule}Prese Enter to CLEAR SCREEN AND UNSET LOCAL SECRETS (*IMPORTANT*)!${HorizontalRule}" #**SECURELY UNSET SENSITIVE VARIABLES** $AppSecret = $null $TenantId = $null $ServicePrincipalId = $null $GraphAppId = $null Remove-Variable -Name AppSecret, TenantId, ServicePrincipalId, GraphAppId, ApplicationRoles, DelegatedScopes -ErrorAction SilentlyContinue [System.Environment]::SetEnvironmentVariable("AppSecret", $null, "Process") [System.Environment]::SetEnvironmentVariable("TenantId", $null, "Process") clear-host Write-Host "If the output shown between these two lines empty, it looks like you're done! If you see anything between these lines, please make sure you clear your secrets." Write-Host "$HorizontalRule" Write-Host "$AppSecret $TenantId $ServicePrincipalId $GraphAppId $ApplicationRoles $DelegatedScopes" Read-Host "$HorizontalRule" clear-hoshttps://files-us-east-1.t-cdn.net/files/pjRPCBMiV5uuYAguft4kt t 0Splunk Sync - Hudu Activity Logs
See Also - Community Github Repo - Splunk-Sync We've created a PowerShell script that allows you to import your Hudu logs into your Splunk Cloud instance. Script is located at the bottom of this post and is also attached. Getting Started Requirements: Splunk Cloud account Active, In-Scope Splunk Token (HEC read/write) Hudu Cloud or Self-Hosted account Active, In-Scope Hudu API Key Powershell 7+ Setup: If you are using this on a repeated basis, it's recommended to utilize a secrets management solution like Azure Key Vault. Variables: First, edit these variables to contain your specific Hudu, Vault, and Splunk info: AzVault_Name # this is the name of your Azure Key Vault HuduBaseURL # this is the url for your Hudu instance, example: https://yoururl.huducloud.com AzVault_HuduSecretName # this is the name of your key vault secret containing your Hudu API key Splunk_Subdomain # this is the subdomain that your Splunk instance is accessed from Splunk_sourcename # this is the name of your data source as named in splunk HEC Splunk_sourcetype # this is the the source type you designated when setting up HEC. It can be main, archive, history. If you aren't sure, just leave on 'history'. DaysAgo # this is how many days of Hudu Logs to sync Secrets: To set up your key vault secrets, create secrets entries with these names in your key vault, which hold your respective secrets: AZVault_SplunkTokenName= default name is splunk-token for this key vault secret which contains splunk token AzVault_HuduSecretName= default name is yourhuduapikey for this key vault secret which contains your Hudu API key Auxiliary: Filtering: Filtering log entries is off by default, but can be turned on by setting AllowFiltering to $true in this script. Filter items out: You can filter out events in hudu by observable objects. To exclude these in your event sync, leave them in the excluded_objects list. You can also filter out by action with the list named excluded_actions. These are verbs that we are excluding. Override key fiiltered items: For key items that are mission-critical, you can elect to always filtered in certain nouns / verbs, even if they would otherwise be filtered out. Override these to be filtered in via observable_objects and observable_actions and observable_actions. These are always logged, so if you leave these entries and try to filter items out, they will be overridden! Running: Test Run When you run this for the first time, you can simply run with . .\Commit_Hudu_Logs.ps1 You may be met with a authentication prompt the first time. Simply log in with a user principal that has access to your Azure Key Vault. It will collect many log entries that are set in your observable_objects variable which also are in observable_actions Setup: Splunk After Logging in, select 'source types' from the top menu bar Add an HTTP Event Collector / HEC ingestion method Create a New Token Take note of your HEC name, which correlates to Splunk_sourcename variable, click 'Next' Select Source Type. If you are unsure, select history. Take note of this, as it relates to variable. Splunk_sourcetype. Proceed. Important: Leave the indexer agreement unchecked / false. Take note of this now-generated token. It is reccomended to place within Azure Key Store for safekeeping! The default name for this secret is splunk-token from the variable: AZVault_SplunkTokenName. If you change this secret name in the script, be sure the secret name matches what is in your key vault. Script: # Usual Secrets Setup $HuduBaseURL = $HuduBaseURL ?? "https://your_domain.hudu.app" $AzVault_HuduSecretName = "yourhuduapikey" $AzVault_Name = "keyvault" # Enable Http Event Collector # This is the name of your splunk subdomain where you have a HTTP Event Collector (HEC) Configured $Splunk_Subdomain="prd-p-e4tyq" #this is the name of your splunk token in azure vault $AZVault_SplunkTokenName = "splunk-token" #this is the name of your data source as named in splunk HEC $Splunk_sourcename="hudu_logs" #usually, this is main, archive, history, lastchance, etc. $Splunk_sourcetype="history" # Number of days ago to fetch logs for $DaysAgo = 99 # Turn on/off filtering of log items to specific verb/noun scope # If action is in excluded noun/verbs list or is not in included noun/verbs list, it will be excluded otherwise $AllowFiltering=$false # Objects/Nouns in excluded_objects will be omitted from reporting if AllowFiltering is true $excluded_objects =@( ) # Objects/Nouns in excluded_objects will be allowed for reporting. Overrides excluded objects $observable_objects = @( "account", "agreement", "alert", "api", "application", "article", "asset", "attachment", "product", "comment", "company", "template", "type", "variable", "configuration", "sync", "dns", "domain", "duo", "job", "expiration", "export", "flag", "folder", "standard", "group", "hit", "import", "record", "integration", "integrator", "invitation", "ip", "list", "log", "matcher", "name", "network", "otp", "password", "photo", "pin", "portal", "procedure", "note", "recording", "relation", "restriction", "rule", "settings", "share", "sidebar", "slug", "ssl", "tag", "time", "upload", "user", "website", "whois" ) #to exclude any actions/verbs, add to excluded_actions. these will be excluded if AllowFiltering is True $excluded_actions = @( ) #to include any actions/verbs and override exclusions, you can add them to this list. $observable_actions = @( "signed in", "viewed", "updated", "created", "archived", "moved", "reverted", "deleted", "viewed", "completed", "shared", "changed", "commented", "unarchived" ) # Initialize Modules Write-Host "Installing and/or Importing Modules, signing into Hudu with API key from Key Vault" foreach ($module in @('Az.KeyVault', 'HuduAPI')) {if (Get-Module -ListAvailable -Name $module) { Write-Host "Importing module, $module..."; Import-Module $module } else {Write-Host "Installing and importing module $module..."; Install-Module $module -Force -AllowClobber; Import-Module $module } } if (-not (Get-AzContext)) { Write-Host "AZContext not yet set. Connecting AZ Account... $(Connect-AzAccount)" } else {Write-Host "AZContext already set. Skipping Sign-on."}; Write-Host "Authenticating to Hudu instance @$HuduBaseURL..." # Authenticate to Hudu $SplunkToken= $SplunkToken ?? "$(Get-AzKeyVaultSecret -VaultName "$AzVault_Name" -Name "$AZVault_SplunkTokenName" -AsPlainText)" $SplunkURL = "https://${Splunk_Subdomain}.splunkcloud.com:8088/services/collector" $HuduAPIKey= $HuduAPIKey ?? "$(Get-AzKeyVaultSecret -VaultName "$AzVault_Name" -Name "$AzVault_HuduSecretName" -AsPlainText)" New-HuduAPIKey $HuduAPIKey New-HuduBaseUrl $HuduBaseURL Write-Host "Getting Splunk Token from azure vault for ${SplunkURL}..." # Calculate the StartDate and EndDate in ISO 8601 format $fetch_date=Get-Date $fetch_date_timestamp=$(Get-Date -UFormat %s) $StartDate = ($fetch_date).AddDays(-$DaysAgo).ToString("yyyy-MM-ddTHH:mm:ssZ") $EndDate = ($fetch_date).ToString("yyyy-MM-ddTHH:mm:ssZ") $localhost_name = $env:COMPUTERNAME $localhost_ip = [System.Net.Dns]::GetHostAddresses("$($env:COMPUTERNAME)") | Where-Object AddressFamily -eq "InterNetwork" | Select-Object -ExpandProperty IPAddressToString Write-Host "Fetching Hudu logs from $HuduBaseURL from $DaysAgo days ago until now ($StartDate - $EndDate). Please be patient..." $activitylogs = Get-HuduActivityLogs -StartDate $StartDate -EndDate $EndDate | ` ForEach-Object { $_ | Add-Member -MemberType NoteProperty -Name FetchedBy -Value $localhost_name -PassThru } | ` ForEach-Object { $_ | Add-Member -MemberType NoteProperty -Name FetchedByIP -Value $localhost_ip -PassThru } | ` ForEach-Object { $user = $_.user_name ?? (($_.user_initials ?? $_.user_short_name) ?? 'someone') $action = $_.action ?? 'did something' $recordType = $_.record_type ?? 'an object' $recordName = $_.record_name ?? '' $ipAddress = "with source IP $($_.ip_address)" ?? '' $company = if ($_.company_name) { "from company: $($_.company_name)" } else { '' } $friendlyDate = if ($_.created_at) { (Get-Date $_.created_at).ToString("dddd, dd 'of' MMMM, yyyy") } else { '' } $browser = if ($_.agent_string -match "Chrome/([\d\.]+)") { "Chrome $($Matches[1])" } elseif ($_.agent_string -match "Firefox/([\d\.]+)") { "Firefox $($Matches[1])" } elseif ($_.agent_string -match "Safari/([\d\.]+)") { "Safari $($Matches[1])" } else { "Unknown" } $appType = if ($_.app_type) { "via $($_.app_type)" } else { $browser } $statement = "$user $action $recordType, $recordName, $company $appType $ipAddress" ` -replace ',\s*,', '' ` -replace ',\s*$', '' ` -replace '\s{2,}', ' ' ` -replace 'app_main', 'main Hudu app' | ForEach-Object { $_.Trim() } $_ | Add-Member -MemberType NoteProperty -Name ActionStatement -Value $statement -PassThru $_ | Add-Member -MemberType NoteProperty -Name FriendlyDate -Value $friendlyDate -PassThru $_ | Add-Member -MemberType NoteProperty -Name Browser -Value $browser -PassThru } $Headers = @{ "Authorization" = "Splunk $SplunkToken" "Content-Type" = "application/json" } # Loop through each log entry and send it to Splunk foreach ($Log in $activitylogs) { if ($Log -and $Log.PSObject.Properties.Count -gt 0) { $action = $Log.action.ToLower() $object = if ($Log.record_type) { $Log.record_type.ToLower() } elseif ($Log.action -and ($Log.action -split ' ').Count -gt 1) { ($Log.action -split ' ')[1].ToLower() } else { 'object' } $skip_entry = $false if ($excluded_actions -contains $action) { Write-Host "action in excluded list: $action" $skip_entry = $AllowFiltering } elseif (-not ($observable_actions -contains $action)) { Write-Host "action not in observable list: $action" $skip_entry = $false } if ($excluded_objects -contains $object) { Write-Host "object in excluded list: $object" $skip_entry = $AllowFiltering } elseif (-not ($observable_objects -contains $object)) { Write-Host "object not in observable list: $object" $skip_entry = $false } if ($true -eq $skip_entry) { Write-Host "skipping: $($Log.ActionStatement)" continue } # Build the payload with the event string $payload = @{ host = $env:COMPUTERNAME source = "$Splunk_sourcename" sourcetype = "$Splunk_sourcetype" event = $($Log | ConvertTo-Json -Depth 10 | ConvertFrom-Json) } | ConvertTo-Json -Depth 10 Write-Output $payload try { # Invoke-RestMethod -Uri $SplunkURL -Method Post -Headers $Headers -Body $payload -SkipCertificateCheck Invoke-RestMethod -Uri $SplunkURL -Method Post -Headers $Headers -Body $payload -SkipCertificateCheck Write-Host "Sent log ID $($Log.id) to Splunk successfully." } catch { Write-Host "Failed to send log ID $($Log.id): $_" } } } remove-variable HuduAPIKey remove-variable SplunkToken 0Automated Autotask-Hudu Company Type Sync Workflow
Objective Hudu's native Autotask integration doesn't synchronise the Company Type field from Autotask to Hudu, leaving this valuable categorisation data missing from your Hudu company records. This workflow fills that gap by automatically updating Hudu companies with their corresponding Company Type from Autotask. Requirements Hudu node (community package) Autotask node (community package) Workflow Overview Schedule: Runs automatically at midnight daily High-Level Steps: Fetch Hudu Companies - Retrieves all companies from Hudu Filter Missing Data - Identifies companies with empty company_type fields Process Each Company - Loops through filtered companies individually Validate Integration - Checks if company has a valid Autotask integration Retrieve Company Type - Fetches the companyType from Autotask using sync_id Update Hudu Record - Writes the Company Type back to the corresponding Hudu company Key Features Only processes companies that need updating (empty company_type) Safely handles companies with multiple integrations How to Use Ensure you have Hudu and Autotask nodes installed and configured on your self-hosted n8n instance Save below JSON and import it into a new workflow in n8n For Hudu and Autotask nodes, ensure that they are using your desired credentials { "name": "Autotask-Hudu Company Type Sync", "nodes": [ { "parameters": { "rule": { "interval": [ {} ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.2, "position": [ -520, -125 ], "id": "06627610-abf9-4697-ba84-192f3587bf0a", "name": "Schedule Trigger" }, { "parameters": { "returnAll": true, "filters": {} }, "type": "n8n-nodes-hudu.hudu", "typeVersion": 1, "position": [ -300, -125 ], "id": "490164ab-c756-455b-8d3e-b07101886162", "name": "Fetch Hudu Companies", "credentials": { "huduApi": { "id": "98G2OC8upm1NlQU8", "name": "Intellect IT Hudu" } } }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 }, "conditions": [ { "id": "ef3ed248-fae2-4dce-aa99-5f623c646dc3", "leftValue": "={{ $('Fetch Hudu Companies').item.json.company_type }}", "rightValue": "", "operator": { "type": "string", "operation": "empty", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ -80, -125 ], "id": "34f339dd-8fc4-425a-b6ae-be2c002f9834", "name": "Filter: Missing Company Types" }, { "parameters": { "options": {} }, "type": "n8n-nodes-base.splitInBatches", "typeVersion": 3, "position": [ 140, -125 ], "id": "11eee90d-17e1-45cc-a8f9-1f93919fc96a", "name": "Process Each Company" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 }, "conditions": [ { "id": "394c676a-d9aa-4ccb-9b98-4cfdfd133e92", "leftValue": "={{ $json.integrations.find(item => item.integrator_name === 'autotask')?.sync_id }}", "rightValue": "", "operator": { "type": "number", "operation": "exists", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ 420, -200 ], "id": "5a750936-62e1-4a49-bca9-50d68bca2134", "name": "Check: Has Autotask Integration" }, { "parameters": { "resource": "company", "id": "={{ $json.integrations.find(item => item.integrator_name === 'autotask')?.sync_id }}", "selectColumns": [ "companyType" ], "flattenUdfs": true }, "type": "n8n-nodes-autotask.autotask", "typeVersion": 1, "position": [ 660, -200 ], "id": "11911178-4401-4087-a0d3-198b91f2fe0c", "name": "Fetch Autotask Company Type", "credentials": { "autotaskApi": { "id": "z5jOWiBUPQ1FprtB", "name": "Intellect IT Autotask - Trigger Nodes" } } }, { "parameters": { "operation": "update", "id": "={{ $('Process Each Company').item.json.id }}", "updateFields": { "company_type": "={{ $('Fetch Autotask Company Type').item.json.companyType_label }}" } }, "type": "n8n-nodes-hudu.hudu", "typeVersion": 1, "position": [ 860, -120 ], "id": "dfe74e9c-edb6-423c-a981-48602b7dbc3f", "name": "Update Hudu with Company Type", "credentials": { "huduApi": { "id": "98G2OC8upm1NlQU8", "name": "Intellect IT Hudu" } } }, { "parameters": { "content": "### Workflow Overview \nThis workflow synchronises company types from Autotask to Hudu. It processes companies that are missing company_type data in Hudu and updates them with the corresponding companyType from Autotask using the integration `sync_id`.", "height": 140, "width": 700, "color": 3 }, "type": "n8n-nodes-base.stickyNote", "position": [ -360, -400 ], "typeVersion": 1, "id": "cdd1fa50-e49e-4f0a-8512-04d7fb9d8ea1", "name": "Sticky Note" }, { "parameters": { "content": "### Data Collection\nFetches all companies from Hudu and filters to only process those with empty company_type fields.", "height": 320, "width": 420, "color": 5 }, "type": "n8n-nodes-base.stickyNote", "position": [ -360, -240 ], "typeVersion": 1, "id": "40850058-b61a-416b-ad8d-7a9cc0706b64", "name": "Sticky Note1" }, { "parameters": { "content": "### Processing Loop\nProcesses each filtered company individually using Split in Batches.", "height": 320, "width": 260, "color": 6 }, "type": "n8n-nodes-base.stickyNote", "position": [ 80, -240 ], "typeVersion": 1, "id": "2cf646f7-12ee-46cf-9f2b-04a0466ac38b", "name": "Sticky Note2" }, { "parameters": { "content": "### Integration Validation\nChecks if the company has an Autotask integration with a valid `sync_id`. Only companies with proper Autotask integration can have their company types retrieved and updated", "height": 480 }, "type": "n8n-nodes-base.stickyNote", "position": [ 360, -400 ], "typeVersion": 1, "id": "87cc2877-14df-4f3d-b59c-e260654c0c50", "name": "Sticky Note3" }, { "parameters": { "content": "### Data Sync\nRetrieves the company type from Autotask using the sync_id, then updates the corresponding Hudu company record. This creates a two-way sync between the systems", "height": 480, "width": 400 }, "type": "n8n-nodes-base.stickyNote", "position": [ 620, -400 ], "typeVersion": 1, "id": "bc7e1464-5c52-4f58-91d9-0796602beefb", "name": "Sticky Note4" } ], "pinData": {}, "connections": { "Schedule Trigger": { "main": [ [ { "node": "Fetch Hudu Companies", "type": "main", "index": 0 } ] ] }, "Fetch Hudu Companies": { "main": [ [ { "node": "Filter: Missing Company Types", "type": "main", "index": 0 } ] ] }, "Filter: Missing Company Types": { "main": [ [ { "node": "Process Each Company", "type": "main", "index": 0 } ] ] }, "Process Each Company": { "main": [ [], [ { "node": "Check: Has Autotask Integration", "type": "main", "index": 0 } ] ] }, "Check: Has Autotask Integration": { "main": [ [ { "node": "Fetch Autotask Company Type", "type": "main", "index": 0 } ] ] }, "Fetch Autotask Company Type": { "main": [ [ { "node": "Update Hudu with Company Type", "type": "main", "index": 0 } ] ] }, "Update Hudu with Company Type": { "main": [ [ { "node": "Process Each Company", "type": "main", "index": 0 } ] ] } }, "active": false, "settings": { "executionOrder": "v1" }, "versionId": "57885386-9bff-414b-8d66-0c8f1283234a", "meta": { "templateCredsSetupCompleted": true, "instanceId": "611ddd66d5de12500d1ef99054392712c274ebf5b09f9b60165457ca4792fd1c" }, "id": "Vw9LTacIiuDQZKwS", "tags": [] } 0Script for bulk enabling all URL features
If you're self-hosted, click here or scroll all the way to the bottom. This script will enable all the URL features for all the websites in your Hudu instance. It requires PowerShell 7 to run, it'll try to run with 7, but if it's not installed it will fail. (it also doesn't work on macOS): You need: api key username password This does enable all the features, so if there are ones you don't want to enable, you can just remove them from lines 64-72 note: being that the API does not natively handle websites, it's 'pretending' to be a web browser session, in addition to api key, it requires a username/password combo from a user with 2FA not-enforced. Copy the script to a blank note document and save as a .ps1. # Relaunch in PowerShell 7 if not already running in pwsh if ($PSCommandPath -and $PSVersionTable.PSEdition -eq 'Desktop') { $pwsh = Get-Command pwsh -ErrorAction SilentlyContinue if ($pwsh) { Write-Host "Restarting script in PowerShell 7..." & $pwsh.Path $PSCommandPath @args exit } else { Write-Host "pwsh (PowerShell 7) not found in PATH. Please install PowerShell 7 and run this script with 'pwsh'." exit 1 } } if (-not (Get-Module -ListAvailable -Name huduapi)) { Install-Module huduapi -Force -AllowClobber } Import-Module huduapi -ErrorAction Stop Import-Module huduapi $apikey=$(Read-host "Enter API Key") $hudu_url = Read-Host "Enter Hudu URL" # Normalize URL: force https, remove trailing slash $hudu_url = $hudu_url -replace '^http://', 'https://' -replace '^(?!https://)', 'https://' -replace '/$', '' $login_email=$(Read-Host "Enter Email used for login") $login_password=$(Read-Host "Enter Password used for login") $loginUrl = "$hudu_url/users/sign_in" Clear-Host New-HuduAPIKey "$apikey" New-HuduBaseUrl "$hudu_url" write-host "Authenticating..." $huduSession=$null try { $auth_response = Invoke-WebRequest -Uri $loginUrl ` -Method Post ` -Body @{ "user[email]" = $login_email; "user[password]" = $login_password } ` -SessionVariable websession ` -UseBasicParsing } catch { write-error "Sorry, authentication failed. Try again" exit 1 } $all_websites=$(get-huduwebsites) $cookie = $websession.Cookies.GetCookies($hudu_url)['_hudu_session'] $authSession = New-Object Microsoft.PowerShell.Commands.WebRequestSession $authSession.Cookies.Add((New-Object System.Net.Cookie('_hudu_session', $cookie.Value, "/", (New-Object System.Uri($hudu_url)).Host))) foreach ($website in $all_websites) { try { $updateUrl = "$hudu_url$($website.url)" $editUrl = "$hudu_url$($website.url)/edit" $editPage = Invoke-WebRequest -Uri "$updateUrl/edit" -WebSession $authSession -UseBasicParsing $csrf = [regex]::Match($editPage.Content, 'name="authenticity_token"\s+value="([^"]+)"').Groups[1].Value if (-not $csrf) { Write-Warning "Could not extract CSRF token for $($website.name)" continue } $body = @{ authenticity_token = $csrf _method = "patch" "website[name]" = $website.name "website[notes]" = $website.notes "website[disable_monitor]" = "0" "website[disable_dns]" = "0" "website[disable_ssl]" = "0" "website[disable_whois]" = "0" "website[enable_dmarc_tracking]" = "1" "website[enable_dkim_tracking]" = "1" "website[enable_spf_tracking]" = "1" "commit" = "Update" } # Patch request to update website settings $response = Invoke-WebRequest -Uri $updateUrl -Method Post -WebSession $authSession -Body $body -UseBasicParsing write-host "$($response.statuscode) for $updateurl" } catch { Write-Warning "Failed to update $($website.name): $_" } } # Remove sensitive variables "apikey","hudu_url","login_email","login_password" | ForEach-Object { Remove-Variable -Name $_ -ErrorAction SilentlyContinue } Self-hosted If you're running a self-hosted instance, you can run the following command from the Rails console to perform a mass-update. sudo docker compose exec app rails c Website.update_all( enable_dmarc_tracking: true, enable_dkim_tracking: true, enable_spf_tracking: true ) 1Syncro / Hudu - Improved Asset Dash Integration
Hudu's native integration for Syncro is great for creating & updating assets in Hudu for each Syncro RMM device. One thing it doesn't do, is show data from Asset Custom Fields in Syncro. These custom fields are great to track extra data against devices, like asset numbers (asset tags) and installed printers. Below is a PowerShell script designed to run on devices, through Syncro's background scheduled scripting module, that creates a visually pleasing dashboard of custom field data on assets in Hudu. The script has been built to work with data we specifically collect and store in custom fields (using a standardised data structure), so may need some tweaking to work in other's environments. Please note we do not have a professional in-house developer, so there may be a more efficient way to design this automation, and our comments / notes can definitely be improved upon! To get this to work you need: Customer names to exactly match in Syncro and Hudu. Custom fields on devices within Syncro. A rich-text field called 'API Info' on your Asset Layout for Syncro device in Hudu. Standardised data structure used in the custom fields (for example, to store printer information, you might store the text like this - -- Printer Name: Office Printer Printer Port: 192.168.1.10 Printer Driver: OfficePrinterDriver -- Printer Name: Home Printer Printer Port: 192.168.1.11 Printer Device: HomePrinterDriver By storing the text in a standardised structure, we can then easily parse through the field in PowerShell to extra the relevant data for the HTML layout. Syncro platform variables assigned in the script, pointing to - SyncroAssetName = asset_name CustomerName = customer_business_name SyncroAssetID = asset_id All custom fields (i.e. FieldAssetNumber = asset_custom_field_asset_number) Syncro password variable assigned in the script called HuduKey with the password value as your Hudu API key. This prevents the API key being stored on the device at-rest. To update the following script sections - Read through the script and replace any use of YOUR_SUBDOMAIN with your Hudu and / or Syncro subdomain(s). Read through the script and replace the existing Asset Layout ID with the Asset Layout ID for your Syncro devices in Hudu. Security Considerations Please remember this script runs directly on devices and therefore is a potential vector for exploitation. It is important you do not store your Hudu API key in the script itself, and instead use a password environment variable that will be passed to the script at runtime. It is recommended to restrict the API key to not have password access, or destructive action rights. A further security improvement would be to create an API key for each Hudu customer, restricted to their Hudu company, and store it as a custom field for the Syncro customer (customer custom field, not asset custom field). You can then pass the customer_custom_field_HuduAPIKey platform value as the password in the script. This would allow you to utilise one script, but separate credentials, for every customer. # --- Declare Asset Fields --- $AssetName = "$($SyncroAssetName)" $SyncroCustomField1 = "$($FieldAssetNumber)" $SyncroCustomField2 = "$($FieldOwnerUser)" $SyncroCustomField3 = "$($FieldLocalAdmins)" $SyncroCustomField4 = "$($FieldLocalUsers)" $SyncroCustomField5 = "$($FieldProfileSizes)" $SyncroCustomField6 = "$($FieldWindows11)" $SyncroCustomField7 = "$($FieldPrinters)" $SyncroCustomField8 = "$($FieldBattery)" $SyncroCustomField9 = "$($FieldPurchaseNotes)" $SyncroCustomField10 = "$($FieldDomainUsers)" $SyncroCustomField11 = "$($FieldMonitors)" $SyncroCustomField12 = "$($FieldBitlockerKey)" $SyncroCustomField13 = "$($FieldMappedDrives)" $CompanyName = "$($CustomerName)" $AssetID = "$($SyncroAssetID)" # --- Hudu API Settings --- $HuduApiKey = "$($HuduKey)" $HuduBaseUrl = "https://YOUR_SUBDOMAIN.huducloud.com" $headers = @{ "x-api-key" = $HuduApiKey "Content-Type" = "application/json" } # --- Helper Function to Get Hudu Company ID --- function Get-HuduCompanyId { param ($CompanyName) $encodedName = [uri]::EscapeDataString($CompanyName) $url = "$HuduBaseUrl/api/v1/companies?name=$encodedName" try { $response = Invoke-RestMethod -Uri $url -Headers $headers -Method Get $company = $response.companies | Where-Object { $_.name -eq $CompanyName } if ($company) { return $company.id } else { Write-Error "❌ Company '$CompanyName' not found in Hudu." exit 1 } } catch { Write-Error "❌ Error querying company ID: $_" exit 1 } } # --- Get Company ID --- $CompanyId = Get-HuduCompanyId -CompanyName $CompanyName Write-Host "✅ Retrieved Company ID: $CompanyId" # --- Step 1: Try to fetch the asset --- $encodedName = [uri]::EscapeDataString($AssetName) $assetUrl = "$HuduBaseUrl/api/v1/assets?name=$encodedName" try { $response = Invoke-RestMethod -Uri $assetUrl -Headers $headers -Method Get $asset = $response.assets | Where-Object { $_.name -eq $AssetName -and $_.company_id -eq $CompanyId } } catch { Write-Error "❌ Failed to query Hudu asset: $_" exit 1 } # --- Step 2: Format the HTML --- function Format-Empty { param ($value) if ([string]::IsNullOrWhiteSpace($value)) { return "<span style='color:#888; font-style:italic;'>(empty)</span>" } else { return $value } } function Format-BatteryBar { param ($batteryText) if ($batteryText -match '(\d+)\s*%') { $percentage = [int]$matches[1] $color = if ($percentage -ge 50) { "#4CAF50" # Green } elseif ($percentage -ge 30) { "#FFC107" # Yellow } else { "#F44336" # Red } return @" <div style='width:100%; background-color:#eee; border-radius:5px; overflow:hidden; height:20px;'> <div style='width:${percentage}%; background-color:$color; height:100%; text-align:center; color:#fff; font-weight:bold;'> $percentage% </div> </div> "@ } else { return "<span style='color:#888; font-style:italic;'>(no battery data)</span>" } } function Format-SectionTable { param ( [string]$rawText, [string]$sectionTitle ) if ([string]::IsNullOrWhiteSpace($rawText)) { return "<p><strong>${sectionTitle}:</strong> <span style='color:#888; font-style:italic;'>(empty)</span></p>" } $entries = $rawText -split '[-]{2,}' $tableHtml = "<h4 style='margin-bottom:8px; font-size:16px; color:#003366;'>$sectionTitle</h4>" foreach ($entry in $entries) { $lines = $entry -split "`r?`n" $rows = foreach ($line in $lines) { if ($line -match '^\s*(.+?):\s*(.+?)\s*$') { "<tr> <td style='padding:6px 12px; border:1px solid #ddd; background-color:#003366; color:white; font-weight:bold; width:35%; vertical-align:top;'>$($matches[1])</td> <td style='padding:6px 12px; border:1px solid #ddd; background-color:#fff; vertical-align:top;'>$($matches[2])</td> </tr>" } } if ($rows.Count -gt 0) { $tableHtml += "<table style='width:100%; border-collapse:collapse; margin-bottom:15px; font-size:14px;'>" $tableHtml += ($rows -join "") $tableHtml += "</table>" } } return $tableHtml } function Format-MappedDrivesTable { param ( [string]$rawText ) if ([string]::IsNullOrWhiteSpace($rawText)) { return "<p><strong>Mapped Drives:</strong> <span style='color:#888; font-style:italic;'>(empty)</span></p>" } # Extract the first line as-is (the header) $lines = $rawText -split "`r?`n" $headerLine = $lines[0].Trim() # Remove the first line from the rest of the content $rawText = ($lines | Select-Object -Skip 1) -join "`n" # Split entries by dashed lines $entries = $rawText -split '[-]{2,}' # Start building the HTML $tableHtml = "<p style='font-size:14px; margin-bottom:8px;'>$headerLine</p>" $tableHtml += "<h4 style='margin-bottom:8px; font-size:16px; color:#003366;'>Mapped Drives</h4>" $tableHtml += "<table style='width:100%; border-collapse:collapse; font-size:14px;'>" $tableHtml += "<thead><tr style='background-color:#003366; color:white;'><th style='padding:8px; text-align:left;'>Drive Letter</th><th style='padding:8px; text-align:left;'>Network Path</th></tr></thead>" $tableHtml += "<tbody>" foreach ($entry in $entries) { $driveLetter = "" $networkPath = "" $lines = $entry -split "`r?`n" foreach ($line in $lines) { if ($line -match 'Drive Letter\s*->\s*(.+)') { $driveLetter = $matches[1].Trim() } elseif ($line -match 'Network Path:\s*(.+)') { $networkPath = $matches[1].Trim() } } if ($driveLetter -and $networkPath) { $tableHtml += "<tr><td style='padding:6px; border:1px solid #ddd;'>$driveLetter</td><td style='padding:6px; border:1px solid #ddd;'>$networkPath</td></tr>" } } $tableHtml += "</tbody></table>" return $tableHtml } $html = @" <div style='font-family:Segoe UI, sans-serif; color:#333;'> <!-- Action Buttons --> <h2 style='color:#003366; border-bottom:2px solid #003366; padding-bottom:5px;'>Syncro Actions</h2> <div style='margin-bottom: 20px;'> <a href='https://YOUR_SUBDOMAIN.syncromsp.com/customer_assets/$AssetID' target='_blank'><button style='background-color:#003366; color:white; border:none; padding:10px 20px; border-radius:5px;'>View Asset</button></a> <a href='https://syncro-live.syncromsp.com/tasks?asset_id=$AssetID' target='_blank'><button style='background-color:#003366; color:white; border:none; padding:10px 20px; border-radius:5px;'>Background Tools</button></a> <a href='https://YOUR_SUBDOMAIN.syncromsp.com/customer_assets/$AssetID#systeminfotab' target='_blank'><button style='background-color:#003366; color:white; border:none; padding:10px 20px; border-radius:5px;'>System Info</button></a> <a href='https://YOUR_SUBDOMAIN.syncromsp.com/customer_assets/$AssetID#procedurestab' target='_blank'><button style='background-color:#003366; color:white; border:none; padding:10px 20px; border-radius:5px;'>Scripts</button></a> <a href='https://YOUR_SUBDOMAIN.syncromsp.com/customer_assets/$AssetID#installedappstab' target='_blank'><button style='background-color:#003366; color:white; border:none; padding:10px 20px; border-radius:5px;'>Installed Apps</button></a> <a href='https://YOUR_SUBDOMAIN.syncromsp.com/customer_assets/$AssetID#patchestab' target='_blank'><button style='background-color:#003366; color:white; border:none; padding:10px 20px; border-radius:5px;'>Patches</button></a> </div> <!-- Info Sections --> <h2 style='color:#003366; border-bottom:2px solid #003366; padding-bottom:5px;'>Asset Overview</h2> <div style='margin-bottom: 20px;'> <!-- Device Basics --> <div style='background:#f9f9f9; border:1px solid #ccc; padding:15px; margin-bottom:20px; border-radius:8px;'> <h3 style='color:#003366;'>Device Info</h3> <p><strong>Asset Number:</strong> $SyncroCustomField1</p> <p><strong>Owner User:</strong> $SyncroCustomField2</p> <p><strong>Windows 11 Compatible?</strong> $SyncroCustomField6</p> <p><strong>Bitlocker Key:</strong> $(Format-Empty $SyncroCustomField12)</p> </div> <!-- Setup / Purchase notes --> <div style='background:#f9f9f9; border:1px solid #ccc; padding:15px; margin-bottom:20px; border-radius:8px;'> <h3 style='color:#003366;'>Setup & Purchase Info</h3> <p><strong>Setup / Notes: </strong> $(Format-Empty $SyncroCustomField9)</p> </div> <!-- Battery Info --> <div style='background:#f9f9f9; border:1px solid #ccc; padding:15px; margin-bottom:20px; border-radius:8px;'> <h3 style='color:#003366;'>Battery Capacity</h3> <p><em>Device battery capacity (full charge capacity in KWh) as a percentage of the out of the box maximum.</em></p> <p>$(Format-BatteryBar $SyncroCustomField8)</p> </div> <!-- User Accounts --> <div style='background:#f9f9f9; border:1px solid #ccc; padding:15px; margin-bottom:20px; border-radius:8px;'> <h3 style='color:#003366;'>Accounts and Access</h3> <p><strong>Local Admin Accounts:</strong> $SyncroCustomField3</p> <p><strong>Local User Accounts:</strong> $SyncroCustomField4</p> <p><strong>Domain User Accounts:</strong> $(Format-Empty $SyncroCustomField10)</p> <p><strong>User Profile Sizes:</strong> $(Format-Empty $SyncroCustomField5)</p> </div> <!-- System Configuration --> <div style='background:#f9f9f9; border:1px solid #ccc; padding:15px; margin-bottom:20px; border-radius:8px;'> <h3 style='color:#003366;'>System Configuration</h3> <details style='margin-bottom: 15px;'> <summary style='font-size:16px; font-weight:bold; color:#003366; cursor:pointer;'>Installed Printers</summary> $(Format-SectionTable -rawText $SyncroCustomField7 -sectionTitle "") </details> <details style='margin-bottom: 15px;'> <summary style='font-size:16px; font-weight:bold; color:#003366; cursor:pointer;'>Connected Monitors</summary> $(Format-SectionTable -rawText $SyncroCustomField11 -sectionTitle "") </details> <details style='margin-bottom: 15px;'> <summary style='font-size:16px; font-weight:bold; color:#003366; cursor:pointer;'>Mapped Drives</summary> $(Format-MappedDrivesTable -rawText $SyncroCustomField13) </details> </div> </div> </div> "@ # --- Step 3: Send HTTPS Request --- if ($asset) { Write-Host "✅ Asset '$AssetName' found. Updating..." # Prepare request body for update (correct custom_fields format) $updateBody = @{ asset = @{ name = $asset.name asset_layout_id = $asset.asset_layout_id company_id = $asset.company_id custom_fields = @( @{ "API Info" = $html } ) } } | ConvertTo-Json -Depth 5 $updateUrl = "$HuduBaseUrl/api/v1/companies/$CompanyId/assets/$($asset.id)" try { $updateResponse = Invoke-RestMethod -Uri $updateUrl -Method Put -Headers $headers -Body $updateBody Write-Host "✅ Asset '$AssetName' successfully updated." # Print full response Write-Host "🔍 Full JSON response from Hudu API:" $updateResponse | ConvertTo-Json -Depth 10 | Write-Host } catch { Write-Error "❌ Failed to update asset '$AssetName': $_" } } else { Write-Host "ℹ️ Asset '$AssetName' not found. Creating new asset..." # If asset doesn't exist, create it $createBody = @{ asset = @{ name = $AssetName asset_layout_id = 5 # Replace with correct layout ID if needed company_id = $CompanyId custom_fields = @( @{ "API Info" = $html } ) } } | ConvertTo-Json -Depth 5 $createUrl = "$HuduBaseUrl/api/v1/assets" try { $createResponse = Invoke-RestMethod -Uri $createUrl -Method Post -Headers $headers -Body $createBody Write-Host "✅ Asset '$AssetName' successfully created." # Print full response Write-Host "🔍 Full JSON response from Hudu API:" $createResponse | ConvertTo-Json -Depth 10 | Write-Host } catch { Write-Error "❌ Failed to create asset '$AssetName': $_" } } 1Hudini Prompt Rules - Existing KB Article Revision
Introduction The following prompt could be used with Hudini to revise the content of an existing KB article. It has been tested with gpt-4o; adjust as needed. Prompt content You are an AI assistant for an MSP / IT integrator company. Your primary role is to help revise existing content in the Hudu knowledge base system. When asked to revise KB articles: - Provide three options for article title. If its a procedure, must start with "How to: ". - Align the article structure with the following: -- Introduction (1-2 sentences on purpose) - always include -- Requirements (essential prerequisites) - include only if specific prerequisites exist -- Preparation (planning steps, naming conventions, IP allocations) - include only if preparation steps are needed -- Service Impact (downtime expectations, duration, affected systems) - include only if service disruption is expected -- Procedure (sequential steps, limited to two nesting levels) - include for process-based articles -- Troubleshooting (common issues and solutions) - include only for processes with known issues - Only update sections that require changes - Preserve technical accuracy while improving clarity - Keep the same level of technical detail appropriate for Level 2+ MSP staff - Highlight significant changes or additions when explaining your revisions When updating procedural content: - Verify steps remain in logical sequence - Update command syntax in code blocks as needed - Ensure screenshots align with current interfaces (request new ones if needed) - Maintain consistent numbering and formatting Follow these guidelines for all KB content revisions: - Use Australian English spelling - Write in concise, objective language - Use present tense for instructions - Format commands in code blocks - Bold critical information Focus on practical, targeted updates without rewriting content unnecessarily. Preserve what works while improving what needs to change. 0
Hudu Automation Library
With Hudu's API, your documentation environment is full of possibilities. This section of the community is dedicated to sharing and collaborating on API scripts that enhance and extend the capabilities of Hudu.
Please Note: The scripts shared here are created by the community and may not have been verified by the Hudu team. Use these scripts at your own risk.
Rules of Posting
Do not include sensitive data in your script.
Verify that the script works.
Provide a description of what your script does.
Provide the scripting language used.
Post screenshots of your script in action (if possible).