Skip to content

[Trace] Content audit: enrich thin API reference pages: 21 endpoint pages - #171

Merged
nicolasiscoding merged 3 commits into
developfrom
trace/enrich-api-reference
Sep 23, 2026
Merged

nicolasiscoding merged 3 commits into
developfrom
trace/enrich-api-reference

Conversation

@nicolasiscoding

@nicolasiscoding nicolasiscoding commented Sep 23, 2026 •

Copy link
Copy Markdown
Member

Closes #170

Trace task: content-audit.mjs (flagged these pages KILL/thin), thin-content-detector.mjs, config/noindex-strategy.json, plus the team rule that thin-but-legitimate pages are improved, never noindexed.

Evidence

GSC shows docs.turbodocx.com API endpoint pages (docs/API/*.api.mdx, generated by docusaurus-plugin-openapi-docs) rendering only 4-9 words of unique content for Googlebot, and many are "Crawled/Discovered - currently not indexed." PR #155 hand-enriched 3 pages as a prototype and validated the strategy: URL Inspection now shows delete-template went from not-on-Google to Submitted and indexed, and upload-template-with-optional-default-values is indexed (get-templates-and-folders hasn't been recrawled since June). This PR rolls that pattern out to the remaining thin pages.

origin/develop and origin/main point at the same commit as of this branch's base, and both already contain #155's enrichment (checked via git log + git diff on delete-template.api.mdx before starting). This branch is based on origin/develop, per the repo's default.

What changed

21 of the 24 remaining thin docs/API/*.api.mdx pages (live word count under 300, excluding the 3 pages #155 already enriched and the turbodocx-api-documentation info page) now have: a real frontmatter description (<= 160 chars, no em-dashes), an intro paragraph, a "When to use it" section, a runnable curl example, a verified example response, a common-errors table, and related-endpoint links — matching #155's structure exactly.

  • Templates (3): edit-template-metadata, get-template-by-id, extract-template-placeholders-and-generate-preview
  • TurboSign webhooks (10): create-webhook, get-webhook, update-webhook, delete-webhook, notify-webhook, test-webhook, regenerate-webhook-secret, list-webhook-deliveries, replay-webhook-delivery, get-webhook-stats
  • Tags/variables (8): create-tag, read-tag, update-tag, delete-tags-by-i-ds, create-image-variable-folder, read-variables-folder, update-variable-by-id, delete-variables-by-i-ds

Every path, method, request field, response shape, and error was verified against the route/handler code in RapidDocxBackend (src/routes/Template, src/routes/Webhooks, src/routes/Tag, src/routes/Variable + their handlers in src/handlers/), not the OpenAPI spec (tdocxcollection.yml), which is stale in places. Where I could not verify a claim against the handler code, I left it out.

Accuracy findings / spec-vs-code discrepancies

  • delete-webhook's existing frontmatter description said "soft-delete," but deleteWebhook() in webhookManagement.ts issues real SQL DELETEs on both the webhook row and its deliveries — it's a hard delete. Fixed the description and documented it correctly.
  • GET /api/webhooks/:name's deliveryStats (via WebhookService.getDeliveryStats) is scoped to the whole organization's deliveries over the last 30 days, not to the single webhook in the URL — documented that explicitly and pointed to Get Webhook Stats for a per-webhook, custom-window alternative.
  • PUT /Tag/:id (Update Tag) responds with the raw updated tag object (res.send(Tag)), not the { data: {...} } envelope almost every other endpoint uses — documented as-is rather than assuming the common envelope.
  • PUT /Variable/:variableMapId (Update Variable by ID) responds { "variable": {...} }, also outside the data envelope — documented as-is.
  • An em-dash in create-webhook's and regenerate-webhook-secret's existing frontmatter descriptions was removed per the no-em-dash content rule; both descriptions were also shortened to fit the 160-char limit.

Generated-file caveat

These .api.mdx files are generated by docusaurus-plugin-openapi-docs, and the plugin's configured outputDir (docs/api/turbodocx) does not match the served path (docs/API/) — so the regen pipeline isn't actually wired to overwrite these files today, but that's fragile to rely on long-term. Recommended follow-up (not in this PR): enrich the descriptions directly in tdocxcollection.yml and fix the plugin's outputDir so a future regeneration doesn't silently invite someone to overwrite this content.

Not covered

docs/API/Deliverable%20API (2603 words, not thin) and turbodocx-api-documentation (info page, excluded by the task) were left untouched, as were the 3 pages #155 already enriched.

Test plan

  • Frontmatter YAML parses on every changed file (verified with yaml.safe_load)
  • Every internal /docs/API/... link added resolves to an existing page (verified against the file list)
  • grep for em-dashes across changed files returns nothing
  • Every description is <= 160 characters
  • Local build
  • Staging deploy

Review vs backend master

Diligence pass against origin/master of RapidDocxBackend and the frontend, checking every documented behavior against the actual deployed code. 14 confirmed inaccuracies fixed:

  • test-webhook: summary.failed/summary.errors only count a DB error on insert, not HTTP-level delivery failures (deliverWebhookToUrl never rethrows on a failed HTTP attempt). Doc now points callers at each delivery's isDelivered/status/errorMessage instead of the unreliable summary counters.
  • replay-webhook-delivery: replay re-sends to the single URL the original delivery targeted, not to every URL configured on the webhook (replayDelivery copies originalDelivery.url into the new row). Fixed the frontmatter description and body copy.
  • create-webhook: the name uniqueness check (and its DB index) is scoped to (orgId, name, isActive), so it's unique only among active webhooks; pausing one with isActive: false (as Update/Delete Webhook recommend) and creating another with the same name silently produces two rows with the same name. Doc now says to delete rather than pause before reusing a name.
  • create-webhook / update-webhook: the 400 validation-error body isn't { "error": "..." }; celebrate/Joi validation failures go through the app's JoiValidationErrorHandler, which returns { "message", "type": "ValidationError", "data": { "errors": [...] } }. Fixed both pages' error tables to match the shape used elsewhere in this PR.
  • list-webhook-deliveries: the documented 1/5/10-minute backoff can't happen with maxAttempts fixed at 3; the retry loop only ever reaches the 1-minute and 5-minute delays before the final attempt dead-letters. Corrected the backoff description.
  • list-webhook-deliveries: isDelivered and httpStatus filters don't work as documented due to a type-coercion bug (celebrate/Joi already converts these to a real boolean/number before the handler's string comparisons run). Added a "known limitation" callout describing current behavior instead of the intended one.
  • read-tag: the page claimed there's no "get tag by ID" endpoint; GET /Tag/:id exists and returns a single tag. Corrected the claim and linked the endpoint.
  • extract-template-placeholders-and-generate-preview: templatePdf is documented as a base64 string, but it's a JSON-serialized Node.js Buffer ({"type":"Buffer","data":[...]}). Documented the actual shape and how to reconstruct it, matching how the frontend already consumes it.
  • create-image-variable-folder: the "placeholder not wrapped in { }" error was listed under the ValidationError row, but it's actually thrown as a TemplateError by the same handler as the "placeholder already exists" case. Moved it to the correct row.
  • create-image-variable-folder: missing a 403 case; isGlobal: true requests are further restricted to administrator/contributor (a second KB-specific middleware rejects the user role). Added the row.
  • update-variable-by-id: the 423 "template is locked" error can't occur for this endpoint's documented knowledge-base/folder-variable request shape, since the lock-check middleware explicitly skips locked-template checks when the VariableMap has no templateId. Removed the row.
  • update-variable-by-id: same isGlobal/role gap as create-image-variable-folder, missing from this page's 403 row. Fixed.
  • update-variable-by-id / create-image-variable-folder / read-variables-folder: all three said isGlobal/templateFolderId are "exactly one required" or "mutually exclusive", but the Joi rule (oxor) only forbids sending both; neither is required. Changed all three to "at most one, sending both is rejected".
  • update-tag: claimed id in the body is "not accepted"; it isn't rejected by validation on this route (body validation context is "PATCH", and id is only forbidden under a "PUT" context) and isn't ignored either, an id differing from the URL's TagId will overwrite the tag's own id. Corrected to warn against sending it, rather than claiming it's rejected.

Backend defects found during this review (not fixed here, for ticketing)

  • WebhookService.deliverWebhookToUrl / attemptDelivery: HTTP-level delivery failures never surface in POST /webhooks/signature/test's summary.failed/summary.errors, only DB-insert errors do. A caller polling summary.failed to detect a broken receiver sees zero failures even when every attempt 500s.
  • WebhookService.replayDelivery: replays only the single URL the original delivery hit, even though a webhook can have up to 10 URLs; there's no way to replay to all of a webhook's URLs via this endpoint.
  • WebhookModel name-uniqueness is scoped to (orgId, name, isActive) rather than (orgId, name), so pausing a webhook (isActive: false) and creating a new one with the same name produces two rows sharing a name; every by-name lookup endpoint (Get/Update/Delete/Test/Notify/Regenerate/List-deliveries/Replay/Stats) then has ambiguous resolution.
  • GET /webhooks/signature/deliveries query filters: isDelivered=true is coerced to false by a === "true" string comparison against an already-Joi-converted boolean, so it returns the same results as isDelivered=false; httpStatus is dropped entirely by a typeof x === "string" check against an already-converted number, so the filter never applies.
  • PUT /Tag/:id: body validation runs in a "PATCH" Joi context, not the "PUT" context that forbids id, so a client-supplied id in the body silently overwrites the tag's own id column via updateAndFetchById. Separately, id has a Joi .default(() => uuidv4()), so if it's ever coerced onto an absent field, that could overwrite the row's id with a fresh random UUID even without user input; worth confirming celebrate's convert behavior doesn't apply defaults back onto req.body here before shipping a fix.

…ining docs/API/*.api.mdx

Rolls out the PR #155 pattern (real description, when-to-use, curl example,
verified request/response, common-errors table, related links) to every
docs/API/*.api.mdx page under 300 live words, excluding the 3 pages #155
already enriched (delete-template, get-templates-and-folders,
upload-template-with-optional-default-values) and the turbodocx-api-documentation
info page.

Covered: 3 template endpoints (edit-template-metadata, get-template-by-id,
extract-template-placeholders-and-generate-preview), all 10 TurboSign webhook
endpoints (create/get/update/delete/notify/test/regenerate-secret/
list-deliveries/replay-delivery/get-stats), and 8 tag/variable endpoints
(create/read/update-tag, delete-tags-by-i-ds, create-image-variable-folder,
read-variables-folder, update-variable-by-id, delete-variables-by-i-ds).

Every path, method, field, response shape, and error was verified against
the route/handler code in RapidDocxBackend (Template, Webhooks, Tag,
Variable routes + handlers), not the OpenAPI spec, which is stale in
several places. Also fixed two pre-existing frontmatter issues on webhook
pages: an em-dash and an inaccurate "soft-delete" claim on delete-webhook
(the handler hard-deletes the row).
@nicolasiscoding nicolasiscoding self-assigned this Sep 23, 2026

This branch was successfully deployed

1 active deployment
preview — ba22bad2 Deployed Sep 23, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Trace] Content audit: enrich thin API reference pages: 21 endpoint pages

1 participant