Skip to content

Query the site

POST
/api/pages

Answers a list of questions in one request — a selection, the facets to count, and how many rows to return. Each question is answered independently and the answers come back in the order they were asked.

Reach for a GET address first where one spells the question you have — those are cacheable and this is not. The grammar itself is published at /api/query-schema.json.

Header Parameters

x-http-method-override*"QUERY"

QUERY is sent as POST carrying x-http-method-override: QUERY, because the edge in front of this API refuses a bare QUERY with a 405 before any code here runs. It is required rather than an alternative spelling: the request cannot be made without it.

Value in

  • "QUERY"

Request Body

application/json

The query grammar, generated from the validator that enforces it. The same schema is published on its own at /api/query-schema.json, which is where a client should fetch it from — that address is cacheable and this document is not small.

TypeScript Definitions

Use the request body type in TypeScript.

A query that satisfies this schema may still be refused at 422. Nesting depth, and the totals counted across a whole request — text clauses, caller-supplied text and declared results — have no vocabulary in JSON Schema and are enforced by the API. See the invalid-query problem type for what each refusal names.

A query that satisfies this schema may still be refused at 422. Nesting depth, and the totals counted across a whole request — text clauses, caller-supplied text and declared results — have no vocabulary in JSON Schema and are enforced by the API. See the invalid-query problem type for what each refusal names.

A query that satisfies this schema may still be refused at 422. Nesting depth, and the totals counted across a whole request — text clauses, caller-supplied text and declared results — have no vocabulary in JSON Schema and are enforced by the API. See the invalid-query problem type for what each refusal names.

Response Body

application/json

application/problem+json

curl -X POST "https://example.com/api/pages" \  -H "x-http-method-override: QUERY" \  -H "Content-Type: application/json" \  -d '{    "match": {      "text": "string",      "in": "title"    }  }'
{  "items": [    {      "results": [        {          "path": "string",          "canonical": "string",          "title": "string",          "description": "string",          "collection": "writing",          "date": "string",          "twin": "string"        }      ],      "matched": 0,      "facets": [        {          "facet": "collection",          "counts": [            {              "value": "string",              "count": 0            }          ]        }      ]    }  ],  "count": 0,  "total": 0}
---
title: "Query the site"
description: "Answers a list of questions in one request — a selection, the facets to count, and how many rows to return. Each question is answered independently and the answers come back in the order they were asked.\n\nReach for a `GET` address first where one spells the question you have — those are cacheable and this is not. The grammar itself is published at [`/api/query-schema.json`](/api/query-schema.json)."
url: "https://lateano.com/developers/api/reference/reading/pages.post"
author: "Colin Lateano"
---

# Query the site

Answers a list of questions in one request — a selection, the facets to count, and how many rows to return. Each question is answered independently and the answers come back in the order they were asked.

Reach for a `GET` address first where one spells the question you have — those are cacheable and this is not. The grammar itself is published at [`/api/query-schema.json`](/api/query-schema.json).

