Skip to main content

Service requests

The end-user side is the self-service portal.

Task walkthrough: Create a service request. This page is the full configuration and troubleshooting reference.

A service request is a form a Builder publishes so that a business user can trigger automation without touching the workflow — for example, "Request a file restore" or "Run an on-demand report." Submitting the form fires one or more events.

What the screens call it

In the interface a service request is a self service button, and the page you author them on is Self Service Configuration — reached from Design → Self Service Config. Global search lists the same objects under Self Service Buttons. The web address is unchanged, so an existing link or bookmark still resolves; a link straight to one button opens the grid with that button's dialog already open.

What a service request contains​

PartNotes
Name1–255 characters, following the platform naming rules — a name like Restart Instance (EU) or START/STOP VM is valid.
InputsThe form fields the user fills in.
EventsThe actions fired on submission, in order.
Documentation / confirmation messageGuidance shown above the form / before submitting.
TagsFor organizing and for filtering in the portal.
CategoryThe container it is filed in — see Categories. One per button, optional.
Hidden / DisabledTwo rules deciding whether the button appears in the portal and whether it can be submitted — see Hidden and disabled.
VersionsEach save creates a new version with an optional change description — including the first, which earlier builds always labelled Initial version. At most 500 characters, trimmed; leave it blank and the first version falls back to Initial version as before.
DeploymentsWhich environments the request is available in, and at which version.
TransformationsPer-environment overrides applied to the request (see below).

The configuration grid​

Self Service Configuration lists every self service button in one grid. Selecting a row opens the button for editing; each row's action menu holds Copy and Delete, and selecting rows with their check boxes enables a bulk Delete.

ColumnShows
NameThe button's name. This column carries the grid's search box rather than a sort control; every other column sorts.
ActiveOne badge per environment the button is live in, with the version deployed there.
CategoryThe category it is filed in, blank when it has none.
TagsIts tags. Beyond three, the rest are summarized as a count.
WorkspaceThe workspace it belongs to.
Last UpdatedWhen it was last saved.

Name, Category and Last Updated are ordered by the server, so they sort the whole catalog. The rest sort the page you are looking at — search or filter a large catalog down first.

A deployment that is outside its effective window is left out of the Active column rather than reported as inactive.

Order Buttons in Category opens the page that arranges the portal — the order of the category sections, each category's band colour, and the order of the buttons inside each section. See Arranging the portal page. It is disabled, with a tooltip saying so, for anyone without permission to edit categories.

Categories​

A category is a container a self service button is filed in, and it is how a set of buttons that a user works through as one task stays together. Categories are tenant-wide and a button belongs to at most one.

Name1–255 characters, unique per tenant regardless of case, following the platform naming rules. Short names such as IT are the point, so the usual three-character minimum does not apply.
Where it is setThe button's dialog. The picker searches existing categories and offers New Category for a name it doesn't find, so a category can be created without leaving the button you are filing.
Clearing itChoose None.
Band colourOne of ten named colours, or none. Set on the Order Buttons in Category page rather than in the button's dialog — see Arranging the portal page.
PositionWhere the category's section sits on the portal page. Also set on Order Buttons in Category.

The portal groups by category. A requester sees one section per category that has at least one button they can see — each headed Category: followed by the category's name — in the order set on Order Buttons in Category, with the buttons that are in no category gathered into a General section pinned last. A category with no visible button draws no section at all — including one that is empty only because every button in it is hidden by a rule.

Both levels are ordered by a saved position, then by name. Sections go by the category's saved position, buttons by their saved position within the section. Where two share a position — which is what every row holds until somebody arranges it — the name decides and the row id breaks a remaining tie, so a catalog nobody has arranged reads alphabetically and stays in the same order between visits. A category that carries a band colour draws its cards on a tinted band; one with no colour draws the plain row.

note
If you have a category called General

