{
  "openapi": "3.0.0",
  "info": {
    "title": "Asamano API",
    "version": "1.1.0",
    "description": "Access your box, item, and image data programmatically to build integrations, automations, and custom applications.",
    "contact": {
      "name": "Asamano Support",
      "email": "support@asamano.com",
      "url": "https://www.asamano.com/support"
    }
  },
  "servers": [
    { "url": "https://api.asamano.com", "description": "Production" }
  ],
  "security": [{ "BearerAuth": [] }],
  "paths": {
    "/api/v1/boxes": {
      "get": {
        "summary": "List boxes",
        "description": "Returns boxes for the authenticated organization. Draft boxes are excluded. Each box includes image_count and item_count. Use /api/v1/images?box_id=... or /api/v1/boxes/{id} to retrieve image URLs.",
        "operationId": "listBoxes",
        "parameters": [
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20, "minimum": 1, "maximum": 100 } },
          { "name": "cursor", "in": "query", "schema": { "type": "string" } },
          { "name": "updated_since", "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "search", "in": "query", "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Successful response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BoxList" } } } },
          "401": { "$ref": "#/components/responses/AuthError" },
          "403": { "$ref": "#/components/responses/Suspended" },
          "429": { "$ref": "#/components/responses/RateLimit" },
          "500": { "$ref": "#/components/responses/InternalError" }
        }
      }
    },
    "/api/v1/boxes/{id}": {
      "get": {
        "summary": "Get box detail",
        "description": "Returns a single box plus its items and images in one call.",
        "operationId": "getBox",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } },
          { "name": "include", "in": "query", "description": "Comma-separated. Default 'items'. Supported: items, images. Images are opt-in — use /api/v1/images for paginated image queries.", "schema": { "type": "string", "default": "items" } }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/BoxDetail" } } } } }
          },
          "404": { "description": "Box not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "$ref": "#/components/responses/AuthError" },
          "403": { "$ref": "#/components/responses/Suspended" },
          "429": { "$ref": "#/components/responses/RateLimit" }
        }
      }
    },
    "/api/v1/items": {
      "get": {
        "summary": "List items",
        "description": "Lists items across all boxes in the organization. Items may be AI-detected (with source_image_id) or manually added (source_image_id null).",
        "operationId": "listItems",
        "parameters": [
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20, "minimum": 1, "maximum": 100 } },
          { "name": "cursor", "in": "query", "schema": { "type": "string" } },
          { "name": "updated_since", "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "search", "in": "query", "schema": { "type": "string" } },
          { "name": "box_id", "in": "query", "schema": { "type": "string", "format": "uuid" } },
          { "name": "category", "in": "query", "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Successful response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ItemList" } } } },
          "401": { "$ref": "#/components/responses/AuthError" },
          "429": { "$ref": "#/components/responses/RateLimit" }
        }
      }
    },
    "/api/v1/images": {
      "get": {
        "summary": "List images",
        "description": "Lists images for boxes in the organization. Each image includes signed URLs for thumbnail (~256px) and display (~1024px). URLs expire after 1 hour — re-request rather than long-term caching.",
        "operationId": "listImages",
        "parameters": [
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20, "minimum": 1, "maximum": 100 } },
          { "name": "cursor", "in": "query", "schema": { "type": "string" } },
          { "name": "box_id", "in": "query", "schema": { "type": "string", "format": "uuid" } }
        ],
        "responses": {
          "200": { "description": "Successful response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ImageList" } } } },
          "401": { "$ref": "#/components/responses/AuthError" },
          "429": { "$ref": "#/components/responses/RateLimit" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": { "type": "http", "scheme": "bearer", "description": "API key in the format: asamano_live_<random_string>" }
    },
    "responses": {
      "AuthError": { "description": "Authentication error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "Suspended": { "description": "Organization suspended", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "RateLimit": { "description": "Rate limit exceeded", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "InternalError": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
    },
    "schemas": {
      "Box": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "title": { "type": "string" },
          "description": { "type": "string", "nullable": true },
          "qr_code": { "type": "string", "nullable": true },
          "location": {
            "type": "object",
            "properties": {
              "building": { "type": "string", "nullable": true },
              "room": { "type": "string", "nullable": true },
              "shelf": { "type": "string", "nullable": true }
            }
          },
          "tags": { "type": "array", "items": { "type": "string" } },
          "image_count": { "type": "integer" },
          "item_count": { "type": "integer" },
          "category": { "type": "string", "nullable": true },
          "owner": { "type": "string", "nullable": true },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" }
        }
      },
      "BoxDetail": {
        "allOf": [
          { "$ref": "#/components/schemas/Box" },
          {
            "type": "object",
            "properties": {
              "items": { "type": "array", "items": { "$ref": "#/components/schemas/Item" } },
              "images": { "type": "array", "items": { "$ref": "#/components/schemas/Image" } }
            }
          }
        ]
      },
      "BoxList": {
        "type": "object",
        "properties": {
          "data": { "type": "array", "items": { "$ref": "#/components/schemas/Box" } },
          "next_cursor": { "type": "string", "nullable": true }
        }
      },
      "Item": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "box_id": { "type": "string" },
          "source_image_id": { "type": "string", "nullable": true, "description": "References the box image this item was detected from. Null for manually added items." },
          "name": { "type": "string" },
          "description": { "type": "string", "nullable": true },
          "category": { "type": "string" },
          "tags": { "type": "array", "items": { "type": "string" } },
          "confidence": { "type": "number", "nullable": true },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" }
        }
      },
      "ItemList": {
        "type": "object",
        "properties": {
          "data": { "type": "array", "items": { "$ref": "#/components/schemas/Item" } },
          "next_cursor": { "type": "string", "nullable": true }
        }
      },
      "Image": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "box_id": { "type": "string" },
          "display_order": { "type": "integer" },
          "original_filename": { "type": "string", "nullable": true },
          "urls": {
            "type": "object",
            "description": "Signed URLs (1h TTL). Versions whose underlying file is missing are omitted.",
            "properties": {
              "thumbnail": { "type": "string", "format": "uri", "description": "~256px — list previews, grids" },
              "display": { "type": "string", "format": "uri", "description": "~1024px — default UI rendering" }
            }
          },
          "recommended": { "type": "string", "enum": ["display"] },
          "created_at": { "type": "string", "format": "date-time" }
        }
      },
      "ImageList": {
        "type": "object",
        "properties": {
          "data": { "type": "array", "items": { "$ref": "#/components/schemas/Image" } },
          "next_cursor": { "type": "string", "nullable": true }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": { "type": "string" },
          "message": { "type": "string" }
        }
      }
    }
  }
}