```json
{
  "openapi": "3.1.1",
  "info": {
    "title": "lateano.com",
    "version": "1.0.0"
  },
  "paths": {
    "/api/pages": {
      "post": {
        "operationId": "pages.post",
        "summary": "Query the site",
        "tags": [
          "Reading"
        ],
        "description": "Answers a list of questions in one request — a selection, the facets to count, and how many rows to return. Each question is answered independently and the answers come back in the order they were asked.\n\nReach for a `GET` address first where one spells the question you have — those are cacheable and this is not. The grammar itself is published at [`/api/query-schema.json`](/api/query-schema.json).",
        "parameters": [
          {
            "name": "x-http-method-override",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "QUERY"
              ]
            },
            "description": "`QUERY` is sent as `POST` carrying `x-http-method-override: QUERY`, because the edge in front of this API refuses a bare `QUERY` with a 405 before any code here runs. It is required rather than an alternative spelling: the request cannot be made without it."
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The query grammar, generated from the validator that enforces it. The same schema is published on its own at [`/api/query-schema.json`](https://lateano.com/api/query-schema.json), which is where a client should fetch it from — that address is cacheable and this document is not small.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueryGrammar"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Query the site",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueryBody"
                }
              }
            }
          },
          "default": {
            "description": "Every other status this operation answers with is a refusal, and carries `problem+json` (RFC 9457).\n\nEvery refusal this API can make, whatever the status. Match on the `type` URI’s last segment — the slug below — rather than on the whole URI, which follows whichever deployment answered.\n\n| Status | Slug | Title |\n| --- | --- | --- |\n| 400 | [`invalid-idempotency-key`](https://lateano.com/api/problems/invalid-idempotency-key) | The Idempotency-Key header carries a value this resource will not accept |\n| 400 | [`malformed-body`](https://lateano.com/api/problems/malformed-body) | The request body did not parse |\n| 400 | [`missing-idempotency-key`](https://lateano.com/api/problems/missing-idempotency-key) | This resource requires an Idempotency-Key header |\n| 400 | [`missing-media-type`](https://lateano.com/api/problems/missing-media-type) | The request carried a body with no media type |\n| 404 | [`no-such-resource`](https://lateano.com/api/problems/no-such-resource) | There is nothing at this address |\n| 405 | [`method-not-allowed`](https://lateano.com/api/problems/method-not-allowed) | This resource does not answer that method |\n| 406 | [`not-acceptable`](https://lateano.com/api/problems/not-acceptable) | This resource cannot answer in any media type the request accepts |\n| 409 | [`conflicting-idempotency-key`](https://lateano.com/api/problems/conflicting-idempotency-key) | That Idempotency-Key already names a different submission |\n| 412 | [`precondition-failed`](https://lateano.com/api/problems/precondition-failed) | The condition the request carried does not hold |\n| 415 | [`unsupported-media-type`](https://lateano.com/api/problems/unsupported-media-type) | The request body is in a media type this resource does not read |\n| 422 | [`invalid-query`](https://lateano.com/api/problems/invalid-query) | The query parsed but does not describe a question this resource can answer |\n| 422 | [`invalid-submission`](https://lateano.com/api/problems/invalid-submission) | The submission parsed but is not something this resource can record |\n| 429 | [`too-many-requests`](https://lateano.com/api/problems/too-many-requests) | The courtesy quota for this caller is spent |\n| 500 | [`unexpected-failure`](https://lateano.com/api/problems/unexpected-failure) | The resource failed while answering |",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDocument"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "QueryGrammar": {
        "anyOf": [
          {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "match": {
                    "$ref": "#/components/schemas/QueryGrammar/$defs/__schema0"
                  },
                  "collection": {
                    "type": "string",
                    "enum": [
                      "writing",
                      "glossary",
                      "demos"
                    ]
                  },
                  "tag": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 8000
                  },
                  "limit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 9007199254740991
                  },
                  "facets": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "collection",
                        "tags"
                      ]
                    }
                  }
                },
                "required": [
                  "match"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "like": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 8000
                  },
                  "collection": {
                    "type": "string",
                    "enum": [
                      "writing",
                      "glossary",
                      "demos"
                    ]
                  },
                  "tag": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 8000
                  },
                  "limit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 9007199254740991
                  },
                  "facets": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "collection",
                        "tags"
                      ]
                    }
                  }
                },
                "required": [
                  "like"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "traverse": {
                    "type": "object",
                    "properties": {
                      "from": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 8000
                      },
                      "follow": {
                        "type": "string",
                        "enum": [
                          "outgoing",
                          "incoming",
                          "both"
                        ]
                      },
                      "depth": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 5
                      }
                    },
                    "required": [
                      "from",
                      "follow",
                      "depth"
                    ],
                    "additionalProperties": false
                  },
                  "collection": {
                    "type": "string",
                    "enum": [
                      "writing",
                      "glossary",
                      "demos"
                    ]
                  },
                  "tag": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 8000
                  },
                  "limit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 9007199254740991
                  },
                  "facets": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "collection",
                        "tags"
                      ]
                    }
                  }
                },
                "required": [
                  "traverse"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "slug": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 8000
                  },
                  "collection": {
                    "type": "string",
                    "enum": [
                      "writing",
                      "glossary",
                      "demos"
                    ]
                  },
                  "tag": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 8000
                  }
                },
                "required": [
                  "slug"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "path": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 8000
                  },
                  "collection": {
                    "type": "string",
                    "enum": [
                      "writing",
                      "glossary",
                      "demos"
                    ]
                  },
                  "tag": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 8000
                  }
                },
                "required": [
                  "path"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "collection": {
                    "type": "string",
                    "enum": [
                      "writing",
                      "glossary",
                      "demos"
                    ]
                  },
                  "tag": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 8000
                  },
                  "limit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 9007199254740991
                  },
                  "facets": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "collection",
                        "tags"
                      ]
                    }
                  }
                },
                "additionalProperties": false
              }
            ]
          },
          {
            "type": "object",
            "properties": {
              "batch": {
                "minItems": 1,
                "maxItems": 10,
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "match": {
                          "$ref": "#/components/schemas/QueryGrammar/$defs/__schema0"
                        },
                        "collection": {
                          "type": "string",
                          "enum": [
                            "writing",
                            "glossary",
                            "demos"
                          ]
                        },
                        "tag": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 8000
                        },
                        "limit": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 9007199254740991
                        },
                        "facets": {
                          "minItems": 1,
                          "type": "array",
                          "items": {
                            "type": "string",
                            "enum": [
                              "collection",
                              "tags"
                            ]
                          }
                        }
                      },
                      "required": [
                        "match"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "type": "object",
                      "properties": {
                        "like": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 8000
                        },
                        "collection": {
                          "type": "string",
                          "enum": [
                            "writing",
                            "glossary",
                            "demos"
                          ]
                        },
                        "tag": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 8000
                        },
                        "limit": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 9007199254740991
                        },
                        "facets": {
                          "minItems": 1,
                          "type": "array",
                          "items": {
                            "type": "string",
                            "enum": [
                              "collection",
                              "tags"
                            ]
                          }
                        }
                      },
                      "required": [
                        "like"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "type": "object",
                      "properties": {
                        "traverse": {
                          "type": "object",
                          "properties": {
                            "from": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 8000
                            },
                            "follow": {
                              "type": "string",
                              "enum": [
                                "outgoing",
                                "incoming",
                                "both"
                              ]
                            },
                            "depth": {
                              "type": "integer",
                              "minimum": 1,
                              "maximum": 5
                            }
                          },
                          "required": [
                            "from",
                            "follow",
                            "depth"
                          ],
                          "additionalProperties": false
                        },
                        "collection": {
                          "type": "string",
                          "enum": [
                            "writing",
                            "glossary",
                            "demos"
                          ]
                        },
                        "tag": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 8000
                        },
                        "limit": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 9007199254740991
                        },
                        "facets": {
                          "minItems": 1,
                          "type": "array",
                          "items": {
                            "type": "string",
                            "enum": [
                              "collection",
                              "tags"
                            ]
                          }
                        }
                      },
                      "required": [
                        "traverse"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "type": "object",
                      "properties": {
                        "slug": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 8000
                        },
                        "collection": {
                          "type": "string",
                          "enum": [
                            "writing",
                            "glossary",
                            "demos"
                          ]
                        },
                        "tag": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 8000
                        }
                      },
                      "required": [
                        "slug"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "type": "object",
                      "properties": {
                        "path": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 8000
                        },
                        "collection": {
                          "type": "string",
                          "enum": [
                            "writing",
                            "glossary",
                            "demos"
                          ]
                        },
                        "tag": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 8000
                        }
                      },
                      "required": [
                        "path"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "type": "object",
                      "properties": {
                        "collection": {
                          "type": "string",
                          "enum": [
                            "writing",
                            "glossary",
                            "demos"
                          ]
                        },
                        "tag": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 8000
                        },
                        "limit": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 9007199254740991
                        },
                        "facets": {
                          "minItems": 1,
                          "type": "array",
                          "items": {
                            "type": "string",
                            "enum": [
                              "collection",
                              "tags"
                            ]
                          }
                        }
                      },
                      "additionalProperties": false
                    }
                  ]
                }
              }
            },
            "required": [
              "batch"
            ],
            "additionalProperties": false
          }
        ],
        "$defs": {
          "__schema0": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "text": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 1000
                  },
                  "in": {
                    "type": "string",
                    "enum": [
                      "title",
                      "body",
                      "description",
                      "aliases",
                      "tags",
                      "all"
                    ]
                  }
                },
                "required": [
                  "text",
                  "in"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "all": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/QueryGrammar/$defs/__schema0"
                    }
                  }
                },
                "required": [
                  "all"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "any": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/QueryGrammar/$defs/__schema0"
                    }
                  }
                },
                "required": [
                  "any"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "not": {
                    "$ref": "#/components/schemas/QueryGrammar/$defs/__schema0"
                  }
                },
                "required": [
                  "not"
                ],
                "additionalProperties": false
              }
            ]
          }
        },
        "title": "lateano.com query",
        "description": "A query that satisfies this schema may still be refused at 422. Nesting depth, and the totals counted across a whole request — text clauses, caller-supplied text and declared results — have no vocabulary in JSON Schema and are enforced by the API. See the invalid-query problem type for what each refusal names."
      },
      "QueryBody": {
        "$ref": "#/components/schemas/ListEnvelope_QueryAnswer",
        "description": "The list holds one answer for each query in the request."
      },
      "ProblemDocument": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "§ 3.1.1. Absolute, on the origin that answered, and it resolves."
          },
          "title": {
            "type": "string",
            "description": "§ 3.1.3. The catalogue row's, unchanged from occurrence to occurrence."
          },
          "status": {
            "type": "number",
            "description": "§ 3.1.2. The same number as the status line, derived rather than passed."
          },
          "instance": {
            "type": "string",
            "description": "§ 3.1.5 RECOMMENDS an absolute URI here. This field carries a full path from the root, which is the fallback form the same section permits."
          },
          "detail": {
            "type": "string",
            "description": "§ 3.1.4. This occurrence only, bounded by `DETAIL_MAX`, absent when there is nothing to add."
          }
        },
        "required": [
          "type",
          "title",
          "status",
          "instance"
        ],
        "additionalProperties": false,
        "description": "The schema generator publishes this declaration as the error schema, so a field here reaches the reference. RFC 9457 § 3.1 makes all five members optional, and this API narrows four of them to required: § 3.1.1 reads an absent `type` as `about:blank` and discards the resolvable URI. An optional member is absent, never present and `undefined`, because `JSON.stringify` drops the value and the wire cannot tell the two apart."
      },
      "ListEnvelope_QueryAnswer": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QueryAnswer"
            }
          },
          "count": {
            "type": "number",
            "description": "How many items this response carries."
          },
          "total": {
            "type": "number",
            "description": "How many items exist across every response."
          }
        },
        "required": [
          "items",
          "count",
          "total"
        ],
        "additionalProperties": false,
        "description": "The one body shape every list resource returns."
      },
      "QueryAnswer": {
        "type": "object",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QueryRow"
            }
          },
          "matched": {
            "type": "number",
            "description": "How many documents the query matched, before any bound reduced them to `results`."
          },
          "facets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FacetGroup"
            }
          }
        },
        "required": [
          "results",
          "matched",
          "facets"
        ],
        "additionalProperties": false,
        "description": "`facets` is empty rather than absent for a query that asked for none, and one group per dimension in the order asked. An empty group is a real answer, so \"did not ask\" and \"asked and nothing matched\" stay apart."
      },
      "QueryRow": {
        "type": "object",
        "properties": {
          "path": {
            "type": "string"
          },
          "canonical": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "collection": {
            "$ref": "#/components/schemas/Collection"
          },
          "date": {
            "type": [
              "string",
              "null"
            ]
          },
          "twin": {
            "type": [
              "string",
              "null"
            ],
            "description": "The markdown twin's address, and where the whole document is fetched from."
          }
        },
        "required": [
          "path",
          "canonical",
          "title",
          "description",
          "collection",
          "date",
          "twin"
        ],
        "additionalProperties": false,
        "description": "`date` is a post's publication or a term's last review, and `null` for a Demo, which has none. `twin` is `null` for a page that publishes no twin, rather than an address that 404s."
      },
      "FacetGroup": {
        "type": "object",
        "properties": {
          "facet": {
            "$ref": "#/components/schemas/Facet"
          },
          "counts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FacetCount"
            }
          }
        },
        "required": [
          "facet",
          "counts"
        ],
        "additionalProperties": false,
        "description": "Counts over every matched document, not over the returned rows; counts over a `limit`-sized page describe the page, which a caller can already derive. Ordered by count and then by value, so the same query answers the same way twice."
      },
      "Collection": {
        "type": "string",
        "enum": [
          "writing",
          "glossary",
          "demos"
        ]
      },
      "Facet": {
        "type": "string",
        "enum": [
          "collection",
          "tags"
        ]
      },
      "FacetCount": {
        "type": "object",
        "properties": {
          "value": {
            "type": "string"
          },
          "count": {
            "type": "number"
          }
        },
        "required": [
          "value",
          "count"
        ],
        "additionalProperties": false,
        "description": "How many documents carried one value of a facet."
      }
    }
  }
}
```