Adds a new step to a job. Steps belong to a specific job version (a draft, before it's published), not the job directly.

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 job's detail (its current jobVersionID comes from Get a Job).
  3. Send the new step's details.

The call

POST /api/job-versions/{jobVersionId}/steps

Permission needed: Job.Edit on the job this version belongs to. Creating with IsGlobal: true also needs Job.ManageGlobal.

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: Get the job's current version id.
var jobName = Uri.EscapeDataString("Nightly ETL Load");
var jobRef = await (await client.GetAsync($"/api/jobs/by-name/{jobName}")).Content.ReadFromJsonAsync<JobRef>(jsonOptions);
var job = await client.GetFromJsonAsync<JobVersionRef>($"/api/jobs/{jobRef!.JobID}", jsonOptions);

// Step 3: Send the new step's details. StepTypeCode 0 = T-SQL.
var newStep = new CreateStepRequest(StepKey: Guid.NewGuid().ToString("N"), StepName: "Stage table 3", StepTypeCode: 0,
    CommandText: "EXEC dbo.usp_LoadStage3", Tags: null);

var response = await client.PostAsJsonAsync($"/api/job-versions/{job!.JobVersionID}/steps", newStep, jsonOptions);
response.EnsureSuccessStatusCode();
var created = await response.Content.ReadFromJsonAsync<CreatedStep>(jsonOptions);
Console.WriteLine($"Created step id: {created!.JobStepID}");

record JobRef(int JobID);
record JobVersionRef(int JobVersionID);
record CreateStepRequest(string StepKey, string StepName, byte StepTypeCode, string CommandText, List<string>? Tags);
record CreatedStep(int JobStepID);

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: Get the job's current version id. (-AllowUnencryptedAuthentication: PowerShell requires this for Windows auth over plain http to anything but localhost -- see "Network Access & Authentication Security".)
$jobName = [Uri]::EscapeDataString("Nightly ETL Load")
$jobRef = Invoke-RestMethod -Uri "http://your-minion-agent-server:5443/api/jobs/by-name/$jobName" -UseDefaultCredentials -AllowUnencryptedAuthentication -Headers $headers
$job = Invoke-RestMethod -Uri "http://your-minion-agent-server:5443/api/jobs/$($jobRef.jobID)" -UseDefaultCredentials -AllowUnencryptedAuthentication -Headers $headers

# Step 3: Send the new step's details. StepTypeCode 0 = T-SQL.
$newStep = @{
    StepKey     = [Guid]::NewGuid().ToString("N")
    StepName    = "Stage table 3"
    StepTypeCode = 0
    CommandText = "EXEC dbo.usp_LoadStage3"
} | ConvertTo-Json

$created = Invoke-RestMethod -Uri "http://your-minion-agent-server:5443/api/job-versions/$($job.jobVersionID)/steps" `
    -Method Post -Body $newStep -ContentType "application/json" -UseDefaultCredentials -AllowUnencryptedAuthentication -Headers $headers

"Created step id: $($created.jobStepID)"

What you get back

201 Created:

{ "JobStepID": 214 }

StepTypeCode values worth knowing: 0 = T-SQL, 1 = PowerShell, 6 = Pool (a step that runs no command of its own, just groups its children -- see the Pool-related fields on Update a Step if you need one), 20 = SSIS Package (see below).

Creating an SSIS Package step

For StepTypeCode: 20, CommandText is ignored (send an empty string) -- the step instead runs a catalog-deployed SSIS package identified by four extra fields, all required together:

record CreateStepRequest(string StepKey, string StepName, byte StepTypeCode, string CommandText, List<string>? Tags,
    string? SsisFolderName = null, string? SsisProjectName = null, string? SsisPackageName = null,
    string? SsisEnvironmentName = null, string? SsisParametersJson = null);

Get the folder/project/package names from Browse an SSIS Catalog rather than typing them by hand. SsisEnvironmentName and SsisParametersJson are stored but not yet applied at run time -- the package runs with whatever SSISDB defaults are already configured.

Codes this call can return

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

  • 201 -- created.
  • 400 -- CommandText contains a blacklisted phrase.
  • 403 -- you don't have Job.Edit on the job (or Job.ManageGlobal, if IsGlobal was true).
  • 404 -- jobVersionId doesn't resolve to a real job.

See also: Update a Step, Set Step Dependencies.