{
  "openapi": "3.1.0",
  "info": {
    "title": "Omnicost Public Catalog API",
    "version": "1.0.0",
    "description": "Machine-readable construction cost catalog API for canonical items, vendor observations, public feeds, developer keys, and workspace plan access.",
    "contact": {
      "email": "jorge@pox.me",
      "url": "https://omnicost.com/"
    },
    "license": {
      "name": "Public read access - Terms of service",
      "url": "https://omnicost.com/terms"
    }
  },
  "servers": [
    {
      "url": "https://omnicost.com/api/v1",
      "description": "Production"
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API key",
        "description": "Use Authorization: Bearer omc_pub_xxx for public developer keys or omc_org_xxx for org keys."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "details": {
            "type": "string"
          },
          "retry_after_seconds": {
            "type": "integer",
            "minimum": 1
          }
        }
      },
      "Money": {
        "type": "object",
        "required": [
          "cents",
          "currency"
        ],
        "properties": {
          "cents": {
            "type": "integer"
          },
          "currency": {
            "type": "string",
            "example": "USD"
          }
        }
      },
      "CanonicalItem": {
        "type": "object",
        "required": [
          "id",
          "name",
          "vendor_count",
          "observation_count",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "ci_018f72ba"
          },
          "name": {
            "type": "string"
          },
          "unit": {
            "type": "string",
            "nullable": true,
            "example": "m3"
          },
          "cpv": {
            "type": "string",
            "nullable": true,
            "example": "44114000-2"
          },
          "category_id": {
            "type": "string",
            "nullable": true
          },
          "vendor_count": {
            "type": "integer",
            "minimum": 0
          },
          "observation_count": {
            "type": "integer",
            "minimum": 0
          },
          "median_price": {
            "type": "object",
            "nullable": true,
            "required": [
              "cents",
              "currency",
              "recorded_at"
            ],
            "properties": {
              "cents": {
                "type": "integer"
              },
              "currency": {
                "type": "string"
              },
              "recorded_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              }
            }
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "VendorObservation": {
        "type": "object",
        "required": [
          "vendor_sku_id",
          "source",
          "price",
          "unit",
          "observed_at"
        ],
        "properties": {
          "vendor_sku_id": {
            "type": "string",
            "example": "vsku_018f72ba"
          },
          "source": {
            "type": "object",
            "required": [
              "name",
              "region",
              "trust_score",
              "url"
            ],
            "properties": {
              "name": {
                "type": "string"
              },
              "region": {
                "type": "string",
                "nullable": true
              },
              "trust_score": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100
              },
              "url": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "price": {
            "$ref": "#/components/schemas/Money"
          },
          "unit": {
            "type": "string",
            "nullable": true
          },
          "observed_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "PriceHistoryPoint": {
        "type": "object",
        "required": [
          "recorded_at",
          "price_cents",
          "currency"
        ],
        "properties": {
          "recorded_at": {
            "type": "string",
            "format": "date-time"
          },
          "price_cents": {
            "type": "integer"
          },
          "currency": {
            "type": "string"
          }
        }
      },
      "ListItemsResponse": {
        "type": "object",
        "required": [
          "items",
          "cursor",
          "meta"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CanonicalItem"
            }
          },
          "cursor": {
            "type": "string",
            "nullable": true
          },
          "meta": {
            "$ref": "#/components/schemas/PublicApiMeta"
          }
        }
      },
      "ItemDetailResponse": {
        "type": "object",
        "required": [
          "item",
          "vendors",
          "price_history"
        ],
        "properties": {
          "item": {
            "$ref": "#/components/schemas/CanonicalItem"
          },
          "vendors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VendorObservation"
            }
          },
          "price_history": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PriceHistoryPoint"
            }
          }
        }
      },
      "SearchResponse": {
        "type": "object",
        "required": [
          "query",
          "results",
          "mode"
        ],
        "properties": {
          "query": {
            "type": "string"
          },
          "results": {
            "type": "array",
            "items": {
              "allOf": [
                {
                  "$ref": "#/components/schemas/CanonicalItem"
                },
                {
                  "type": "object",
                  "required": [
                    "score"
                  ],
                  "properties": {
                    "score": {
                      "type": "number",
                      "minimum": 0
                    }
                  }
                }
              ]
            }
          },
          "mode": {
            "type": "string",
            "enum": [
              "vector",
              "fallback_no_ai",
              "vector_no_match",
              "empty_embedding"
            ]
          }
        }
      },
      "PublicApiMeta": {
        "type": "object",
        "required": [
          "tier",
          "rate_limit_per_min"
        ],
        "properties": {
          "tier": {
            "type": "string",
            "enum": [
              "anon",
              "public_dev",
              "org"
            ]
          },
          "rate_limit_per_min": {
            "type": "integer"
          }
        }
      },
      "PricingTier": {
        "type": "object",
        "required": [
          "tier",
          "display_name",
          "price_usd_month",
          "rate_limit_per_min",
          "monthly_request_cap",
          "features"
        ],
        "properties": {
          "tier": {
            "type": "string",
            "enum": [
              "free"
            ]
          },
          "display_name": {
            "type": "string"
          },
          "price_usd_month": {
            "type": "number"
          },
          "rate_limit_per_min": {
            "type": "integer"
          },
          "monthly_request_cap": {
            "type": "integer"
          },
          "features": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "PricingResponse": {
        "type": "object",
        "required": [
          "tiers",
          "plan_url",
          "note",
          "docs"
        ],
        "properties": {
          "tiers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PricingTier"
            }
          },
          "plan_url": {
            "type": "string"
          },
          "note": {
            "type": "string"
          },
          "docs": {
            "type": "string"
          }
        }
      },
      "UsageResponse": {
        "type": "object",
        "required": [
          "tier",
          "rate_limit_per_min",
          "monthly_cap",
          "monthly_used",
          "monthly_remaining",
          "reset_at",
          "upgrade_url"
        ],
        "properties": {
          "tier": {
            "type": "string"
          },
          "rate_limit_per_min": {
            "type": "integer"
          },
          "monthly_cap": {
            "type": "integer"
          },
          "monthly_used": {
            "type": "integer"
          },
          "monthly_remaining": {
            "type": "integer"
          },
          "reset_at": {
            "type": "string",
            "format": "date-time"
          },
          "upgrade_url": {
            "type": "string"
          }
        }
      },
      "CreateDeveloperKeyRequest": {
        "type": "object",
        "required": [
          "email"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 255
          },
          "name": {
            "type": "string",
            "maxLength": 200
          }
        }
      },
      "CreateDeveloperKeyResponse": {
        "type": "object",
        "required": [
          "key",
          "rate_limit_per_min",
          "tier",
          "docs",
          "note"
        ],
        "properties": {
          "key": {
            "type": "string",
            "example": "omc_pub_xxxxxxxxxxxx"
          },
          "rate_limit_per_min": {
            "type": "integer"
          },
          "tier": {
            "type": "string",
            "example": "free"
          },
          "docs": {
            "type": "string"
          },
          "note": {
            "type": "string"
          }
        }
      },
      "RevokeKeyResponse": {
        "type": "object",
        "required": [
          "revoked",
          "id"
        ],
        "properties": {
          "revoked": {
            "type": "boolean"
          },
          "id": {
            "type": "string"
          }
        }
      }
    }
  },
  "paths": {
    "/items": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "operationId": "listCatalogItems",
        "summary": "List canonical catalog items",
        "description": "Returns canonical construction cost items with cursor pagination. Supports optional region and text query filters.",
        "parameters": [
          {
            "in": "query",
            "name": "region",
            "schema": {
              "type": "string",
              "enum": [
                "ES",
                "US",
                "AR",
                "MX",
                "CL",
                "CO",
                "PE",
                "BR",
                "GB",
                "EU",
                "LATAM"
              ]
            }
          },
          {
            "in": "query",
            "name": "q",
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of canonical catalog items.",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "Link": {
                "schema": {
                  "type": "string"
                },
                "description": "Cursor link for the next page."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListItemsResponse"
                }
              }
            }
          },
          "429": {
            "description": "The caller exceeded its per-minute or monthly limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/items/{id}": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "operationId": "getCatalogItem",
        "summary": "Get one canonical catalog item",
        "description": "Returns one canonical item with vendor observations and 90-day price history. Send Accept: text/markdown for an agent-readable rendering.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "ci_018f72ba"
          }
        ],
        "responses": {
          "200": {
            "description": "Canonical item, vendor observations, and price history.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemDetailResponse"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string",
                  "description": "Markdown rendering for LLM consumption."
                }
              }
            }
          },
          "404": {
            "description": "The item does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "The caller exceeded its per-minute or monthly limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/search": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "operationId": "searchCatalogItems",
        "summary": "Semantic catalog search",
        "description": "Vectorize-backed multilingual semantic search over canonical catalog items.",
        "parameters": [
          {
            "in": "query",
            "name": "q",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 256
            }
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer",
              "default": 10,
              "minimum": 1,
              "maximum": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Search results sorted by score.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResponse"
                }
              }
            }
          },
          "400": {
            "description": "The query is missing or too short.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "The caller exceeded its per-minute or monthly limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Search AI is temporarily unavailable or over budget.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/pricing": {
      "get": {
        "tags": [
          "Billing"
        ],
        "operationId": "listApiAccess",
        "summary": "List public API access limits",
        "responses": {
          "200": {
            "description": "Public developer-key limits and workspace plan URL.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PricingResponse"
                }
              }
            }
          }
        }
      }
    },
    "/usage": {
      "get": {
        "tags": [
          "Billing"
        ],
        "operationId": "getApiUsage",
        "summary": "Get current API key usage",
        "security": [
          {
            "BearerKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Current-month usage for the calling key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageResponse"
                }
              }
            }
          },
          "401": {
            "description": "A bearer API key is required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/keys/signup": {
      "post": {
        "tags": [
          "Keys"
        ],
        "operationId": "createDeveloperKey",
        "summary": "Create a free developer key",
        "description": "Issues a public developer API key. The plaintext key is returned only once.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDeveloperKeyRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Key issued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateDeveloperKeyResponse"
                }
              }
            }
          },
          "400": {
            "description": "The request body is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many signup attempts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/keys/revoke": {
      "post": {
        "tags": [
          "Keys"
        ],
        "operationId": "revokeDeveloperKey",
        "summary": "Revoke the calling developer key",
        "security": [
          {
            "BearerKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Key revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RevokeKeyResponse"
                }
              }
            }
          },
          "401": {
            "description": "A public developer bearer key is required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "The key was not found or is already revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/feeds/items.atom": {
      "get": {
        "tags": [
          "Feeds"
        ],
        "operationId": "getItemsAtomFeed",
        "summary": "Get the Atom delta feed",
        "responses": {
          "200": {
            "description": "Atom feed with the latest changed catalog items."
          }
        }
      }
    },
    "/feeds/items.rss": {
      "get": {
        "tags": [
          "Feeds"
        ],
        "operationId": "getItemsRssFeed",
        "summary": "Get the RSS delta feed",
        "responses": {
          "200": {
            "description": "RSS feed with the latest changed catalog items."
          }
        }
      }
    },
    "/feeds/region/{region}": {
      "get": {
        "tags": [
          "Feeds"
        ],
        "operationId": "getRegionAtomFeed",
        "summary": "Get a per-region Atom delta feed",
        "parameters": [
          {
            "in": "path",
            "name": "region",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Atom feed for one region."
          }
        }
      }
    }
  },
  "security": [
    {
      "BearerKey": []
    }
  ]
}