PDQ Connect API (Early Access)

PLAN AVAILABILITY COMPONENT. DO NOT EDIT ME
 

Early Access. The new API, PDQ Connect API (Early access), is available from October 20, 2026 and will be generally available in Q4 2026. The API and its documentation carry an Early Access banner until then; at general availability the label is dropped and it becomes PDQ Connect API. The previous API continues as PDQ Connect API (Legacy); nothing forces you to switch today. 

During Early Access, we could potentially make breaking changes to the API. The versioning policy described below takes effect at general availability. Early Access is rolled out per organization and per operation, so a 403 Forbidden response could mean your organization is not yet enrolled in the EA program. To join our Early Access Program, please fill out this form.

PDQ Connect provides an HTTP based, REST-style API that enables admins to securely integrate with their own scripts, integrations, and other tools. PDQ Connect API (Early access) follows the JSON:API 1.1 standard, so any JSON:API client library works with it, and it is versioned by date so an integration you write today keeps working until you choose to upgrade.

Where PDQ Connect API (Legacy) was mostly for reading data, PDQ Connect API (Early access) lets you change it. You can create and manage static groups, organize packages into folders, delete custom packages and devices, set custom field values, reboot devices, and deploy packages to any mix of devices and groups. Every resource uses the same paging, filtering, sorting, and error format.

Capabilities

Detailed API usage documentation (including a comprehensive list of available endpoints and schemas) is available at https://app.pdq.com/api-docs. The OpenAPI 3.1 specification is served at https://app.pdq.com/openapi and is generated from the server, so you can use it to generate clients or validate requests. 

The list below is intended to be an overview of what functions you can expect to find in the API. 

Target API functions available
Devices
  • Get info about a device or list of devices, including online status, last check-in time, networking, processors, Active Directory and Microsoft Entra details
  • List a device's disks, drivers, software, Windows features, custom field values, and vulnerabilities (each as its own paged list)
  • Reboot one or more devices (up to 1,000 per request)
  • New: Delete a device
  • Custom fields: Update or clear a custom field value on a device
Groups
  • Get a group or list of groups
  • List the devices in a group
  • New: Create a static group, with or without members
  • New: Rename a static group or replace its membership (up to 1,000 devices per request)
  • New: Delete a static group

Dynamic groups are read only through the API. Manage them in the PDQ Connect console.

Deployments
  • Get info about a deployment or list of deployments, filterable by package version
  • Deploy a package version to any mix of devices and groups in one request. Every target is checked before the deployment is created, so a bad ID returns 404 and nothing is created.
Packages
  • Get a package or list of packages
  • List the versions of a package, or get a single package version
  • New: Move a package into a folder
  • New: Delete a custom package (PDQ library packages cannot be deleted)
Package folders

New. Package folders are not available in PDQ Connect API (Legacy).

  • Get a folder or list of folders
  • List the packages in a folder
  • Create a folder, nested up to five levels deep
  • Rename or move a folder
  • Delete an empty folder
Vulnerabilities
  • New: List every vulnerability across your organization, or get a single vulnerability
  • New: Ignore a vulnerability, or stop ignoring it
  • List the vulnerabilities on a device (see Devices above)
Custom Fields

Note: These endpoints exist in addition to the Custom Field endpoints for Devices above.

  • Get a custom field or list all custom fields
  • Create a custom field
  • Rename a custom field
  • Delete a custom field

PDQ Connect API (Early access) does not create packages or upload installers, and it does not cancel deployments. Publishing a package still happens in the console.


 

Authentication

Before you can use the API, you will need to set up authentication using Connect's secure, token-based authentication system. Only admins can create API keys.

The API keys page itself is only visible to users with the Admin role. If you don't see it under Settings, ask an admin on your team to generate or manage keys for you.

API keys created for PDQ Connect API (Legacy) work with PDQ Connect API (Early access) as well, as long as they hold the scopes the request needs. You do not need separate keys for the two APIs.

 

PDQ Connect only accepts encrypted HTTPS requests.

First, generate a new API key using the "API keys" page in Connect's settings page located in the lower left-hand corner of the console. 1.png

 

Then, in the "API keys" page, click on the "Create API key" button.

Give your API key a descriptive name that helps you remember what you are using it for. Each key name has to be unique, so if you enter a name that is already in use, Connect shows an error and asks you to choose a different one.

Next, set the access level for each resource: Devices, Deployments, Groups, Packages, Custom fields, and Vulnerabilities. Every resource starts at No access. Raise the ones the key needs to read, or to read and write, and leave the rest at No access. This limits the key to exactly what it should be able to do.

Then press the "Generate key" button to create the key.

 

