Skip to main content

User API: SweepTick Endpoints

Last updated November 4, 2026

This article is the reference for SweepTick from your own code: finding out which settings can be swept, previewing the positions a sweep would generate, creating the SweepTick, reading and changing its definition, and running it like any other Backtick.

The plan you need is in Use the tradeSteward API From Your Own Code. Backtick Professional allows up to 256 combinations in one SweepTick, plus the core position. Reading sweep settings, previewing and reading a SweepTick need backtick.view (View Backticks and results). Creating one needs backtick.create (Create Backticks), changing one needs backtick.edit (Edit Backticks and positions), and a bot used as the source also needs bots.settings.view (View bot settings). Running it needs backtick.run (Run Backticks), as in Running Backticks and Following a Run. If you have not used SweepTick on the website, SweepTick explains the idea. AI Assistant Tools: SweepTick covers the same endpoints through an assistant.

How a SweepTick is built

A SweepTick is a Backtick that steps one setting across a range (one axis), or two settings for a grid (two axes), and generates one position for every value next to its core position. Its positions are generated, so you never add, edit or remove them yourself: those requests answer 409 invalid_state with the reason sweep_managed, and so does changing its name, test dates, starting balance or run settings with PATCH /backtests/{uid}. You change all of that with PATCH /backtests/{uid}/sweep, which builds the positions again.

Sources. The core position comes from exactly one of:

  • {"backtestUID": "...", "positionId": 48213}: a position of one of your Backticks.
  • {"botId": "..."}: one of your bots. Needs bots.settings.view.
  • {"settings": {...}}: a settings object in the shape GET /backtests/{uid}/positions/{positionId} returns it. This lets you sweep without creating a Backtick first. The settings of GET /bots/{botId} hold bot-only members that a source refuses, so for a bot send botId instead.

A SweepTick's core never keeps position dependencies or launch-on-stop: those settings are removed from every source. A Multi-Entry position or bot cannot be a source itself; send one of its entries.

Axes. Each axis is an object with setting (a key from GET /backtests/sweep-settings), min, max, method (count spreads count values, at least 2, from min to max; interval steps from min by interval up to max) and the matching count or interval. Left out, the method follows the member you send: interval when you send interval, otherwise count. Sending both count and interval needs method. On a position with several legs, a setting that is scoped to legs takes ::legN after its key to step one leg (all-strikeTarget-delta::leg2) or ::legsA,B to step several legs together (all-strikeTarget-delta::legs1,2); legs are counted from 1. Two axes make a grid of every pair of values.

Names. Each generated position is named from a baseName and its value in brackets, for example 10d PCS [15]. On a two-axis grid both settings' tags and values are in the brackets, for example 10d PCS [Delta 15 | Width 10]. A name is at most 40 characters; a long base name is shortened to fit. baseName falls back to the core position's name, then to the SweepTick's name.

Caps. The size of a SweepTick is capped by your plan: on Backtick Professional, up to 256 combinations plus the core position, which the limit fields report as 257. The preview and GET /backtests/sweep-settings carry maxIterations, and GET /backtick/capabilities reports it as sweeptickMaxIterations. A sweep past the cap is refused with 422 validation_failed and nothing is saved: a one-axis sweep names axes.0.count, or axes.0.interval for an interval axis, and a two-axis grid whose cells add up to more than the cap names axes.1.count.

The order of calls. Read the sweepable settings with a source attached so you see what that core offers. Preview, which saves nothing. Create. Run with POST /backtests/{uid}/run. Read results per position, since a SweepTick's positions are alternatives to compare. Preview first: a create that is refused for its source has already spent change allowance and a SweepTick write slot.

  SweepTick previews (each also counts toward the validation limit), and SweepTick creates and edits, have limits of their own. Running a SweepTick needs a plan that includes SweepTick runs; otherwise the run answers 403 entitlement_required with the reason sweeptick_run.

Operations

GET /backtests/sweep-settings The settings a SweepTick can sweep

