Developer Docs - Mobile Docs - Endpoint Responses
Your endpoint's job is to return a XAML fragment. It can also send response headers to tell the app to do something other than a plain swap.
The response contract
Never return a XAML fragment with an error status code. Non-2xx bodies are never parsed. If you want to render an error as UI, return 200 with the error markup as your fragment, or use HX-Retarget to aim it at an error slot.
Response headers
All of them are set the same way, with the existing httpresponse Lava command, and a template can send more than one. No server changes are needed.
{% httpresponse header:'HX-Reswap' value:'outer' %}
{% httpresponse header:'X-Helix-Command' value:'ShowToast' %}
They are read in the order listed above, which matters because the first two short-circuit everything after them: if you send HX-Redirect, your body is never swapped and your X-Helix-Command never runs. Both are also read before the status code, so a redirect or a refresh is honored even on a non-2xx response, and the error notification you might have expected never appears.
HX-Redirect
Replaces the current page with another one. The value is a page Guid, optionally carrying a query string and an anchor.
{% httpresponse header:'HX-Redirect' value:'0d1a1e37-e5f1-4a0f-9d0a-0d0e1a9d3b21' %}
{% comment %} Page parameters, and an anchor to scroll to on arrival. {% endcomment %}
{% assign target = '0d1a1e37-e5f1-4a0f-9d0a-0d0e1a9d3b21?GroupId=' | Append:groupIdKey %}
{% httpresponse header:'HX-Redirect' value:'{{ target }}#roster' %}
HX-Refresh
Reloads the current page, so every block on it re-renders.
{% httpresponse header:'HX-Refresh' value:'true' %}
HX-Retarget
Aims this one response somewhere other than where the request said. The id resolves the same way Hx.Target does, and an id that does not resolve is an error.
The common use is the one the Note above describes: keep the 200, but send failure markup to an error slot instead of into the target the request originally named.
{% if isEmailTaken %}
{% comment %} Land in the form's error slot rather than replacing the field. {% endcomment %}
{% httpresponse header:'HX-Retarget' value:'formErrors' %}
{% else %}
{% endif %}
A retargeted response always lands in the page, even when the request declared Hx.Target="coversheet". That is how you let a cover sheet action write back into the page-side flow instead of opening another sheet.
HX-Reswap
Overrides the strategy. Reach for it when the response is a different shape than the request expected, most often an empty state coming back to a target that was set up to append.
{% if rows == empty %}
{% comment %} Nothing to append, so replace the list with an empty state instead. {% endcomment %}
{% httpresponse header:'HX-Reswap' value:'outer' %}
{% else %}
{% for row in rows %}
{% endfor %}
{% endif %}
It accepts both vocabularies, so a shared endpoint can emit one value that works for the browser and the app:
{% comment %} Understood by both clients, so no ClientType branch is needed. {% endcomment %}
{% httpresponse header:'HX-Reswap' value:'outerHTML' %}
The strategy you name still has to suit the target. HX-Reswap overrides your Hx.Swap, it does not exempt you from the target type rules in Requests and Targeting, and an unknown strategy is an error.
HX-Reswap goes through the same parser Hx.Swap does, so it can carry the animation modifiers too. That lets an endpoint pick the motion to match the content it is returning:
{% comment %} An empty state replaces the list, and should fade rather than slide. {% endcomment %}
{% httpresponse header:'HX-Reswap' value:'outer animate:fade' %}
Because the header replaces the whole declaration, any modifiers the element declared are replaced along with the strategy. Repeat the ones you still want.
X-Helix-Command
The mobile-only extension to the header channel. It runs one of the app's named client commands, the same way a Callback's command response does.
{% comment %} An object parameter, sent as JSON. {% endcomment %}
{% httpresponse header:'X-Helix-Command' value:'ShowToast' %}
{% httpresponse header:'X-Helix-Command-Parameter' value:'{"Message":"Saved."}' %}
{% comment %} No parameter needed. Swap in the saved state, then close the page behind you. {% endcomment %}
{% httpresponse header:'X-Helix-Command' value:'PopPage' %}
Unsupported headers
HX-Location, HX-Push-Url, HX-Replace-Url, and HX-Trigger do nothing. The app has no URL bar and no history stack, and client-side event triggering is not implemented.
Redirect and refresh from inside a cover sheet
HX-Redirect and HX-Refresh act on the presenting page, and they do not dismiss the sheet. Refreshing the presenting page is the supported way for a sheet to update it, since a sheet cannot target ids on the page. See Cover Sheets.
Caching and rate limiting
The app does not cache Helix responses. Every request goes to the server, and response cache headers are ignored. Your endpoint's cache settings still apply to web clients.
The per-endpoint rate limit fields in the endpoint editor are not currently enforced on the execute route, so do not rely on them to protect an expensive endpoint. If the app does receive a 429, it shows it as an error and never retries automatically.