{
  "openapi": "3.1.0",
  "info": {
    "title": "Stockful site content API",
    "version": "1.0.0",
    "summary": "Read-only JSON access to the public content of stockful.app.",
    "description": "A small, unauthenticated, read-only API over the public content of\nstockful.app: Stockful's published pricing, its FAQ, an index of every\npage (each with a Markdown URL), and the blog.\n\nThis API describes **the product**. It does not expose any merchant's\nstore data. Live inventory, forecasts and alerts for a specific Shopify\nstore come from Stockful's remote MCP server, which uses a per-store\nconnection URL created in the app - see https://docs.stockful.app/user-guide/mcp-server.\n\nEvery page on stockful.app also serves Markdown via content negotiation:\nsend `Accept: text/markdown` to any page URL, or fetch its `/index.md`\nsibling. Responses set `Vary: Accept`.",
    "contact": {
      "name": "Stockful support",
      "email": "support@stockful.app",
      "url": "https://stockful.app/contact"
    },
    "license": {
      "name": "Stockful Terms of Service",
      "url": "https://docs.stockful.app/policies/terms-of-service"
    }
  },
  "servers": [
    {
      "url": "https://stockful.app",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "Stockful developer resources",
    "url": "https://stockful.app/developers"
  },
  "tags": [
    {
      "name": "discovery",
      "description": "Finding your way around this API."
    },
    {
      "name": "product",
      "description": "Stockful's published plans and answers."
    },
    {
      "name": "content",
      "description": "Pages and blog posts, with Markdown URLs."
    }
  ],
  "paths": {
    "/api/v1/index.json": {
      "get": {
        "operationId": "getApiIndex",
        "tags": [
          "discovery"
        ],
        "summary": "Discovery document: product facts, when to use Stockful, and every other endpoint in this API.",
        "description": "Start here. Returns product-level facts about Stockful, explicit guidance on when an agent should and should not use it, the full endpoint catalogue, and the error format.",
        "responses": {
          "200": {
            "description": "The discovery document.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiIndex"
                }
              }
            }
          },
          "404": {
            "description": "No such resource. The body names the endpoint index to try instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Only GET is supported on this API.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header rules out every representation this endpoint can produce.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/pricing.json": {
      "get": {
        "operationId": "getPricing",
        "tags": [
          "product"
        ],
        "summary": "Stockful's published plans, monthly prices in USD, tracked-SKU and location limits, overage rates and trial length.",
        "description": "Stockful's published pricing: one entry per plan with its monthly price in USD, tracked-SKU allowance and location allowance, plus overage rates and the trial length. Prices are billed through the Shopify App Store. Every feature is on every plan; plans differ only by limits.",
        "responses": {
          "200": {
            "description": "Current published pricing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Pricing"
                }
              }
            }
          },
          "404": {
            "description": "No such resource. The body names the endpoint index to try instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Only GET is supported on this API.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header rules out every representation this endpoint can produce.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/faq.json": {
      "get": {
        "operationId": "getFaq",
        "tags": [
          "product"
        ],
        "summary": "Frequently asked questions about Stockful, grouped by topic, as question and answer pairs.",
        "description": "The questions and answers published on stockful.app/faq, grouped by topic (getting started, Stocky, pricing, features and AI).",
        "responses": {
          "200": {
            "description": "Grouped question and answer pairs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Faq"
                }
              }
            }
          },
          "404": {
            "description": "No such resource. The body names the endpoint index to try instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Only GET is supported on this API.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header rules out every representation this endpoint can produce.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/pages.json": {
      "get": {
        "operationId": "listPages",
        "tags": [
          "content"
        ],
        "summary": "Every page on stockful.app with its locale, title, meta description, HTML URL and Markdown URL.",
        "description": "Every page the site builds, in every locale, with its title, meta description, canonical HTML URL and Markdown URL. Use this to crawl the site in one request instead of following links.",
        "responses": {
          "200": {
            "description": "The full page index.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageIndex"
                }
              }
            }
          },
          "404": {
            "description": "No such resource. The body names the endpoint index to try instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Only GET is supported on this API.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header rules out every representation this endpoint can produce.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/posts.json": {
      "get": {
        "operationId": "listBlogPosts",
        "tags": [
          "content"
        ],
        "summary": "Published Stockful blog posts, newest first, with title, description, publication date, tags and Markdown URL.",
        "description": "Published blog posts, newest first. Future-dated posts are excluded until their publication date. Each entry links to the post's full Markdown.",
        "responses": {
          "200": {
            "description": "The blog index.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostList"
                }
              }
            }
          },
          "404": {
            "description": "No such resource. The body names the endpoint index to try instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Only GET is supported on this API.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header rules out every representation this endpoint can produce.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/posts/{slug}.json": {
      "get": {
        "operationId": "getBlogPost",
        "tags": [
          "content"
        ],
        "summary": "One published blog post by slug: metadata, tags, reading time, and the URL of its full Markdown text.",
        "description": "Metadata for one published blog post. The post's full text is served as Markdown at the returned `markdownUrl`.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "The post's slug, as returned by listBlogPosts. Matches the URL segment after /blog/.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9-]+$",
              "enum": [
                "abc-analysis-shopify-inventory",
                "calculate-safety-stock-shopify",
                "demand-forecasting-shopify-guide",
                "how-much-safety-stock-shopify",
                "inventory-planner-vs-stockful",
                "inventory-velocity-shopify-stores",
                "multi-location-shopify-inventory-management",
                "overstock-cash-tied-up-shopify-inventory",
                "prepare-shopify-inventory-bfcm-2026",
                "reorder-point-formula-problems-dtc-shopify",
                "reorder-points-shopify-stores",
                "reorder-recommendations-to-shopify-purchase-order",
                "replace-stocky-replenishment-transfers-shopify",
                "sell-through-rate-shopify",
                "shopify-180-day-inventory-history-limit",
                "shopify-cycle-counts-inventory",
                "shopify-inventory-mcp-server-claude-chatgpt",
                "shopify-inventory-reports-missing",
                "shopify-inventory-transfers-incoming-stock",
                "shopify-inventory-valuation",
                "spot-clear-dead-stock-shopify",
                "spot-dead-stock-before-it-happens-shopify",
                "stockful-ai-inventory-assistant-shopify",
                "stockful-demand-forecasting-upgrade",
                "stockful-shopify-flow-integration",
                "stockful-shopify-inventory-reporting-engine",
                "stockful-shopify-storefront-inventory-badges-metafields",
                "stocky-export-checklist-before-shutdown",
                "stocky-removed-from-shopify-what-merchants-need-to-do-now",
                "stocky-vs-shopify-native-inventory-app",
                "true-cost-of-stockouts-shopify",
                "what-sell-through-rate-tells-you-shopify"
              ],
              "examples": [
                "abc-analysis-shopify-inventory",
                "calculate-safety-stock-shopify",
                "demand-forecasting-shopify-guide"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The post's metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Post"
                }
              }
            }
          },
          "404": {
            "description": "No such resource. The body names the endpoint index to try instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Only GET is supported on this API.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header rules out every representation this endpoint can produce.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "description": "A machine-readable error. Every non-2xx response uses this shape.",
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "status"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable, machine-readable error code. Match on this, not on `message`.",
                "enum": [
                  "not_found",
                  "method_not_allowed",
                  "not_acceptable",
                  "internal_error"
                ]
              },
              "message": {
                "type": "string",
                "description": "Human-readable description of what went wrong."
              },
              "hint": {
                "type": "string",
                "description": "How to resolve it - usually the URL to try instead."
              },
              "documentation": {
                "type": "string",
                "format": "uri",
                "description": "Where the behaviour of this API is documented."
              },
              "status": {
                "type": "integer",
                "description": "The HTTP status code, repeated in the body."
              }
            }
          }
        }
      },
      "WhenToUse": {
        "type": "array",
        "description": "Concrete jobs Stockful is the right tool for, phrased so an agent can pattern-match a user request against them.",
        "items": {
          "type": "string"
        }
      },
      "ApiIndex": {
        "type": "object",
        "required": [
          "name",
          "version",
          "product",
          "endpoints"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "version": {
            "type": "string",
            "description": "Semantic version of this API."
          },
          "description": {
            "type": "string"
          },
          "documentation": {
            "type": "string",
            "format": "uri"
          },
          "openapi": {
            "type": "string",
            "format": "uri"
          },
          "llmsTxt": {
            "type": "string",
            "format": "uri"
          },
          "product": {
            "$ref": "#/components/schemas/Product"
          },
          "endpoints": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EndpointDoc"
            }
          },
          "errors": {
            "type": "object",
            "description": "How errors are shaped, with a worked example.",
            "properties": {
              "format": {
                "type": "string"
              },
              "example": {
                "$ref": "#/components/schemas/Error"
              }
            }
          }
        }
      },
      "EndpointDoc": {
        "type": "object",
        "required": [
          "operationId",
          "method",
          "path",
          "url",
          "summary"
        ],
        "properties": {
          "operationId": {
            "type": "string",
            "description": "Matches the operationId in this OpenAPI document."
          },
          "method": {
            "type": "string",
            "enum": [
              "GET"
            ]
          },
          "path": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "summary": {
            "type": "string"
          }
        }
      },
      "Product": {
        "type": "object",
        "required": [
          "name",
          "url",
          "platform",
          "whenToUse"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "description": {
            "type": "string"
          },
          "platform": {
            "type": "string",
            "enum": [
              "Shopify"
            ]
          },
          "appStoreListing": {
            "type": "string",
            "format": "uri"
          },
          "documentation": {
            "type": "string",
            "format": "uri"
          },
          "documentationIndex": {
            "type": "string",
            "format": "uri",
            "description": "llms.txt index of the documentation site."
          },
          "supportEmail": {
            "type": "string",
            "format": "email"
          },
          "developerResources": {
            "type": "string",
            "format": "uri"
          },
          "liveStoreData": {
            "$ref": "#/components/schemas/LiveStoreData"
          },
          "whenToUse": {
            "$ref": "#/components/schemas/WhenToUse"
          },
          "whenNotToUse": {
            "$ref": "#/components/schemas/WhenToUse"
          }
        }
      },
      "LiveStoreData": {
        "type": "object",
        "description": "How to reach a specific store's live inventory. Not part of this API.",
        "required": [
          "protocol",
          "documentation"
        ],
        "properties": {
          "protocol": {
            "type": "string",
            "enum": [
              "mcp"
            ]
          },
          "documentation": {
            "type": "string",
            "format": "uri"
          },
          "connectionUrlExample": {
            "type": "string",
            "description": "Placeholder form of a connection URL. The real one is minted per store inside the app and contains a secret token."
          },
          "note": {
            "type": "string"
          }
        }
      },
      "Plan": {
        "type": "object",
        "required": [
          "id",
          "name",
          "monthlyPrice",
          "currency",
          "limits"
        ],
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "starter"
            ]
          },
          "name": {
            "type": "string",
            "examples": [
              "Starter"
            ]
          },
          "description": {
            "type": "string"
          },
          "monthlyPrice": {
            "type": "number",
            "examples": [
              19.99
            ]
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD"
            ]
          },
          "limits": {
            "type": "object",
            "required": [
              "trackedSkus",
              "locations"
            ],
            "properties": {
              "trackedSkus": {
                "type": "integer",
                "description": "Tracked variants included in the plan."
              },
              "locations": {
                "type": "integer",
                "description": "Shopify locations included in the plan."
              }
            }
          }
        }
      },
      "Overage": {
        "type": "object",
        "required": [
          "id",
          "price",
          "currency",
          "per"
        ],
        "properties": {
          "id": {
            "type": "string",
            "enum": [
              "additional-skus",
              "additional-locations"
            ]
          },
          "price": {
            "type": "number"
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD"
            ]
          },
          "per": {
            "type": "string",
            "description": "The unit the price applies to."
          },
          "description": {
            "type": "string"
          }
        }
      },
      "Pricing": {
        "type": "object",
        "required": [
          "plans",
          "currency",
          "trial"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD"
            ]
          },
          "billing": {
            "type": "string"
          },
          "trial": {
            "type": "object",
            "required": [
              "days"
            ],
            "properties": {
              "days": {
                "type": "integer",
                "examples": [
                  14
                ]
              },
              "description": {
                "type": "string"
              }
            }
          },
          "featureGating": {
            "type": "string"
          },
          "plans": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Plan"
            }
          },
          "overages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Overage"
            }
          },
          "includedOnEveryPlan": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "Faq": {
        "type": "object",
        "required": [
          "groups"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "totalQuestions": {
            "type": "integer"
          },
          "groups": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "title",
                "items"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "items": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "question",
                      "answer"
                    ],
                    "properties": {
                      "question": {
                        "type": "string"
                      },
                      "answer": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "Page": {
        "type": "object",
        "required": [
          "path",
          "url",
          "markdownUrl",
          "locale",
          "title"
        ],
        "properties": {
          "path": {
            "type": "string",
            "examples": [
              "/pricing"
            ]
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "markdownUrl": {
            "type": "string",
            "format": "uri",
            "description": "The same page as Markdown."
          },
          "locale": {
            "type": "string",
            "enum": [
              "en",
              "de",
              "es",
              "fr"
            ]
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "section": {
            "type": "string",
            "description": "Coarse grouping: home, product, comparison, blog, company."
          }
        }
      },
      "PageIndex": {
        "type": "object",
        "required": [
          "total",
          "pages"
        ],
        "properties": {
          "total": {
            "type": "integer"
          },
          "generatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "pages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Page"
            }
          }
        }
      },
      "Post": {
        "type": "object",
        "required": [
          "slug",
          "title",
          "url",
          "markdownUrl",
          "datePublished"
        ],
        "properties": {
          "slug": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "datePublished": {
            "type": "string",
            "format": "date"
          },
          "author": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "readingMinutes": {
            "type": "integer"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "markdownUrl": {
            "type": "string",
            "format": "uri"
          },
          "apiUrl": {
            "type": "string",
            "format": "uri"
          },
          "note": {
            "type": "string"
          }
        }
      },
      "PostList": {
        "type": "object",
        "required": [
          "total",
          "posts"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "total": {
            "type": "integer"
          },
          "posts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Post"
            }
          }
        }
      }
    }
  }
}