Lists every sweepable setting, the leg scope grammar and your plan's cap. Add a core position to also get that position's settings and the options it offers right now, with the exact key to use in an axis. Operation id: getSweepSettings. Permission: backtick.view (View Backticks and results).

NameTypeRequiredMeaning
backtestUIDquery, stringNoThe Backtick that holds the core position. Send with positionId.
positionIdquery, integerNoThe core position in that Backtick. Send with backtestUID.
botIdquery, stringNoA bot to take the core position from, instead of a position. Send it alone.

Returns settings: one item per sweepable setting with setting (the key), category, label, type, unit, nameTag (the tag its iteration names carry), legScoped (true when it takes ::legN) and gates (the conditions a core must meet to offer it, such as requiresType for a strike target of a particular kind, requiresExitDte, trailingStop, profitTargetType, enabledField or entryWindowRange); legScopeGrammar with single (<setting>::leg<N>) and group (<setting>::legs<A>,<B>); and maxIterations. With a source it adds core (name and settings) and options: one item per axis the core can take right now, each with the ready setting key (leg scope included), category, label, legs, type, currentValue and enables (true when sweeping it would switch that setting on). Examples of keys: all-strikeTarget-delta, all-strikeTarget-distance (vertical width), exit-profitTarget-percent, exit-time, entryWindow-start, stop-creditMultiple, stop-delta, botsize-Qty.

Refusals: 422 validation_failed when the query mixes botId with the other two or sends backtestUID without positionId, or naming botId with the reason bot_not_found for a bot that is not yours; 404 not_found for a Backtick or position that is not yours, or a Backtick in the trash; 422 family_edit_unsupported for a Multi-Entry position or bot (send one of its entries: error.data.entryPositionIds, with backtick.view, or error.data.entryBotIds lists the ones you may use); 403 permission_denied for a bot source without bots.settings.view.

POST /backtests/sweeps/preview Preview the positions a sweep would generate

Builds a SweepTick's positions from a source and its axes and answers how many there are and what each one is called. Nothing is saved and nothing is run. Operation id: previewSweep. Permission: backtick.view (View Backticks and results); a bot source also needs bots.settings.view. No Idempotency-Key.

NameTypeRequiredMeaning
sourceobjectYesExactly one of backtestUID with positionId, botId, or settings.
axesarrayYesOne or two axis objects: setting, min, max (required), method, and count or interval.
namestringNoThe SweepTick's name, used for the base name when nothing else gives one.
baseNamestringNoThe name each position's name is built from.
summarybooleanNotrue answers the short form described below, for checking a large sweep. Absent or false lists every position.