The uncategorised section cannot answer to a name one of your own categories already has, or two sections would read identically. It takes Uncategorised instead, then No Category, then that wording numbered. Nothing reserves General, so this is decided per tenant from the categories you actually have.

A category is not part of the versioned configuration. Filing a button, refiling it, or renaming a category therefore needs no redeploy — unlike a change to the button's inputs or events. Saving the button from the dialog still mints a version, as every save does; it is only the category itself that sits outside versioning.

Deleting a category never deletes a button. Every button filed in it becomes uncategorised instead. Deleting also requires permission to edit self service buttons across the whole tenant, not just in one workspace, because the detach touches buttons in every workspace — see Roles and permissions.

note

A button whose category has been deleted while its dialog was open shows Category unavailable rather than an empty picker, so the value isn't silently dropped on the next save.

Arranging the portal page​

Order Buttons in Category, on the Self Service Configuration toolbar, is where the requester's page is arranged. It holds three things at once and saves them as one layout:

  • the order of the category sections,
  • each category's band colour,
  • the order of the buttons inside each section.

The page draws the sections and cards the way the portal draws them, so what you arrange is what a requester sees.

Moving things​

A drag handle sits next to each section's Category: heading and on the top-left corner of each card. Drag a heading's handle to move a whole section; drag a card's handle to move a button. The handle is the only thing that starts a drag — selecting the card itself opens its preview instead. By keyboard, Space lifts the item, the arrow keys move it, Space drops it and Escape cancels.

A button cannot change category here. Each section is its own list: a card released away from its own section returns to where it was. To refile a button, change its Category in the button's dialog.

The General section for uncategorised buttons sits last, and has no handle and no colour picker — there is no category row to store a position or a colour on.

Band colour​

The colour picker at the right of each section's heading offers None plus ten named colours — Secondary, Accent, Success, Warning, Invalid, Info, Sapphire, Flame, Warning yellow and Teal — as a four-column grid of swatches. Arrow keys move between them, Enter or Space picks one and Escape closes without a change. These ten are the whole palette: the categories API refuses any other name.

Narrowing what you see​

Four controls narrow the page. None of them change the arrangement — a card they hide keeps its place in the order, and a save still carries it.

ControlEffect
EnvironmentShows the page as a requester in that environment sees it: the buttons deployed and active there, with their hidden and disabled rules evaluated, so a hidden button drops out. Leave it empty and you see the saved configuration for every button instead, with no rule evaluated.
WorkspaceLimits the cards to one workspace.
Search Self ServiceA picker over the buttons in view. Choosing a name scrolls to that card and highlights it rather than filtering the page.
Tag pillsOne per tag the cards in view carry, used as toggles. Select several and a card matching any of them is shown.

The environment here is independent of the one selected in the header, and switching either picker never discards moves you have not saved. A section whose cards are all narrowed away still shows, with a line saying no button in it matches the current view.

Previewing a button​

Selecting a card opens the form the portal would render for it: the documentation, the confirmation message and the input fields, all disabled, with no way to submit. With no environment picked it says it is showing the saved configuration.

Saving​

Save writes the whole layout in one go, and it is presentation only: it mints no version, needs no redeploy, touches no deployment and leaves each button's Last Updated alone.

The save carries the whole tenant

The layout is one object covering every live category and button in the tenant, so a save must list all of them. A role that cannot view every self service button therefore cannot save an arrangement — the save is refused rather than writing a partial order. Reordering is a category-administrator job; see Roles and permissions.

Leaving the page with unsaved moves asks first, and offers to discard them or keep editing.

Changed elsewhere

If somebody else changed a category or a button between your opening the page and saving it, the save is refused and you are offered Reload. Reloading brings in the latest arrangement and discards your unsaved moves, so a concurrent change is never silently overwritten. A failed reload leaves your moves in place to try again.

Hidden and disabled​

Hidden and Disabled decide whether a button appears in the portal and whether it can be submitted. Each is a switch coupled to an expression, and the portal acts on the answer.

