PowerShell REST API and Web Requests

REST APIs are the standard way modern applications communicate over the internet. Almost every cloud platform, SaaS tool, payment gateway, monitoring service, and business application exposes a REST API. PowerShell's Invoke-RestMethod and Invoke-WebRequest cmdlets let scripts consume APIs, post data, retrieve reports, trigger workflows, and integrate systems — all without a browser or third-party tools.

How REST APIs Work

  PowerShell Script              REST API Server
  +-----------------+            +------------------+
  | Invoke-RestMethod|--HTTP---> | GET /api/users   |
  |                  |           | POST /api/orders |
  |                  |           | PUT /api/item/5  |
  |                  |           | DELETE /api/job/3|
  |                  |<--JSON--- | Returns Data     |
  +-----------------+            +------------------+

HTTP Methods

MethodPurposeExample Action
GETRetrieve dataGet a list of users
POSTCreate new dataCreate a new order
PUTReplace/update dataUpdate a user's full record
PATCHPartial updateChange only the email field
DELETERemove dataDelete a record

Invoke-RestMethod – The Primary API Cmdlet

Invoke-RestMethod sends HTTP requests and automatically parses JSON or XML responses into PowerShell objects — no manual parsing needed.

GET Request – Retrieve Data


# Fetch public user data (JSONPlaceholder – a free test API)
$response = Invoke-RestMethod -Uri "https://jsonplaceholder.typicode.com/users/1" -Method GET

Write-Host "Name:     $($response.name)"
Write-Host "Email:    $($response.email)"
Write-Host "Company:  $($response.company.name)"
Write-Host "City:     $($response.address.city)"

Output:


Name:     Leanne Graham
Email:    Sincere@april.biz
Company:  Romaguera-Crona
City:     Gwenborough

GET a List of Items


# Get all posts from the test API
$posts = Invoke-RestMethod -Uri "https://jsonplaceholder.typicode.com/posts" -Method GET

Write-Host "Total posts: $($posts.Count)"

# Show first 3 posts
$posts | Select-Object -First 3 | ForEach-Object {
    Write-Host "Post $($_.id): $($_.title)"
}

POST Request – Send Data


# Define the data to send
$newPost = @{
    title  = "PowerShell REST API Guide"
    body   = "This tutorial covers REST API usage with PowerShell."
    userId = 1
}

# Convert to JSON and POST
$response = Invoke-RestMethod `
    -Uri "https://jsonplaceholder.typicode.com/posts" `
    -Method POST `
    -Body ($newPost | ConvertTo-Json) `
    -ContentType "application/json"

Write-Host "Created Post ID: $($response.id)"
Write-Host "Title:           $($response.title)"

Output:


Created Post ID: 101
Title:           PowerShell REST API Guide

PUT and PATCH Requests – Update Data


# PUT – replace the full record
$updatedPost = @{
    id     = 1
    title  = "Updated Title"
    body   = "Updated body content."
    userId = 1
}

$response = Invoke-RestMethod `
    -Uri "https://jsonplaceholder.typicode.com/posts/1" `
    -Method PUT `
    -Body ($updatedPost | ConvertTo-Json) `
    -ContentType "application/json"

Write-Host "Updated: $($response.title)"

# PATCH – update only specific fields
$patch = @{ title = "Only Title Changed" }

$response = Invoke-RestMethod `
    -Uri "https://jsonplaceholder.typicode.com/posts/1" `
    -Method PATCH `
    -Body ($patch | ConvertTo-Json) `
    -ContentType "application/json"

Write-Host "Patched: $($response.title)"

DELETE Request


$response = Invoke-RestMethod `
    -Uri "https://jsonplaceholder.typicode.com/posts/1" `
    -Method DELETE

Write-Host "Deleted. Response: $($response | ConvertTo-Json)"

Authentication Methods

API Key in Header


$apiKey  = "your-api-key-here"
$headers = @{
    "Authorization" = "Bearer $apiKey"
    "Content-Type"  = "application/json"
    "Accept"        = "application/json"
}

$response = Invoke-RestMethod `
    -Uri "https://api.example.com/v1/data" `
    -Method GET `
    -Headers $headers

$response | Format-Table

Basic Authentication


$username = "admin"
$password = "Password123"
$base64   = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("$username`:$password"))

$headers  = @{
    "Authorization" = "Basic $base64"
}

$response = Invoke-RestMethod `
    -Uri "https://api.example.com/users" `
    -Method GET `
    -Headers $headers

OAuth2 Token


# Step 1 – Get the token
$tokenBody = @{
    grant_type    = "client_credentials"
    client_id     = "your-client-id"
    client_secret = "your-client-secret"
    scope         = "api.read"
}

$tokenResponse = Invoke-RestMethod `
    -Uri "https://auth.example.com/oauth/token" `
    -Method POST `
    -Body $tokenBody

