Skip to content

docs: document Templates search and the search query language - #598

Draft
danielfsousa wants to merge 4 commits into
mainfrom
docs-templates-search
Draft

danielfsousa wants to merge 4 commits into
mainfrom
docs-templates-search

Conversation

@danielfsousa

@danielfsousa danielfsousa commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Refs SparkPost/email-monorepo#964. Refs SparkPost/email-monorepo#956, the query grammar. Refs SparkPost/email-monorepo#948, the epic.

Important

Do not merge before the production phase 3 Soak ends. Merging this PR is Publication: it makes the search API public and starts the freeze on searchable field types in ADR search-api-query-grammar. It stays a draft until then, so reviewers can read the deploy preview from production phase 1.

Summary

List all Templates returns at most a customer's first 50,000 templates, and the API reference offers no way past that cap. This PR documents the Templates search endpoint, QUERY /api/v1/templates, and the query language that every searchable resource will share. It also fixes the parser so that a QUERY action renders at all.

Changes

  • content/api/search.apib is a new Search page in the Introduction category. It covers the request body, the query language with its grammar, the limits, consistency, cursor pagination, the response envelope with the optional total_count, the errors with their positions, and the Templates field table with its Default fields and aliases.
  • content/api/templates.apib gains the Search Templates action after List all Templates. It has the body fields, one worked request, a 200 with two rows, a 400 with a position, and a request that follows the cursor. List all Templates gains one sentence that points to it.
  • content/api/table-of-contents.json lists the Search page after Overview.
  • plugins/gatsby-transformer-api-blueprint/parse-api-blueprint.js lets an action use QUERY. The API Blueprint parser accepts a fixed list of methods, and QUERY is not on it. Without the fix, the parser drops the heading with an "unexpected header block" warning and merges Search Templates into List all Templates. The parser now reads QUERY as MKCOL, which no page uses, and renames it back on every request. A page that uses MKCOL fails the build.

What changed since the first draft

The grammar changed after the first draft of this PR on 2026-09-25, and the pages now follow what the service ships:

Before Now Changed in
= matches the whole value := matches the whole value, and = is ordinary text SparkPost/email-monorepo#1275
A : fragment needs three characters, and name:ab was the 400 example A fragment of any length matches, and the 400 example is welcome status:nope at 15 SparkPost/email-monorepo#1450, SparkPost/email-monorepo#1453
Sort by name, id, status or a date Sort by last_update_time or created_at SparkPost/email-monorepo#1452
No total count include: ["total_count"] adds total_count, counted up to 10,000 SparkPost/email-monorepo#1451
No last_updated last_updated is an alias of last_update_time SparkPost/email-monorepo#1272
16 KB body cap 64 KB body cap, plus the 4,096-byte query and 100-value limits spec section 6

Choices worth knowing

  • The pages follow the spec section 6 and section 17, and the docs-devsite skill. The examples match the OpenAPI document in SparkPost/email-monorepo#1462, which lists every valid query on the Search page, so the service's CI parses each one.
  • The grammar is copied verbatim from the spec, and so are the worked queries and the error positions. The error messages are copied from the service. The spec fixes the code and the position, not the message.
  • The sort and include members are described in each attribute's text. The site's Data Structure renderer drops the members of an array[object], and a Default on one fails server rendering.
  • QUERY renders in the default text colour. Transition.js colours only GET, POST, PUT, and DELETE.
  • The 400 hangs under the worked request, and the text says it is the error for welcome status:nope. CONTRIBUTING.md caps an action at two requests, and the second one follows the cursor.
  • docs(templates): document cursor pagination on List all Templates #604 also edits List all Templates, so whichever of the two PRs merges second needs a merge there.

Proof

Run locally on 2026-11-09 at commit e2093a9b, with npm run docs on Node 16.14.0.

What Where Result
Every query on the Search page query.Parse in search-api with the Templates fields each valid query parses, and each one the page calls a 400 fails at the position it states
The 400 example search-api handler, QUERY /api/v1/templates 400 {"errors":[{"code":"invalid_search_query","message":"status is one of draft, published, published_with_draft","position":15}]}
Verification step 3, the parser on templates.apib local QUERY Search Templates sits between GET List all Templates and POST Create an RFC 822 Template. One "already defined" warning more than main, which every action on /v1/templates triggers
Verification step 1, /api/search/ local renders with 23 headings and 9 tables, and no rendering error in the log
Verification step 2, /api/templates/ local anchor templates-query-search-templates resolves, and the method renders as QUERY /api/v1/templates
Every link in the new sections local each /api/...#... target exists on its page

Verification

  1. The Search page lists every section. Its Templates field table names the Default fields and the subaccount and last_updated aliases, and marks only the two date fields sortable.

    https://deploy-preview-598--developers-sparkpost.netlify.app/api/search/
    
  2. Search Templates sits after List all Templates with the method QUERY. It has two requests, a 200 and a 400 on the first, and a 200 on the second.

    https://deploy-preview-598--developers-sparkpost.netlify.app/api/templates/#templates-query-search-templates
    
  3. The parser reads the action as QUERY and keeps its heading. Run it from plugins/gatsby-transformer-api-blueprint after npm run bootstrap.

    node -e "require('./parse-api-blueprint')(require('fs').readFileSync('../../content/api/templates.apib','utf8')).then(r=>{r.api.resourceGroups.forEach(g=>g.resources.forEach(x=>x.transitions.forEach(t=>console.log(t.method.toValue(),t.title.toValue()))));console.log(r.annotations.toValue())})"

The API Blueprint parser accepts a fixed list of HTTP methods, and
QUERY is not on it. It drops an action heading such as
`### Search Templates [QUERY /v1/templates]` with an "unexpected header
block" warning, and merges that action's requests into the action above.

parseApiBlueprint now swaps QUERY for MKCOL in action headings before
parsing, and renames MKCOL back to QUERY on every parsed request. No
page uses MKCOL, and a page that does fails the build.
Add a Search page to the Introduction category. It covers the request
body, the query language, limits, consistency, pagination, the response
envelope, errors, and the Templates field table with its Default fields.

Add the Search Templates action, QUERY /v1/templates, after List all
Templates, which now points to it for accounts past 50,000 templates.

Refs SparkPost/email-monorepo#964
:= is now the exact match and = is ordinary text. Fragments of any
length match, so the three-character minimum and its name:ab example
are gone. The body cap is 64 KB, include adds total_count, Templates
sort by last_update_time or created_at only, and last_updated is an
alias. The examples and error positions come from the search service.

Refs SparkPost/email-monorepo#964

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant