PowerShell Universal
DownloadsIssuesDiscordForums
v5
v5
  • ❓About
  • 🆕What's New in v5?
  • ⏯️Get Started
  • 📺Video Library
  • 📚Additional Resources
  • ⬇️Installation
    • Docker
    • Upgrade
    • Uninstall
    • Downgrade
    • Migrate and Restore
  • 🔑Licensing
  • 📊System Requirements
  • 🌐Supported Browsers
  • Release Support Policy
  • Cmdlet Help
  • 🔌API
    • About
    • Endpoints
    • OpenAPI
    • Event Hubs
    • Security
    • Error Handling
    • Rate Limiting
  • 🤖Automation
    • About Automation
    • Scripts
      • Parameters
    • Jobs
    • Schedules
    • Terminals
    • Tests
    • Triggers
  • 📊Apps
    • About
    • Apps
    • Components
      • Pages
      • Data Display
        • Alert
        • Badge
        • Chip
        • Data Grid
        • Date and Time
        • Icon
        • List
        • Markdown
        • Table
        • Timeline
        • Tooltip
        • Tree View
        • Typography
      • Data Visualization
        • Charts
        • Image
        • Map
      • Feedback
        • Backdrop
        • Modal
        • Progress
        • Skeleton
      • Inputs
        • Autocomplete
        • Button
        • Checkbox
        • Code Editor
        • Date Picker
        • Editor
        • Floating Action Button
        • Form
        • Radio
        • Rating
        • Select
        • Slider
        • Switch
        • Textbox
        • Time Picker
        • Transfer List
        • Upload
      • Navigation
        • Drawer
        • Link
        • Menu
        • Stepper
        • Tabs
      • Layout
        • Grid Layout
        • Grid
        • Hidden
        • Stack
      • Utilities
        • Dynamic Regions
        • Element
        • Error Boundary
        • Protect Section
        • Transitions
        • HTML
      • Surfaces
        • AppBar
        • Card
        • Paper
        • Expansion Panel
      • Custom Components
        • Building Custom JavaScript Components
    • Custom Variable Scopes
    • Interaction
    • Role Based Access
    • Scheduled Endpoints
    • Sessions
    • Static Apps
    • Themes
      • Colors
      • Cascading Style Sheets
      • Styles
  • 🌐Portal
    • About the Universal Portal
    • Portal Pages
    • Portal Widgets
      • Syntax
      • Conditions
      • Dynamic
      • Forms
      • Properties
      • Services
      • Tables
  • 🏗️Platform
    • Cache
    • Computers
    • Health Checks
    • Gallery
    • Middleware
    • Modules
    • Monitoring
    • Notifications
    • Plugins
    • Published Folders
    • Tags
    • Telemetry
    • Translations
    • User Sessions
    • Variables
  • 🔒Security
    • About
    • Local Accounts
    • Forms Authentication
    • Authorization
    • App Tokens
    • Enterprise Security
      • Client Certificate
      • OpenID Connect
      • SAML2
      • WS-Federation
      • Windows SSO
      • Permissions
  • ⚙️Configuration
    • Agent
    • App Settings
    • Best Practices
    • Branding
    • Command Line Options
    • Deployments
    • Environments
    • Feature Flags
    • Git
    • Hosting
      • Azure
      • High Availability
      • IIS
      • Reverse Proxy
    • Management API
    • Module
    • Persistence
    • psu Command Line Tool
    • Repository
    • Running as a Service Account
  • 👩‍💻Development
    • Debugging Scripts
    • Editor
    • Hangfire
    • Logging
    • Profiling
    • Visual Studio Code Extension
  • Changelogs
    • Changelog
    • Extension Changelog
    • Roadmap
    • CVEs
Powered by GitBook

PowerShell Universal

  • Downloads
  • Pricing
  • Gallery

Community

  • Issues
  • Forums
  • Discord

Support

  • Portal
  • Knowledgebase

Copyright 2025 Ironman Software

On this page
  • HTTP Methods
  • Variable URL
  • Query String Parameters
  • Security Considerations
  • Headers
  • Cookies
  • Body
  • Live Log
  • Testing
  • Form Data
  • JSON Data
  • Param Block
  • Returning Data
  • Processing Files
  • Uploading Files
  • Downloading Files
  • Returning Custom Responses
  • Persistent Runspaces
  • Timeout
  • External Endpoint Content
  • C# APIs
  • API

Was this helpful?

Edit on GitHub
Export as PDF
  1. API

Endpoints

Endpoint configuration for Universal APIs.

