# Job: Minimal Windows

**Audience:** Integrators deploying a custom executable on Windows endpoints.

This example shows the simplest valid job JSON for Windows: a single task that runs your binary on an interval schedule, as the agent service account, with permission to publish logs to KeeperLogger. Use it as a starting point and replace the placeholder values before deploying.

## The Job JSON

```json
{
  "id": "my-tool",
  "name": "My Tool",
  "description": "Runs MyTool on a 60-minute interval.",
  "enabled": true,

  "schedule": {
    "intervalMinutes": 60
  },

  "osFilter": {
    "windows": true,
    "linux": false,
    "macOS": false
  },

  "mqttTopics": {
    "allowedPublications": ["KeeperLogger"],
    "allowedSubscriptions": []
  },

  "parameters": [],

  "tasks": [
    {
      "id": "run-tool",
      "name": "Run tool",
      "ExecutionType": "Service",
      "command": "MyTool",
      "executablePath": "C:\\Program Files\\KeeperPrivilegeManager\\Jobs\\bin\\MyTool\\MyTool.exe",
      "arguments": "--keeper-api-base={KeeperApiBaseUrl}",
      "timeoutSeconds": 3600,
      "continueOnFailure": false,
      "scriptType": "Auto"
    }
  ]
}
```

## What to Change

<table data-header-hidden="false" data-header-sticky><thead><tr><th width="237.333251953125">Field</th><th>What to put here</th></tr></thead><tbody><tr><td><code>id</code></td><td>A unique identifier for this job. Use hyphens — no underscores. The filename must match: <code>my-tool.json</code> for <code>"id": "my-tool"</code>.</td></tr><tr><td><code>name</code></td><td>A human-readable name shown in logs and the admin view.</td></tr><tr><td><code>description</code></td><td>Optional, but useful for anyone maintaining the deployment later.</td></tr><tr><td><code>schedule.intervalMinutes</code></td><td>How often to run, in minutes. <code>60</code> = every hour. This is time between runs, not a clock-aligned schedule — see <a href="https://claude.ai/integration/custom-job-guide#schedule-options">schedule options</a> for cron and calendar alternatives.</td></tr><tr><td><code>tasks[0].command</code></td><td>The name of your binary without a path or extension. The agent resolves <code>Jobs\bin\{command}\{command}.exe</code> automatically.</td></tr><tr><td><code>tasks[0].executablePath</code></td><td>The full path to your binary on the endpoint. Replace <code>MyTool</code> with your executable name throughout.</td></tr><tr><td><code>tasks[0].arguments</code></td><td>Any flags your binary accepts. Keep <code>{KeeperApiBaseUrl}</code> — the agent substitutes the local HTTPS API base URL here so your binary can call Plugin Settings at runtime.</td></tr><tr><td><code>tasks[0].timeoutSeconds</code></td><td>Maximum run time before the agent kills the task. <code>3600</code> = one hour. Set this to something meaningful for your tool.</td></tr></tbody></table>

Leave `osFilter`, `mqttTopics`, `ExecutionType`, `continueOnFailure`, and `scriptType` as shown for a standard Windows background task.

## How this Works

**`osFilter`** tells the agent to only run this job on Windows endpoints. When the job is deployed to a mixed fleet, agents on Linux and macOS will skip it. The validator also skips binary existence checks on non-matching platforms, which means you can register this job from a Windows machine without worrying about Linux paths.

**`ExecutionType: Service`** runs the task as the agent service account — the right choice for any background tool that needs machine-wide access but not an interactive user session. The process is registered in the agent's launched-process registry immediately on start, which grants it access to MQTT and Plugin Settings without needing a certificate check.

**`mqttTopics.allowedPublications`** grants your task permission to publish to the `KeeperLogger` topic. The MQTT broker enforces this list — without it, connection succeeds but publish calls are denied. If your tool does not publish to MQTT at all, you can remove the `mqttTopics` block entirely, but then the agent will not inject `KEEPER_JOB_ID` or `KEEPER_JOB_NAME` as environment variables.

**`{KeeperApiBaseUrl}`** is replaced at run time by the agent with the local HTTPS API base URL (typically `https://127.0.0.1:6889`). Your binary reads this from its command-line arguments and uses it to call `GET /api/PluginSettings/KeeperPrivilegeManager` to fetch the MQTT broker address.

## Before you Deploy

1. **Deploy the binary first.** Place `MyTool.exe` at the `executablePath` on the endpoint before registering the job. The validator checks that the binary exists at the time `POST /api/Jobs` is called.
2. **Confirm the binary path.** The default agent install root on Windows is `C:\Program Files\KeeperPrivilegeManager`. If your deployment uses a different root, update `executablePath` accordingly.
3. **Save the file as `{id}.json`.** If you change the `id` field, the filename must match. A job with `"id": "my-tool"` must be saved as `my-tool.json`.

## Deploy

Validate the JSON against a live agent before saving:

```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-tool.json)
```

Then create the job:

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

Trigger a manual run to confirm everything is working:

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

For fleet deployments, use a `JobUpdate` policy via the Keeper console instead of calling the API directly on each endpoint. Contact your Keeper administrator for the current policy schema.


---

# 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/examples/job-minimal-windows.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.
