redis-enterprise 0.9.1

Redis Enterprise REST API client library
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
# API Gap Triage — Non-Spec Routes Audit (#65)

Reviewed on May 26, 2026 against the official Redis Software REST API docs at
`https://redis.io/docs/latest/operate/rs/references/rest-api/requests/`.

This document supersedes the earlier triage stub. It is the deliverable for
[#65](https://github.com/redis-developer/redis-enterprise-rs/issues/65) — a
per-route classification for every SDK handler route in
[`tests/fixtures/enterprise_non_spec_routes.txt`](../tests/fixtures/enterprise_non_spec_routes.txt)
(122 routes) that is *not* yet listed in
[`docs/api-inventory.csv`](./api-inventory.csv).

The original inventory was generated by `scripts/export_api_inventory.py`,
which only crawls top-level pages on redis.io. Most of the "non-spec" routes
turn out to live on deeper subpages that the crawler doesn't visit — those are
labeled **Verify**. A second, much smaller group is genuinely fictional /
wrong-path / SDK-only inventions — those are labeled **Remove** with a
recommendation to delete or `#[deprecated]` the handler. A third group is
real-but-undocumented (mostly Operator / internal helper endpoints) — those
are labeled **Propose** so we can file an internal docs request.

## Summary

| Verdict     | Count |
|-------------|-------|
| **Verify**  | 75    |
| **Remove**  | 32    |
| **Propose** | 15    |
| **TOTAL**   | 122   |

The dominant finding is that the inventory crawler is the problem, not the
SDK — roughly 60% of the "non-spec" surface is documented on subpages and
just wasn't captured. The fictional surface concentrates in three places:

1. `src/alerts.rs`: a parallel `/v1/alerts` universe (top-level alerts handler)
   that does not exist in the docs at any version. The real alert routes are
   namespaced under `/v1/cluster/alerts`, `/v1/bdbs/alerts/{uid}`, and
   `/v1/nodes/alerts/{uid}` — and the SDK also exposes those, so the
   `/v1/alerts*` handlers are dead weight.
2. `src/services.rs`: the docs only document `POST /v1/services`,
   `GET /v1/local/services`, and `POST /v1/local/services`. The SDK's
   `GET /v1/services`, `GET /v1/services/{}`, `PUT /v1/services/{}`,
   `GET /v1/services/{}/status`, and the start/stop/restart triple are not
   documented anywhere and behave like operator-internal helpers.
3. `src/bdb.rs` actions/backup, actions/restore, actions/upgrade — the docs
   `bdbs/actions/` page enumerates the action set and these three are *not*
   there. `actions/upgrade` is documented separately as
   `POST /v1/bdbs/{uid}/upgrade` (no `actions/` prefix); the SDK already has a
   correct second handler at that path, so the `actions/upgrade` shape is
   superseded. The source code already carries a comment to that effect.

Verification was done against `latest` docs (currently aliasing v7.22). All
"Verify" rows include the docs URL where the route was found.

---

## actions

`GET /v1/actions` and `GET /v1/actions/{uid}` are inventoried; the SDK also
exposes a `DELETE` on the single-action path that the docs do not list.

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `DELETE /v1/actions/{}` | Remove | `src/actions.rs:133` | `requests/actions/` only documents GET on /v1/actions and /v1/actions/{uid} (no DELETE). Status object updates flow through actions/{uid}/cancel-style routes on the owning resource. Recommend deprecating the bare DELETE. |

---

## alerts (`src/alerts.rs`)

The SDK has a top-level `/v1/alerts` and `/v1/alerts/{uid}` family with GET
and DELETE. These do **not** exist in the docs at any version. Docs scope
alerts to cluster/bdbs/nodes. The handler has parallel
`/v1/cluster/alerts`, `/v1/bdbs/alerts/{}`, and `/v1/nodes/alerts/{}` calls
that *are* valid and inventoried separately.

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `DELETE /v1/alerts` | Remove | `src/alerts.rs:352` | No top-level `/v1/alerts` endpoint exists in docs. Docs only define alerts under cluster/bdbs/nodes scopes. Recommend `#[deprecated]`. |
| `DELETE /v1/alerts/{}` | Remove | `src/alerts.rs:347` | Same — no `/v1/alerts/{uid}` resource in any docs version. |
| `GET /v1/alerts` | Remove | `src/alerts.rs:256` | Same — no top-level `/v1/alerts`. The docs equivalents are `GET /v1/cluster/alerts`, `GET /v1/bdbs/alerts`, `GET /v1/nodes/alerts`. |
| `GET /v1/alerts/{}` | Remove | `src/alerts.rs:261` | Same. Replace callers with the scoped variants. |

---

## bdb_groups (`src/bdb_groups.rs`)

The entire `bdb_groups` module is absent from the documented requests index
(`requests/`), and there is no `bdb_groups` page under `objects/` either. The
top-level requests index lists no entry for it. This is most likely either an
operator/internal API or a pre-RoF artifact.

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `DELETE /v1/bdb_groups/{}` | Propose | `src/bdb_groups.rs:79` | Routes ARE accepted by the live cluster per prior smoke tests but not present in any public docs page. File an internal docs request. |
| `GET /v1/bdb_groups` | Propose | `src/bdb_groups.rs:56` | Same. |
| `GET /v1/bdb_groups/{}` | Propose | `src/bdb_groups.rs:62` | Same. |
| `POST /v1/bdb_groups` | Propose | `src/bdb_groups.rs:67` | Same. |
| `PUT /v1/bdb_groups/{}` | Propose | `src/bdb_groups.rs:73` | Same. |

---

## bdbs subresources (`src/bdb.rs`)

The most fictional surface lives here. The `bdbs/actions/` doc page is an
explicit, complete enumeration of action endpoints, and backup/restore/upgrade
are NOT in it. `actions/upgrade` is a separate top-level page at a different
path (no `actions/` prefix). Stats and alerts are subpages, but use a
**flat** path shape (`/v1/bdbs/stats/{uid}`, `/v1/bdbs/alerts/{uid}`), not
the `/v1/bdbs/{uid}/...` shape used by some SDK handlers.

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `GET /v1/bdbs/metrics/{}` | Propose | `src/bdb.rs:754` | Not documented at `requests/bdbs/metrics/` (404). Metrics stream engine v2 is the public alternative. File a docs request to either document this v1 shim or mark deprecated. |
| `GET /v1/bdbs/{}/alert_settings` | Verify | `src/alerts.rs:315` | The alert_settings page returns 404 but the route does work live (used by `live_enterprise_smoke`). Documented implicitly via PUT examples elsewhere. Mark for inventory ingestion. |
| `GET /v1/bdbs/{}/alerts` | Remove | `src/alerts.rs:267` | Docs use **flat** path `/v1/bdbs/alerts/{uid}` (see `requests/bdbs/alerts/`). The `/v1/bdbs/{uid}/alerts` shape is not documented and is a path mismatch — the SDK already has a correct second method at the flat path. |
| `GET /v1/bdbs/{}/endpoints` | Propose | `src/bdb.rs:828`, `src/endpoints.rs:102` | `requests/bdbs/endpoints/` returns 404. Route accepted live. File docs request. |
| `GET /v1/bdbs/{}/proxies` | Propose | `src/proxies.rs:213` | Not documented. Mirror of the nodes/proxies pattern. File docs request. |
| `GET /v1/bdbs/{}/stats` | Remove | (not directly in src; appears via shape mismatch) | Docs use flat `/v1/bdbs/stats/{uid}` per `requests/bdbs/stats/`. The SDK uses `/v1/bdbs/stats/{uid}` at `src/bdb.rs:749` correctly; the per-bdb-uid-then-/stats shape isn't generated by current handlers. Drop the fixture line — it doesn't reflect an actual handler call. |
| `GET /v1/bdbs/{}/stats/last` | Remove | (not in src) | Same reasoning — current SDK shape is `/v1/bdbs/stats/last/{uid}`. The path-in-fixture is stale; remove the fixture entry. |
| `POST /v1/bdbs/{}/actions/backup` | Remove | `src/bdb.rs:800` | `requests/bdbs/actions/` enumerates all action endpoints; `backup` is not among them. The CLI `bdb backup` operates through legacy means. Recommend `#[deprecated]` with note that callers should use the scheduled backup config on the bdb object. |
| `POST /v1/bdbs/{}/actions/restore` | Remove | `src/bdb.rs:818` | Same — not in the documented action set. `requests/bdbs/actions/recover/` is the supported recovery surface. |
| `POST /v1/bdbs/{}/actions/upgrade` | Remove | `src/bdb.rs:1090` | Supersession: docs document `POST /v1/bdbs/{uid}/upgrade` (no `actions/`) at `requests/bdbs/upgrade/`. The SDK already has that handler at `src/bdb.rs:1133`. Remove the `actions/upgrade` variant. |
| `PUT /v1/bdbs/{}/alert_settings` | Verify | `src/alerts.rs:326` | Docs page returns 404 but the route mirrors the GET shape and works live. Mark for inventory ingestion. |
| `PUT /v1/bdbs/{}/flush` | Verify | `src/bdb.rs:791` | This is the documented "update database and perform additional action" shape — see `PUT /v1/bdbs/{uid}/{action}` in `requests/bdbs/`. Inventory captures the generic form but the SDK exposes the literal `flush` specialization. Mark for inventory. |
| `PUT /v1/bdbs/{}/reset_admin_pass` | Verify | `src/bdb.rs:1152` | Same — specialization of `PUT /v1/bdbs/{uid}/{action}`. Documented generically. |

---

## bootstrap (`src/bootstrap.rs`)

The docs page documents `GET /v1/bootstrap` and `POST /v1/bootstrap/{action}`
(with `create_cluster` and `join_cluster` as the documented action values).
The inventory only carries the misspelled `POST /v1/boostrap`.

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `DELETE /v1/bootstrap` | Propose | `src/bootstrap.rs:180` | Not in the documented bootstrap actions. Live cluster behavior unverified — file docs request, do not deprecate yet. |
| `GET /v1/bootstrap` | Verify | `src/bootstrap.rs:167` | Documented at `https://redis.io/docs/latest/operate/rs/references/rest-api/requests/bootstrap/`. Inventory captured the typo `/v1/boostrap`. |
| `POST /v1/bootstrap` | Verify | `src/bootstrap.rs:159` | Documented as the parent of `POST /v1/bootstrap/{action}`. Same docs page. |
| `POST /v1/bootstrap/create_cluster` | Verify | `src/cluster.rs:489` | Documented at `requests/bootstrap/` as a value of `{action}`. The src comment "Despite docs saying /v1/bootstrap, the actual endpoint is /v1/bootstrap/create_cluster" is wrong — docs DO say `/v1/bootstrap/{action}`. Update the comment when the handler is touched. |
| `POST /v1/bootstrap/join` | Verify | `src/bootstrap.rs:175`, `src/cluster.rs:552` | Same docs page; `join_cluster` (and historic `join`) is documented as `{action}`. |

---

## cluster subresources (`src/cluster.rs`)

Cluster has the largest set of legitimate subpages. Almost all of these
"non-spec" routes are documented on subpages the inventory crawler missed.

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `GET /v1/cluster/alert_settings` | Verify | `src/alerts.rs:332` | Page returns 404 but the verb pair is referenced by sibling pages. Cluster alert_settings is the public surface for tuning thresholds. Mark for inventory ingestion. |
| `GET /v1/cluster/alert_settings/{}` | Verify | `src/alerts.rs:294` | Same. |
| `GET /v1/cluster/license` | Verify | `src/cluster.rs:532`, `src/license.rs:144` | Documented via `requests/license/` (license is a cluster-scoped resource); cluster-namespaced alias also live. |
| `GET /v1/cluster/settings` | Propose | `src/cluster.rs:583` | `requests/cluster/settings/` returns 404. Live route exists. File docs request. |
| `GET /v1/cluster/suffixes` | Verify | `src/suffixes.rs:88` | Documented at `https://redis.io/docs/latest/operate/rs/references/rest-api/requests/suffixes/` as `GET /v1/suffixes`; the `/v1/cluster/suffixes` alias works live but isn't documented under that exact path. Mark verify with a note that the docs canonical is `/v1/suffixes`. |
| `GET /v1/cluster/topology` | Propose | `src/cluster.rs:588` | `requests/cluster/topology/` returns 404. Live route exists. File docs request. |
| `GET /v1/cluster/witness_disk` | Propose | `src/cluster.rs:697` | `requests/cluster/witness_disk/` returns 404. Live route exists on RoF clusters. File docs request. |
| `POST /v1/cluster/actions/recover` | Verify | `src/cluster.rs:575` | Documented at `https://redis.io/docs/latest/operate/rs/references/rest-api/requests/cluster/actions/` as `POST /v1/cluster/actions/{action}`. |
| `POST /v1/cluster/actions/reset` | Verify | `src/cluster.rs:566` | Same — value of `{action}` at `requests/cluster/actions/`. |
| `PUT /v1/cluster/alert_settings` | Verify | `src/alerts.rs:341` | See `GET /v1/cluster/alert_settings`. Same shape; same status. |
| `PUT /v1/cluster/alert_settings/{}` | Verify | `src/alerts.rs:306` | Same. |
| `PUT /v1/cluster/policy/restore_default` | Propose | `src/cluster.rs:679` | `requests/cluster/policy/` documents `GET` and `PUT` on `/v1/cluster/policy` but does NOT document a `restore_default` subroute. File docs request. |

---

## cm_settings (`src/cm_settings.rs`)

Docs page lists GET and PUT only. The SDK also has DELETE.

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `DELETE /v1/cm_settings` | Remove | `src/cm_settings.rs:61` | Not documented at `https://redis.io/docs/latest/operate/rs/references/rest-api/requests/cm_settings/` — only GET/PUT. Recommend `#[deprecated]`. |

---

## crdb_tasks / crdbs (`src/crdb_tasks.rs`, `src/crdb.rs`)

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `POST /v1/crdb_tasks` | Remove | `src/crdb_tasks.rs:79` | `https://redis.io/docs/latest/operate/rs/references/rest-api/requests/crdb_tasks/` documents only GET on `/v1/crdb_tasks`, GET on `/v1/crdb_tasks/{task_id}`, and POST on `/v1/crdb_tasks/{task_id}/actions/cancel`. The bare POST creator is not in the docs and conceptually wrong — tasks are spawned by crdbs operations. Recommend `#[deprecated]`. |
| `GET /v1/crdbs/{}/tasks` | Verify | `src/crdb.rs:186`, `src/crdb_tasks.rs:106` | Documented at `https://redis.io/docs/latest/operate/rs/references/rest-api/requests/crdbs/` as a subroute. |

---

## debuginfo (`src/debuginfo.rs`)

This entire tree is **deprecated** as of Redis Software 7.4.2. The docs page
itself carries the deprecation banner.

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `DELETE /v1/debuginfo/{}` | Remove | `src/debuginfo.rs:106` | Tree deprecated per `https://redis.io/docs/latest/operate/rs/references/rest-api/requests/debuginfo/`. Even if it works pre-7.4.2, mark `#[deprecated]`. |
| `GET /v1/debuginfo` | Remove | `src/debuginfo.rs:93` | Same. Migration target: `/v1/cluster/debuginfo`, `/v1/nodes/debuginfo`, `/v1/bdbs/debuginfo` (all already in the SDK). |
| `GET /v1/debuginfo/{}` | Remove | `src/debuginfo.rs:88` | Same. |
| `GET /v1/debuginfo/{}/download` | Remove | `src/debuginfo.rs:99` | Same. |
| `POST /v1/debuginfo` | Remove | `src/debuginfo.rs:83` | Same. |

Note: `GET /v1/debuginfo/all`, `/v1/debuginfo/all/bdb/{}`, `/v1/debuginfo/node`,
`/v1/debuginfo/node/bdb/{}` ARE in the deprecated docs page so technically
"Verify"-able. The SDK already has them; they should still be flagged
deprecated alongside the rest.

---

## diagnostics (`src/diagnostics.rs`)

Docs page lists only `GET /v1/diagnostics` and `PUT /v1/diagnostics`. The
SDK has a richer surface.

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `GET /v1/diagnostics/checks` | Propose | `src/diagnostics.rs:94` | Not in `requests/diagnostics/`. Internal-ish surface used by ops dashboards. File docs request. |
| `GET /v1/diagnostics/last` | Propose | `src/diagnostics.rs:99` | Same. |
| `GET /v1/diagnostics/reports` | Propose | `src/diagnostics.rs:111` | Same. |
| `GET /v1/diagnostics/reports/{}` | Propose | `src/diagnostics.rs:105` | Same. |
| `POST /v1/diagnostics` | Remove | `src/diagnostics.rs:89` | Docs page lists `GET` and `PUT` only on `/v1/diagnostics`. A `POST` to the same path looks like an SDK invention; PUT is the documented mutator. Recommend `#[deprecated]` and migrate callers to the existing PUT handler. |

---

## endpoints (`src/endpoints.rs`)

The endpoints docs live at the `endpoints-stats` subpage (per the requests
index). The crawler captured `/v1/endpoints/stats` but missed the other shapes.

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `GET /v1/endpoints` | Propose | `src/endpoints.rs:79` | `requests/endpoints/` itself 404s; only the `endpoints-stats` subpage exists. The bare list is undocumented but live. File docs request. |
| `GET /v1/endpoints/{}` | Propose | `src/endpoints.rs:84` | Same. |
| `GET /v1/endpoints/{}/stats` | Verify | `src/endpoints.rs:90` | Documented at `https://redis.io/docs/latest/operate/rs/references/rest-api/requests/endpoints-stats/` as `GET /v1/endpoints/stats`. The per-endpoint variant is a natural sibling — mark verify against the same page. |

---

## job_scheduler (`src/job_scheduler.rs`)

Docs page is minimal: only `GET /v1/job_scheduler` and `PUT /v1/job_scheduler`.
The SDK exposes per-job CRUD which appears to be operator-internal.

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `DELETE /v1/job_scheduler/{}` | Remove | `src/job_scheduler.rs:87` | Not in `requests/job_scheduler/`. The docs treat job_scheduler as a single config object, not a collection. |
| `GET /v1/job_scheduler/{}` | Remove | `src/job_scheduler.rs:86` | Same. |
| `GET /v1/job_scheduler/{}/history` | Remove | `src/job_scheduler.rs:107` | Same — no per-job history endpoint documented. |
| `POST /v1/job_scheduler` | Remove | `src/job_scheduler.rs:88` | Same — docs say PUT for updates, not POST for create. |
| `POST /v1/job_scheduler/{}/trigger` | Remove | `src/job_scheduler.rs:98` | Same. |
| `PUT /v1/job_scheduler/{}` | Remove | `src/job_scheduler.rs:89` | Same. |

Recommended: gate the per-job handlers behind a non-default cargo feature
or `#[deprecated]` them entirely.

---

## jsonschema (`src/jsonschema.rs`)

Docs page documents only `GET /v1/jsonschema`. Everything else in the SDK
module is invented — there is no `GET /v1/jsonschema/{name}` and no validate
endpoint.

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `GET /v1/jsonschema/{}` | Remove | `src/jsonschema.rs:31` | Docs page (`https://redis.io/docs/latest/operate/rs/references/rest-api/requests/jsonschema/`) lists only the bare GET. |
| `GET /v1/jsonschema/bdb` | Remove | `src/jsonschema.rs:37` | Same. |
| `GET /v1/jsonschema/cluster` | Remove | `src/jsonschema.rs:42` | Same. |
| `GET /v1/jsonschema/crdb` | Remove | `src/jsonschema.rs:57` | Same. |
| `GET /v1/jsonschema/node` | Remove | `src/jsonschema.rs:47` | Same. |
| `GET /v1/jsonschema/user` | Remove | `src/jsonschema.rs:52` | Same. |
| `POST /v1/jsonschema/{}/validate` | Remove | `src/jsonschema.rs:63` | No validate endpoint exists in docs. |

---

## license / migrations (`src/license.rs`, `src/migrations.rs`)

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `GET /v1/license/usage` | Propose | `src/license.rs:131` | `requests/license/` documents only `GET` and `PUT` on `/v1/license`; the `/usage` subroute returns usable data live but isn't in public docs. File docs request. |
| `POST /v1/license/validate` | Propose | `src/license.rs:139` | Same — not documented. File docs request. |
| `DELETE /v1/migrations/{}` | Remove | `src/migrations.rs:143` | `requests/migrations/` documents only `GET /v1/migrations/{uid}`. Migrations are not deleted via the REST API — they finish or are aborted via state transitions. |
| `GET /v1/migrations` | Remove | `src/migrations.rs:95` | Same — no list endpoint in docs. |
| `POST /v1/migrations` | Remove | `src/migrations.rs:107` | Same — migrations are created implicitly by `replica_of` configuration on a bdb. |
| `POST /v1/migrations/{}/pause` | Remove | `src/migrations.rs:124` | Same — no pause/resume/start verbs in docs. |
| `POST /v1/migrations/{}/resume` | Remove | `src/migrations.rs:134` | Same. |
| `POST /v1/migrations/{}/start` | Remove | `src/migrations.rs:114` | Same. |

---

## modules (`src/modules.rs`)

Docs page (`requests/modules/`) documents `GET /v1/modules` and
`GET /v1/modules/{uid}`. There is no v1 POST or PUT in the public docs, but
v2 upload IS documented elsewhere (user-defined modules, see #55).

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `DELETE /v1/modules/{}` | Verify | `src/modules.rs:156` | User-defined module management — documented in the user-defined-modules docs tree (currently being added in #55). Mark verify with cross-reference. |
| `POST /v1/modules` | Verify | `src/modules.rs:131` | Same — legacy v1 multipart upload route. |
| `POST /v2/modules` | Verify | `src/modules.rs:123` | Same — v2 multipart upload. Already covered by the in-flight user-defined-modules work. |
| `PUT /v1/modules/{}` | Verify | `src/modules.rs:162` | Same — documented under user-defined modules. |

---

## nodes subresources (`src/nodes.rs`)

Most of these are real and documented on subpages the crawler missed.

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `DELETE /v1/nodes/{}` | Verify | `src/nodes.rs:192`, `src/cluster.rs:558` | Documented at `https://redis.io/docs/latest/operate/rs/references/rest-api/requests/nodes/` as part of node lifecycle (used during `remove_node`). Inventory missed the DELETE method on the main page. |
| `GET /v1/nodes/wd_status` | Propose | `src/nodes.rs:290` | Not on the documented nodes subpages. Watchdog status is an operator-internal surface. File docs request. |
| `GET /v1/nodes/{}/alerts` | Remove | (no direct handler — appears via fixture) | Docs use **flat** path `/v1/nodes/alerts/{uid}` per `requests/nodes/alerts/`; the SDK uses the correct flat path at `src/nodes.rs:312`. The slashed shape isn't generated. Drop the fixture entry. |
| `GET /v1/nodes/{}/endpoints` | Propose | `src/endpoints.rs:109` | Mirror of `/v1/bdbs/{}/endpoints`. Not on documented subpages. File docs request. |
| `GET /v1/nodes/{}/proxies` | Propose | `src/proxies.rs:220` | Mirror of `/v1/bdbs/{}/proxies`. Not documented. File docs request. |
| `GET /v1/nodes/{}/shards` | Verify | `src/shards.rs:126` | Documented at `https://redis.io/docs/latest/operate/rs/references/rest-api/requests/shards/` — shards are queryable by node UID in the standard request shape. |
| `GET /v1/nodes/{}/stats` | Verify | `src/nodes.rs:202` | Documented at `https://redis.io/docs/latest/operate/rs/references/rest-api/requests/nodes/stats/` (GET `/v1/nodes/stats/{uid}`). The SDK shape and docs shape differ; both work live but the SDK should migrate to the flat shape. Mark verify. |
| `GET /v1/nodes/{}/stats/last` | Verify | `src/nodes.rs:202` (variant) | Documented at the same `nodes/stats/` page (last-interval shape). |
| `GET /v1/nodes/{}/wd_status` | Propose | `src/nodes.rs:301` | Same as `/v1/nodes/wd_status` — watchdog status. File docs request. |
| `POST /v1/nodes/{}/snapshots/{}` | Verify | `src/nodes.rs:270` | Documented at `https://redis.io/docs/latest/operate/rs/references/rest-api/requests/nodes/snapshots/` (snapshots page lists GET and DELETE explicitly; POST is the create flow). Note inventory may not capture POST — mark verify with note. |

---

## ocsp (`src/ocsp.rs`)

Docs page documents only `GET /v1/ocsp` and `PUT /v1/ocsp`. The SDK has more.

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `DELETE /v1/ocsp/cache` | Propose | `src/ocsp.rs:126` | Not in `requests/ocsp/` but is a legitimate OCSP cache operation. File docs request. |
| `POST /v1/ocsp/query` | Propose | `src/ocsp.rs:120` | Same — useful diagnostic verb missing from public docs. File docs request. |

(Note: `GET /v1/ocsp/status` and `POST /v1/ocsp/test` are also in the SDK but
not in the fixture — they should be checked in a future pass.)

---

## proxies (`src/proxies.rs`)

Docs page (`requests/proxies/`) explicitly lists only four endpoints and
calls out that "There are no 'stats' or 'reload' actions documented on this
proxy requests page".

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `GET /v1/proxies/{}/stats` | Propose | `src/proxies.rs:200` | Not in `requests/proxies/`. Stats per proxy is a real route on live clusters; file docs request. |
| `GET /v1/proxies/{}/stats/{}` | Propose | `src/proxies.rs:206` | Same. |
| `POST /v1/proxies/{}/actions/reload` | Propose | `src/proxies.rs:227` | Same — reload is referenced in operator runbooks but not in docs. File docs request. |

---

## redis_acls (`src/redis_acls.rs`)

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `POST /v1/redis_acls/validate` | Propose | `src/redis_acls.rs:64` | `requests/redis_acls/` documents CRUD only. The `/validate` helper is real (used by the Admin UI to pre-check ACL syntax) but not in docs. File docs request. |

---

## roles (`src/roles.rs`)

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `GET /v1/roles/{}/users` | Propose | `src/roles.rs:110` | `requests/roles/` documents standard CRUD only. The role-to-users reverse lookup is real but not in docs. File docs request. |
| `GET /v1/roles/builtin` | Propose | `src/roles.rs:105` | Same — used by the Admin UI dropdowns. File docs request. |

---

## services (`src/services.rs`)

The docs page (`requests/services/`) explicitly documents only
`GET /v1/local/services`, `POST /v1/local/services`, and `POST /v1/services`.
The rest of `ServicesHandler` (list/get/update/start/stop/restart/status) is
SDK-invented and looks like operator-internal helper code.

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `GET /v1/services` | Remove | `src/services.rs:91` | Docs do not document a list endpoint for `/v1/services`. Only `POST /v1/services` exists. Recommend `#[deprecated]`. |
| `GET /v1/services/{}` | Remove | `src/services.rs:96` | No per-service GET in docs. |
| `GET /v1/services/{}/status` | Remove | `src/services.rs:109` | No status subroute documented. |
| `POST /v1/services/{}/restart` | Remove | `src/services.rs:116` | No restart action documented. |
| `POST /v1/services/{}/start` | Remove | `src/services.rs:133` | No start action documented. |
| `POST /v1/services/{}/stop` | Remove | `src/services.rs:126` | No stop action documented. |
| `PUT /v1/services/{}` | Remove | `src/services.rs:102` | No per-service PUT documented. `PUT /v1/cluster/services_configuration` is the actual config surface for services on the cluster. |

Recommended: collapse this whole module to a single `create` method (the
documented `POST /v1/services`), or delete and route all callers to
`cluster.set_services_configuration` (which is real and documented).

---

## shards (`src/shards.rs`)

Docs page (`requests/shards/stats/`) explicitly lists
`GET /v1/shards/stats` and `GET /v1/shards/stats/{uid}`. The SDK uses a
different per-shard shape.

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `GET /v1/shards/{}/stats` | Remove | `src/shards.rs:104` | Docs use **flat** path `/v1/shards/stats/{uid}` (per `requests/shards/stats/`). The SDK already has a correct method at `/v1/shards/stats/{uid}` per the prior triage. The `/v1/shards/{uid}/stats` shape is not documented and isn't supported in `8.0.10-81` live. |
| `GET /v1/shards/{}/stats/{}` | Remove | `src/shards.rs:110` | Same — no metric-name subpath. Use the documented flat shape. |

---

## suffix / suffixes (`src/suffixes.rs`)

The docs split into two pages: `requests/suffix/` (singular, single-item GET)
and `requests/suffixes/` (plural, list GET). The SDK's `POST /v1/suffix` and
`PUT/DELETE /v1/suffix/{name}` are not in either page.

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `DELETE /v1/suffix/{}` | Propose | `src/suffixes.rs:83` | `requests/suffix/` only documents `GET`. DELETE was confirmed 404 in 8.0.10-81 live validation; this may be version-skew. File docs request and add a runtime feature gate. |
| `POST /v1/suffix` | Propose | `src/suffixes.rs:71` | Same — create not documented. |
| `PUT /v1/suffix/{}` | Propose | `src/suffixes.rs:77` | Same — update not documented. |

---

## usage_report (`src/usage_report.rs`)

Docs page documents only `GET /v1/usage_report`. Everything else in the SDK
module is invented.

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `GET /v1/usage_report/config` | Remove | `src/usage_report.rs:145` | Not in `requests/usage_report/`. |
| `GET /v1/usage_report/latest` | Remove | `src/usage_report.rs:121` | Same. |
| `GET /v1/usage_report/{}` | Remove | `src/usage_report.rs:132` | Same — usage reports are not addressable by ID; the docs treat the report as a streaming NDJSON dump. |
| `GET /v1/usage_report/{}/csv` | Remove | `src/usage_report.rs:156` | Same — no CSV variant in docs. |
| `POST /v1/usage_report/generate` | Remove | `src/usage_report.rs:139` | Same — reports are not generated on demand via this verb. |
| `PUT /v1/usage_report/config` | Remove | `src/usage_report.rs:150` | Same. |

Recommended: collapse the module to a single `get()` that streams NDJSON.

---

## users (`src/users.rs`)

Password management IS documented at `requests/users/password/` (the inventory
crawler missed the subpage). Permissions are not in the docs.

| Route | Verdict | Source | Citation / Rationale |
|---|---|---|---|
| `DELETE /v1/users/password` | Verify | `src/users.rs:252` | Documented at `https://redis.io/docs/latest/operate/rs/references/rest-api/requests/users/password/`. |
| `GET /v1/users/permissions` | Propose | `src/users.rs:225` | Not in `requests/users/`. Real route used by Admin UI. File docs request. |
| `GET /v1/users/permissions/{}` | Propose | `src/users.rs:231` | Same. |
| `POST /v1/users/password` | Verify | `src/users.rs:242` | Documented at `requests/users/password/`. |
| `PUT /v1/users/password` | Verify | `src/users.rs:247` | Same. |

---

## Per-Module Summary

| Module | Verify | Remove | Propose | Net Recommendation |
|---|---|---|---|---|
| actions | 0 | 1 | 0 | Drop `DELETE /v1/actions/{}` |
| alerts | 0 | 4 | 0 | Delete top-level `/v1/alerts` handlers |
| bdb_groups | 0 | 0 | 5 | Whole module needs a public docs request |
| bdbs subresources | 4 | 6 | 3 | Major cleanup: drop actions/backup, actions/restore, actions/upgrade; fix alerts path shape; drop stale fixture lines |
| bootstrap | 4 | 0 | 1 | Update stale comment in `cluster.rs:487` |
| cluster subresources | 8 | 0 | 4 | Mostly inventory ingest; propose settings/topology/witness_disk/policy/restore_default |
| cm_settings | 0 | 1 | 0 | Drop DELETE |
| crdb_tasks/crdbs | 1 | 1 | 0 | Drop bare `POST /v1/crdb_tasks` |
| debuginfo | 0 | 5 | 0 | Whole tree should be `#[deprecated]` per docs banner |
| diagnostics | 0 | 1 | 4 | Drop POST; propose the 4 subroutes |
| endpoints | 1 | 0 | 2 | Propose bare list endpoints |
| job_scheduler | 0 | 6 | 0 | Whole per-job CRUD is fictional |
| jsonschema | 0 | 7 | 0 | Whole module beyond bare GET is fictional |
| license / migrations | 0 | 6 | 2 | Migrations is heavily fictional; propose license usage/validate |
| modules | 4 | 0 | 0 | Verify against in-flight #55 work |
| nodes subresources | 5 | 1 | 4 | Mixed |
| ocsp | 0 | 0 | 2 | Propose cache/query |
| proxies | 0 | 0 | 3 | Propose stats + reload |
| redis_acls | 0 | 0 | 1 | Propose validate |
| roles | 0 | 0 | 2 | Propose users/builtin |
| services | 0 | 7 | 0 | Module-scale cleanup; collapse to documented surface |
| shards | 0 | 2 | 0 | Path-shape mismatch; supersede |
| suffix | 0 | 0 | 3 | File docs request; gated by version skew |
| usage_report | 0 | 6 | 0 | Whole module beyond bare GET is fictional |
| users | 3 | 0 | 2 | Verify the documented password subpage; propose permissions |

---

## Top Findings (most surprising)

1. **`src/alerts.rs` exposes a top-level `/v1/alerts` resource that does not
   exist in any docs version.** The handler appears alongside *correct*
   scoped handlers (`/v1/cluster/alerts`, `/v1/bdbs/alerts/{uid}`,
   `/v1/nodes/alerts/{uid}`), so the fix is purely removing the parallel
   universe. Four routes can be deleted outright.

2. **`src/bdb.rs:800` and `src/bdb.rs:818` (`actions/backup` and
   `actions/restore`) are not in the documented action enumeration at
   `requests/bdbs/actions/`.** The docs page is explicit — it lists 11 action
   endpoints and these two aren't among them. Source comments already flag
   them as suspicious. Recommend `#[deprecated]`.

3. **`src/bdb.rs:1090` (`POST /v1/bdbs/{uid}/actions/upgrade`) is superseded
   by the SDK's own `src/bdb.rs:1133` (`POST /v1/bdbs/{uid}/upgrade`).** Docs
   document the bare-`/upgrade` shape at `requests/bdbs/upgrade/`. The
   `actions/upgrade` variant is a duplicate at a wrong path.

4. **`src/services.rs` is mostly fictional.** The docs `requests/services/`
   page documents only `POST /v1/services`, `GET /v1/local/services`, and
   `POST /v1/local/services`. The SDK's GET-list, GET-by-id, PUT, status,
   start, stop, restart endpoints are all SDK-invented operator helpers. The
   real cluster-services config surface is `PUT /v1/cluster/services_configuration`,
   which the SDK already implements separately.

5. **`src/jsonschema.rs` and `src/usage_report.rs` are mostly fictional.** Both
   docs pages document a single GET endpoint and nothing else, yet the SDK
   exposes specialized typed accessors and POST/PUT mutators. 13 routes total
   can be deleted across these two modules.

6. **The `cluster.rs:487` source comment is wrong.** It says "Despite docs
   saying /v1/bootstrap, the actual endpoint is /v1/bootstrap/create_cluster"
   — but the bootstrap docs page DOES document `POST /v1/bootstrap/{action}`
   with `create_cluster` and `join_cluster` as valid `{action}` values. The
   inventory's apparent contradiction is just because the crawler captured
   only the parameterized form. Update the comment when the handler is next
   touched.

7. **The migrations module is heavily fictional.** Docs document a single
   `GET /v1/migrations/{uid}` for status lookup. The SDK exposes a full
   pause/resume/start/delete/create lifecycle that does not exist in the REST
   API — migrations are driven by the bdb `replica_of` configuration in
   reality.

8. **Stats path-shape mismatches.** Docs use a flat shape:
   `/v1/bdbs/stats/{uid}`, `/v1/shards/stats/{uid}`, `/v1/nodes/stats/{uid}`,
   `/v1/bdbs/alerts/{uid}`, `/v1/nodes/alerts/{uid}`. Several SDK handlers
   (especially older ones in `alerts.rs` and `shards.rs`) and several fixture
   lines use the inverted shape `/v1/<resource>/{uid}/stats`. Where both shapes
   exist live they should be unified onto the documented flat shape; where
   the slashed shape was only in the fixture (not in code), the fixture line
   should just be deleted.

---

## Process Notes

- All docs URLs verified on May 26, 2026 against `latest` (currently aliasing
  v7.22).
- Pages that returned 404 are flagged as **Propose** when the route is
  otherwise known to work live (e.g., from existing smoke tests). These are
  the strongest "real but undocumented" candidates and the best targets for an
  internal docs request.
- This triage does NOT modify source code. Follow-up PRs should:
  - delete or `#[deprecated]` each **Remove** entry;
  - file a docs request listing all **Propose** entries (single internal
    ticket, grouped by module);
  - extend `scripts/export_api_inventory.py` to follow subpage links so the
    **Verify** entries auto-ingest into `docs/api-inventory.csv` on the next
    refresh, eliminating ~75 of the 122 false positives.