PreviousAboutNextOpenAPI

Last updated 1 month ago

Was this helpful?

Endpoints are defined by their URI and HTTP method. Calls made to the Universal server that match your defined API endpoint and method execute the API endpoint script.

New-PSUEndpoint -Url '/endpoint' -Method 'GET' -Endpoint {
   "Hello, world!"
}

To invoke the above method, you can use Invoke-RestMethod.

Invoke-RestMethod http://localhost:5000/endpoint

When defining endpoints in the management API, you can skip the New-PSUEndpoint call, as the admin console defines it.

The only contents that you need to provide in the editor are the script you wish to call.

HTTP Methods

Endpoints can have one or more HTTP methods defined. To determine which method is used by an endpoint, use the built-in $Method variable.

New-PSUEndpoint -Url '/user' -Method @('GET', 'POST') -Endpoint {
    if ($Method -eq 'GET')
    {
       Get-User
    }
    else {
       New-User
    }
}

Variable URL

URLs can contain variable segments. You can denote a variable segment using a colon (:). For example, the following URL would provide a variable for the ID of the user. The $Id variable will be defined within the endpoint when it is executed. Variables must be unique in the same endpoint URL.

New-PSUEndpoint -Url '/user/:id' -Method 'GET' -Endpoint {
   Get-User -Id $Id
}

To call this API and specify the ID, do the following:

Invoke-RestMethod http://localhost:5000/user/123

Query String Parameters

Query string parameters are automatically passed into endpoints as variables that you can then access. For example, if you have an endpoint that expects an $Id variable, you can provide it in the query string.

New-PSUEndpoint -Url '/user' -Method 'GET' -Endpoint {
   Get-User -Id $Id
}

The resulting Invoke-RestMethod call must then include the query string parameter.

Invoke-RestMethod http://localhost:5000/user?Id=123

When using multiple query string parameters, ensure that your URL is surrounded by quotes so PowerShell translates it properly. Including an ampersand (&) without quotes will cause issues in both Windows PowerShell and PowerShell 7.

Invoke-RestMethod "http://localhost:5000/user?Id=123&name=tim"

Security Considerations

Below is an example of CWE-914. Include a $IsChallengePassed query string parameter to bypass the challenge.

New-PSUEndpoint -Url "/api/v1.0/CWE914Test" -Description "Vulnerable to CWE-914" -Endpoint {
	if($ChallengeInputData -eq "AcceptableInput") {
		$IsChallengePassed = $true
	}
	if($IsChallengePassed) {
		"Challenge passed. Here is Sensitive Information"
	} else {
		"Challenge not passed"
	}
}

In order to avoid this particular issue, you can use a param block.

New-PSUEndpoint -Url "/api/v1.0/CWE914Test" -Description "Not Vulnerable to CWE-914" -Endpoint {
	Param(
		$ChallengeInputData
	)
	if($ChallengeInputData -eq "AcceptableInput") {
		$IsChallengePassed = $true
	}
	if($IsChallengePassed) {
		"Challenge passed. Here is Sensitive Information"
	} else {
		"Challenge not passed"
	}
}

Headers

Request headers are available in APIs using the $Headers variable. The variable is a hashtable. To access a header, use the following syntax:

$Headers['Content-Type']

Cookies

Request cookies are available in APIs using the $Cookies variable. The variable is a hashtable. To access a cookie, use the following syntax:

$Cookies['Request-Cookie']

Send back request cookies with the New-PSUApiResponse cmdlet. Use the -Cookies parameter with a supplied hashtable.

New-PSUApiResponse -StatusCode 200 -Cookies @{
    ResponseCookie = '123'
}

Body

To access a request body, you will simply access the $Body variable. Universal $Body variable will be a string. If you expect JSON, you should use ConvertFrom-Json.

New-PSUEndpoint -Url '/user' -Method Post -Endpoint {
    $User = ConvertFrom-Json $Body 
    New-User $User
}

To call the above endpoint, specify the body of Invoke-RestMethod.

Invoke-RestMethod http://localhost:5000/user -Method Post -Body "{'username': 'adam'}"

Live Log

You can view the live log information for any endpoint by clicking the log tab. Live logs include URL, HTTP method, source IP address, PowerShell streams, status code, return Content Type, and HTTP content length.

You can write to the live log from within your endpoints with cmdlets like Write-Host.

Testing

You can use the Test tab in the Endpoint editor to test your APIs. Using this Test tool, you can adjust headers, the query string, and body. You can also adjust the Authentication and Authorization for the test.

