{
  "openapi": "3.1.0",
  "info": {
    "title": "Circuit Sherpa API",
    "version": "1.0.0",
    "summary": "Electronic part search, quantity-aware BOM pricing and price alerts, for your own scripts and AI agents.",
    "description": "Every endpoint authenticates with a per-customer API key (`Authorization: Bearer cs_sk_...`) created in Settings at https://circuitsherpa.com/settings#agent-access. A key acts AS the customer: the same plan limits apply as in the web app (Free: 10 searches/day, no BOM costing, no alerts; Pro/Team: unlimited search, BOM costing up to 500 lines, up to 20 active alerts). Keys have a `read` or `write` scope. Rate limit: 300 calls per key per hour. The same jobs are available as MCP tools at https://circuitsherpa.com/mcp and from the `circuitsherpa` CLI (`npx circuitsherpa --help`). Setup guide: https://circuitsherpa.com/docs/agents. Prices are USD from distributor APIs (Digi-Key, Mouser, Nexar network), cached up to 24 hours; purchases happen at the distributor.",
    "termsOfService": "https://circuitsherpa.com/terms",
    "contact": { "name": "Circuit Sherpa support", "email": "support@circuitsherpa.com", "url": "https://circuitsherpa.com/support" }
  },
  "servers": [{ "url": "https://circuitsherpa.com" }],
  "security": [{ "apiKey": [] }],
  "tags": [
    { "name": "account" },
    { "name": "parts", "description": "Search and part detail. Search counts toward the Free plan's daily quota." },
    { "name": "bom", "description": "Quantity-aware BOM costing and saved BOM history (Pro/Team)." },
    { "name": "alerts", "description": "Daily price alerts (Pro/Team, up to 20 active)." }
  ],
  "paths": {
    "/api/v1/me": {
      "get": {
        "tags": ["account"], "operationId": "getMe", "summary": "Who this key belongs to, plan limits, recent agent calls",
        "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Me" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/RateLimited" } }
      }
    },
    "/api/v1/parts": {
      "get": {
        "tags": ["parts"], "operationId": "searchParts", "summary": "Search parts by part number or keyword",
        "description": "Queries Digi-Key and Mouser live (and the Nexar network when configured; LCSC is not queried). Exact MPN matches are flagged. Counts toward the Free plan's 10 searches/day.",
        "parameters": [
          { "name": "q", "in": "query", "required": true, "schema": { "type": "string" }, "example": "STM32F103C8T6" },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 50, "default": 10 } }
        ],
        "responses": {
          "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SearchResponse" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "description": "Daily search limit (Free) or per-key rate limit reached", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "503": { "$ref": "#/components/responses/Outage" }
        }
      }
    },
    "/api/v1/parts/{mpn}": {
      "get": {
        "tags": ["parts"], "operationId": "getPart", "summary": "One part's live offers and recorded price history",
        "parameters": [
          { "name": "mpn", "in": "path", "required": true, "schema": { "type": "string" }, "example": "NE555PWR" },
          { "name": "history", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 30 }, "description": "Newest N recorded price points, returned oldest first" }
        ],
        "responses": {
          "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "required": ["part", "priceHistory"], "properties": { "part": { "$ref": "#/components/schemas/Part" }, "priceHistory": { "type": "array", "items": { "$ref": "#/components/schemas/PricePoint" } } } } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimited" }, "503": { "$ref": "#/components/responses/Outage" }
        }
      }
    },
    "/api/v1/bom/price": {
      "post": {
        "tags": ["bom"], "operationId": "priceBom", "summary": "Cost a BOM at build quantities and save it to history",
        "description": "Each line is matched to a part and priced at the price-break tier for its quantity across distributors, with MOQ and match warnings. The result is SAVED to BOM history (90-day retention; shared with the team by default on the Team plan). Pro or Team plan. Requires a write-scope key. If every distributor is unreachable the request fails with 503 and nothing is saved.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PriceBomRequest" } } } },
        "responses": {
          "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PricedBom" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/PlanOrScope" }, "429": { "$ref": "#/components/responses/RateLimited" }, "503": { "$ref": "#/components/responses/Outage" }
        }
      }
    },
    "/api/v1/bom/history": {
      "get": {
        "tags": ["bom"], "operationId": "listBomHistory", "summary": "Saved BOMs this account (and its team) can see",
        "parameters": [{ "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 50, "default": 20 } }],
        "responses": { "200": { "description": "OK (empty list on the Free plan)", "content": { "application/json": { "schema": { "type": "object", "required": ["history"], "properties": { "history": { "type": "array", "items": { "$ref": "#/components/schemas/BomSummary" } } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/RateLimited" } }
      }
    },
    "/api/v1/bom/{id}": {
      "get": {
        "tags": ["bom"], "operationId": "getBom", "summary": "Every costed line of one saved BOM",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "required": ["bom"], "properties": { "bom": { "$ref": "#/components/schemas/BomDetail" } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimited" } }
      }
    },
    "/api/v1/alerts": {
      "get": {
        "tags": ["alerts"], "operationId": "listAlerts", "summary": "All price alerts on this account",
        "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "required": ["alerts"], "properties": { "alerts": { "type": "array", "items": { "$ref": "#/components/schemas/Alert" } } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/RateLimited" } }
      },
      "post": {
        "tags": ["alerts"], "operationId": "createAlert", "summary": "Create a price alert",
        "description": "Checked once a day at 09:00 UTC against the lowest single-unit price across offers; emails once (and pushes to the iOS app), then stays triggered until deleted. Pro or Team; up to 20 active. Requires a write-scope key.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["mpn", "targetPrice"], "properties": { "mpn": { "type": "string" }, "targetPrice": { "type": "number", "exclusiveMinimum": 0, "description": "USD per unit" } } } } } },
        "responses": { "200": { "description": "Created", "content": { "application/json": { "schema": { "type": "object", "required": ["id", "mpn", "targetPrice"], "properties": { "id": { "type": "string" }, "mpn": { "type": "string" }, "targetPrice": { "type": "number" }, "checkedDailyAtUtc": { "type": "string" } } } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/PlanOrScope" }, "429": { "$ref": "#/components/responses/RateLimited" } }
      }
    },
    "/api/v1/alerts/{id}": {
      "get": {
        "tags": ["alerts"], "operationId": "getAlert", "summary": "One alert",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Alert" } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimited" } }
      },
      "delete": {
        "tags": ["alerts"], "operationId": "deleteAlert", "summary": "Permanently delete an alert (not undoable)",
        "description": "Destructive. Agents should show the alert (GET) and get the user's confirmation before calling this. Requires a write-scope key.",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Deleted", "content": { "application/json": { "schema": { "type": "object", "properties": { "deleted": { "type": "object", "properties": { "id": { "type": "string" }, "mpn": { "type": "string" } } } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/PlanOrScope" }, "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimited" } }
      }
    },
    "/api/v1/search": {
      "get": {
        "tags": ["parts"], "operationId": "teamBulkSearch", "summary": "Team plan bulk search (legacy endpoint)",
        "description": "The original Team-plan REST endpoint. Same results as /api/v1/parts but Team plan only and not quota-counted. Kept for existing integrations; new integrations should use /api/v1/parts.",
        "parameters": [
          { "name": "q", "in": "query", "required": true, "schema": { "type": "string" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 50, "default": 10 } }
        ],
        "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "results": { "type": "array", "items": { "$ref": "#/components/schemas/Part" } } } } } } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/PlanOrScope" }, "503": { "$ref": "#/components/responses/Outage" } }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": { "type": "http", "scheme": "bearer", "bearerFormat": "cs_sk_<40 hex>", "description": "Create and revoke keys at https://circuitsherpa.com/settings#agent-access. Scopes: read, write." }
    },
    "responses": {
      "Unauthorized": { "description": "Missing, unknown or revoked key. Carries `WWW-Authenticate: Bearer realm=\"circuitsherpa\"`.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "BadRequest": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "NotFound": { "description": "Not found, or not visible to this account", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "PlanOrScope": { "description": "The plan does not include this feature (body carries `upgradeUrl`), or the key lacks the write scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "RateLimited": { "description": "300 calls per key per hour exceeded", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "Outage": { "description": "Every distributor was unreachable. Nothing was saved; this is a Circuit Sherpa outage, not a statement about the part.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
    },
    "schemas": {
      "Error": { "type": "object", "required": ["error"], "properties": { "error": { "type": "string" }, "upgradeUrl": { "type": "string" }, "docs": { "type": "string" }, "createKeyAt": { "type": "string" } } },
      "Me": {
        "type": "object", "required": ["email", "plan", "limits", "key"],
        "properties": {
          "email": { "type": "string" }, "plan": { "type": "string", "enum": ["free", "pro", "team"] },
          "limits": { "type": "object" },
          "key": { "type": "object", "properties": { "id": { "type": ["string", "null"] }, "name": { "type": "string" }, "scopes": { "type": "array", "items": { "type": "string", "enum": ["read", "write"] } } } },
          "recentCalls": { "type": "array", "items": { "type": "object", "properties": { "action": { "type": "string" }, "surface": { "type": "string", "enum": ["mcp", "rest"] }, "ok": { "type": "boolean" }, "durationMs": { "type": "integer" }, "createdAt": { "type": "string" } } } }
        }
      },
      "PriceBreak": { "type": "object", "required": ["qty", "price"], "properties": { "qty": { "type": "integer" }, "price": { "type": "number" } } },
      "Offer": {
        "type": "object", "required": ["distributor", "price", "stock", "url", "sku"],
        "properties": { "distributor": { "type": "string" }, "price": { "type": "number", "description": "qty-1 unit price, USD" }, "stock": { "type": "integer" }, "url": { "type": "string" }, "sku": { "type": "string" }, "priceBreaks": { "type": "array", "items": { "$ref": "#/components/schemas/PriceBreak" } }, "moq": { "type": "integer" } }
      },
      "Part": {
        "type": "object", "required": ["mpn", "manufacturer", "description", "offers", "bestPrice", "totalStock"],
        "properties": { "mpn": { "type": "string" }, "manufacturer": { "type": "string" }, "description": { "type": "string" }, "category": { "type": "string" }, "offers": { "type": "array", "items": { "$ref": "#/components/schemas/Offer" } }, "bestPrice": { "type": "number" }, "totalStock": { "type": "integer" }, "datasheet": { "type": "string" }, "imageUrl": { "type": "string" }, "exactMatch": { "type": "boolean" } }
      },
      "SearchResponse": { "type": "object", "required": ["query", "results"], "properties": { "query": { "type": "string" }, "results": { "type": "array", "items": { "$ref": "#/components/schemas/Part" } }, "remaining": { "type": ["integer", "null"], "description": "Free searches left today; null on Pro/Team" } } },
      "PricePoint": { "type": "object", "required": ["distributor", "price", "recordedAt"], "properties": { "distributor": { "type": "string" }, "price": { "type": "number" }, "recordedAt": { "type": "string" } } },
      "PriceBomRequest": {
        "type": "object", "required": ["lines"],
        "properties": {
          "lines": { "type": "array", "minItems": 1, "maxItems": 500, "items": { "type": "object", "required": ["mpn"], "properties": { "mpn": { "type": "string" }, "qty": { "type": "integer", "minimum": 1, "default": 1 } } } },
          "name": { "type": "string", "maxLength": 120 },
          "saveToTeam": { "type": "boolean", "default": true, "description": "Team plan: share with the team library" }
        }
      },
      "BomLine": {
        "type": "object", "required": ["mpn", "qty", "found"],
        "properties": { "mpn": { "type": "string" }, "qty": { "type": "integer" }, "found": { "type": "boolean" }, "manufacturer": { "type": "string" }, "description": { "type": "string" }, "matchedMpn": { "type": "string" }, "exactMatch": { "type": "boolean" }, "matchWarning": { "type": "string" }, "unitPrice": { "type": "number" }, "tierQty": { "type": "integer" }, "moq": { "type": "integer" }, "moqWarning": { "type": "string" }, "distributor": { "type": "string" }, "bestPrice": { "type": "number" }, "lineCost": { "type": "number" }, "totalStock": { "type": "integer" }, "offers": { "type": "array", "items": { "$ref": "#/components/schemas/Offer" } }, "error": { "type": "string" } }
      },
      "PricedBom": {
        "type": "object", "required": ["bomId", "name", "partsCount", "foundCount", "totalCost", "results"],
        "properties": { "bomId": { "type": "string" }, "name": { "type": "string" }, "partsCount": { "type": "integer" }, "foundCount": { "type": "integer" }, "totalCost": { "type": "number", "description": "USD" }, "sharedWithTeam": { "type": "boolean" }, "results": { "type": "array", "items": { "$ref": "#/components/schemas/BomLine" } } }
      },
      "BomSummary": { "type": "object", "required": ["id", "name", "partsCount", "totalCost", "createdAt"], "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "partsCount": { "type": "integer" }, "totalCost": { "type": "number" }, "createdAt": { "type": "string" }, "shared": { "type": "boolean" }, "uploadedByEmail": { "type": ["string", "null"] }, "isMine": { "type": "boolean" } } },
      "BomDetail": { "type": "object", "required": ["id", "name", "partsCount", "totalCost", "createdAt", "results"], "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "partsCount": { "type": "integer" }, "totalCost": { "type": "number" }, "createdAt": { "type": "string" }, "results": { "type": "array", "items": { "$ref": "#/components/schemas/BomLine" } } } },
      "Alert": { "type": "object", "required": ["id", "mpn", "targetPrice", "triggered", "createdAt"], "properties": { "id": { "type": "string" }, "mpn": { "type": "string" }, "targetPrice": { "type": "number" }, "currentPrice": { "type": ["number", "null"] }, "triggered": { "type": "boolean" }, "lastChecked": { "type": ["string", "null"] }, "createdAt": { "type": "string" } } }
    }
  }
}
