{
  "openapi": "3.1.0",
  "info": {
    "title": "YOOtraffic Content API",
    "version": "1.0.0",
    "summary": "Read-only access to YOOtraffic products, pricing, pages, and articles.",
    "description": "A public, unauthenticated, read-only API over everything yootraffic.com publishes:\nthe product catalog, the pricing model, the page index, page text as markdown, and the blog.\n\nIt answers questions about the product. It does not order traffic or manage a campaign;\nthat happens in the account application and is not exposed here.\n\nThe same operations are available as MCP tools over Streamable HTTP at https://yootraffic.com/mcp.",
    "contact": {
      "name": "YOOtraffic support",
      "email": "support@yootraffic.com",
      "url": "https://yootraffic.com/en/contact"
    },
    "license": {
      "name": "Free to read and cite, attribution appreciated",
      "identifier": "CC-BY-4.0"
    }
  },
  "servers": [
    {
      "url": "https://yootraffic.com",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "Developer documentation",
    "url": "https://yootraffic.com/en/developers"
  },
  "tags": [
    {
      "name": "catalog",
      "description": "Products and how they are priced."
    },
    {
      "name": "content",
      "description": "Pages, articles, and their markdown source."
    },
    {
      "name": "meta",
      "description": "Service description and capability discovery."
    }
  ],
  "paths": {
    "/api/v1": {
      "get": {
        "operationId": "getServiceIndex",
        "tags": [
          "meta"
        ],
        "summary": "Describe the API",
        "description": "Returns the API version, every available operation, and the URLs of the OpenAPI document, the MCP endpoint, and llms.txt. Start here when discovering the service.",
        "responses": {
          "200": {
            "description": "Service description.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceIndex"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products": {
      "get": {
        "operationId": "listProducts",
        "tags": [
          "catalog"
        ],
        "summary": "List products",
        "description": "Returns every YOOtraffic product with its traffic type, billing unit, entry price, and what is included. Use this to answer what the company sells and what each tool does.",
        "responses": {
          "200": {
            "description": "The full product catalog.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "products"
                  ],
                  "properties": {
                    "products": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Product"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products/{productId}": {
      "get": {
        "operationId": "getProduct",
        "tags": [
          "catalog"
        ],
        "summary": "Get one product",
        "description": "Returns a single product by its stable identifier.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "description": "Stable product identifier.",
            "schema": {
              "type": "string",
              "enum": [
                "traffic-generator",
                "serp-clicks",
                "link-clicker",
                "behavioral-factors"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The requested product.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "404": {
            "description": "No resource exists at the requested identifier.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/pricing": {
      "get": {
        "operationId": "getPricing",
        "tags": [
          "catalog"
        ],
        "summary": "Get the pricing model",
        "description": "Returns unit prices for every product together with the account terms (minimum deposit, refunds, balance expiry) and an explicit list of what the service does not deliver. Prices are in USD and billing is pay-as-you-go with no subscription.",
        "responses": {
          "200": {
            "description": "The pricing model.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Pricing"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/pages": {
      "get": {
        "operationId": "listPages",
        "tags": [
          "content"
        ],
        "summary": "List public pages",
        "description": "Returns every public page with its canonical URL, its markdown URL, and its title. Use it to find the page that answers a question before fetching the text.",
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Language to answer in. Defaults to English.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ru",
                "uk"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The page index.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "pages"
                  ],
                  "properties": {
                    "pages": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PageRef"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/content": {
      "get": {
        "operationId": "getPageContent",
        "tags": [
          "content"
        ],
        "summary": "Get a page as markdown",
        "description": "Returns the markdown representation of any public page, including blog posts and legal documents. The same text is served by the page URL itself under `Accept: text/markdown` or with `.md` appended.",
        "parameters": [
          {
            "name": "path",
            "in": "query",
            "required": true,
            "description": "Site path, with or without a locale prefix. Example: `/en/pricing`.",
            "schema": {
              "type": "string",
              "examples": [
                "/en/pricing",
                "/en/blog"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The page, as markdown.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageContent"
                }
              }
            }
          },
          "400": {
            "description": "A required query parameter is missing or malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No resource exists at the requested identifier.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/posts": {
      "get": {
        "operationId": "listBlogPosts",
        "tags": [
          "content"
        ],
        "summary": "List blog posts",
        "description": "Returns published articles, newest first, with title, excerpt, publication date, and the URL of the markdown version.",
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Language to answer in. Defaults to English.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ru",
                "uk"
              ],
              "default": "en"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "One-based page number.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Posts per page.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of posts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostList"
                }
              }
            }
          },
          "400": {
            "description": "A required query parameter is missing or malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/search": {
      "get": {
        "operationId": "searchSite",
        "tags": [
          "content"
        ],
        "summary": "Search pages and posts",
        "description": "Case-insensitive substring search over page titles, page descriptions, and article titles and excerpts. Returns the matching URLs and their markdown URLs so the text can be fetched directly.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Search terms.",
            "schema": {
              "type": "string",
              "minLength": 2
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Language to answer in. Defaults to English.",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "ru",
                "uk"
              ],
              "default": "en"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum results to return.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Search results, best match first.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResults"
                }
              }
            }
          },
          "400": {
            "description": "A required query parameter is missing or malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Machine-readable error code."
          },
          "message": {
            "type": "string",
            "description": "What went wrong, in one sentence."
          }
        }
      },
      "ProductPricing": {
        "type": "object",
        "required": [
          "model",
          "currency",
          "unitPrice",
          "rateVaries"
        ],
        "properties": {
          "model": {
            "type": "string",
            "enum": [
              "per-session",
              "per-click",
              "included"
            ],
            "description": "How the product is billed."
          },
          "currency": {
            "type": "string",
            "const": "USD"
          },
          "unitPrice": {
            "type": [
              "string",
              "null"
            ],
            "description": "Price of one billing unit, as a decimal string. Null when the product carries no separate charge."
          },
          "rateVaries": {
            "type": "boolean",
            "description": "True when `unitPrice` is an entry rate rather than the rate every unit is billed at."
          },
          "note": {
            "type": "string",
            "description": "Qualification a price alone would misstate."
          }
        }
      },
      "Product": {
        "type": "object",
        "required": [
          "id",
          "name",
          "summary",
          "trafficType",
          "billingUnit",
          "pricing",
          "includes",
          "url"
        ],
        "properties": {
          "id": {
            "type": "string",
            "enum": [
              "traffic-generator",
              "serp-clicks",
              "link-clicker",
              "behavioral-factors"
            ]
          },
          "name": {
            "type": "string"
          },
          "summary": {
            "type": "string"
          },
          "trafficType": {
            "type": "string",
            "enum": [
              "direct",
              "organic-search",
              "referral",
              "configuration"
            ],
            "description": "How the visit appears in the customer analytics."
          },
          "billingUnit": {
            "type": "string",
            "enum": [
              "session",
              "click",
              "none"
            ]
          },
          "pricing": {
            "$ref": "#/components/schemas/ProductPricing"
          },
          "includes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Product page."
          },
          "markdownUrl": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "AccountTerms": {
        "type": "object",
        "required": [
          "billing",
          "subscription",
          "currency",
          "minimumDeposit",
          "refundable"
        ],
        "properties": {
          "billing": {
            "type": "string",
            "const": "pay-as-you-go"
          },
          "subscription": {
            "type": "boolean"
          },
          "currency": {
            "type": "string",
            "const": "USD"
          },
          "minimumDeposit": {
            "type": "string"
          },
          "maximumDeposit": {
            "type": [
              "string",
              "null"
            ]
          },
          "balanceExpires": {
            "type": "boolean"
          },
          "refundable": {
            "type": "boolean"
          },
          "refundPolicy": {
            "type": "string"
          },
          "freeRegistration": {
            "type": "boolean"
          },
          "creditCardRequiredToRegister": {
            "type": "boolean"
          },
          "featureTiers": {
            "type": "boolean",
            "description": "False: every account has the same capabilities and pays only for volume."
          }
        }
      },
      "Pricing": {
        "type": "object",
        "required": [
          "currency",
          "products",
          "accountTerms",
          "includedEverywhere",
          "limitations"
        ],
        "properties": {
          "currency": {
            "type": "string",
            "const": "USD"
          },
          "products": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Product"
            }
          },
          "accountTerms": {
            "$ref": "#/components/schemas/AccountTerms"
          },
          "includedEverywhere": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "limitations": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What the service does not deliver, stated so an evaluation need not guess."
          },
          "humanReadableUrl": {
            "type": "string",
            "format": "uri"
          },
          "machineReadableUrl": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "PageRef": {
        "type": "object",
        "required": [
          "path",
          "locale",
          "url",
          "markdownUrl"
        ],
        "properties": {
          "path": {
            "type": "string",
            "description": "Locale-prefixed site path."
          },
          "locale": {
            "type": "string",
            "enum": [
              "en",
              "ru",
              "uk"
            ]
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "markdownUrl": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "PageContent": {
        "type": "object",
        "required": [
          "path",
          "locale",
          "url",
          "markdown"
        ],
        "properties": {
          "path": {
            "type": "string"
          },
          "locale": {
            "type": "string",
            "enum": [
              "en",
              "ru",
              "uk"
            ]
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "markdown": {
            "type": "string",
            "description": "The full page text in markdown."
          }
        }
      },
      "PostSummary": {
        "type": "object",
        "required": [
          "slug",
          "title",
          "url",
          "markdownUrl"
        ],
        "properties": {
          "slug": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "excerpt": {
            "type": "string"
          },
          "publishedAt": {
            "type": "string",
            "format": "date-time"
          },
          "locale": {
            "type": "string",
            "enum": [
              "en",
              "ru",
              "uk"
            ]
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "markdownUrl": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "PostList": {
        "type": "object",
        "required": [
          "posts",
          "page",
          "limit",
          "total"
        ],
        "properties": {
          "posts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PostSummary"
            }
          },
          "page": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "total": {
            "type": "integer"
          }
        }
      },
      "SearchResult": {
        "type": "object",
        "required": [
          "type",
          "title",
          "url",
          "markdownUrl"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "page",
              "post"
            ]
          },
          "title": {
            "type": "string"
          },
          "snippet": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "markdownUrl": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "SearchResults": {
        "type": "object",
        "required": [
          "query",
          "results"
        ],
        "properties": {
          "query": {
            "type": "string"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SearchResult"
            }
          }
        }
      },
      "ServiceIndex": {
        "type": "object",
        "required": [
          "name",
          "version",
          "operations"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "documentationUrl": {
            "type": "string",
            "format": "uri"
          },
          "openapiUrl": {
            "type": "string",
            "format": "uri"
          },
          "mcpUrl": {
            "type": "string",
            "format": "uri"
          },
          "llmsTxtUrl": {
            "type": "string",
            "format": "uri"
          },
          "operations": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "operationId",
                "method",
                "path",
                "summary"
              ],
              "properties": {
                "operationId": {
                  "type": "string"
                },
                "method": {
                  "type": "string"
                },
                "path": {
                  "type": "string"
                },
                "summary": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}
