{
  "openapi": "3.1.0",
  "info": {
    "title": "PriceMoved",
    "version": "0.2.0",
    "description": "PriceMoved is waitlist-only: monitoring, sign-in and checkout are not live yet. This API returns product facts and checks whether a site's robots.txt allows PriceMovedBot. No key. robots-check: about 10/min and 30/hour per network.",
    "contact": {
      "email": "digitalpromohub.support@gmail.com"
    }
  },
  "servers": [
    {
      "url": "https://pricemoved.com"
    }
  ],
  "paths": {
    "/api/product": {
      "get": {
        "operationId": "getProduct",
        "summary": "Product status, early pricing and links",
        "responses": {
          "200": {
            "description": "Product info",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "available_now": {
                      "type": "string"
                    },
                    "summary": {
                      "type": "string"
                    },
                    "pricing": {
                      "type": "object",
                      "properties": {
                        "heading": {
                          "type": "string"
                        },
                        "note": {
                          "type": "string"
                        },
                        "currency": {
                          "type": "string"
                        },
                        "early_pricing_subject_to_change": {
                          "type": "boolean"
                        },
                        "plans": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              },
                              "price_usd_per_month": {
                                "type": "number"
                              },
                              "pages": {
                                "type": "number"
                              },
                              "intervals": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              "email_alerts": {
                                "type": "boolean"
                              },
                              "slack_webhook": {
                                "type": "boolean"
                              },
                              "history_days": {
                                "type": "number"
                              }
                            },
                            "required": [
                              "id",
                              "name",
                              "price_usd_per_month",
                              "pages",
                              "intervals",
                              "slack_webhook",
                              "history_days"
                            ]
                          }
                        }
                      }
                    },
                    "crawler": {
                      "type": "object",
                      "properties": {
                        "user_agent": {
                          "type": "string"
                        },
                        "robots_token": {
                          "type": "string"
                        },
                        "respects_robots_txt": {
                          "type": "boolean"
                        },
                        "info_url": {
                          "type": "string"
                        }
                      }
                    },
                    "links": {
                      "type": "object",
                      "properties": {
                        "homepage": {
                          "type": "string"
                        },
                        "waitlist": {
                          "type": "string"
                        },
                        "privacy": {
                          "type": "string"
                        },
                        "terms": {
                          "type": "string"
                        }
                      }
                    },
                    "contact": {
                      "type": "string"
                    },
                    "version": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "name",
                    "status",
                    "available_now",
                    "pricing",
                    "links",
                    "version"
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "productPostNotAllowed",
        "summary": "Not supported",
        "responses": {
          "405": {
            "description": "method_not_allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Allow": {
                "schema": {
                  "type": "string",
                  "const": "GET, HEAD, OPTIONS"
                }
              }
            }
          }
        }
      }
    },
    "/api/robots-check": {
      "get": {
        "operationId": "robotsCheck",
        "summary": "Does the site's robots.txt allow PriceMovedBot to fetch this URL?",
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 2048,
              "pattern": "^https?://"
            },
            "description": "Public http(s) URL (domain names only, no IP addresses or ports)"
          }
        ],
        "responses": {
          "200": {
            "description": "Verdict",
            "headers": {
              "X-Cache": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "HIT",
                    "MISS"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string"
                    },
                    "robots_url": {
                      "type": "string"
                    },
                    "user_agent": {
                      "type": "string"
                    },
                    "verdict": {
                      "type": "string",
                      "enum": [
                        "allowed",
                        "disallowed",
                        "skipped"
                      ]
                    },
                    "allowed": {
                      "type": "boolean"
                    },
                    "note": {
                      "type": "string"
                    },
                    "checked_at": {
                      "type": "string"
                    },
                    "cached": {
                      "type": "boolean"
                    },
                    "version": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "url",
                    "robots_url",
                    "verdict",
                    "allowed",
                    "note",
                    "checked_at",
                    "cached",
                    "version"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "invalid_url",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "rate_limited or busy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "503": {
            "description": "temporarily_unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "robotsCheckPostNotAllowed",
        "summary": "Not supported",
        "responses": {
          "405": {
            "description": "method_not_allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Allow": {
                "schema": {
                  "type": "string",
                  "const": "GET, HEAD, OPTIONS"
                }
              }
            }
          }
        }
      }
    },
    "/health": {
      "get": {
        "operationId": "health",
        "summary": "Health and version",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "app": {
                      "type": "string"
                    },
                    "version": {
                      "type": "string"
                    },
                    "deployed_version": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "deployed_at": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "launch_mode": {
                      "type": "string"
                    },
                    "time": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "operationId": "mcp",
        "summary": "Remote MCP server (JSON-RPC 2.0 over Streamable HTTP, stateless)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "JSON-RPC 2.0 request, notification or batch (max 10, at most one tools/call; body max 65536 bytes)"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "JSON-RPC 2.0 response (or batch array)"
                }
              }
            }
          },
          "202": {
            "description": "Notification or client response accepted (empty body)"
          },
          "400": {
            "description": "Parse error, invalid request or protocol/header mismatch",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "JSON-RPC 2.0 response (or batch array)"
                }
              }
            }
          },
          "401": {
            "description": "Reserved (no keys exist today)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "JSON-RPC 2.0 response (or batch array)"
                }
              }
            }
          },
          "403": {
            "description": "Origin not allowed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "JSON-RPC 2.0 response (or batch array)"
                }
              }
            }
          },
          "404": {
            "description": "Method not found (2026-07-28 requests)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "JSON-RPC 2.0 response (or batch array)"
                }
              }
            }
          },
          "413": {
            "description": "Body too large",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "JSON-RPC 2.0 response (or batch array)"
                }
              }
            }
          },
          "429": {
            "description": "Too many MCP requests (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "JSON-RPC 2.0 response (or batch array)"
                }
              }
            }
          },
          "500": {
            "description": "Internal error"
          },
          "503": {
            "description": "Temporarily unavailable"
          }
        }
      },
      "get": {
        "operationId": "mcpGet",
        "summary": "Not supported (no SSE stream)",
        "responses": {
          "405": {
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "schema": {
                  "type": "string",
                  "const": "POST, OPTIONS"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "mcpDelete",
        "summary": "Not supported (no sessions)",
        "responses": {
          "405": {
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "schema": {
                  "type": "string",
                  "const": "POST, OPTIONS"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "invalid_url",
                  "rate_limited",
                  "busy",
                  "method_not_allowed",
                  "temporarily_unavailable",
                  "not_found",
                  "internal_error"
                ]
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      }
    }
  }
}