Authoring a rule​

The two halves are one control over one stored value:

  • Switch off stores false. The field is emptied and disabled — the switch is the decision, so a disabled field still showing text would claim an expression survives a save that writes false.
  • Switch on enables the field and requires it. Save stays disabled while a switch is on with nothing typed, and the field says "Enter an expression, or turn the switch off."

The expression is the same language properties use, written as a bare condition — [[MAINTENANCE_WINDOW]] == "true" — with no [[= ]] wrapper needed. A rule is capped at 1,000 characters.

On the fieldWhat it does
The property picker beside itInserts a property token. Scoped to global properties and the clock, which is all the server resolves a rule against — there is no job, schedule or agent in context, so a token from one of those scopes could only ever evaluate to an error.
TestRuns the rule as the portal will and reports the answer under the field — True, False, or the reason it could not be evaluated. Nothing is saved, and the result is retired as soon as you change the text it describes.

Testing a rule reads the tenant's global properties, so it needs view on properties as well as edit on service requests. The outcome is one bit, but a bit is enough to recover a property's value by repeated comparison, so reading the store is gated as its own permission here, exactly as it is everywhere else.

How a rule is evaluated​

WhenEvery time the portal loads the button list, and again when a request form opens.
Against whatThe tenant's global properties and the server clock, in UTC. Each rule is resolved strictly: there is no fallback in which a failed expression renders as its own text.
Per environmentOver the transformed configuration, so a transformation rule that overrides hideRule or disableRule for one environment takes effect there.
The literalstrue, false, empty and unset are answered directly, with no property lookup — so a button that was never given a rule costs nothing to evaluate.
Encrypted properties are refusedA rule naming an encrypted property evaluates to an error rather than comparing against the decrypted value. A rule's author can read the outcome off the button they are editing, which would make the rule a one-bit oracle over every secret in the tenant.

Three outcomes, not two. A rule answers true, false, or error — a syntax problem, an unknown property name, a result that is neither True nor False, an encrypted property, or a lookup that failed. An error fails open: the button stays visible and stays submittable.

One kind of error fails closed instead

Rule evaluation is bounded, so one tenant's rule cannot spend the portal's time without limit. A rule that asks for more work than its budget allows — typically one reading a very large property, or building a very large string — is refused.

When that happens to a Disable rule, the submission is refused: the rule never said "enabled", so the request reports that its availability could not be checked. Every other error still fails open, as above. Keep a rule's work small — compare against short properties, and keep text operations off large values.

What the portal does with the answer​

OutcomeIn the portal
Hide rule trueThe button is dropped from the catalog. Its tags do not appear as filters and searching for it finds nothing. A deep link to its form lands on the same not-found state a deleted button would. When every deployed button is hidden, the catalog shows its ordinary empty state.
Disable rule trueThe card is shown but inert — no selection, no keyboard activation, greyed, with the tooltip "This button is currently disabled." If it is reached by a direct link, its request dialog opens read-only with an alert naming the button, and Submit is disabled.
Either rule in errorThe button stays usable, with a warning icon in the card header and a warning in the request dialog: "This button's visibility rule could not be evaluated. Contact your administrator."

Neither the rule text nor the evaluator's message ever reaches a portal user. The expression and the property names it reads are design information, and submitting a request needs no design permission — so the portal's copy is deliberately generic, and the message that names the expression is returned only to Test.

Both rules are checked again when the submission arrives

The request dialog re-reads the deployed list on every open, so the rule a portal user is held to is at most one open old, and Submit is held disabled while that read is in flight or has failed rather than acting on a stale answer. The rules are then evaluated again on the server when the submission arrives, so a button hidden or disabled since the dialog opened is refused and nothing is sent:

  • Hidden — the submission is refused as "This service request is not available in this environment", the same answer as for a button that is not deployed there.
  • Disabled — it is refused as "This service request is disabled and cannot be submitted right now".