$token = $tokenResponse.access_token
Write-Host "Token obtained."

# Step 2 – Use the token
$headers = @{ "Authorization" = "Bearer $token" }

$data = Invoke-RestMethod `
    -Uri "https://api.example.com/v1/reports" `
    -Method GET `
    -Headers $headers

$data | Format-Table

Invoke-WebRequest – Lower-Level HTTP Access

Invoke-WebRequest returns the raw HTTP response including headers, status code, and content. Use it when full HTTP response details are needed.


$response = Invoke-WebRequest -Uri "https://jsonplaceholder.typicode.com/posts/1"

# HTTP status code
Write-Host "Status Code: $($response.StatusCode)"

# Response headers
$response.Headers["Content-Type"]

# Raw response body (string)
$response.Content

# Parse JSON content manually
$data = $response.Content | ConvertFrom-Json
Write-Host $data.title

Handling API Errors


try {
    $response = Invoke-RestMethod `
        -Uri "https://api.example.com/data/999" `
        -Method GET `
        -Headers $headers `
        -ErrorAction Stop
}
catch {
    $statusCode = $_.Exception.Response.StatusCode.value__
    $message    = $_.Exception.Message

    Write-Host "HTTP Error $statusCode : $message" -ForegroundColor Red

    switch ($statusCode) {
        401 { Write-Host "Unauthorized – check your API key" }
        403 { Write-Host "Forbidden – insufficient permissions" }
        404 { Write-Host "Resource not found" }
        429 { Write-Host "Rate limited – slow down requests" }
        500 { Write-Host "Server error – try again later" }
        Default { Write-Host "Unexpected error" }
    }
}

Pagination – Retrieving Large Datasets


$allItems = @()
$page     = 1
$pageSize = 100

do {
    $url      = "https://api.example.com/items?page=$page&limit=$pageSize"
    $response = Invoke-RestMethod -Uri $url -Method GET -Headers $headers

    $allItems += $response.items
    Write-Host "Page $page – loaded $($response.items.Count) items"

    $page++
} while ($response.hasMore -eq $true)

Write-Host "Total items loaded: $($allItems.Count)"

Real-World Example – Get GitHub Repository Info


function Get-GitHubRepoInfo {
    param (
        [string]$Owner,
        [string]$Repo
    )

    $url      = "https://api.github.com/repos/$Owner/$Repo"
    $headers  = @{
        "Accept"     = "application/vnd.github+json"
        "User-Agent" = "PowerShell-Client"
    }

    try {
        $repo = Invoke-RestMethod -Uri $url -Method GET -Headers $headers
        [PSCustomObject]@{
            Name        = $repo.name
            Description = $repo.description
            Stars       = $repo.stargazers_count
            Forks       = $repo.forks_count
            Language    = $repo.language
            LastUpdated = $repo.updated_at
            URL         = $repo.html_url
        }
    }
    catch {
        Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red
    }
}

$info = Get-GitHubRepoInfo -Owner "PowerShell" -Repo "PowerShell"
$info | Format-List

Output:


Name        : PowerShell
Description : PowerShell for every system!
Stars       : 44000
Forks       : 7200
Language    : C#
LastUpdated : 2026-03-20T14:22:00Z
URL         : https://github.com/PowerShell/PowerShell

Invoke-RestMethod Parameters Reference

ParameterPurposeExample
-UriAPI endpoint URL"https://api.example.com/data"
-MethodHTTP verbGET, POST, PUT, PATCH, DELETE
-HeadersHTTP headers hash table@{"Authorization"="Bearer token"}
-BodyRequest body (POST/PUT)$data | ConvertTo-Json
-ContentTypeData format of body"application/json"
-OutFileSave response to file"C:\Downloads\file.pdf"
-TimeoutSecRequest timeout in seconds30
-ErrorActionError handling behaviorStop
-SkipCertificateCheckIgnore SSL errors (PS7)$true (dev only)

Summary

Invoke-RestMethod is the gateway between PowerShell and the connected world of APIs. GET requests retrieve data, POST creates it, PUT and PATCH update it, and DELETE removes it. Authentication through API keys, Basic Auth, and OAuth2 tokens covers virtually every API security model. Error handling with try-catch and HTTP status codes makes API calls robust. Pagination loops collect large datasets reliably. REST API integration unlocks GitHub, Azure, Slack, ServiceNow, Salesforce, Jira, and thousands of other platforms — all from PowerShell scripts.

Leave a Comment