# HTTP Reference Guide

## HTTP Reference

This page is the reference for the two parts of the local HTTPS API that integrators use: the **Plugin Settings API**, called from inside a running job task or plugin to read runtime configuration, and the **Job Management API**, called by deployment tooling to create, update, and trigger jobs.

The [Custom Job Integration Guide](/keeperpam/endpoint-privilege-manager/integrations/custom-job-guide.md) covers when and why to call each endpoint. The [Custom Plugin Integration Guide](/keeperpam/endpoint-privilege-manager/integrations/custom-plugin-guide.md) covers Plugin Settings for managed plugins. This page is what you reach for when scripting a deployment or checking an endpoint signature.

## Base URL and TLS

The agent exposes its API on the loopback interface only. There is no remote access.

<table data-header-hidden="false" data-header-sticky><thead><tr><th width="164.333251953125">Setting</th><th width="157.666748046875">Typical value</th><th>Source</th></tr></thead><tbody><tr><td>HTTPS port</td><td><code>6889</code></td><td><code>Settings:KestrelHttpsPort</code> in <code>appsettings.json</code></td></tr><tr><td>HTTP port</td><td><code>6888</code></td><td><code>Settings:KestrelHttpPort</code> in <code>appsettings.json</code></td></tr><tr><td>TLS certificate</td><td>Self-signed, locally generated</td><td>Confirm with your administrator; use your org's CA bundle if provided</td></tr></tbody></table>

Use HTTPS for all API calls. The base URL is:

```
https://127.0.0.1:{KestrelHttpsPort}
```

The agent uses a self-signed TLS certificate on many installs. HTTP clients connecting from loopback must either trust that certificate explicitly (via a CA bundle your administrator exports) or disable certificate verification for loopback connections per your security policy. Do not use the HTTP port for sensitive operations — prefer HTTPS.

Confirm actual port values with your deployment team before hardcoding them. Use `{KeeperApiBaseUrl}` argument substitution in your job task to receive the correct base URL at runtime rather than hardcoding `127.0.0.1:6889`.

## Authorization Tiers

Every request is classified by the agent's authorization middleware into a required tier. The two tiers integrators interact with are:

<table data-header-hidden="false" data-header-sticky><thead><tr><th width="97.666748046875">Tier</th><th width="398.333251953125">Who can call it</th><th>What it covers</th></tr></thead><tbody><tr><td><strong>Admin</strong></td><td>Deployment tooling authenticated with admin-class credentials — typically mutual TLS with a client certificate provisioned by your Keeper deployment team</td><td>All job management endpoints: create, update, delete, validate, trigger, reload</td></tr><tr><td><strong>Plugin</strong></td><td>Processes the agent launched and registered as trusted — a job task started by the job runner, or a managed plugin started by the orchestrator</td><td>All Plugin Settings endpoints: read merged settings, read/write individual keys, revert</td></tr></tbody></table>

The key practical implication: **these are two separate callers, not two modes for the same binary.**

Your job task binary calls Plugin Settings (Plugin tier) from inside a running job. Your deployment scripts call the Job Management API (Admin tier) from outside — from a CI system, a workstation, or an automation tool provisioned with admin credentials. Do not attempt to call `/api/Jobs` from inside your task binary, and do not expect `/api/PluginSettings/...` to work from an arbitrary script or shell session.

If you receive `403` and TLS succeeded, the problem is the authorization tier — not the certificate or the network. Confirm which tier the endpoint requires and whether the calling process satisfies it.

## Plugin Settings API

All endpoints under `/api/PluginSettings` require **Plugin-tier** authorization. The caller must be a process that the agent launched and registered — a job task or managed plugin. Manual invocations (running your binary from a shell, a CI runner, or a test script) will receive `403`.

### Endpoints