When using the test tab, any changes to the values of the test will result in an updated Code block that you can then use within PowerShell. Click the Code tab to view the test code.

Invoke-RestMethod -Uri 'http://localhost:5000/test-api?Page=1' -Headers @{'X-Custom-Header' = 'Value';} -Method 'POST'

Additionally, tests performed within the tester will be stored for 30 days to allow for retesting without having to reconfigure all the properties. Clicking the Apply button will setup the Test tool with the same properties.

Form Data

You can pass data to an endpoint as form data. Form data will pass into your endpoint as parameters.

New-PSUEndpoint -Url '/user' -Method Post -Endpoint {
    param([Parameter(Mandatory)]$userName, $FirstName, $LastName)
     
    New-User $UserName -FirstName $FirstName -LastName $LastName
}

You can then use a hashtable with Invoke-RestMethod to pass form data.

Invoke-RestMethod http://localhost:5000/user -Method Post -Body @{ 
    UserName = "adriscoll"
    FirstName = "Adam"
    LastName = "Driscoll"
}

JSON Data

You can pass JSON data to an endpoint and it will automatically bind to a param block.

New-PSUEndpoint -Url '/user' -Method Post -Endpoint {
    param([Parameter(Mandatory)]$userName, $FirstName, $LastName)
     
    New-User $UserName -FirstName $FirstName -LastName $LastName
}

You can then send JSON data to the endpoint.

Invoke-RestMethod http://localhost:5000/user -Method Post -Body (@{ 
    UserName = "adriscoll"
    FirstName = "Adam"
    LastName = "Driscoll"
} | ConvertTo-Json) -ContentType 'application/json'

Param Block

You can use a param block within your script to enforce mandatory parameters and provide default values for optional parameters such as query string parameters. Variables such as $Body, $Headers and $User are provided automatically.

In the below example, the $Name parameter is mandatory and the $Role parameter has a default value of Default.

New-PSUEndpoint -Url '/user/:name' -Endpoint {
    param([Parameter(Mandatory)$Name, $Role = "Default")
}

When using the param block with route parameters like the above example, you must include the route variable in your parameter. If it is not specified, you will not have access to that value.

For example, the following $Name variable is always $null. The endpoint always returns false.

New-PSUEndpoint -Url '/user/:name' -Endpoint {
    param($Role = "Default")
    
    $Name -eq 'Adam'
}

If you use the CmdletBinding or Parameter attribute within your param block, the endpoint will strictly enforce which parameters are allowed into the endpoint.

For example, the following enforces that the name parameter is specified.

New-PSUEndpoint -Url '/user' -Endpoint {
    param([Parameter(Mandatory)$Name)
}

That said, you cannot specify additional parameters to the endpoint. Doing the following will cause an error.

Invoke-RestMethod http://localhost:5000/user -Method Post -Body (@{ 
    Name = "adriscoll"
    DisplayName = 'Adam'
} | ConvertTo-Json) -ContentType 'application/json'

If you change your endpoint to avoid using the Parameter attribute, you can pass in any number of params and they will be bound as variables and not parameters to the endpoint.

New-PSUEndpoint -Url '/user' -Endpoint {
    param($Name)
}

Returning Data

Data returned from endpoints is assumed to be JSON data. If you return an object from the endpoint script block, it is automatically serialized to JSON. If you want to return another type of data, you can return a string formatted however you chose.

Processing Files

Uploading Files

You can process uploaded files by using the $Data parameter to access the byte array of data uploaded to the endpoint.

New-PSUEndpoint -Url '/file' -Method Post -Endpoint {
    $Data
}

PS C:\Users\adamr> iwr http://localhost:5000/file -method post -InFile '.\Desktop\add-dashboard.png'

