{
  "openapi": "3.1.0",
  "info": {
    "title": "Layers site API",
    "version": "1.0.0",
    "summary": "Public, unauthenticated endpoints served by www.uselayers.com and the machine-readable files that describe the site to agents.",
    "description": "The Layers marketing site exposes a small set of public endpoints for its\nnewsletter, gated content, live counters and the arcade game on the 404 page,\nplus the discovery documents an agent needs to work with Layers.\n\nNo authentication is required for any operation in this document. The Layers\nproduct API — search, browse, catalog and merchandising — is a separate,\nauthenticated surface documented at https://docs.uselayers.com/api-reference/browse and\nexposed to agents over MCP at https://www.uselayers.com/.well-known/mcp.\n\nErrors are always JSON. Every error body carries a stable `error.code`, a human\n`error.message`, an actionable `error.hint`, and the RFC 9457 problem fields\n(`type`, `title`, `status`, `detail`).",
    "termsOfService": "https://docs.uselayers.com/legal/terms-of-use",
    "contact": {
      "name": "Building Blocks For eCommerce, Inc. support",
      "email": "support@uselayers.com",
      "url": "https://www.uselayers.com/contact"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://docs.uselayers.com/legal/terms-of-use"
    }
  },
  "externalDocs": {
    "description": "Layers developer hub and product API reference",
    "url": "https://docs.uselayers.com/developers/overview"
  },
  "servers": [
    {
      "url": "https://www.uselayers.com",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Discovery",
      "description": "Machine-readable descriptions of the site."
    },
    {
      "name": "Site",
      "description": "Live values rendered on the marketing site."
    },
    {
      "name": "Subscriptions",
      "description": "Newsletter and gated content delivery."
    },
    {
      "name": "Arcade",
      "description": "The Arkanoid game and leaderboard on the 404 page."
    }
  ],
  "paths": {
    "/openapi.json": {
      "get": {
        "operationId": "getOpenApiDocument",
        "tags": [
          "Discovery"
        ],
        "summary": "Get this OpenAPI document",
        "description": "Returns the OpenAPI 3.1 description of the public Layers site API. Also available as YAML at /openapi.yaml.",
        "responses": {
          "200": {
            "description": "The OpenAPI document.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "operationId": "getLlmsTxt",
        "tags": [
          "Discovery"
        ],
        "summary": "Get the llms.txt site overview",
        "description": "Plain-text summary of what Layers is, who it is for, and where the rest of the machine-readable resources live.",
        "responses": {
          "200": {
            "description": "The llms.txt document.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/sitemap.xml": {
      "get": {
        "operationId": "getSitemap",
        "tags": [
          "Discovery"
        ],
        "summary": "Get the XML sitemap",
        "description": "Lists every indexable URL on the marketing site.",
        "responses": {
          "200": {
            "description": "A urlset sitemap.",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/mcp": {
      "get": {
        "operationId": "getMcpServerCard",
        "tags": [
          "Discovery"
        ],
        "summary": "Get the MCP server card",
        "description": "Returns the Model Context Protocol server card for Layers: transport, endpoint URLs, capabilities and the OAuth metadata needed to connect.",
        "responses": {
          "200": {
            "description": "The MCP server card.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpServerCard"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "callSiteMcpServer",
        "tags": [
          "Discovery"
        ],
        "summary": "Call the read-only site MCP server",
        "description": "JSON-RPC 2.0 over Streamable HTTP. Supports `initialize`, `tools/list` and `tools/call` for read-only tools that describe the Layers site, its integrations, articles and agent endpoints. No authentication is required. Store data lives on the authenticated MCP server named in the server card.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonRpcRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A JSON-RPC response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          },
          "202": {
            "description": "A JSON-RPC notification was accepted."
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "405": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/.well-known/api-catalog": {
      "get": {
        "operationId": "getApiCatalog",
        "tags": [
          "Discovery"
        ],
        "summary": "Get the RFC 9727 API catalog",
        "description": "A linkset naming the service description, service documentation and OpenAPI document for this site.",
        "responses": {
          "200": {
            "description": "A linkset document.",
            "content": {
              "application/linkset+json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/agent-skills/index.json": {
      "get": {
        "operationId": "listAgentSkills",
        "tags": [
          "Discovery"
        ],
        "summary": "List published agent skills",
        "description": "Lists the Layers agent skills, each with its name, description, URL and content digest.",
        "responses": {
          "200": {
            "description": "The agent skills index.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/searches-served": {
      "get": {
        "operationId": "getSearchesServed",
        "tags": [
          "Site"
        ],
        "summary": "Get the running searches-served counter",
        "description": "Returns the cumulative number of searches Layers has served, as both a raw value and a display label. The counter is updated hourly.",
        "responses": {
          "200": {
            "description": "The current counter.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "count",
                    "label"
                  ],
                  "properties": {
                    "count": {
                      "type": "string",
                      "description": "Cumulative searches served, in billions, as a decimal string.",
                      "examples": [
                        "1.25"
                      ]
                    },
                    "label": {
                      "type": "string",
                      "description": "Display label rendered in the site footer.",
                      "examples": [
                        "1.250B searches served"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/footer-subscribe": {
      "post": {
        "operationId": "subscribeToNewsletter",
        "tags": [
          "Subscriptions"
        ],
        "summary": "Subscribe an email address to the Layers newsletter",
        "description": "Adds an email address to the Layers newsletter audience. Submit the address as `application/x-www-form-urlencoded`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "The email address to subscribe."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The address was subscribed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcknowledgedResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "405": {
            "$ref": "#/components/responses/Error"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          },
          "502": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/article-unlock": {
      "post": {
        "operationId": "unlockGatedArticle",
        "tags": [
          "Subscriptions"
        ],
        "summary": "Unlock a gated article and email the link",
        "description": "Subscribes the supplied email address and returns the canonical URL of the requested article. Submit as `application/x-www-form-urlencoded`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "slug"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "slug": {
                    "type": "string",
                    "description": "Article slug, as it appears in /articles/{slug}.",
                    "examples": [
                      "algolia-alternatives"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The article was unlocked.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/AcknowledgedResult"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "articleUrl": {
                          "type": "string",
                          "format": "uri"
                        },
                        "emailSent": {
                          "type": "boolean"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "405": {
            "$ref": "#/components/responses/Error"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/lead-magnet/{assetSlug}": {
      "parameters": [
        {
          "name": "assetSlug",
          "in": "path",
          "required": true,
          "description": "Slug of the downloadable asset.",
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "operationId": "downloadLeadMagnet",
        "tags": [
          "Subscriptions"
        ],
        "summary": "Redirect to a lead magnet PDF",
        "description": "Redirects to the PDF for the named asset. Follow the redirect to download the file.",
        "responses": {
          "302": {
            "description": "Redirect to the PDF.",
            "headers": {
              "Location": {
                "description": "Absolute URL of the PDF.",
                "schema": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "requestLeadMagnet",
        "tags": [
          "Subscriptions"
        ],
        "summary": "Request a lead magnet by email",
        "description": "Subscribes the supplied email address and emails a download link for the asset. Submit as `application/x-www-form-urlencoded`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The download is ready.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/AcknowledgedResult"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "downloadUrl": {
                          "type": "string"
                        },
                        "emailSent": {
                          "type": "boolean"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "405": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/404-leaderboard": {
      "get": {
        "operationId": "listArcadeLeaderboard",
        "tags": [
          "Arcade"
        ],
        "summary": "List the top arcade scores",
        "description": "Returns the top ten scores from the Arkanoid game on the Layers 404 page, highest first.",
        "responses": {
          "200": {
            "description": "The current leaderboard.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "leaders"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "leaders": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LeaderboardEntry"
                      }
                    }
                  }
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/404-leaderboard/session": {
      "post": {
        "operationId": "createArcadeSession",
        "tags": [
          "Arcade"
        ],
        "summary": "Start an arcade game session",
        "description": "Creates the server-side session a score submission must reference, and returns the scoring rules in force for it.",
        "responses": {
          "200": {
            "description": "A new session.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "sessionId",
                    "pointsPerBlock",
                    "maxSpeedBonus",
                    "speedBonusWindowMs"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "sessionId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "pointsPerBlock": {
                      "type": "integer"
                    },
                    "maxSpeedBonus": {
                      "type": "integer"
                    },
                    "speedBonusWindowMs": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/404-leaderboard/score": {
      "post": {
        "operationId": "submitArcadeScore",
        "tags": [
          "Arcade"
        ],
        "summary": "Submit a completed arcade game",
        "description": "Submits a finished game against a session created by createArcadeSession. Only completed games that cleared every block are accepted, and each session may be submitted once.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "sessionId",
                  "initials",
                  "score",
                  "durationMs",
                  "blocksBroken",
                  "totalBlocks",
                  "livesRemaining",
                  "won"
                ],
                "properties": {
                  "sessionId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "initials": {
                    "type": "string",
                    "pattern": "^[A-Za-z0-9]{3}$"
                  },
                  "score": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "durationMs": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1800000
                  },
                  "blocksBroken": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1200
                  },
                  "totalBlocks": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 1200
                  },
                  "livesRemaining": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 3
                  },
                  "won": {
                    "type": "boolean",
                    "const": true,
                    "description": "Only winning games can be submitted."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The score was recorded.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "scoreId",
                    "claimToken",
                    "rank",
                    "prizeEligible",
                    "leaders"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "scoreId": {
                      "type": "integer"
                    },
                    "claimToken": {
                      "type": "string",
                      "description": "Single-use token required by claimArcadePrize. Not retrievable later."
                    },
                    "rank": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "prizeEligible": {
                      "type": "boolean"
                    },
                    "leaders": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LeaderboardEntry"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "405": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/404-leaderboard/prize": {
      "post": {
        "operationId": "claimArcadePrize",
        "tags": [
          "Arcade"
        ],
        "summary": "Claim a prize for a top-three score",
        "description": "Records the shipping details for a top-three score, using the claim token returned by submitArcadeScore.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "scoreId",
                  "claimToken",
                  "name",
                  "email",
                  "shippingAddress"
                ],
                "properties": {
                  "scoreId": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "claimToken": {
                    "type": "string",
                    "minLength": 32,
                    "maxLength": 120
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 180
                  },
                  "socialHandle": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "shippingAddress": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 600
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The claim was saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcknowledgedResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "405": {
            "$ref": "#/components/responses/Error"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AcknowledgedResult": {
        "type": "object",
        "required": [
          "ok",
          "message"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "message": {
            "type": "string",
            "description": "Human-readable confirmation."
          }
        }
      },
      "LeaderboardEntry": {
        "type": "object",
        "description": "One ranked entry on the 404-page arcade leaderboard.",
        "required": [
          "rank",
          "initials",
          "score",
          "blocksBroken",
          "totalBlocks",
          "won",
          "createdAt"
        ],
        "properties": {
          "rank": {
            "type": "integer",
            "minimum": 1,
            "description": "Position on the board."
          },
          "initials": {
            "type": "string",
            "pattern": "^[A-Z0-9]{3}$",
            "description": "Three-character player initials."
          },
          "score": {
            "type": "integer",
            "minimum": 0,
            "description": "Final score."
          },
          "blocksBroken": {
            "type": "integer",
            "minimum": 0
          },
          "totalBlocks": {
            "type": "integer",
            "minimum": 1
          },
          "won": {
            "type": "boolean",
            "description": "True when every block was cleared."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the score was recorded."
          }
        }
      },
      "McpServerCard": {
        "type": "object",
        "description": "Model Context Protocol server card: how to reach the Layers MCP servers and what they require.",
        "required": [
          "protocolVersion",
          "serverInfo",
          "transport",
          "remotes"
        ],
        "properties": {
          "version": {
            "type": "string"
          },
          "protocolVersion": {
            "type": "string",
            "description": "MCP protocol revision this card describes."
          },
          "serverInfo": {
            "type": "object",
            "required": [
              "name",
              "version"
            ],
            "properties": {
              "name": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "version": {
                "type": "string"
              },
              "description": {
                "type": "string"
              },
              "websiteUrl": {
                "type": "string",
                "format": "uri"
              },
              "documentationUrl": {
                "type": "string",
                "format": "uri"
              }
            }
          },
          "transport": {
            "type": "object",
            "required": [
              "type",
              "endpoint"
            ],
            "properties": {
              "type": {
                "type": "string",
                "const": "streamable-http"
              },
              "endpoint": {
                "type": "string",
                "format": "uri"
              }
            }
          },
          "capabilities": {
            "type": "object"
          },
          "authentication": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string"
              },
              "scopes_supported": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "protectedResourceMetadata": {
                "type": "string",
                "format": "uri"
              },
              "authorizationServers": {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "remotes": {
            "type": "array",
            "description": "Every MCP endpoint Layers publishes.",
            "items": {
              "type": "object",
              "required": [
                "type",
                "url"
              ],
              "properties": {
                "type": {
                  "type": "string",
                  "const": "streamable-http"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "description": {
                  "type": "string"
                }
              }
            }
          },
          "wellKnown": {
            "type": "object",
            "description": "Related discovery documents.",
            "additionalProperties": {
              "type": "string",
              "format": "uri"
            }
          }
        }
      },
      "JsonRpcRequest": {
        "type": "object",
        "required": [
          "jsonrpc",
          "method"
        ],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {
            "description": "Omit for notifications.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              }
            ]
          },
          "method": {
            "type": "string",
            "description": "One of initialize, notifications/initialized, ping, tools/list, tools/call."
          },
          "params": {
            "type": "object"
          }
        }
      },
      "JsonRpcResponse": {
        "type": "object",
        "required": [
          "jsonrpc"
        ],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              }
            ]
          },
          "result": {
            "type": "object"
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "integer"
              },
              "message": {
                "type": "string"
              },
              "data": {
                "type": "object"
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "description": "Structured error body. Carries both the legacy `ok`/`message` fields and the RFC 9457 problem fields.",
        "required": [
          "ok",
          "message",
          "type",
          "title",
          "status",
          "detail",
          "error"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": false
          },
          "message": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "format": "uri",
            "description": "Stable URI identifying the error class, under https://www.uselayers.com/errors/."
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "hint",
              "documentation_url"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "invalid_request",
                  "not_found",
                  "method_not_allowed",
                  "rate_limited",
                  "internal_error",
                  "upstream_error",
                  "service_unavailable"
                ],
                "description": "Stable machine-readable error code."
              },
              "message": {
                "type": "string"
              },
              "hint": {
                "type": "string",
                "description": "How to resolve or retry the request."
              },
              "documentation_url": {
                "type": "string",
                "format": "uri",
                "default": "https://docs.uselayers.com/developers/overview"
              }
            }
          }
        }
      }
    },
    "responses": {
      "Error": {
        "description": "A structured JSON error.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}