What changed from the switches​

An earlier build reduced each rule to a plain on/off switch, because there was no way to evaluate an expression. Three things follow:

  • A stored expression opens as itself again. The warning that saving would flatten it is gone, along with the flattening. Restoring an older version of a button puts its expression back unchanged.
  • The literal true a switch wrote is not a special case — it is simply the expression that is always on, and it opens as a switch on with true in the field.
  • The configuration grid has no Hidden or Disabled column. Rule state is authored and tested in the button dialog and takes effect in the portal; the grid reports which environments a button is live in and nothing about its rules.

Input types​

Eight types are offered in the input editor:

TypeNotes
Text, Password, Number, Date, ChoiceThe ordinary form fields.
Text CollectionThe user builds a list of text entries, submitted as one delimited string.
Workflow Selection, Job SelectionA type-ahead picker over real workflows or jobs — see below.

Workflow Instance Selection and Job Instance Selection are not offered. Both remain valid in stored configuration, so a request that already uses one still loads and still saves; on the request form such an input renders as free text.

Each input can be required, have a default, and type-specific validation (min/max, length, pattern, date range). Choice options can be reordered in the builder so they appear in the order you want.

What a validation pattern may be​

A pattern you write on a Text or Text Collection input is applied in the browser of every person who opens the request. It is not handed to the browser's own regular-expression engine: it is compiled and matched by the platform, in time proportional to the value's length however the pattern is written. The practical effect is that a pattern can no longer hang a requester's form — but a few things are refused when you save:

RefusedWhy
A pattern longer than 200 charactersThat is the length the portal applies; a longer one was previously stored and then ignored
Backreferences (\1) and lookaround ((?=…), (?!…))Their meaning cannot be matched this way
The legacy escapes \8, \a, \c1Easy to misread, and they mean different things in different engines
A {n,m} count above 1000, or a pattern that compiles to more than 1000 statesThe size bound a counted repeat is held to
A default value longer than 5000 characters, or one that is not a single valueIt is checked against the pattern, and it feeds the event line

Everything whose meaning is plain set membership is supported: literals, escapes, character classes, ., ^, $, \b, \B, groups, alternation, and every quantifier. A pattern that is accepted means exactly what it would mean to the browser.

Two limits apply when the pattern is matched rather than saved: a value longer than 5000 characters does not match, and a match that would be unusually expensive is abandoned and the value refused. An ordinary pattern on an ordinary value is nowhere near either.

A stored pattern these rules refuse can no longer be saved

These rules are applied on save, to the whole request. A service request stored before them that uses a refused pattern will be refused the next time you save it, naming the input — and until then the portal stops applying that pattern rather than applying it unsafely. Replace the pattern with one the rules accept.

Placeholder and help text are no longer editable. The two fields have been removed from the input editor for every type. A value already stored is preserved on save and still renders on the request form — there is simply no longer a way to write a new one.

Choice​

A Choice input renders on the request form as a searchable list: the requester can type into the field to narrow a long set of options rather than scrolling the whole list. An optional Choice carries a clear control for emptying it once a value is picked; a required one does not, since it has to hold a value to submit. There is no longer a None entry inside the option list itself — an optional Choice is cleared with that control instead.

The field can show text it will not submit

Because the field is a real text box, typing into it does not by itself change the selection. If you have already picked an option and then type something that matches no option, the field keeps displaying what you typed while the request still submits the option you picked — including after you move to another field.

Type to narrow the list and then pick an option, so that what you see is what the request carries. If you want the input empty, use the clear control on an optional Choice rather than deleting the text.

Text Collection​

A Text Collection input lets the user build a list of text entries, shown as removable chips, and submits them as a single delimited string. The separator is configurable per input and defaults to a colon (:). It mirrors the legacy text-collection variable.

Each entry is validated on its own against the input's min/max length, pattern, and an optional set of invalid characters. An entry can't contain the delimiter, and you can optionally disallow duplicate entries.