<table data-header-hidden="false" data-header-sticky><thead><tr><th width="101">Method</th><th width="198.666748046875">Path</th><th width="185.666748046875">Request body</th><th>Response</th></tr></thead><tbody><tr><td><code>GET</code></td><td><code>/api/PluginSettings/{pluginName}</code></td><td>—</td><td><code>200</code> — flat JSON object of string keys to string values (merged effective settings)</td></tr><tr><td><code>GET</code></td><td><code>/api/PluginSettings/{pluginName}/{settingName}</code></td><td>—</td><td><code>200</code> — single setting value</td></tr><tr><td><code>PUT</code></td><td><code>/api/PluginSettings/{pluginName}/{settingName}</code></td><td><code>PluginSettingValue</code> JSON</td><td><code>200</code> on success</td></tr><tr><td><code>POST</code></td><td><code>/api/PluginSettings/{pluginName}/revert</code></td><td>—</td><td><code>200</code> — re-imports that plugin's on-disk JSON into unified storage</td></tr><tr><td><code>POST</code></td><td><code>/api/PluginSettings/revert-all</code></td><td>—</td><td><code>200</code> — re-imports all plugins from their on-disk JSON</td></tr><tr><td><code>GET</code></td><td><code>/api/PluginSettings/{pluginName}/status</code></td><td>—</td><td>Configuration change and hash status</td></tr></tbody></table>

### `{pluginName}` Values

Use `KeeperPrivilegeManager` as the plugin name to read system-wide merged settings, including `broker.host` and `broker.port`. This is the standard call for any job task that needs the MQTT broker address.

Use your own plugin's `id` (for example `MyBridge`) to read or write settings scoped to that plugin specifically.

### Response Shape for `GET /api/PluginSettings/{pluginName}`

The response is a flat JSON object where every value is a string:

```json
{
  "broker.host": "127.0.0.1",
  "broker.port": "8675",
  "some.other.key": "value"
}
```

Parse only the keys your integration needs. Other keys may be present depending on the agent version and policy configuration.

### `PUT` Request body

To write a single setting:

```json
{
  "value": "new-value-here"
}
```

### Common Failures

<table data-header-hidden="false" data-header-sticky><thead><tr><th width="126.666748046875">Response</th><th>Cause</th></tr></thead><tbody><tr><td><code>403</code></td><td>Process is not Plugin-authenticated — it was not started by the agent, or it has not yet been registered in the launched-process registry. Add a retry on startup if the failure occurs immediately after the process starts.</td></tr><tr><td><code>404</code></td><td>The plugin name does not exist in the agent's plugin registry. Confirm the plugin is deployed and the name matches exactly.</td></tr></tbody></table>

## Job Management API

All endpoints under `/api/Jobs` require **Admin-tier** authorization unless noted. The exact authentication mechanism — client certificates, mutual TLS, or another admin credential — is deployment-specific. Your Keeper deployment team will provide the credentials and tooling for your environment.

### Endpoints

<table data-header-hidden="false" data-header-sticky><thead><tr><th width="105.6666259765625">Method</th><th width="180">Path</th><th width="143.6666259765625">Request body</th><th>Response</th></tr></thead><tbody><tr><td><code>GET</code></td><td><code>/api/Jobs</code></td><td>—</td><td><code>200</code> — object with <code>jobs</code> array, <code>count</code>, and <code>message</code></td></tr><tr><td><code>GET</code></td><td><code>/api/Jobs/{jobId}</code></td><td>—</td><td><code>200</code> — job definition JSON; <code>404</code> if not found</td></tr><tr><td><code>POST</code></td><td><code>/api/Jobs</code></td><td>Job JSON</td><td><code>200</code> on success; <code>400</code> with validation errors if invalid</td></tr><tr><td><code>PUT</code></td><td><code>/api/Jobs/{jobId}</code></td><td>Job JSON</td><td><code>200</code> on success; <code>404</code> if job does not exist</td></tr><tr><td><code>DELETE</code></td><td><code>/api/Jobs/{jobId}</code></td><td>—</td><td><code>200</code> on success; <code>404</code> if not found</td></tr><tr><td><code>POST</code></td><td><code>/api/Jobs/validate</code></td><td>Job JSON</td><td><code>200</code> — object with <code>valid</code>, <code>errors</code>, <code>warnings</code>, <code>jobId</code>; does not save</td></tr><tr><td><code>POST</code></td><td><code>/api/Jobs/{jobId}/trigger</code></td><td>Optional JSON object</td><td><code>200</code> — triggers a run with optional event context; <code>400</code> if job is disabled</td></tr><tr><td><code>POST</code></td><td><code>/api/Jobs/{jobId}/run</code></td><td>—</td><td><code>200</code> — triggers async execution; <code>400</code> if job is disabled</td></tr><tr><td><code>POST</code></td><td><code>/api/Jobs/reload</code></td><td>—</td><td><code>200</code> — reloads job definitions from disk</td></tr></tbody></table>

