Skip to content
Back to skills

Api Patterns

ASecurity

ThreatLocker Portal API fundamentals: raw-key authentication (no Bearer prefix), multi-tenant routing via the organizationId header, POST-based "GetByParameters" list endpoints, pagination shape, and child-organization fan-out patterns.

  • 48 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 2, 2026
ai-agentsbashapi

Works with

  • cursor
  • cli
  • api
  • mcp

Security analysis

A100/100

Scanned October 2, 2026

npx -y skills add wyre-technology/msp-claude-plugins --skill api-patterns --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Api Patterns?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Api Patterns
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/wyre-technology-api-patterns-26f5c319/badge)](https://www.skillsdirectory.com/skills/wyre-technology-api-patterns-26f5c319)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: "ThreatLocker API Patterns"
description: >
  ThreatLocker Portal API fundamentals: raw-key authentication (no Bearer prefix),
  multi-tenant routing via the organizationId header, POST-based "GetByParameters" list
  endpoints, pagination shape, and child-organization fan-out patterns.
when_to_use: >-
  When working with ThreatLocker auth headers, multi-tenant requests, POST-based list
  endpoints, pagination, or fanning queries across child organizations. Use when:
  threatlocker api, threatlocker authentication, threatlocker pagination, threatlocker
  organizationid, threatlocker mcp, threatlocker tools, threatlocker child
  organizations, threatlocker getbyparameters, or threatlocker portalapi.
---

# ThreatLocker MCP Tools & API Patterns

## Overview

The ThreatLocker MCP server wraps the ThreatLocker Portal API
(`https://portalapi.g.threatlocker.com/portalapi`) and exposes tools
across computers, computer groups, approval requests, audit log
("Action Log" in the UI), and organizations. The API has two quirks
that surprise people: the auth header does NOT use `Bearer`, and most
"list" endpoints are POSTs against `/Entity/EntityGetByParameters` with
a structured body — not GETs with query strings.

## Anti-triggers

- **Enumerating or pivoting between tenants.** This skill explains the
  `organizationId` header and the `childOrganizations` flag; the tools
  that actually list children, fetch auth keys, and resolve move targets
  are `threatlocker-organizations`.
- **Reading or storing an organization's auth key.** The header mechanics
  are here, but the tool that returns a live credential is in
  `threatlocker-organizations` — treat its output as a secret.

## Connection & Authentication

### Raw API Key Header

ThreatLocker authenticates with a raw API key — no `Bearer` prefix:

| Header | Value |
|--------|-------|
| `Authorization` | `<apiKey>` (raw, no prefix) |
| `ManagedClientId` | (optional) for legacy partner setups |
| `organizationId` | (optional) tenant to scope this call to |

> **Common mistake:** Sending `Authorization: Bearer <key>` returns
> 401. Send the key bare.

### Environment Variables

```bash
export THREATLOCKER_API_KEY="your-raw-api-key"
export THREATLOCKER_BASE_URL="https://portalapi.g.threatlocker.com/portalapi"
```

## Multi-Tenant Routing

ThreatLocker is built for MSPs and uses organizations as the tenant
boundary. Three patterns:

1. **Default org** — Omit the `organizationId` header. The API uses
   the API key's primary organization.
2. **Specific child org** — Set `organizationId` to a child org ID to
   scope a single call to that tenant.
3. **Fleet-wide fan-out** — Set the body flag `childOrganizations: true`
   on `*GetByParameters` endpoints to roll up data across all child
   organizations the API key can see.

For tenant pivots, see the `organizations` skill.

## Available MCP Tools

### Computers

| Tool | Description |
|------|-------------|
| `threatlocker_computers_list` | List computers with pagination/filters |
| `threatlocker_computers_get` | Get full details for one computer |
| `threatlocker_computers_get_checkins` | Recent check-in history |

### Computer Groups

| Tool | Description |
|------|-------------|
| `threatlocker_computer_groups_list` | Full group list with metadata |
| `threatlocker_computer_groups_dropdown` | Slim list for selection UIs |

### Approval Requests

| Tool | Description |
|------|-------------|
| `threatlocker_approvals_list` | List approval requests |
| `threatlocker_approvals_get` | Single approval with full context |
| `threatlocker_approvals_pending_count` | Quick pending-queue size |
| `threatlocker_approvals_get_permit_application` | Application that would be permitted |

### Audit Log (Action Log)

| Tool | Description |
|------|-------------|
| `threatlocker_audit_search` | Search Action Log by time/host/file |
| `threatlocker_audit_get` | Full record for one action |
| `threatlocker_audit_file_history` | All actions for a given file path/hash |

### Organizations

| Tool | Description |
|------|-------------|
| `threatlocker_organizations_list_children` | All child orgs visible to the key |
| `threatlocker_organizations_get_auth_key` | Auth key for a specific org |
| `threatlocker_organizations_for_move_computers` | Orgs eligible as move targets |

## POST-Based "GetByParameters" Pattern

Most list endpoints are `POST /Entity/EntityGetByParameters` with a
JSON body. Request shape:

```json
{
  "pageNumber": 1,
  "pageSize": 50,
  "isAscending": false,
  "orderBy": "lastCheckin",
  "searchText": "",
  "childOrganizations": false
}
```

Response shape:

```json
{
  "totalItems": 1284,
  "items": [ /* array of entities */ ]
}
```

### Pagination

ThreatLocker uses page numbers, not cursors:

1. Call with `pageNumber: 1`, `pageSize: 50` (or 100/200).
2. Compute `totalPages = ceil(totalItems / pageSize)`.
3. Continue until you have collected `totalItems` rows or reached
   the last page.

Avoid huge `pageSize` values — large pages can time out. 50–200 is the
sweet spot.

### Sort and Search

- `orderBy` is an entity-specific column name (e.g. `lastCheckin`,
  `computerName`).
- `isAscending` toggles direction.
- `searchText` is a substring match across the entity's searchable
  columns (computer name, hostname, OS, etc.).

## Error Handling

| Code | Meaning | Fix |
|------|---------|-----|
| 401 | Bad API key OR `Bearer` prefix included | Send raw key |
| 403 | Key valid, but no access to requested org | Check `organizationId` |
| 404 | Wrong endpoint or unknown entity ID | Recheck path |
| 429 | Rate limited | Backoff and retry |
| 500 | Portal API hiccup | Retry, then escalate |

## Best Practices

- Default to `pageSize: 100` and paginate; always check `totalItems`
  before assuming you have the full set.
- For multi-tenant reports, fan out with `childOrganizations: true`
  rather than looping per-org when the entity supports it.
- Cache the result of `threatlocker_organizations_list_children` —
  child org lists rarely change within a session.
- Always pass `organizationId` explicitly when generating client-facing
  reports so the source tenant is unambiguous.

## Related Skills

- [computers](../computers/SKILL.md) — Endpoint inventory
- [computer-groups](../computer-groups/SKILL.md) — Policy scoping
- [approval-requests](../approval-requests/SKILL.md) — Application approvals
- [audit-log](../audit-log/SKILL.md) — Action Log investigation
- [organizations](../organizations/SKILL.md) — Multi-tenant pivots

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…