Parses SQL Server Agent job script (the exact T-SQL SSMS's "Script Job as -> CREATE To" produces) and returns a preview of what it found -- jobs, steps, schedules, flagged problems, and a proposed credential match per step -- without persisting anything. Nothing is created until you follow up with Commit a Job Import.

Having trouble reaching the API, or logging in from another machine? See Network Access & Authentication Security -- by default the Api only answers localhost, and PowerShell needs an extra flag once it does answer elsewhere.

Order of Operations

  1. Authenticate to the API.
  2. Get the script text (paste it directly, or get it from Request a Job Import Scan instead of typing it by hand).
  3. Parse it.
  4. Resolve any flagged step/schedule before committing.

The call

POST /api/job-imports/parse

Permission needed: Job.Edit.

C# example

var jsonOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web);

// Step 1: Authenticate to the API.
using var handler = new HttpClientHandler { UseDefaultCredentials = true };
using var client = new HttpClient(handler) { BaseAddress = new Uri("http://your-minion-agent-server:5443") };
client.DefaultRequestHeaders.Add("X-App-Name", "MyIntegration");

// Step 2: You already have the script text (pasted, or from a scan's ResultScriptText).
var scriptText = File.ReadAllText(@"C:\temp\NightlyETL.sql");

// Step 3: Parse it.
var response = await client.PostAsJsonAsync("/api/job-imports/parse", new ImportParseRequest(scriptText), jsonOptions);
response.EnsureSuccessStatusCode();
var parsed = await response.Content.ReadFromJsonAsync<ImportParseResponse>(jsonOptions);

// Step 4: Check for flags before committing.
foreach (var job in parsed!.Jobs)
{
    Console.WriteLine($"{job.JobName}: duplicate = {job.IsDuplicate}, can commit = {job.CanCommit}");
    foreach (var step in job.Steps)
        foreach (var flag in step.Flags)
            Console.WriteLine($"  step '{step.StepName}': [{flag.Severity}] {flag.Message}");
}

record ImportParseRequest(string ScriptText);
record ImportFlagDto(string Severity, string Message);
record ImportStepDto(int StepId, string StepName, string Subsystem, string CommandText, string? DatabaseName,
    byte? StepTypeCode, int? MatchedCredentialId, string? MatchedCredentialName, ImportFlagDto[] Flags, bool CanCommit);
record ImportScheduleDto(string Name, string? Day, int? Ordinal, TimeSpan? StartTime, TimeSpan? EndTime,
    int? MaxForTimeframe, int? FrequencyMinutes, bool RunOnStartup, ImportFlagDto[] Flags, bool CanCommit);
record ImportJobDto(string JobName, string? Description, bool Enabled, ImportStepDto[] Steps, ImportScheduleDto[] Schedules,
    bool CanCommit, bool IsDuplicate = false, int? ExistingJobId = null);
record ImportParseResponse(ImportJobDto[] Jobs);

Not on a domain machine? Swap in the app-account login from Calling the API From Your Own Code.

PowerShell example

# Step 1: Authenticate to the API.
$headers = @{ "X-App-Name" = "MyIntegration" }

# Step 2: You already have the script text.
$scriptText = Get-Content -Raw -Path "C:\temp\NightlyETL.sql"

# Step 3: Parse it. (-AllowUnencryptedAuthentication: PowerShell requires this for Windows auth over plain http to anything but localhost -- see "Network Access & Authentication Security".)
$body = @{ ScriptText = $scriptText } | ConvertTo-Json
$parsed = Invoke-RestMethod -Uri "http://your-minion-agent-server:5443/api/job-imports/parse" `
    -Method Post -Body $body -ContentType "application/json" -UseDefaultCredentials -AllowUnencryptedAuthentication -Headers $headers

# Step 4: Check for flags before committing.
foreach ($job in $parsed.jobs) {
    "$($job.jobName): duplicate = $($job.isDuplicate), can commit = $($job.canCommit)"
    foreach ($step in $job.steps) {
        foreach ($flag in $step.flags) { "  step '$($step.stepName)': [$($flag.severity)] $($flag.message)" }
    }
}

What you get back

200 OK:

{
    "jobs": [
        {
            "jobName": "Nightly ETL",
            "description": "Imported nightly load",
            "enabled": true,
            "steps": [
                {
                    "stepId": 1, "stepName": "Load Staging", "subsystem": "TSQL", "commandText": "EXEC dbo.LoadStaging",
                    "databaseName": "Warehouse", "stepTypeCode": 0, "matchedCredentialId": null, "matchedCredentialName": null,
                    "flags": [ { "severity": "Warning", "message": "No credential matched by name -- pick one before committing." } ],
                    "canCommit": false
                }
            ],
            "schedules": [
                { "name": "Nightly", "day": "Daily", "ordinal": null, "startTime": "02:00:00", "endTime": null, "maxForTimeframe": null, "frequencyMinutes": null, "runOnStartup": false, "flags": [], "canCommit": true }
            ],
            "canCommit": false,
            "isDuplicate": false,
            "existingJobId": null
        }
    ]
}

matchedCredentialId/matchedCredentialName is a name-match proposal against your existing credentials (List Credentials) -- it's a suggestion only, never pre-selected for you; you must supply a real CredentialId per step when you commit. isDuplicate/existingJobId is set when a job of the same name already exists and is active -- Parse's check is a convenience preview; Commit re-checks this itself as the authoritative decision.

Codes this call can return

See API Response Codes for what each one means in general. For this specific call:

  • 200 -- parsed (even if every job/step ends up flagged canCommit: false).
  • 400 -- the script text isn't parseable T-SQL in the expected SQL Agent script shape.
  • 403 -- you don't have Job.Edit.

Not audited -- nothing is persisted by this call.

See also: Commit a Job Import, Request a Job Import Scan.