After you press the "Generate key" button, you will be given an opportunity to copy the API key to your computer's clipboard. Press the copy button to the right of the hidden API key to copy it.

 

Make sure to save the API key somewhere safe, as this is the only chance you have to see the API key. If you lose it, you will have to make a new one.

 

Scopes and key visibility

Every new key is scoped, which means it only works for the actions you granted it. You can review the scopes on any key from the "API keys" page at any time.

PDQ Connect API (Early access) checks scopes on every request, per resource and per action. Each resource has a read scope and a write scope, for example devices:read and devices:write. Read scopes cover GET requests. Write scopes cover requests that create, change, or delete data, and actions such as rebooting a device. A write scope does not include read access, so a key that reads and writes a resource needs both.

Some operations touch more than one resource and need every scope involved. Setting a custom field value on a device needs both custom_fields:write and devices:write. Listing a device's vulnerabilities needs both vulnerabilities:read and devices:read.

When a key is missing a scope, the API returns 403 Forbidden and the error names only the scopes that are missing:

{
  "errors": [
    {
      "status": 403,
      "detail": "Missing required scopes: groups:write"
    }
  ]
}

A key's scopes are fixed once it is created. To change them, create a new key with the scopes you need and revoke the old one.

During Early Access a 403 can also mean your organization is not enrolled for that operation yet. If the error does not list a missing scope, that is the likely cause.

The API ID column shows the last four characters of each API key. API IDs are only available for keys created after August 17, 2026.

API key names appear in your Deployments and Audit logs, so you can see which key triggered a deployment or made a change.

API keys created before scoped keys were released keep full access to every endpoint and appear as fully scoped keys. You do not need to recreate them.

Request Header Authentication

To use the API key you generated, you will need to include it in an HTTP header to the Connect API endpoint. It must be included in each request.

PDQ Connect API (Early access) also requires a version header, x-pdq-connect-api-version, on every request. The current version is 2026-10-20. A request without the header, or with a version the API does not recognize, returns 400 Bad Request with the list of supported versions.

Invoke-RestMethod -Uri https://app.pdq.com/api/devices -Headers @{'Authorization' = 'Bearer API_KEY_HERE'; 'x-pdq-connect-api-version' = '2026-10-20'}

Requests that send a body (create, update, and reboot requests) must use the content type application/vnd.api+json.

You can now use the API key to interact with the Connect API. If you ever stop using an API key or if you have reason to believe your key has been viewed by someone who shouldn't have API access, remember to revoke the API key as soon as possible. You can revoke a key by pressing the "Revoke" button and following the prompts.

API versions

Versions of PDQ Connect API (Early access) are named by the date they were released. From general availability, when PDQ makes a change that could break an integration, such as removing a field or adding a required parameter, that change ships as a new version. Additive changes, such as a new endpoint or a new optional field, land in the current version without a version bump. During Early Access, breaking changes can land in the current version; the version header value may change, and the error body of a 400 lists the versions the API currently accepts.

Each version stays supported for at least 18 months after the next version is released. When a version is approaching retirement, responses include a Sunset header with the retirement date. After that date, requests for the retired version return 410 Gone. Before you move an integration to a newer version, read the Changelog section of the API docs for the breaking changes in that version.

Examples using PowerShell

Get Devices

#Get Devices
$ConnectApiBaseUrl = "https://app.pdq.com/api"
$ConnectApiToken = "YOUR CONNECT API TOKEN"
$headers = @{'authorization' = "Bearer $ConnectApiToken"; 'x-pdq-connect-api-version' = '2026-10-20' }
Invoke-RestMethod -Headers $headers -Uri "$ConnectApiBaseUrl/devices?page[size]=100"

Get every device, following the cursor until the last page

#Get every device, following the cursor until the last page
$ConnectApiBaseUrl = "https://app.pdq.com/api"
$ConnectApiToken = "YOUR CONNECT API TOKEN"
$headers = @{'authorization' = "Bearer $ConnectApiToken"; 'x-pdq-connect-api-version' = '2026-10-20' }
$uri = "$ConnectApiBaseUrl/devices?page[size]=100"
$devices = @()
while ($uri) {
    $response = Invoke-RestMethod -Headers $headers -Uri $uri
    $devices += $response.data
    $uri = $response.links.next
}
$devices.Count

Get Windows devices, most recently updated first

#Get Windows devices, most recently updated first
$ConnectApiBaseUrl = "https://app.pdq.com/api"
$ConnectApiToken = "YOUR CONNECT API TOKEN"
$headers = @{'authorization' = "Bearer $ConnectApiToken"; 'x-pdq-connect-api-version' = '2026-10-20' }
Invoke-RestMethod -Headers $headers -Uri "$ConnectApiBaseUrl/devices?filter[os]=windows&sort=-updatedAt"