Why the default is a colon, not a comma​

An event template separates its own fields with commas and has no escape character, so a comma-joined list is indistinguishable from several template fields. The request form therefore refuses any entry containing a comma unless the input's delimiter is itself a comma. The input editor shows the delimiter as editable text seeded with the default, so the effective value is visible rather than implied.

A comma is still a legal choice, for one case: an input that fills the last field of its event, which rejoins the comma-separated tail. The editor warns when the delimiter is a comma, and refuses to save a delimiter that contains a comma without being exactly a comma — that value can never be submitted with more than one entry.

Fields that need a specific delimiter​

A few event fields carry several values inside one template field and are split back apart on a character the event contract fixes:

FieldSeparator it needs
tags ($JOB:TAGADD / TAGDEL, $JOBMASTER:TAGADD / TAGDEL),
dates ($CALENDAR:ADD / DEL);
properties ($JOB:ADD / ADDHLD, $SCHEDULE:BUILD / BUILDHLD);

A list input feeding one of these must use that character. If it doesn't, the submission is refused with a message naming the character the field needs — because the mismatch is otherwise accepted downstream as a single fused value and nothing reports it. The colon default therefore governs single-valued fields, which is where a wrong separator was actually being noticed.

Pick a delimiter your values never contain

The delimiter is applied when the stored value is split back into entries, so a value that already contains it breaks apart. A default of 08:30 under a \d{2}:\d{2} pattern arrives as 08 and 30 and is refused — and re-entering 08:30 is refused too, because an entry can't contain the delimiter. Times, Windows paths and host:port values all collide with the colon; choose something else for those.

The same applies to a list stored under the old comma default: it arrives as one entry and is refused. A requester fixes it by removing the entry and re-entering the values, which rejoin on the colon. A stored default value does not self-heal that way — re-entering doesn't write it back, so every requester meets the same refusal until the stored default is rewritten through the API.

Workflow Selection and Job Selection​

Both types put a type-ahead picker on the request form in place of the text box they used to fall back to. The requester types to narrow the list, and the value submitted is the name — which is what an event template expects.

TypeWhat the requester picksConfigured with
Workflow SelectionAny workflow they are allowed to readNothing extra
Job SelectionA job from one workflow, de-duplicated and sorted by nameThe workflow, chosen by the author in the input editor

Job Selection needs a workflow. The input editor requires one before it will save the input. The API does not, because the type shipped before the setting existed: rejecting a stored input that lacks one would have frozen its whole button, so those load and save as before and render as free text on the form.

When a picker falls back to free text​

Both pickers read workflows from the design side, which is a separate permission from using the portal — so a requester can legitimately be allowed to submit the request and not allowed to read the list behind one of its fields. A picker with no options can never satisfy a required input, which would leave Submit permanently unavailable and the whole button unusable. So when the list cannot be produced and the requester cannot do anything about it, the input falls back to the free-text box the type used before it had a picker:

SituationResult
The requester may not read workflowsFree text
The workflow the author chose has been deletedFree text
Job Selection with no workflow configured, or a workflow with no jobsFree text
A temporary failure — a server error, a dropped connectionThe picker stays, with an explanation; retrying can still succeed

A fallback caused by the list itself being unreachable says so on the field, so the change is not silent.

Date​

A Date input can be bounded by a fixed minimum and maximum date, or by today:

  • Minimum is today and Maximum is today are check boxes under the matching date field. Each one disables and clears the fixed date beside it, so a bound is either a fixed date or today, not both.
  • "Today" is evaluated when the requester's entry is validated, at local midnight — so a request that may not be back-dated stays correct every day without being edited.

A crossed pair of fixed dates is refused by the input editor, which names the problem on the field: a minimum after its maximum leaves no answerable day, and a required input in that state makes the whole button unsubmittable. The API still accepts one, because a crossed pair is ordinary stored data from before the check existed — refusing it there would freeze every button holding one, and would make such a version impossible to Copy or Restore, neither of which goes through the input editor.

