{
  "openapi": "3.1.0",
  "info": {
    "title": "Site Speed Labs API",
    "version": "1.0.0",
    "summary": "Run a plain-language website speed check, or fetch published pricing.",
    "description": "Speed checks are backed by Google PageSpeed Insights. A full run takes 10–90 seconds depending on the target site; clients should allow at least 120 seconds. All /api routes are rate limited to 15 requests per minute per IP. The same speed check is also exposed as an MCP tool at /api/mcp (Streamable HTTP).",
    "contact": {
      "url": "https://www.sitespeedlabs.com/contact"
    }
  },
  "servers": [
    {
      "url": "https://www.sitespeedlabs.com"
    }
  ],
  "paths": {
    "/api/audit.json": {
      "post": {
        "operationId": "checkSiteSpeed",
        "summary": "Run a speed check and return the plain-language summary",
        "description": "Returns the Lighthouse performance score, three Core Web Vitals (labelled as real-visitor field data or simulated lab data), and the three most valuable fixes in plain language. The remaining fixes are available by email via /api/audit-report.json.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "The page to check. A bare hostname is accepted and treated as https.",
                    "examples": [
                      "example.com",
                      "https://example.com/pricing"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The check ran.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "summary": {
                      "$ref": "#/components/schemas/AuditSummary"
                    },
                    "totalIssues": {
                      "type": "integer",
                      "description": "How many fixes were found in total."
                    },
                    "hiddenIssues": {
                      "type": "integer",
                      "description": "How many are not in `summary.issues` and are only in the emailed report."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Failure"
          },
          "429": {
            "description": "Either the per-IP rate limit (15/min) or the daily PageSpeed quota was hit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Failure"
                }
              }
            }
          },
          "502": {
            "$ref": "#/components/responses/Failure"
          },
          "503": {
            "$ref": "#/components/responses/Failure"
          },
          "504": {
            "$ref": "#/components/responses/Failure"
          }
        }
      }
    },
    "/api/audit-report.json": {
      "post": {
        "operationId": "emailFullReport",
        "summary": "Email the full report for a URL to an address",
        "description": "Re-runs the check server-side and emails every fix, ordered by value, to the given address. The address is stored as a contact. Only call this with an address the user has given you for this purpose.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url",
                  "email"
                ],
                "properties": {
                  "url": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The report was sent.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Failure"
          },
          "429": {
            "$ref": "#/components/responses/Failure"
          },
          "502": {
            "description": "The check ran and the address was saved, but the email could not be sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Failure"
                }
              }
            }
          }
        }
      }
    },
    "/api/pricing.json": {
      "get": {
        "operationId": "getPricing",
        "summary": "Published pricing as structured data",
        "responses": {
          "200": {
            "description": "The current tiers.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Failure": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "const": false
          },
          "message": {
            "type": "string",
            "description": "Plain-language explanation, safe to show a user."
          }
        }
      },
      "AuditSummary": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "The normalised URL that was checked."
          },
          "strategy": {
            "type": "string",
            "enum": [
              "mobile",
              "desktop"
            ]
          },
          "score": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "maximum": 100,
            "description": "Lighthouse performance score. Lab data; not what Google ranks on."
          },
          "scoreLabel": {
            "type": "string",
            "enum": [
              "good",
              "needs-improvement",
              "poor",
              "unknown"
            ]
          },
          "metricSource": {
            "type": "string",
            "enum": [
              "field",
              "lab"
            ],
            "description": "\"field\" means real Chrome visitors over 28 days (what Google ranks on). \"lab\" means a simulated run because the site lacks enough traffic for field data."
          },
          "metrics": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "lcp, inp or cls for field data; lcp, tbt or cls for lab."
                },
                "label": {
                  "type": "string",
                  "description": "Plain-language name, e.g. \"Loading speed\"."
                },
                "display": {
                  "type": "string",
                  "description": "Preformatted value, e.g. \"2.4s\"."
                },
                "rating": {
                  "type": "string",
                  "enum": [
                    "good",
                    "needs-improvement",
                    "poor",
                    "unknown"
                  ]
                },
                "explanation": {
                  "type": "string"
                }
              }
            }
          },
          "issues": {
            "type": "array",
            "description": "Fixes, worst first. In the summary, at most three.",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "Lighthouse audit id."
                },
                "title": {
                  "type": "string",
                  "description": "Plain-language statement of the problem."
                },
                "explanation": {
                  "type": "string",
                  "description": "Why it matters, in plain language."
                },
                "detail": {
                  "type": "string",
                  "description": "Lighthouse's own figure, e.g. \"Est savings of 1,608 KiB\"."
                },
                "savingsMs": {
                  "type": "number",
                  "description": "Estimated milliseconds saved by this fix alone. Savings across fixes overlap, so their sum is a ceiling, not a total."
                }
              }
            }
          },
          "fetchedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      }
    },
    "responses": {
      "Failure": {
        "description": "The request could not be completed. `message` is safe to show the user.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Failure"
            }
          }
        }
      }
    }
  }
}