Returns count, stepSize, positions (each with name, displayValue and storedValue, and for two axes xValue, yValue, xDisplay and yDisplay), for two axes grid with countX and countY (how many values each axis has) and axisX and axisY (each axis's label and nameTag), and maxIterations. Without summary, every position is listed; the values of each cell are in its xValue and yValue.

The summary. With summary set to true, count, stepSize and maxIterations are the same, but positions holds only the first three and the last three positions (all of them when there are six or fewer), and positionsOmitted says how many were left out of the list. A two-axis preview also gets grid.valuesX and grid.valuesY: the values on each axis, in order, which with countX and countY describe every cell. The MCP tool preview_sweep gives the same answer for the same request. A summary that is not true or false is refused with 422 validation_failed naming summary with the reason wrong_type.

POST /rest/v1/backtests/sweeps/preview
{
  "source": {"backtestUID": "a1B2c3D4e5F6", "positionId": 48213},
  "baseName": "10d PCS",
  "axes": [{"setting": "all-strikeTarget-delta::leg1", "min": 5, "max": 20, "method": "interval", "interval": 5}]
}

{"ok": true, "data": {
  "count": 4, "stepSize": 5,
  "positions": [
    {"name": "10d PCS [5]", "displayValue": "5", "storedValue": 5},
    {"name": "10d PCS [10]", "displayValue": "10", "storedValue": 10},
    {"name": "10d PCS [15]", "displayValue": "15", "storedValue": 15},
    {"name": "10d PCS [20]", "displayValue": "20", "storedValue": 20}
  ],
  "maxIterations": 257
}, "error": null, "apiVersion": "rest-v1", "requestId": "req_4kZ9"}

Refusals: 422 validation_failed with each bad axis member named as axes.0.count (for example method missing when the axis cannot be inferred, count sent on an interval axis, or more positions than maxIterations), or source.botId with the reason bot_not_found; a refusal from the generator may carry error.data.invalidIterations; 404 not_found for a Backtick or position that is not yours; 422 family_edit_unsupported when the source is a Multi-Entry position or bot (send one of its entries: error.data.entryPositionIds, with backtick.view, or error.data.entryBotIds lists the ones you may use); 403 permission_denied for a bot source without bots.settings.view; 403 entitlement_required when your Backtick plan does not include SweepTick; 429 rate_limited past the preview limit or the validation limit; 503 service_unavailable, also when the preview limit cannot be counted.

POST /backtests/sweeps Create a SweepTick

Creates a draft SweepTick: its core position and the positions built from one or two axes, with its run settings. It is not started. The positions are built in the same transaction that stores them, so a refusal stores nothing. Operation id: createSweep. Permission: backtick.create (Create Backticks); a bot source also needs bots.settings.view; libraryStatus needs backtick.library. Header: Idempotency-Key (required).

NameTypeRequiredMeaning
namestringYesThe SweepTick's name in your library.
sourceobjectYesExactly one of backtestUID with positionId, botId, or settings.
axesarrayYesOne or two axis objects, as in the preview.
baseNamestringNoThe name each position's name is built from. Falls back to the core position's name, then to name.
testPeriodStartdateNoFirst day of the test period.
testPeriodEnddate or nullNoLast day of the test period.
startingBalancestringNoStarting balance in dollars, as a decimal string.
settingsobjectNoThe run settings: commissionProfile, skipDays, coercePrice, qty1normalize, maxQty49SPX and the six slippage and delay overrides. On a sweep a slippage override is 0 to 200 and a delay override 0 to 60. Fields left out start from your Backtick defaults.
signalsCsvstringNoSignals text, when your plan includes signals files. An empty string stores none.
tagsarray of integersNoIds of your tags to attach, 50 at most.
libraryStatusstringNoOnly recent, which is where a new SweepTick goes anyway, so leave it out. Sending it, even as recent, needs backtick.library; saved or archived is refused. Save it afterwards with POST /backtests/{uid}/library-status.

Returns 201 with the SweepTick as every Backtick write answers it (see What a write answers; testType is sweep), plus positionCount (the core and the generated positions together) and corePositionId. Keep backtestUID and editVersion. Like any API Backtick it is unsaved and moves to the trash 48 hours after its last change unless you save it.

Refusals: 422 validation_failed as in the preview, plus settings.commissionProfile with the reason required when your account has no default commission profile, testPeriodEnd before testPeriodStart, a name or baseName with characters a name cannot hold, tags that are not yours or more than 50, or a libraryStatus other than recent; 422 validation_failed with the reason not_a_sweep_setting for notes, ignoreConflicts, minLevQty1 or minPercQty1 in the body or in settings (change those with PATCH /backtests/{uid}), and unknown for any other member not listed above; 422 family_edit_unsupported when the source is a Multi-Entry position or bot (send one of its entries: error.data.entryPositionIds, with backtick.view, or error.data.entryBotIds lists the ones you may use); 403 entitlement_required for SweepTick itself or for signalsCsv on a plan without signals files; 403 permission_denied for libraryStatus without backtick.library; 404 not_found; 409 backtick_quota with the reason position_limit; 429 rate_limited past the SweepTick write limit; 503 service_unavailable with backtestUID and outcome in error.data: saved when the SweepTick was made but could not be read back, unknown when it may or may not have been made (check your Backticks before trying again).

GET /backtests/{uid}/sweep Read a SweepTick's definition

Returns a SweepTick's definition: its axes in the same form a create takes, its base name, core position, run settings, tags and generated positions. The same object comes embedded as sweep in GET /backtests/{uid}, or null there when the definition cannot be read back. Operation id: getSweep. Permission: backtick.view (View Backticks and results).

NameTypeRequiredMeaning
uidpath, stringYesThe SweepTick's id.

Returns corePositionId, name, baseName, axes, iterationCount, iterations (each with positionId, name, xValue and yValue), core (name and settings), run (testPeriodStart, testPeriodEnd, startingBalance and settings), hasSignalsCsv and tags. The positionId of each iteration is what you send as positionIds to the results views, the chart and portfolio links. Refusals: 409 invalid_state with the reason not_a_sweep for a plain Backtick, or sweep_definition_unavailable when the axes cannot be read back (send new axes with the update below); 404 not_found; 503 service_unavailable when the definition cannot be read just now.

PATCH /backtests/{uid}/sweep Change a SweepTick and build it again

Changes a draft or failed SweepTick and generates its positions again from the axes and the core, in the same transaction that stores them, so a refusal stores nothing. Send only the fields to change, at least one. Operation id: updateSweep. Permission: backtick.edit (Edit Backticks and positions); a bot core also needs bots.settings.view; libraryStatus needs backtick.library. Headers: If-Match and Idempotency-Key (both required).

NameTypeRequiredMeaning
uidpath, stringYesThe SweepTick's id.
namestringNoNew name. Left out, it is kept.
baseNamestringNoNew base name. Left out, the stored one is kept.
coreobjectNoA new core position, replacing the current one in place: exactly one of backtestUID with positionId, botId, or settings. Left out, the core is kept.
axesarrayNoOne or two axis objects. Left out, the stored axes are used again.
testPeriodStart, testPeriodEnd, startingBalance, settings, signalsCsv, tagsas in createNoThe same meaning as in POST /backtests/sweeps. Settings left out keep their stored values.
libraryStatusstringNorecent, saved or archived.

Returns 200 with the SweepTick, its new editVersion, positionCount, corePositionId and, when libraryStatus was sent, sharesEnded. The generated positions get new ids, so read the definition again before using positionIds. Refusals: 422 validation_failed as in create (also for an empty body, and with not_a_sweep_setting for the fields PATCH /backtests/{uid} owns); 422 family_edit_unsupported for a Multi-Entry core (send one of its entries: error.data.entryPositionIds, with backtick.view, or error.data.entryBotIds lists the ones you may use); 403 permission_denied or 403 entitlement_required as in create; 409 not_editable for a queued, running or completed SweepTick (clone it and change the copy); 409 invalid_state with the reason scheduled while a run is scheduled, sweep_definition_unavailable when the stored axes cannot be read back and you sent none, sweep_core_changed when the SweepTick changed while your request was being prepared (read it again and retry), not_a_sweep, or in_trash; 404 not_found; 412 version_mismatch; 428 precondition_required; 429 rate_limited; 503 service_unavailable.

Reading a SweepTick's results

Run a SweepTick with POST /backtests/{uid}/run and follow it as any run. When it completes, its positions are alternatives, so read them side by side:

  • GET /backtests/{uid}/results/positions lists the core and every generated position with its full metrics, in position order, 25 to a page. Read every page and sort them yourself by the metric you care about.
  • GET /backtests/{uid}/results/positions-daily returns every position's daily P/L in one call, with commonSettings holding what the positions share and each position's settings holding only the swept values. This is the view to build a heat map of a two-axis grid from.
  • GET /backtests/{uid}/results/series?positionIds=..., .../breakdowns?positionIds=... and the chart need positionIds on a SweepTick; without it they answer 400 bad_request.
  • A portfolio link from the best cells (POST /backtests/{uid}/portfolio-links) lets a person Test them together or create bots from them, saved switched off. A single winning position becomes a bot with POST /backtests/{uid}/positions/{positionId}/to-bot.

All of these are in Backtick Results, Charts, Links and Bots.