### Notes on Specific Endpoints

**`POST /api/Jobs`** — Creates or updates a job. Runs the full job validator, which requires the task binary to exist on disk at the path specified in the job JSON at the time of the call. Deploy the binary before calling this endpoint. If the job's `osFilter` excludes the current OS, binary existence checks are skipped for that run.

**`POST /api/Jobs/validate`** — Identical validation to `POST /api/Jobs` but does not write anything. Use this to test a job JSON against a live agent before committing. The response body tells you whether the job is valid and lists any errors or warnings.

**`PUT /api/Jobs/{jobId}`** — The `id` in the URL is authoritative. If the job JSON body contains a different `id`, it is overwritten with the URL value.

**`POST /api/Jobs/{jobId}/trigger`** — The preferred way to run a job manually during testing. The optional request body can pass event context as a key-value JSON object. An empty body (`{}`) is also accepted.

**`POST /api/Jobs/reload`** — Forces the agent to re-read job definitions from the `Jobs/` directory. Use after placing files on disk via a blessed path to pick up changes without restarting the agent.

### `{jobId}` format

Job IDs are URL-encoded in path segments. Hyphens are allowed. Do not use underscores in job IDs — the MQTT broker splits client IDs on underscores to extract the job ID, and underscores in the ID break that parsing. See the [Custom Job Integration Guide](https://claude.ai/chat/custom-job-guide#step-3-form-the-mqtt-client-id) for details.

## Common Failures

<table data-header-hidden="false" data-header-sticky><thead><tr><th width="114">Response</th><th>Cause</th></tr></thead><tbody><tr><td><code>400</code></td><td>Validation failed — binary not found on the validating host, malformed JSON, or a required field is missing. Check the <code>errors</code> array in the response body.</td></tr><tr><td><code>403</code></td><td>Admin credentials not provided or not accepted. Confirm with your deployment team that the client certificate or auth token is correct for this agent.</td></tr><tr><td><code>404</code></td><td>Job ID not found — either the job was never created or the ID does not match. Use <code>GET /api/Jobs</code> to list what exists.</td></tr></tbody></table>

## Basic Examples

These examples use PowerShell and curl. Replace the certificate paths, URL, and JSON file with values for your environment.

### **Validate a Job Without Saving (PowerShell):**

```powershell
Invoke-RestMethod -Method Post `
  -Uri "https://127.0.0.1:6889/api/Jobs/validate" `
  -ContentType "application/json" `
  -Certificate $adminClientCert `
  -Body (Get-Content -Raw .\my-job.json)
```

### **Create a Job (PowerShell):**

```powershell
Invoke-RestMethod -Method Post `
  -Uri "https://127.0.0.1:6889/api/Jobs" `
  -ContentType "application/json" `
  -Certificate $adminClientCert `
  -Body (Get-Content -Raw .\my-job.json)
```

### **Trigger a Job Run Manually (PowerShell):**

```powershell
Invoke-RestMethod -Method Post `
  -Uri "https://127.0.0.1:6889/api/Jobs/my-job-id/trigger" `
  -ContentType "application/json" `
  -Certificate $adminClientCert `
  -Body "{}"
```

### **List All Registered Jobs (curl):**

```bash
curl -s https://127.0.0.1:6889/api/Jobs \
  --cert /path/to/client.pem \
  --key /path/to/client.key \
  --cacert /path/to/ca.pem
```

### **Create a Job (curl):**

```bash
curl -s -X POST https://127.0.0.1:6889/api/Jobs \
  --cert /path/to/client.pem \
  --key /path/to/client.key \
  --cacert /path/to/ca.pem \
  -H "Content-Type: application/json" \
  -d @my-job.json
```

### **Delete a Job (curl):**

```bash
curl -s -X DELETE https://127.0.0.1:6889/api/Jobs/my-job-id \
  --cert /path/to/client.pem \
  --key /path/to/client.key \
  --cacert /path/to/ca.pem
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.keeper.io/keeperpam/endpoint-privilege-manager/integrations/http-reference-guide.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