Get groups

#Get groups
$ConnectApiBaseUrl = "https://app.pdq.com/api"
$ConnectApiToken = "YOUR CONNECT API TOKEN"
$headers = @{'authorization' = "Bearer $ConnectApiToken"; 'x-pdq-connect-api-version' = '2026-10-20' }
Invoke-RestMethod -Headers $headers -Uri "$ConnectApiBaseUrl/groups"

Get devices in group

#Get devices in group
$ConnectApiBaseUrl = "https://app.pdq.com/api"
$ConnectApiToken = "YOUR CONNECT API TOKEN"
$headers = @{'authorization' = "Bearer $ConnectApiToken"; 'x-pdq-connect-api-version' = '2026-10-20' }
Invoke-RestMethod -Headers $headers -Uri "$ConnectApiBaseUrl/groups/[groupId]/devices"

Create a static group and add devices to it

#Create a static group and add devices to it
$ConnectApiBaseUrl = "https://app.pdq.com/api"
$ConnectApiToken = "YOUR CONNECT API TOKEN"
$headers = @{'authorization' = "Bearer $ConnectApiToken"; 'x-pdq-connect-api-version' = '2026-10-20' }
$body = @{
    data = @{
        type = "groups"
        attributes = @{ name = "Failed audit"; groupType = "static" }
        relationships = @{
            devices = @{ data = @( @{ type = "devices"; id = "[deviceId]" }, @{ type = "devices"; id = "[deviceId]" } ) }
        }
    }
} | ConvertTo-Json -Depth 10
Invoke-RestMethod -Headers $headers -Method Post -ContentType "application/vnd.api+json" -Uri "$ConnectApiBaseUrl/groups" -Body $body

Get packages by name contains

#Get packages by name contains
$ConnectApiBaseUrl = "https://app.pdq.com/api"
$ConnectApiToken = "YOUR CONNECT API TOKEN"
$headers = @{'authorization' = "Bearer $ConnectApiToken"; 'x-pdq-connect-api-version' = '2026-10-20' }
Invoke-RestMethod -Headers $headers -Uri "$ConnectApiBaseUrl/packages?filter[name]=~windows"

Get package versions

#Get package versions
$ConnectApiBaseUrl = "https://app.pdq.com/api"
$ConnectApiToken = "YOUR CONNECT API TOKEN"
$headers = @{'authorization' = "Bearer $ConnectApiToken"; 'x-pdq-connect-api-version' = '2026-10-20' }
Invoke-RestMethod -Headers $headers -Uri "$ConnectApiBaseUrl/packages/[packageId]/packageVersions"

Start a deployment

#Start a deployment of a package version to devices and groups
$ConnectApiBaseUrl = "https://app.pdq.com/api"
$ConnectApiToken = "YOUR CONNECT API TOKEN"
$headers = @{'authorization' = "Bearer $ConnectApiToken"; 'x-pdq-connect-api-version' = '2026-10-20' }
$body = @{
    data = @{
        type = "deployments"
        relationships = @{
            packageVersion = @{ data = @{ type = "packageVersions"; id = "[packageVersionId]" } }
            devices = @{ data = @( @{ type = "devices"; id = "[deviceId]" } ) }
            groups = @{ data = @( @{ type = "groups"; id = "[groupId]" } ) }
        }
    }
} | ConvertTo-Json -Depth 10
$deployment = Invoke-RestMethod -Headers $headers -Method Post -ContentType "application/vnd.api+json" -Uri "$ConnectApiBaseUrl/deployments" -Body $body
$deployment.data.id

Set a custom field value on a device

#Set a custom field value on a device
$ConnectApiBaseUrl = "https://app.pdq.com/api"
$ConnectApiToken = "YOUR CONNECT API TOKEN"
$headers = @{'authorization' = "Bearer $ConnectApiToken"; 'x-pdq-connect-api-version' = '2026-10-20' }
$body = @{ data = @{ type = "deviceCustomFields"; attributes = @{ value = "Marketing" } } } | ConvertTo-Json -Depth 10
Invoke-RestMethod -Headers $headers -Method Put -ContentType "application/vnd.api+json" -Uri "$ConnectApiBaseUrl/devices/[deviceId]/deviceCustomFields/[customFieldId]" -Body $body

Delete a device

#Delete a device
$ConnectApiBaseUrl = "https://app.pdq.com/api"
$ConnectApiToken = "YOUR CONNECT API TOKEN"
$headers = @{'authorization' = "Bearer $ConnectApiToken"; 'x-pdq-connect-api-version' = '2026-10-20' }
Invoke-RestMethod -Headers $headers -Method Delete -Uri "$ConnectApiBaseUrl/devices/[deviceId]"

 