StatusCode        : 200
StatusDescription : OK
Content           : [137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,2,17,0,0,1,92,8,2,0,0,0,249,210,123,106,0,0,0,1,
                    115,82,71,66,0,174,206,28,233,0,0,0,4,103,65,77,65,0,0,177,143,11,252,97,5,0,0,0,9,112,72,89,115,0,
                    0,…

The multipart/form-datacontent type is not supported for uploading files to APIs.

You can also save the file into a directory.

New-PSUEndpoint -Url '/file' -Method Post -Endpoint {
    [IO.File]::WriteAllBytes("tempfile.dat", $Data)
}

Downloading Files

You can send files down using the New-PSUApiResponse cmdlet.

New-PSUEndpoint -Url '/image' -Endpoint {
    $ImageData = [IO.File]::ReadAllBytes("image.jpeg")
    New-PSUApiResponse -ContentType 'image/jpg' -Data $ImageData
}

Returning Custom Responses

You can return custom responses from endpoints by using the New-PSUApiResponse cmdlet in your endpoint. This cmdlet allows you to set the status code, content type and even specify the byte[] data for the content to be returned.

New-PSUEndpoint -Url '/file' -Method Get -Endpoint {
    New-PSUApiResponse -StatusCode 410
}

You can also return custom body data with the -Body parameter of New-PSUApiResponse.

New-PSUEndpoint -Url '/file' -Method Get -Endpoint {
    New-PSUApiResponse -Body "Not what you're looking for." -StatusCode 404
}

Invoking the REST method returns the custom error code.

PS C:\Users\adamr\Desktop> invoke-restmethod http://localhost:8080/file

Invoke-RestMethod: Not what you're looking for.

You can control the content type of the returned data with the -ContentType parameter.

New-PSUEndpoint -Url '/file' -Method Get -Endpoint {
    New-PSUApiResponse -Body "<xml><node>1</node><node2>2</node2></xml>" -ContentType 'text/xml'
}

You can control the response headers with a hashtable of values that you pass to the -Headersparameter.

New-PSUApiResponse -StatusCode 200 -Headers @{
    "Referrer-Policy" = "no-referrer"
}

Persistent Runspaces

Persistent runspaces allow you to maintain runspace state between API calls. This is important for users that perform some sort of initialization within their endpoints that they do not want to execute on subsequent API calls.

By default, runspaces are reset after each execution. This removes variables, modules and functions defined during the execution of the API.

New-PSUEnvironment -Name 'Env' -Path 'powershell.exe' -PersistentRunspace

You can then assign the API environment in the settings.ps1 script.

Set-PSUSetting -ApiEnvironment 'Env'

Timeout

By default, endpoints will not time out. To set a timeout for your endpoints, you can use the New-PSUEndpoint -Timeout parameter. The timeout is set in the number of seconds.

External Endpoint Content

You can define the path to an external endpoint content file with the -Path parameter of New-PSUEndpoint. The path is relative to the .universal directory in Repository.

The content of the endpoints.ps1 file is then this:

New-PSUEndpoint -Url "/path" -Path "endpoint-path.ps1"

C# APIs

There is no UI for creating a C# API, so you need to do so using configuration files. First, create a .cs file that runs your API.

You will have access to a request parameter that includes all the data about the API request.

public class ApiRequest
{
    public long Id;
    public ICollection<KeyValue> Variables;
    public IEnumerable<ApiFile> Files { get; set; };
    public string Url;
    public ICollection<KeyValue> Headers;
    public byte[] Data;
    public int ErrorAction;
    public ICollection<KeyValue> Parameters;
    public string Method;
    public ICollection<KeyValue> Cookies;
    public string ClaimsPrincipal;
    public string ContentType;
}

You will also have access to a ServiceProvider property that allows you to access services within PowerShell Universal. These are not currently well-documented, but below is an example of restarting a dashboard.

var dm = ServiceProvider.GetService(typeof(IDashboardManager));
var dashboard = dm.GetDashboard(1);
dm.Restart(dashboard);

Some other useful services include:

  • IDatabase

  • IApiService

  • IConfigurationService

  • IJobService

You can choose to return an ApiResponse from your endpoint.

return new ApiResponse {
    StatusCode = 404
};

Once you have defined your C# endpoint file, you can add it by editing endpoints.ps1.

New-PSUEndpoint -Url /csharp -Path endpoint.cs -Environment 'C#'

The PowerShell Universal service automatically compiles and runs C# endpoints.

API

Avoid using endpoint URLs that match internal PowerShell Universal Management API URLs, as this causes unexpected behavior. You can reference the for the to verify that none of the URLs match.

When accepting input via Query String parameters you may be vulnerable to . Consider using a param block to ensure that only valid parameters are provided to the endpoint.

To enable persistent runspaces, you will need to configure an for your API. Set the -PersistentRunspace parameter to enable this feature. This is configured in the environments.ps1 script.

C# APIs are enabled as a .

🔌
OpenAPI documentation
Management API
CWE-914: Improper Control of Dynamically-Identified Variables
environment
plugin
New-PSUEndpoint
Get-PSUEndpoint
Remove-PSUEndpoint
New-PSUApiResponse
Set-PSUSetting
API Properties
API Content
Endpoint Live Log
Endpoint Test Tab
Test History