Text formatting (Text and Password)​

Text and Password inputs can reshape the submitted value at submit time, matching the legacy text variable:

  • Strip characters — remove specified characters from the value before it's submitted.
  • Padding — pad the value to a fixed length with a chosen character, on the left or the right. Padding is all-or-nothing: direction, character, and length are set together. The length is capped at 5000, which is also the longest an event line can be — a larger value is refused when you save, and a request already storing one is refused at submit rather than having the padding allocated.

Events and variable substitution​

Each event has a type, structured parameters, and an order. A parameter can include placeholders that are replaced when the request is submitted — either with the requester's form values or with facts about the requester themselves.

The events run in the order you arranged them​

A request's events are submitted sequentially, in order — one finishes before the next starts. Arrange them so that anything an event depends on has already happened.

That is what makes a chain safe to author:

$PROPERTY:SET,RUN_REGION,${Region}
$JOB:ADD,[[$DATE]],DAILY,EXTRACT,RUN_REGION=[[OI.RUN_REGION]]

Earlier builds sent the events as a batch that ran several at once, so the $JOB:ADD above could be carried out before the $PROPERTY:SET it depends on and add the job with the previous value. Ordering is now the contract.

One event failing does not stop the others. The remaining events still run, and the result names which ones failed. That is deliberate and matches Classic — but it means a chain's later events may run after an earlier one failed, so do not rely on a failure part-way through stopping the rest.

A request that is authorized against a property an earlier event writes is checked against every value that property might hold — including the value it had before the request started, since a write can fail and the request carries on. A write whose value cannot be worked out in advance refuses any later event that reads that property, rather than letting it through unchecked.

What a requester needs permission for​

The events are checked as the requester, not as the Builder who saved the button. A requester needs:

PermissionWhere it must applyWithout it
self-service-portal.viewAnywhereThe Self Service page does not open.
self-service-portal.executeThe button's workspace, in this environmentThe submission is refused as "This service request is not available in this environment".
The permission each event type requires — $JOB:ADD needs workflow-instances.edit, for exampleThe workspace of the object the event names, in this environment, once the form values are filled inThe submission is refused with permission.denied.
properties.viewEach property the events name in a [[…]] token, in that property's workspaceThe submission is refused with permission.denied.

One refused event refuses the whole submission, and nothing is sent. The portal shows Request Failed with the text permission.denied and does not say which permission is missing, so a requester who sees it needs an administrator to compare their roles with the button's events.

The page lists every button deployed to the environment, including ones whose workspace the requester cannot submit in; such a button opens normally and is refused on submit.

What the requester sees when it does not simply succeed​

OutcomeWhat the portal shows
Every event acceptedSuccess
Some events failedThe failures by name, and that the other events ran — so submitting again would run those a second time. No retry is offered.
No answer came back in timeRequest Outcome Unknown, and a prompt to check the event log before submitting again. Some events may already have run. No retry is offered.

The last two deliberately do not invite a retry. An earlier build said Please try again on a partial failure, which is the one thing a requester should not do: the events that worked would run twice.

A submission the platform could not even start — because there was not enough time left to get an answer — is reported as such, with nothing sent, so it is safe to submit again.

A submission is bounded in size, independently of what was stored​

Whatever the stored request says, the submit path refuses a submission that would build something too large, before it builds it:

BoundWhat is refused
16,384 characters per submitted valueA single value longer than an event line can carry
16,384 characters per built event lineA value that would push the line past the limit as it is assembled, including the template's own tail
100 events per submissionA request that would submit more

These are checked independently of the stored configuration, so a request saved before the save-time caps cannot get a large value or an over-long line through by having been stored earlier.

Input variables​

Write an input placeholder as ${Name}. The name is any text that does not contain a brace, so spaces, dots, slashes and punctuation are all fine:

