Code mode primitives
Both namespaces expose the same five primitives. wifi operates on the
SmartZone WSG API, switches on SwitchM; nothing else differs between them.
| Primitive | Purpose | Network call |
|---|---|---|
list_tags | Tags with operation counts | No |
search_endpoints | Keyword search over the index | No |
list_endpoints_by_tag | Every endpoint under a tag | No |
get_endpoint_details | Full schema for one endpoint | First call per surface, per isolate |
call | Execute an authenticated request | Yes |
The first three read the index bundled into the Worker, so they are effectively
free. get_endpoint_details loads the full spec from object storage the first
time it is used for a surface in a given isolate. Only call reaches your
controller.
list_tags
Section titled “list_tags”Takes no arguments. This is the starting point for discovery.
const { tags } = await switches.list_tags();| Returns | Type |
|---|---|
tags | Array of { name, description?, operationCount } |
Returns every tag on the surface — 119 on wifi, 42 on switches.
description is absent on every tag for the same reason the specs carry no
operation descriptions.
There is no tag-group level above tags. An earlier list_tag_groups primitive,
and a group argument on list_tags, were removed because the SmartZone specs
define no tag groups, so both could only return an empty list.
search_endpoints
Section titled “search_endpoints”const { results, count } = await wifi.search_endpoints({ query: 'wlan profile' });| Argument | Type | Default | Notes |
|---|---|---|---|
query | string | — | Required. Minimum 2 characters |
tag | string | — | Restrict to one tag, exact match |
method | enum | — | GET, POST, PUT, PATCH, DELETE |
limit | number | 20 | Accepted range 1–50 |
| Returns | Type |
|---|---|
results | Array of index entries, ranked best first |
count | Total matches before the limit was applied |
Query text is lower-cased and split on whitespace; each token is matched as a
substring. Scoring adds +2 for a hit in operationId and +1 each for the search
blob, a tag name and the path.
Because count is the pre-limit total, a count far above results.length
means narrowing the query or adding a tag will serve you better than raising
limit.
list_endpoints_by_tag
Section titled “list_endpoints_by_tag”const { results, count } = await switches.list_endpoints_by_tag({ tag: 'Switch Health' });| Argument | Type | Default | Notes |
|---|---|---|---|
tag | string | — | Required. Exact name from list_tags |
method | enum | — | Filter by HTTP method |
limit | number | 50 | Accepted range 1–200 |
offset | number | 0 | For paging through a large tag |
| Returns | Type |
|---|---|
results | Index entries for this page |
count | Total under the tag, ignoring limit and offset |
Tag matching is exact and case-sensitive — pass the name verbatim as
list_tags returned it.
Index entry fields
Section titled “Index entry fields”Both search and browse return entries of this shape:
| Field | Notes |
|---|---|
method | Upper-case HTTP method |
path | Spec path, with {placeholder} segments |
operationId | Present on all 1,354 operations |
tags | Tag names this operation belongs to |
summary | One line. Present on all but two WSG operations |
description | Always absent — the specs populate none |
paramsSummary | Parameter names grouped by location, e.g. path: id; query: listSize,index |
hasBody | Always false — see the caution under get_endpoint_details |
deprecated | Present only when true. No operation in either spec is marked deprecated |
get_endpoint_details
Section titled “get_endpoint_details”const details = await wifi.get_endpoint_details({ method: 'POST', path: '/rkszones' });| Argument | Type | Notes |
|---|---|---|
method | enum | Required |
path | string | Required. Must start with / and match the spec path exactly |
| Returns | Field |
|---|---|
surface, method, path | Echoed back |
operationId, summary, description, deprecated | From the spec |
parameters | Array — this is where the request body lives |
requestBody | Always null |
responses | Response definitions by status code |
security, tags | From the spec |
$ref pointers are inlined up to three levels deep. Beyond that, or on a
cycle, the { $ref: "…" } object is left in place rather than expanded.
You will also see serviceTicket as a required query parameter on nearly every
operation. Do not pass it — SZ-MCP attaches it server-side.
Error returns
Section titled “Error returns”Unlike call, this primitive returns a plain object on failure:
| Return | Meaning |
|---|---|
{ error: 'not_found', method, path } | No such operation in the bundled index |
{ error: 'details_unavailable', method, path } | In the index, but absent from the stored full spec |
The only primitive that reaches your controller.
const r = await wifi.call({ method: 'GET', path: '/rkszones/{zoneId}/wlans', pathParams: { zoneId: 'abc-123' }, query: { listSize: 100, index: 0 },});if (!r.ok) return { failed: r.status, body: r.body };| Argument | Type | Notes |
|---|---|---|
method | enum | Required. GET, POST, PUT, PATCH, DELETE |
path | string | Required. Spec path, starting /, no base prefix |
pathParams | object | Values substituted into {placeholder} segments, URL-encoded |
query | object | Query parameters. Arrays append the key once per value |
body | any | JSON-serialised unless already a string. Ignored on GET and DELETE |
headers | object | Extra request headers |
Accept: application/json is sent always; Content-Type: application/json is
added for requests that carry a body.
Return shape
Section titled “Return shape”| Field | Notes |
|---|---|
ok | true for 2xx |
status | HTTP status code |
statusText | HTTP status text |
headers | Response headers as an object |
body | Parsed JSON when the response is JSON; raw text otherwise; null when empty |
durationMs | Time for the request, including any 401 retry |
url | The upstream URL with serviceTicket=<redacted> |
Automatic retry
Section titled “Automatic retry”A 401 discards the cached service ticket, mints a fresh one and retries
exactly once. A second 401 is returned to you. No other status is retried.
Error envelopes
Section titled “Error envelopes”When the failure happens before the request reaches SmartZone, call still
returns rather than throwing — with status: 0:
statusText | body.error | Meaning |
|---|---|---|
sz_auth_error | no_credentials | Nothing saved for this account. body.message says to save credentials on the dashboard |
sz_auth_error | login_failed | The controller rejected the login, e.g. http_401 |
sz_auth_error | forbidden_host | The saved host is not publicly routable |
sz_auth_error | invalid_host | Controller unreachable — DNS, timeout, refused connection, or TLS validation failure |
sz_auth_error | decryption_failed | Stored password could not be decrypted |
network_error | network | Unexpected failure; body.message carries the detail |
url is an empty string on all of these, since no request was made.