{
  "openapi": "3.1.0",
  "info": {
    "title": "Lucio Duran Portfolio API",
    "description": "Public, read-only publication APIs. Canonical HTML, Markdown and JSON share one content source. No authentication or model invocation. MCP is documented separately at https://lucioduran.com/access#mcp.",
    "version": "3.0.0",
    "contact": {
      "name": "Lucio Duran",
      "url": "https://lucioduran.com",
      "email": "email@lucioduran.com"
    }
  },
  "servers": [
    {
      "url": "https://lucioduran.com"
    }
  ],
  "paths": {
    "/api/content": {
      "servers": [
        {
          "url": "https://lucioduran.com"
        }
      ],
      "get": {
        "operationId": "readPublishedDocument",
        "summary": "Read the published main content of a page",
        "parameters": [
          {
            "name": "path",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "example": "/es/education"
            }
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "md"
              ],
              "default": "json"
            }
          },
          {
            "name": "section",
            "in": "query",
            "required": false,
            "description": "Exact heading fragment ID from a search result or document. Returns only that passage, with its own hash and the full document hash in source.contentHash.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 300
            }
          },
          {
            "name": "If-None-Match",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "ETag from an earlier request. Matching content returns 304."
          }
        ],
        "responses": {
          "200": {
            "description": "Published document, or a scoped passage when section is supplied. Both expose canonical citation URLs and content hashes.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/PublishedDocument"
                    },
                    {
                      "$ref": "#/components/schemas/PublishedPassage"
                    }
                  ]
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "304": {
            "description": "Unchanged representation",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "400": {
            "description": "Invalid format",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Document not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "502": {
            "description": "Source unavailable; never a fabricated successful document",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Content service busy",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string"
                },
                "description": "Retry delay in seconds when supplied."
              }
            }
          },
          "405": {
            "description": "Unsupported method",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "head": {
        "operationId": "readPublishedDocumentHeaders",
        "summary": "The GET response headers without a body",
        "parameters": [
          {
            "name": "path",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "example": "/es/education"
            }
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "md"
              ],
              "default": "json"
            }
          },
          {
            "name": "section",
            "in": "query",
            "required": false,
            "description": "Exact heading fragment ID from a search result or document. Returns only that passage, with its own hash and the full document hash in source.contentHash.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 300
            }
          },
          {
            "name": "If-None-Match",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "ETag from an earlier request. Matching content returns 304."
          }
        ],
        "responses": {
          "200": {
            "description": "Published document, or a scoped passage when section is supplied. Both expose canonical citation URLs and content hashes.",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "304": {
            "description": "Unchanged representation",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "400": {
            "description": "Invalid format"
          },
          "404": {
            "description": "Document not found"
          },
          "502": {
            "description": "Source unavailable; never a fabricated successful document"
          },
          "503": {
            "description": "Content service busy",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string"
                },
                "description": "Retry delay in seconds when supplied."
              }
            }
          },
          "405": {
            "description": "Unsupported method"
          }
        }
      },
      "options": {
        "operationId": "readPublishedDocumentOptions",
        "summary": "Public CORS preflight",
        "responses": {
          "204": {
            "description": "GET, HEAD and OPTIONS allowed"
          }
        }
      }
    },
    "/api/content-index": {
      "servers": [
        {
          "url": "https://lucioduran.com"
        }
      ],
      "get": {
        "operationId": "listPublishedDocuments",
        "summary": "Discover published pages; filter by kind or title and paginate",
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "es"
              ],
              "default": "en"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "section",
                "experience",
                "education",
                "technology",
                "blog",
                "project",
                "decision"
              ]
            }
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Search published full text. Results include a matching excerpt and section citation URL."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 10000
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 500
            }
          },
          {
            "name": "If-None-Match",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "ETag from an earlier request. Matching content returns 304."
          }
        ],
        "responses": {
          "200": {
            "description": "Index containing canonical URLs, titles, kinds, content version, counts and next page link",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "304": {
            "description": "Unchanged index",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "400": {
            "description": "Invalid query",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "502": {
            "description": "A source of the index is unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "405": {
            "description": "Unsupported method",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "head": {
        "operationId": "listPublishedDocumentsHeaders",
        "summary": "The GET response headers without a body",
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "es"
              ],
              "default": "en"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "section",
                "experience",
                "education",
                "technology",
                "blog",
                "project",
                "decision"
              ]
            }
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Search published full text. Results include a matching excerpt and section citation URL."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 10000
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 500
            }
          },
          {
            "name": "If-None-Match",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "ETag from an earlier request. Matching content returns 304."
          }
        ],
        "responses": {
          "200": {
            "description": "Index containing canonical URLs, titles, kinds, content version, counts and next page link",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "304": {
            "description": "Unchanged index",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "400": {
            "description": "Invalid query"
          },
          "502": {
            "description": "A source of the index is unavailable"
          },
          "405": {
            "description": "Unsupported method"
          }
        }
      },
      "options": {
        "operationId": "listPublishedDocumentsOptions",
        "summary": "Public CORS preflight",
        "responses": {
          "204": {
            "description": "GET, HEAD and OPTIONS allowed"
          }
        }
      }
    },
    "/api/search": {
      "get": {
        "operationId": "searchPublishedContent",
        "summary": "Retrieve matching passages from the complete server-rendered publication",
        "description": "Deterministic BM25 lexical search. Results contain excerpts, citationUrl fragments and contentHash. Scores measure lexical relevance only. Empty results are valid. Follow next for pagination.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "es"
              ],
              "default": "en"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "section",
                "experience",
                "education",
                "technology",
                "blog",
                "project",
                "decision"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 10
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 10000,
              "default": 0
            }
          },
          {
            "name": "If-None-Match",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "ETag from an earlier request. Matching content returns 304."
          }
        ],
        "responses": {
          "200": {
            "description": "Matching published passages",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "version",
                    "items",
                    "matched"
                  ],
                  "properties": {
                    "version": {
                      "type": "string"
                    },
                    "matched": {
                      "type": "integer"
                    },
                    "next": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "url",
                          "citationUrl",
                          "excerpt",
                          "contentHash"
                        ],
                        "properties": {
                          "url": {
                            "type": "string"
                          },
                          "citationUrl": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "heading": {
                            "type": "string"
                          },
                          "excerpt": {
                            "type": "string"
                          },
                          "contentHash": {
                            "type": "string"
                          },
                          "contentLanguage": {
                            "type": "string"
                          },
                          "readUrl": {
                            "type": "string",
                            "description": "Read only the matching section to reduce transferred content."
                          }
                        }
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "400": {
            "description": "Invalid query",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "304": {
            "description": "Unchanged ETag",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "503": {
            "description": "Search index unavailable; retry later",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string"
                },
                "description": "Retry delay in seconds when supplied."
              }
            }
          },
          "405": {
            "description": "Unsupported method",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "head": {
        "operationId": "searchPublishedContentHeaders",
        "summary": "The GET response headers without a body",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "es"
              ],
              "default": "en"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "section",
                "experience",
                "education",
                "technology",
                "blog",
                "project",
                "decision"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 10
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 10000,
              "default": 0
            }
          },
          {
            "name": "If-None-Match",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "ETag from an earlier request. Matching content returns 304."
          }
        ],
        "responses": {
          "200": {
            "description": "Matching published passages",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "400": {
            "description": "Invalid query"
          },
          "304": {
            "description": "Unchanged ETag",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "503": {
            "description": "Search index unavailable; retry later",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string"
                },
                "description": "Retry delay in seconds when supplied."
              }
            }
          },
          "405": {
            "description": "Unsupported method"
          }
        }
      },
      "options": {
        "operationId": "searchPublishedContentOptions",
        "summary": "Public CORS preflight",
        "responses": {
          "204": {
            "description": "GET, HEAD and OPTIONS allowed"
          }
        }
      }
    },
    "/api/ai-profile": {
      "get": {
        "operationId": "getAiProfile",
        "summary": "Read the published professional profile snapshot",
        "responses": {
          "200": {
            "description": "Person, experience, education, skills, technologies, duties and publication provenance"
          },
          "405": {
            "description": "Unsupported method"
          }
        }
      }
    },
    "/api/publication": {
      "get": {
        "operationId": "getPublicationInventory",
        "summary": "Inspect build snapshot hashes and counts",
        "description": "Build-time snapshot, not a live audit. Live ISR pages can be newer. Compare versions and per-document hashes, then re-read canonical sources before citing.",
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "es"
              ],
              "default": "en"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 10000,
              "default": 0
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          },
          {
            "name": "If-None-Match",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "ETag from an earlier request. Matching content returns 304."
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated snapshot inventory",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "schemaVersion",
                    "locale",
                    "version",
                    "generatedAt",
                    "scope",
                    "hashAlgorithm",
                    "total",
                    "passages",
                    "offset",
                    "next",
                    "items"
                  ],
                  "properties": {
                    "schemaVersion": {
                      "const": 1
                    },
                    "locale": {
                      "type": "string"
                    },
                    "version": {
                      "type": "string",
                      "pattern": "^[a-f0-9]{64}$"
                    },
                    "generatedAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "scope": {
                      "type": "string"
                    },
                    "hashAlgorithm": {
                      "const": "sha256"
                    },
                    "total": {
                      "type": "integer"
                    },
                    "passages": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    },
                    "next": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "url",
                          "title",
                          "kind",
                          "language",
                          "contentHash",
                          "datePublished",
                          "dateModified",
                          "passages",
                          "representations"
                        ],
                        "properties": {
                          "url": {
                            "type": "string",
                            "format": "uri"
                          },
                          "title": {
                            "type": "string"
                          },
                          "kind": {
                            "type": "string"
                          },
                          "language": {
                            "type": "string"
                          },
                          "contentHash": {
                            "type": "string",
                            "pattern": "^[a-f0-9]{64}$"
                          },
                          "datePublished": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Date declared in the source, or null when unavailable."
                          },
                          "dateModified": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Date declared in the source, or null when unavailable."
                          },
                          "passages": {
                            "type": "integer"
                          },
                          "representations": {
                            "type": "object",
                            "required": [
                              "markdown",
                              "json"
                            ],
                            "properties": {
                              "markdown": {
                                "type": "string",
                                "format": "uri"
                              },
                              "json": {
                                "type": "string",
                                "format": "uri"
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "304": {
            "description": "Unchanged inventory",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "400": {
            "description": "Invalid query",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Snapshot unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string"
                },
                "description": "Retry delay in seconds when supplied."
              }
            }
          },
          "405": {
            "description": "Unsupported method",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "head": {
        "operationId": "getPublicationInventoryHeaders",
        "summary": "The GET response headers without a body",
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "es"
              ],
              "default": "en"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 10000,
              "default": 0
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          },
          {
            "name": "If-None-Match",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "ETag from an earlier request. Matching content returns 304."
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated snapshot inventory",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "304": {
            "description": "Unchanged inventory",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "400": {
            "description": "Invalid query"
          },
          "503": {
            "description": "Snapshot unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string"
                },
                "description": "Retry delay in seconds when supplied."
              }
            }
          },
          "405": {
            "description": "Unsupported method"
          }
        }
      },
      "options": {
        "operationId": "getPublicationInventoryOptions",
        "summary": "Public CORS preflight",
        "responses": {
          "204": {
            "description": "GET, HEAD and OPTIONS allowed"
          }
        }
      }
    },
    "/api/capabilities": {
      "get": {
        "operationId": "getPublicationCapabilities",
        "summary": "Read the same capability registry displayed on the homepage",
        "description": "Implementation declarations with evidence links. Not an independent audit or a guarantee of indexing, ranking or citation.",
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "es"
              ],
              "default": "en"
            }
          },
          {
            "name": "If-None-Match",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "ETag from an earlier request. Matching content returns 304."
          }
        ],
        "responses": {
          "200": {
            "description": "Capabilities grouped by purpose",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "schemaVersion",
                    "locale",
                    "statusMeaning",
                    "scope",
                    "groups"
                  ],
                  "properties": {
                    "schemaVersion": {
                      "const": 1
                    },
                    "locale": {
                      "type": "string"
                    },
                    "statusMeaning": {
                      "type": "string"
                    },
                    "scope": {
                      "type": "string"
                    },
                    "groups": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "title",
                          "items"
                        ],
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "items": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "required": [
                                "id",
                                "status",
                                "title",
                                "detail",
                                "evidence"
                              ],
                              "properties": {
                                "id": {
                                  "type": "string"
                                },
                                "status": {
                                  "const": "implemented"
                                },
                                "title": {
                                  "type": "string"
                                },
                                "detail": {
                                  "type": "string"
                                },
                                "evidence": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "required": [
                                      "href",
                                      "label"
                                    ],
                                    "properties": {
                                      "href": {
                                        "type": "string"
                                      },
                                      "label": {
                                        "type": "string"
                                      }
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "304": {
            "description": "Unchanged registry",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "400": {
            "description": "Unsupported locale",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "405": {
            "description": "Unsupported method",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "head": {
        "operationId": "getPublicationCapabilitiesHeaders",
        "summary": "The GET response headers without a body",
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "es"
              ],
              "default": "en"
            }
          },
          {
            "name": "If-None-Match",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "ETag from an earlier request. Matching content returns 304."
          }
        ],
        "responses": {
          "200": {
            "description": "Capabilities grouped by purpose",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "304": {
            "description": "Unchanged registry",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "400": {
            "description": "Unsupported locale"
          },
          "405": {
            "description": "Unsupported method"
          }
        }
      },
      "options": {
        "operationId": "getPublicationCapabilitiesOptions",
        "summary": "Public CORS preflight",
        "responses": {
          "204": {
            "description": "GET, HEAD and OPTIONS allowed"
          }
        }
      }
    },
    "/api/feed": {
      "get": {
        "operationId": "getArticleFeed",
        "summary": "Read published articles through JSON Feed, Atom or RSS",
        "description": "Stable aliases: /feed.json, /atom.xml, /rss.xml and their /es equivalents. JSON Feed and Atom retain the article body as plain Markdown source. RSS contains summaries. Paginated: default 20 articles, maximum 50. Follow Link rel=next, JSON Feed next_url or Atom next links.",
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "es"
              ],
              "default": "en"
            }
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "atom",
                "rss"
              ],
              "default": "json"
            }
          },
          {
            "name": "If-None-Match",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "ETag from an earlier request. Matching content returns 304."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 10000,
              "default": 0
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Article feed",
            "content": {
              "application/feed+json": {
                "schema": {
                  "type": "object"
                }
              },
              "application/atom+xml": {
                "schema": {
                  "type": "string"
                }
              },
              "application/rss+xml": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "304": {
            "description": "Unchanged feed",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "400": {
            "description": "Invalid query",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "405": {
            "description": "Unsupported method",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "head": {
        "operationId": "getArticleFeedHeaders",
        "summary": "The GET response headers without a body",
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "es"
              ],
              "default": "en"
            }
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "atom",
                "rss"
              ],
              "default": "json"
            }
          },
          {
            "name": "If-None-Match",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "ETag from an earlier request. Matching content returns 304."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 10000,
              "default": 0
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Article feed",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "304": {
            "description": "Unchanged feed",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "400": {
            "description": "Invalid query"
          },
          "405": {
            "description": "Unsupported method"
          }
        }
      },
      "options": {
        "operationId": "getArticleFeedOptions",
        "summary": "Public CORS preflight",
        "responses": {
          "204": {
            "description": "GET, HEAD and OPTIONS allowed"
          }
        }
      }
    },
    "/.well-known/api-catalog": {
      "get": {
        "operationId": "discoverPublicationApis",
        "summary": "RFC 9727 API catalog in Linkset format",
        "responses": {
          "200": {
            "description": "API links with machine and human documentation",
            "content": {
              "application/linkset+json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "linkset"
                  ],
                  "properties": {
                    "linkset": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "304": {
            "description": "Unchanged catalog",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "405": {
            "description": "Unsupported method",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "If-None-Match",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "ETag from an earlier request. Matching content returns 304."
          }
        ]
      },
      "head": {
        "operationId": "discoverPublicationApisHeaders",
        "summary": "The GET response headers without a body",
        "parameters": [
          {
            "name": "If-None-Match",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "ETag from an earlier request. Matching content returns 304."
          }
        ],
        "responses": {
          "200": {
            "description": "API links with machine and human documentation",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "304": {
            "description": "Unchanged catalog",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Opaque representation validator; send as If-None-Match."
              }
            }
          },
          "405": {
            "description": "Unsupported method"
          }
        }
      },
      "options": {
        "operationId": "discoverPublicationApisOptions",
        "summary": "Public CORS preflight",
        "responses": {
          "204": {
            "description": "GET, HEAD and OPTIONS allowed"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "PublishedDocument": {
        "type": "object",
        "required": [
          "schemaVersion",
          "url",
          "title",
          "language",
          "datePublished",
          "dateModified",
          "contentFormat",
          "content",
          "contentHash",
          "id",
          "description",
          "headings",
          "sections",
          "links",
          "structuredData",
          "provenance"
        ],
        "properties": {
          "schemaVersion": {
            "type": "integer",
            "const": 1
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "title": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "datePublished": {
            "type": [
              "string",
              "null"
            ],
            "description": "Date declared in the source, or null when unavailable."
          },
          "dateModified": {
            "type": [
              "string",
              "null"
            ],
            "description": "Date declared in the source, or null when unavailable."
          },
          "contentFormat": {
            "const": "text/markdown"
          },
          "content": {
            "type": "string"
          },
          "contentHash": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          },
          "id": {
            "type": "string",
            "format": "uri"
          },
          "description": {
            "type": "string"
          },
          "headings": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "level",
                "text",
                "url"
              ],
              "properties": {
                "level": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 6
                },
                "text": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "sections": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "heading",
                "level",
                "url",
                "content"
              ],
              "properties": {
                "heading": {
                  "type": "string"
                },
                "level": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 6
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "content": {
                  "type": "string"
                }
              }
            }
          },
          "links": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "text",
                "url"
              ],
              "properties": {
                "text": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "structuredData": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "provenance": {
            "type": "object",
            "required": [
              "method",
              "source",
              "hashAlgorithm",
              "hashScope",
              "sourceHTMLBytes",
              "contentBytes"
            ],
            "properties": {
              "method": {
                "type": "string"
              },
              "source": {
                "type": "string",
                "format": "uri"
              },
              "hashAlgorithm": {
                "const": "sha256"
              },
              "hashScope": {
                "type": "string"
              },
              "sourceHTMLBytes": {
                "type": "integer",
                "minimum": 0
              },
              "contentBytes": {
                "type": "integer",
                "minimum": 0
              }
            }
          }
        }
      },
      "PublishedPassage": {
        "type": "object",
        "required": [
          "schemaVersion",
          "url",
          "title",
          "language",
          "datePublished",
          "dateModified",
          "contentFormat",
          "content",
          "contentHash",
          "scope",
          "heading",
          "source"
        ],
        "properties": {
          "schemaVersion": {
            "type": "integer",
            "const": 1
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "title": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "datePublished": {
            "type": [
              "string",
              "null"
            ],
            "description": "Date declared in the source, or null when unavailable."
          },
          "dateModified": {
            "type": [
              "string",
              "null"
            ],
            "description": "Date declared in the source, or null when unavailable."
          },
          "contentFormat": {
            "const": "text/markdown"
          },
          "content": {
            "type": "string"
          },
          "contentHash": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          },
          "scope": {
            "const": "section"
          },
          "heading": {
            "type": "string"
          },
          "source": {
            "type": "object",
            "required": [
              "url",
              "contentHash"
            ],
            "properties": {
              "url": {
                "type": "string",
                "format": "uri"
              },
              "contentHash": {
                "type": "string",
                "pattern": "^[a-f0-9]{64}$"
              }
            }
          }
        }
      },
      "Problem": {
        "type": "object",
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "error"
        ],
        "properties": {
          "type": {
            "const": "about:blank"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "error": {
            "type": "string"
          }
        }
      }
    }
  },
  "jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema"
}