${Start or Stop}
${Resource Group Name}
${TargetPath}

Writing one is what creates the input: the configuration dialog detects every ${…} across your events and adds a matching input definition — type Text, required — for any it does not already have. The reverse is also true: an input no event references is removed. A placeholder is matched to an input by its id first and then by its name, ignoring case.

${input.Name} is a legacy spelling that names the same input as ${Name}. Nothing produces it any more, but it is still resolved so that configurations written before it was retired keep working.

Earlier builds deleted an imported button's inputs

A name with a space in it — ${Start or Stop}, as a Classic button would have written it — was not detected as a placeholder. Because an input no event references is removed, simply opening such a button in the configuration dialog silently deleted all of its inputs. Any name is now detected, so opening a button removes nothing. A button whose inputs went missing needs them re-added once; it will not happen again.

System variables​

Four placeholders are filled in from the user who submits the request, not from the form. The event form lists them as chips beside your own input variables.

PlaceholderResolves to
${SM.USER.EMAIL}The requester's email address.
${SM.USER.NAME}The requester's display name.
${SM.USER.LOGIN}The requester's email address. Sign-in here is by email and there is no separate login name, so the two are the same value.
${SM.USER.COMMENTS}The empty string. Nothing on a platform user holds the free-text notes this named in Classic.

Any name beginning SM. is treated as a system variable, never as an input — so no input is auto-created for one, and an input you happen to name SM.Something can never be reached from a template. A name under that prefix which is not one of the four above is refused at submit, with a message listing the four. Classic substituted an empty string for an unknown one silently; naming a job or setting a property with nothing is the failure this refuses.

${SM.USER.COMMENTS} resolving to nothing is a value, not a failure — it substitutes as empty. The other three are refused if the requester's record holds nothing for them.

When a placeholder cannot be resolved​

Every placeholder must resolve, or the submission is refused — it is never replaced with blank and never sent as literal text. A $PROPERTY:SET event that shipped the characters ${TargetPath} as the property's value would be worse than an error.

The submission is also refused when:

