{
  "openapi": "3.1.0",
  "info": {
    "title": "AuctFlow API",
    "version": "1.0.0",
    "description": "The AuctFlow API lets auction houses integrate their catalog, auctions, lots, and bids with external systems. Authentication uses Bearer tokens (API keys). Request sandbox credentials via info@auctflow.com. All responses are JSON. Rate limit: 100 requests per minute per key, enforced via RFC 9051 RateLimit-* headers and Retry-After on 429 responses. Versioning: URL-based (current: v1). Breaking changes are signaled via Deprecation and Sunset headers at least 6 months before removal. See https://auctflow.com/developers for the full versioning and deprecation policy. Base URL: https://auctflow.com",
    "contact": {
      "name": "AuctFlow Support",
      "email": "info@auctflow.com",
      "url": "https://auctflow.com/developers"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://auctflow.com/algemene-voorwaarden"
    },
    "x-deprecation-policy": {
      "versioning": "URL-based (current: v1, path prefix /api/v1/)",
      "backwardCompatibleChanges": "Added without warning — new optional fields, new endpoints, new enum values.",
      "breakingChanges": "Signaled via Deprecation header (RFC 8594) and Sunset header on deprecated endpoints, at least 6 months before removal.",
      "sunsetHeaderFormat": "HTTP date (RFC 7231), e.g. Sun, 31 May 2026 00:00:00 GMT",
      "policyUrl": "https://auctflow.com/developers/deprecation-policy"
    }
  },
  "servers": [
    {
      "url": "https://auctflow.com",
      "description": "Production"
    },
    {
      "url": "https://sandbox.auctflow.com",
      "description": "Sandbox — request access via info@auctflow.com"
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key issued by AuctFlow. Pass as: Authorization: Bearer <your-key>"
      }
    },
    "schemas": {
      "Auction": {
        "type": "object",
        "description": "An auction event containing lots that bidders can bid on.",
        "required": ["id", "title", "status", "type", "startTime", "endTime"],
        "properties": {
          "id": { "type": "string", "format": "uuid", "description": "Unique auction identifier", "readOnly": true },
          "title": { "type": "string", "description": "Auction title shown to bidders", "example": "Voorjaarsveiling 2026" },
          "status": { "type": "string", "enum": ["draft", "published", "live", "closed", "cancelled"], "description": "Current auction lifecycle state", "readOnly": true },
          "type": { "type": "string", "enum": ["live", "timed"], "description": "Live auctions close lot-by-lot in real time; timed auctions auto-close at a set end time." },
          "startTime": { "type": "string", "format": "date-time", "description": "When the auction opens for bidding (ISO 8601, UTC)" },
          "endTime": { "type": "string", "format": "date-time", "description": "When the auction closes (ISO 8601, UTC). Required for timed auctions." },
          "currency": { "type": "string", "description": "ISO 4217 currency code", "example": "EUR", "default": "EUR" },
          "language": { "type": "string", "description": "Primary language code", "example": "nl" },
          "lotCount": { "type": "integer", "description": "Total number of lots in this auction", "readOnly": true }
        }
      },
      "Lot": {
        "type": "object",
        "description": "A single item (kavel) within an auction that bidders can bid on.",
        "required": ["id", "auctionId", "lotNumber", "title", "startingPrice", "status"],
        "properties": {
          "id": { "type": "string", "format": "uuid", "description": "Unique lot identifier", "readOnly": true },
          "auctionId": { "type": "string", "format": "uuid", "description": "Parent auction ID" },
          "lotNumber": { "type": "integer", "description": "Sequential lot number within the auction", "example": 1 },
          "title": { "type": "string", "description": "Lot title", "example": "Volkswagen Golf 7 GTI 2018" },
          "description": { "type": "string", "description": "Detailed lot description" },
          "startingPrice": { "type": "number", "format": "float", "description": "Opening bid amount in the auction currency", "example": 5000 },
          "currentBid": { "type": "number", "format": "float", "description": "Highest bid so far", "readOnly": true },
          "reservePrice": { "type": "number", "format": "float", "description": "Minimum selling price (hidden from bidders)" },
          "status": { "type": "string", "enum": ["pending", "open", "sold", "unsold", "withdrawn"], "description": "Lot lifecycle state", "readOnly": true },
          "imageUrl": { "type": "string", "format": "uri", "description": "Primary image URL for the lot" },
          "attributes": { "type": "object", "description": "Custom key-value attributes (e.g. merk, model, bouwjaar)", "additionalProperties": { "type": "string" } },
          "bidCount": { "type": "integer", "description": "Total bids placed on this lot", "readOnly": true }
        }
      },
      "Bid": {
        "type": "object",
        "description": "A bid placed by a registered bidder on a specific lot.",
        "required": ["id", "lotId", "bidderId", "amount", "createdAt"],
        "properties": {
          "id": { "type": "string", "format": "uuid", "description": "Unique bid identifier", "readOnly": true },
          "lotId": { "type": "string", "format": "uuid", "description": "Lot the bid was placed on" },
          "bidderId": { "type": "string", "format": "uuid", "description": "Authenticated bidder who placed the bid" },
          "amount": { "type": "number", "format": "float", "description": "Bid amount in auction currency", "example": 5500 },
          "createdAt": { "type": "string", "format": "date-time", "description": "When the bid was placed (ISO 8601, UTC)", "readOnly": true },
          "isWinning": { "type": "boolean", "description": "Whether this is currently the winning bid", "readOnly": true }
        }
      },
      "BidRequest": {
        "type": "object",
        "description": "Request body for placing a bid on a lot.",
        "required": ["amount"],
        "properties": {
          "amount": { "type": "number", "format": "float", "description": "Bid amount in the auction currency. Must be higher than the current bid.", "example": 5500 },
          "maxAutoBid": { "type": "number", "format": "float", "description": "Optional maximum for auto-bidding. AuctFlow will bid incrementally up to this amount.", "example": 6000 }
        }
      },
      "Error": {
        "type": "object",
        "description": "Structured error response returned by all API endpoints on failure.",
        "required": ["error"],
        "properties": {
          "error": {
            "type": "object",
            "required": ["code", "message"],
            "properties": {
              "code": { "type": "string", "description": "Machine-readable error code", "example": "NOT_FOUND" },
              "message": { "type": "string", "description": "Human-readable explanation in English or Dutch", "example": "The requested auction was not found." },
              "hint": { "type": "string", "description": "Optional resolution hint guiding the caller to fix the issue", "example": "Verify the auction ID or list auctions with GET /api/v1/auctions" },
              "details": { "type": "array", "items": { "type": "object" }, "description": "Optional field-level validation errors" }
            }
          }
        }
      },
      "PaginatedAuctions": {
        "type": "object",
        "description": "Paginated list of auctions.",
        "required": ["data", "page", "perPage", "total"],
        "properties": {
          "data": { "type": "array", "items": { "$ref": "#/components/schemas/Auction" } },
          "page": { "type": "integer", "description": "Current page number (1-based)", "example": 1 },
          "perPage": { "type": "integer", "description": "Items per page", "example": 20 },
          "total": { "type": "integer", "description": "Total matching items", "example": 42 }
        }
      },
      "PaginatedLots": {
        "type": "object",
        "description": "Paginated list of lots within an auction.",
        "required": ["data", "page", "perPage", "total"],
        "properties": {
          "data": { "type": "array", "items": { "$ref": "#/components/schemas/Lot" } },
          "page": { "type": "integer", "example": 1 },
          "perPage": { "type": "integer", "example": 50 },
          "total": { "type": "integer", "example": 120 }
        }
      }
    }
  },
  "security": [{ "BearerAuth": [] }],
  "paths": {
    "/api/v1/auctions": {
      "get": {
        "operationId": "listAuctions",
        "summary": "List auctions",
        "description": "Returns a paginated list of auctions visible to the authenticated API key. Filter by status or type using query parameters.",
        "tags": ["Auctions"],
        "parameters": [
          { "name": "status", "in": "query", "required": false, "description": "Filter by auction status", "schema": { "type": "string", "enum": ["draft", "published", "live", "closed", "cancelled"] } },
          { "name": "type", "in": "query", "required": false, "description": "Filter by auction type", "schema": { "type": "string", "enum": ["live", "timed"] } },
          { "name": "page", "in": "query", "required": false, "description": "Page number (1-based)", "schema": { "type": "integer", "minimum": 1, "default": 1 } },
          { "name": "perPage", "in": "query", "required": false, "description": "Items per page (max 100)", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 } }
        ],
        "responses": {
          "200": {
            "description": "A paginated list of auctions.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PaginatedAuctions" } } }
          },
          "401": { "description": "Missing or invalid API key.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }, "headers": { "RateLimit-Limit": { "schema": { "type": "integer" }, "description": "Maximum requests per minute per key" }, "RateLimit-Remaining": { "schema": { "type": "integer" }, "description": "Remaining requests in the current window" }, "RateLimit-Reset": { "schema": { "type": "integer" }, "description": "Seconds until the rate-limit window resets" } } },
          "429": { "description": "Rate limit exceeded. Retry after the indicated seconds.", "headers": { "RateLimit-Limit": { "schema": { "type": "integer" } }, "RateLimit-Remaining": { "schema": { "type": "integer" } }, "RateLimit-Reset": { "schema": { "type": "integer" } }, "Retry-After": { "schema": { "type": "integer" }, "description": "Seconds to wait before retrying" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/api/v1/auctions/{auctionId}/lots": {
      "get": {
        "operationId": "listLots",
        "summary": "List lots in an auction",
        "description": "Returns a paginated list of lots (kavels) for a specific auction. Lots are ordered by lotNumber ascending.",
        "tags": ["Lots"],
        "parameters": [
          { "name": "auctionId", "in": "path", "required": true, "description": "UUID of the auction", "schema": { "type": "string", "format": "uuid" } },
          { "name": "status", "in": "query", "required": false, "description": "Filter by lot status", "schema": { "type": "string", "enum": ["pending", "open", "sold", "unsold", "withdrawn"] } },
          { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "default": 1 } },
          { "name": "perPage", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 } }
        ],
        "responses": {
          "200": {
            "description": "A paginated list of lots.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PaginatedLots" } } }
          },
          "401": { "description": "Missing or invalid API key.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "404": { "description": "Auction not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "429": { "description": "Rate limit exceeded.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/api/v1/auctions/{auctionId}/lots/{lotId}/bids": {
      "post": {
        "operationId": "placeBid",
        "summary": "Place a bid on a lot",
        "description": "Places a bid on behalf of an authenticated bidder. The bid amount must exceed the current highest bid. If maxAutoBid is provided, AuctFlow will automatically bid incrementally up to that maximum.",
        "tags": ["Bids"],
        "parameters": [
          { "name": "auctionId", "in": "path", "required": true, "description": "UUID of the auction", "schema": { "type": "string", "format": "uuid" } },
          { "name": "lotId", "in": "path", "required": true, "description": "UUID of the lot to bid on", "schema": { "type": "string", "format": "uuid" } }
        ],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BidRequest" } } }
        },
        "responses": {
          "201": {
            "description": "Bid placed successfully.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Bid" } } }
          },
          "400": { "description": "Invalid bid amount or lot not open for bidding.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Missing or invalid API key.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "404": { "description": "Auction or lot not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "409": { "description": "Bid amount is not higher than the current bid.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "429": { "description": "Rate limit exceeded.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/api/v1/health": {
      "get": {
        "operationId": "healthCheck",
        "summary": "API health check",
        "description": "Returns the current operational status of the AuctFlow API. No authentication required.",
        "tags": ["System"],
        "security": [],
        "responses": {
          "200": {
            "description": "API is operational.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["status", "version", "timestamp"],
                  "properties": {
                    "status": { "type": "string", "enum": ["ok"], "example": "ok" },
                    "version": { "type": "string", "example": "1.0.0" },
                    "timestamp": { "type": "string", "format": "date-time", "example": "2026-10-13T10:00:00Z" }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "tags": [
    { "name": "Auctions", "description": "Manage and query auction events" },
    { "name": "Lots", "description": "Browse and manage lots (kavels) within auctions" },
    { "name": "Bids", "description": "Place and query bids on lots" },
    { "name": "System", "description": "System endpoints like health checks" }
  ]
}
