# Policy: Create, Modify, or Delete Job

<figure><img src="https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2Fplx6vEekek24CWRmMWRq%2Fimage.png?alt=media&#x26;token=6ca319a2-282f-40fb-a16c-a2a68896d2e1" alt=""><figcaption></figcaption></figure>

**Audience:** IT admins. This example walks through **creating**, **modifying**, and **deleting** a job using either **files** in the Jobs directory or the **local management API**.

***

### Overview

* **Create** — Add a new job by placing a JSON file in the Jobs directory, by calling **POST /api/Jobs** with the job JSON in the body, or by using a **JobUpdate** policy with **Action: "Add"**.
* **Modify** — Edit the job JSON file and save (the loader may pick it up automatically), call **PUT /api/Jobs/{jobId}** with the updated JSON, or use a **JobUpdate** policy with **Action: "Update"**.
* **Delete** — Remove the job file from the Jobs directory, call **DELETE /api/Jobs/{jobId}**, or use a **JobUpdate** policy with **Action: "Delete"**.

The job **id** must be unique. For file-based jobs, the **filename** must be `{id}.json`. See [Jobs: Definition & Format](https://docs.keeper.io/en/keeperpam/endpoint-privilege-manager/reference/jobs-definition-and-format) and [Plugin & Job Registration](https://docs.keeper.io/en/keeperpam/endpoint-privilege-manager/reference/plugin-and-job-registration).

***

### Create a Job

#### Method 1: File-Based (add a new JSON file)

1. **Choose a job id** (e.g. `my-maintenance-job`). The file will be `my-maintenance-job.json`.
2. **Create the job JSON** with at least: `id`, `name`, `enabled`, and either `events` and/or `schedule`, and `tasks`. Example minimal structure:

   ```
   {
     "id": "my-maintenance-job",
     "name": "My maintenance job",
     "description": "Runs a script every hour",
     "enabled": true,
     "priority": 5,
     "schedule": {
       "intervalMinutes": 60
     },
     "events": [],
     "parameters": [],
     "tasks": [
       {
         "id": "run-script",
         "name": "Run script",
         "executionType": "Service",
         "command": "MyScript",
         "executablePath": "{jobroot}/bin/MyScript.exe",
         "arguments": ""
       }
     ]
   }
   ```
3. **Save the file** as `Jobs/my-maintenance-job.json` under the application root (e.g. `C:\Program Files\KeeperPrivilegeManager\Jobs\my-maintenance-job.json`). Ensure the **id** inside the JSON matches the filename (without `.json`).
4. **Load the job:** The job service may rescan the Jobs directory automatically. If not, restart the agent (or trigger a reload if the product supports it). The job will then run when its schedule or events fire.

#### Method 2: API (POST)

1. **Validate first (optional):**\
   `POST /api/Jobs/validate`\
   Body: your full job JSON. Fix any validation errors.
2. **Create the job:**\
   `POST /api/Jobs`\
   Body: your full job JSON (same structure as above).\
   Auth: **Admin** (e.g. from an elevated script or with the required certificate).
3. The service will register the job. Depending on implementation, it may also write the JSON to the Jobs directory. The job is then available for triggers and runs.

**Example (PowerShell, conceptual):**

```
$job = @{
  id = "my-maintenance-job"
  name = "My maintenance job"
  enabled = $true
  schedule = @{ intervalMinutes = 60 }
  events = @()
  parameters = @()
  tasks = @(
    @{
      id = "run-script"
      executionType = "Service"
      command = "MyScript"
      executablePath = "{jobroot}/bin/MyScript.exe"
      arguments = ""
    }
  )
} | ConvertTo-Json -Depth 10

Invoke-RestMethod -Method Post -Uri "https://127.0.0.1:6889/api/Jobs" -Body $job -ContentType "application/json" -SkipCertificateCheck
```

***

### Modify a Job

#### Method 1: File-based (edit the JSON file)

1. **Open** the job file (e.g. `Jobs/my-maintenance-job.json`) in an editor.
2. **Change** the fields you need (e.g. `schedule.intervalMinutes`, `tasks`, `enabled`, `name`). Keep the **id** the same and the filename as `{id}.json`.
3. **Save** the file. The job loader may pick up changes automatically; if not, restart the agent or trigger a job reload (if available).
4. **Optional:** If the product caches job definitions, call **POST /api/PluginSettings/revert-all** or the documented “reload jobs” step so the running service uses the new definition.

#### Method 2: API (PUT)

1. **Get the current job (optional):**\
   `GET /api/Jobs/my-maintenance-job`\
   to see the full definition.
2. **Edit** the JSON (e.g. change schedule, add/remove tasks, set `enabled` to `false`).
3. **Update:**\
   `PUT /api/Jobs/my-maintenance-job`\
   Body: the **full** updated job JSON.\
   Auth: **Admin**.
4. The service updates the job. Subsequent runs use the new definition.

**Example (PowerShell, conceptual):**

```
$updated = Invoke-RestMethod -Method Get -Uri "https://127.0.0.1:6889/api/Jobs/my-maintenance-job" -SkipCertificateCheck
$updated.schedule.intervalMinutes = 30
$updated | ConvertTo-Json -Depth 10 | Invoke-RestMethod -Method Put -Uri "https://127.0.0.1:6889/api/Jobs/my-maintenance-job" -ContentType "application/json" -SkipCertificateCheck
```

***

### Delete a Job

#### Method 1: File-based (remove the file)

1. **Delete** the file `Jobs/{job-id}.json` (e.g. `Jobs/my-maintenance-job.json`) from the application root.
2. The job service may stop running it once the file is gone (after a rescan). If not, restart the agent so the job is no longer registered.

#### Method 2: API (DELETE)

1. **Delete the job:**\
   `DELETE /api/Jobs/my-maintenance-job`\
   Auth: **Admin**.
2. The service unregisters the job. Depending on implementation, it may also remove the file from the Jobs directory. The job will no longer run.

**Example (PowerShell, conceptual):**

```
Invoke-RestMethod -Method Delete -Uri "https://127.0.0.1:6889/api/Jobs/my-maintenance-job" -SkipCertificateCheck
```

***

### Create, modify, or delete a job using policy (JobUpdate)

You can **create**, **modify**, or **delete** jobs on endpoints by using a **JobUpdate** configuration policy. The policy defines which job to add, update, or remove; the **Process Configuration Policies** job on each agent reads these policies and writes or deletes the job file under the Jobs directory. This lets you roll out or change jobs from the dashboard or policy store without editing files or calling the API on each machine.

#### How it Works

1. You create a policy with **PolicyType** `"JobUpdate"` and an **Extension** that contains:
   * **JobId** — The job id (e.g. `my-maintenance-job`). The processor will write to or delete `Jobs/{JobId}.json`.
   * **Action** — `"Add"` (create), `"Update"` (modify), or `"Delete"` (remove).
   * **JobJson** — Required for **Add** and **Update** only. The full job JSON (same structure as in a file or API). Omit for **Delete**.
2. You deploy the policy to the right collections or machines (e.g. from the Keeper Admin Console or policy store).
3. On each agent, the **Process Configuration Policies** job runs (on a schedule or when you trigger it via **POST /api/Jobs/{jobId}/run**). It finds all **JobUpdate** policies and, for each one, adds, updates, or deletes the corresponding job file under `Jobs/`.
4. The job loader on the agent picks up the new or changed file (or stops seeing the job after delete). No need to restart the agent in many cases; if the product caches job definitions, a reload or restart may be required.

#### Create a Job via Policy (Action: Add)

Create a **JobUpdate** policy with **Extension**:

```
{
  "PolicyId": "deploy-my-maintenance-job",
  "PolicyName": "Deploy my maintenance job",
  "PolicyType": "JobUpdate",
  "Status": "enabled",
  "Extension": {
    "JobId": "my-maintenance-job",
    "Action": "Add",
    "JobJson": {
      "id": "my-maintenance-job",
      "name": "My maintenance job",
      "description": "Runs a script every hour",
      "enabled": true,
      "priority": 5,
      "schedule": { "intervalMinutes": 60 },
      "events": [],
      "parameters": [],
      "tasks": [
        {
          "id": "run-script",
          "name": "Run script",
          "executionType": "Service",
          "command": "MyScript",
          "executablePath": "{jobroot}/bin/MyScript.exe",
          "arguments": ""
        }
      ]
    }
  }
}
```

**JobJson** can be the full job object (as above) or a string containing the JSON. The **id** inside JobJson must match **JobId**. Deploy the policy and run **Process Configuration Policies** on the agent; the job file will be created.

#### Modify a Job via Policy (Action: Update)

Use the same **PolicyType** `"JobUpdate"` and **Extension** with **Action** `"Update"`, the same **JobId**, and **JobJson** set to the **full updated** job JSON (including any fields you did not change). The processor **replaces** the entire job file. Deploy the policy and run Process Configuration Policies; the job file will be updated.

#### Delete a Job via Policy (Action: Delete)

Use **JobUpdate** with **Extension**:

```
"Extension": {
  "JobId": "my-maintenance-job",
  "Action": "Delete"
}
```

No **JobJson** is needed for Delete. Deploy the policy and run Process Configuration Policies; the job file `Jobs/my-maintenance-job.json` will be removed. The job **process-configuration-policies** is protected and cannot be deleted by a JobUpdate policy.

#### Summary (policy method)

| Action     | Extension                                                            | Result                          |
| ---------- | -------------------------------------------------------------------- | ------------------------------- |
| **Create** | **JobId**, **Action: "Add"**, **JobJson** (full job JSON)            | Writes `Jobs/{JobId}.json`.     |
| **Modify** | **JobId**, **Action: "Update"**, **JobJson** (full updated job JSON) | Overwrites `Jobs/{JobId}.json`. |
| **Delete** | **JobId**, **Action: "Delete"** (no JobJson)                         | Deletes `Jobs/{JobId}.json`.    |

For more on configuration policies and how to run the processor, see [Use a policy to set or change settings](https://docs.keeper.io/en/keeperpam/endpoint-privilege-manager/examples/advanced-examples/policy-create-a-policy-to-set-settings).

***

### Quick Reference

| Action       | File-based                                                                     | API                                                                              | Using policy                                                                                                  |
| ------------ | ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| **Create**   | Add `Jobs/{id}.json` with full job JSON; ensure `id` in JSON matches filename. | **POST /api/Jobs** with job JSON in body (Admin).                                | **JobUpdate** policy: **Action "Add"**, **JobId**, **JobJson**; run Process Configuration Policies.           |
| **Modify**   | Edit `Jobs/{id}.json`; keep `id` and filename the same; save.                  | **PUT /api/Jobs/{jobId}** with full updated JSON (Admin).                        | **JobUpdate** policy: **Action "Update"**, **JobId**, **JobJson** (full); run Process Configuration Policies. |
| **Delete**   | Remove `Jobs/{id}.json`.                                                       | **DELETE /api/Jobs/{jobId}** (Admin).                                            | **JobUpdate** policy: **Action "Delete"**, **JobId**; run Process Configuration Policies.                     |
| **Validate** | —                                                                              | **POST /api/Jobs/validate** with job JSON in body to check before create/update. | —                                                                                                             |
| **Run once** | —                                                                              | **POST /api/Jobs/{jobId}/run** (Admin).                                          | —                                                                                                             |

Use **HTTPS** (e.g. `https://127.0.0.1:6889`) and **Admin** auth for the API. See [Local Endpoints](https://docs.keeper.io/en/keeperpam/endpoint-privilege-manager/reference/local-endpoints) for full endpoint list.