Example using Postman

  1. Open Postman, and click + icon to Create new request (which will open in a new tab). 
  2. In the method selection dropdown (set to GET by default), select the appropriate method for your request, and then enter your request in the text box. 
    (e.g. https://app.pdq.com/api/devices)
  3. Within the request, switch to the Authorization tab. 
  4. Select an Auth Type of Bearer Token, and paste your PDQ Connect API key into the Token box.
  5. Switch to the Headers tab and add a header with the key x-pdq-connect-api-version and the value 2026-10-20.
  6. (optional) In order to store your PDQ Connect API token more securely, click the padlock icon and then click Set as Variable.

    Enter a Variable name in the text box, and then click to select a Scope for the variable. Store the variable within a defined scope or in your vault in accordance with your organization's security practices. 
    (See Postman KB: Store and reuse values using variables)
  7. Click Send to send the request. 
     

 

Rate limits and paging

The API is rate limited per organization. When you exceed the limit, the API returns 429 Too Many Requests. Wait and retry the request.

List endpoints return 10 results per page by default and up to 100 when you set page[size]=100. If you are querying more than 100 objects (devices, packages, etc.), follow the links.next URL in each response until it is empty. Each response also carries links.prev for paging backwards. The cursors in those links are opaque: pass them back exactly as given, and do not store them between runs. Keep the same sort and filter parameters while paging through a collection.

Filtering and sorting

Every list endpoint accepts filter[attribute] parameters, and the operators are the same on every resource. The API docs list the attributes you can filter and sort on for each resource.

Attribute type Syntax Example
String value exact, ^value starts with, ~value contains, value$ ends with filter[name]=^LAB
Date and time <value before, >value after. A bare value matches a 12 hour window either side of it, not an exact instant. filter[insertedAt]=>2026-10-20
Integer value, <value, >value, <=value, >=value filter[riskScore]=>=7
Enum, boolean, and ID Exact match only filter[os]=windows, filter[isIgnored]=false

Sort with sort=attribute for ascending or sort=-attribute for descending. One sort attribute per request.

PDQ Connect API (Early access) is strict about input. An unknown query parameter, an unknown field in a request body, a filter on an attribute that is not in the allow list, or a badly formatted date returns 400 Bad Request with a pointer to the offending field. An ID that does not exist, or that belongs to another organization, returns 404 Not Found. PDQ Connect API (Legacy) ignored unknown parameters, so a script that passed a misspelled parameter to it and got results will get a 400 from PDQ Connect API (Early access) until the parameter is fixed.

Moving from PDQ Connect API (Legacy)

PDQ Connect API (Legacy) keeps working during Early Access and after GA, and no retirement date has been announced. When you are ready to move an integration, these are the differences to account for.

Area PDQ Connect API (Legacy) PDQ Connect API (Early access)
Base URL https://app.pdq.com/v1/api https://app.pdq.com/api plus the header x-pdq-connect-api-version: 2026-10-20 (the current version; a 400 lists the accepted values if it changes during Early Access)
Response format Varies by endpoint JSON:API 1.1: data, attributes, relationships, links, errors
Paging page and pageSize, up to 250 per page page[size] up to 100 per page; follow links.next
Related data includes parameter No include parameter. Common details are inline on the device; larger lists (software, disks, drivers, Windows features, custom field values, vulnerabilities) are separate paged endpoints under the device.
Sorting sortAsc and sortDesc sort=field and sort=-field
Filtering Different filter object per endpoint filter[attribute] with the same operators on every endpoint
Deployment create Query parameters package and targets JSON:API body with relationships.packageVersion, relationships.devices, and relationships.groups; every ID is checked before the deployment is created
Reboot POST /v1/api/devices/reboot POST /api/deviceReboots with a list of up to 1,000 devices
Unknown parameters and IDs Unknown parameters ignored; unknown IDs returned 401 or 404 Unknown parameters return 400; unknown, malformed, and other-organization IDs return 404 on every verb
Documentation Static docs page Generated OpenAPI 3.1 spec at /openapi and docs at /api-docs

Changelog

October 20, 2026: PDQ Connect API (Early access)

PDQ Connect API (Early access) released. At general availability the Early access label is dropped and it becomes PDQ Connect API. The previous API continues as PDQ Connect API (Legacy).

Coming soon (but not yet in this release): creating packages or uploading installers, cancelling or retrying deployments, per-device deployment results, and an include parameter.

 

Was this article helpful?