SituationWhy
A placeholder names no input on this requestSubmitting would send the placeholder text as the value.
A required input was left empty
A resolved value contains a commaAn event template separates its fields with commas and cannot escape one, so a comma would shift every later field. This applies to a system variable too: a display name like Dimick, Ryan is refused.
A Password input is referenced from anything but a property event$PROPERTY:ADD and $PROPERTY:SET have their stored payload redacted; every other event type keeps its template as submitted, which would hold the secret in clear text.
A Text Collection value's delimiter would not survive the target field's own separatorSee Fields that need a specific delimiter.
A resolved value reads an encrypted property, or still contains a [[ or {{ after resolvingA requester's input must not be a route to a secret, and a token that survives resolution here would be expanded later under the platform's own trust rather than the requester's.
The built event line carries more [[…]] / {{…}} tokens than the template wroteSee A token the author did not write.
A suffixed date token such as [[$DATE_EU]] lands in a field read as a dateThose fields render in the built-in format, so a suffixed name has no format to use. See Date and time tokens.

A token the author did not write​

A requester's input is substituted into the template, and a value can assemble a token the author never wrote — by supplying the [ that completes an opener, or by two adjacent placeholders each contributing half of one. Text formatting on the input can do it too: Strip Characters turning [ [OI.RATE]] into [[OI.RATE]], or left-padding a value with [.

Each built line's token openers are therefore counted against what its own template wrote. A line with more is refused. Nobody authored that token, so nothing has decided it may be read — and the author's own tokens are unaffected, including a template that deliberately builds one around an input, as [[OI.${Region}]] does.

Property tokens are a separate mechanism​

${…} is the portal's own substitution and it happens at submit, from the form. An event parameter can also carry a [[…]] property token, and that is resolved later — by the platform, when the event is carried out. The two do not compete: use ${…} for what the requester types and [[…]] for what the tenant already knows.

$JOB:ADD,[[$DATE]],DAILY,${Job Name}

Earlier builds carried a service request's [[…]] tokens through as literal text, so the line above was refused for an invalid date. Both now resolve.

The rules for the [[…]] half are the platform's, not the portal's, and they are strict: a token that does not resolve fails that event rather than leaving the text in place, and only global properties and the clock are in scope — a submitted event has no job for a JI, SI or MI token to read. See An event raised from outside a job.

Password inputs and encrypted properties are different things

A Password input is the requester's secret, handled by the redaction rules above. An encrypted property is the tenant's, and a [[…]] token naming one may appear only as the value of $PROPERTY:SET / $PROPERTY:ADD, written as a single bare reference, into a target that is itself encrypted. Anywhere else the event is refused.

Editing an event imported from Classic​

A button brought over from Classic stores its event as a type plus a raw template, because Classic had no structured form. Opening it in Edit Event now fills the form by decoding that template, where earlier builds showed every field blank under a correct Generated Template — and the first edit then regenerated the template from those blanks.

Two limits are worth knowing:

  • The template is only decoded when the type it declares is the event's own type and one the form knows. Otherwise the form is left empty rather than filled from the wrong definition.
  • A value past the last field the form defines cannot be shown, and is dropped when you next save. That was already true before the form could be filled at all, so nothing is lost that was not lost before.

Deployments​

Like workflows, a service request is deployed to an environment with a version strategy:

FieldNotes
versionStrategyLATEST or PINNED.
pinnedVersionUsed when PINNED.
effectiveDate / expirationDateOptional active window.
isActiveWhether the deployment is active.

Transformations​

A transformation rule overrides a value in the request for a specific environment or deployment — e.g. swap a dev value for a production value so the same request behaves correctly in each environment. Rules are applied when the portal serves the request. (The builder UI currently exposes the replace transform; other transform types exist at the API level.)

Rules on a service-request deployment are listed, added, edited, and removed in the deployment dialog, the same way a workflow deployment's rules are. Earlier builds couldn't load them: opening a service-request deployment reported "Failed to load deployment rules." and adding one failed.

Rules are edited in place, in rows, and saved with the deployment. Adding a rule adds a row to the deployment dialog rather than opening a second dialog on top of it — earlier builds did open one, and it left the page unresponsive, so Add, Edit and Delete Rule could not be completed at all. Nothing is written until you save the deployment, and the save applies your additions, edits and deletions together.

Each row asks for:

FieldRequiredNotes
NameYesUnique within your tenant.
Target pathYesThe value to override, as a JSONPath — it must begin with $ or ..
Replacement valueYesWhat to put there.
DescriptionNo

A row that is missing any of the required fields, or whose target path isn't shaped like a path, blocks Save for the whole deployment until you fix or remove it.

One transform type doesn't apply here. RENAME_KEY is refused on a service-request deployment, because a request's configuration has no job structure for a key rename to act on. A rule belongs to one deployment, so a rule can't be reached or edited through a different deployment's dialog.

note

A deployment that has been deleted reports that specifically rather than as a generic not-found — so a dialog that can't load its rules tells you whether the deployment is gone or the identifier is simply wrong.

Good to know
  • Workflow Selection and Job Selection offer a real picker; Workflow Instance and Job Instance selection are not offered and render as text fields. A picker also falls back to a text field when the requester cannot read the list behind it — see When a picker falls back to free text.
  • Hidden and Disabled are acted on by the portal and checked again when a submission arrives: a hidden button is not in the catalog and a disabled one cannot be submitted. A rule that cannot be evaluated fails open — see Hidden and disabled.
  • A request not appearing in an environment usually means it isn't deployed there (or the deployment is pinned/expired/inactive) — check the deployment, like with workflows.
  • Encrypted/secret handling: sensitive values should come from connections/properties, not from a plain text input.

Related topics