{
  "openapi": "3.0.3",
  "info": {
    "title": "PartsBid Public API",
    "description": "B2B Spare Parts Inquiry Platform API for RFQ management, bid submission, supplier discovery, and webhook integration.",
    "version": "1.0.0",
    "contact": {
      "name": "PartsBid Support",
      "email": "support@partsbid.io",
      "url": "https://partsbid.io"
    }
  },
  "servers": [
    {
      "url": "https://partsbid.io/api/v1",
      "description": "Production"
    },
    {
      "url": "http://localhost:3000/api/v1",
      "description": "Local development"
    }
  ],
  "security": [
    { "apiKey": [] }
  ],
  "paths": {
    "/rfqs": {
      "get": {
        "summary": "List RFQs",
        "operationId": "listRfqs",
        "tags": ["RFQs"],
        "security": [{ "apiKey": ["rfq:read"] }],
        "parameters": [
          { "name": "category", "in": "query", "schema": { "type": "string" }, "example": "Bearings" },
          { "name": "region", "in": "query", "schema": { "type": "string" }, "example": "SA" },
          { "name": "status", "in": "query", "schema": { "type": "string", "enum": ["open", "closed", "awarded"] } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20, "maximum": 100, "minimum": 1 } },
          { "name": "cursor", "in": "query", "schema": { "type": "string" }, "description": "Cursor for pagination" }
        ],
        "responses": {
          "200": {
            "description": "List of RFQs",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "data": { "type": "array", "items": { "$ref": "#/components/schemas/RFQSummary" } },
                        "nextCursor": { "type": "string", "nullable": true }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      },
      "post": {
        "summary": "Create RFQ",
        "operationId": "createRfq",
        "tags": ["RFQs"],
        "security": [{ "apiKey": ["rfq:write"] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/CreateRFQRequest" }
            }
          }
        },
        "responses": {
          "201": {
            "description": "RFQ created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": { "data": { "$ref": "#/components/schemas/RFQDetail" } }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/ValidationError" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      }
    },
    "/rfqs/{id}": {
      "get": {
        "summary": "Get RFQ details",
        "operationId": "getRfq",
        "tags": ["RFQs"],
        "security": [{ "apiKey": ["rfq:read"] }],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "RFQ details with line items",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": { "data": { "$ref": "#/components/schemas/RFQDetail" } }
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/rfqs/{id}/bids": {
      "post": {
        "summary": "Submit bid on RFQ",
        "operationId": "createBid",
        "tags": ["Bids"],
        "security": [{ "apiKey": ["bid:write"] }],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/CreateBidRequest" }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Bid submitted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": { "data": { "$ref": "#/components/schemas/Bid" } }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/ValidationError" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "409": {
            "description": "Company already submitted a bid",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
          }
        }
      },
      "get": {
        "summary": "List bids on RFQ",
        "operationId": "listBids",
        "tags": ["Bids"],
        "security": [{ "apiKey": ["bid:read"] }],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "List of bids. Buyers see all bids on their RFQs; suppliers see only their own.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": { "type": "array", "items": { "$ref": "#/components/schemas/Bid" } }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/suppliers": {
      "get": {
        "summary": "List suppliers",
        "operationId": "listSuppliers",
        "tags": ["Suppliers"],
        "security": [{ "apiKey": ["supplier:read"] }],
        "parameters": [
          { "name": "category", "in": "query", "schema": { "type": "string" } },
          { "name": "region", "in": "query", "schema": { "type": "string" } },
          { "name": "verified", "in": "query", "schema": { "type": "boolean" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20, "maximum": 100 } },
          { "name": "cursor", "in": "query", "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "List of suppliers",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "data": { "type": "array", "items": { "$ref": "#/components/schemas/SupplierSummary" } },
                        "nextCursor": { "type": "string", "nullable": true }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/suppliers/{id}": {
      "get": {
        "summary": "Get supplier profile",
        "operationId": "getSupplier",
        "tags": ["Suppliers"],
        "security": [{ "apiKey": ["supplier:read"] }],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Supplier profile with scorecard",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": { "data": { "$ref": "#/components/schemas/SupplierProfile" } }
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/webhooks": {
      "post": {
        "summary": "Create webhook endpoint",
        "operationId": "createWebhook",
        "tags": ["Webhooks"],
        "security": [{ "apiKey": ["webhook:write"] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/CreateWebhookRequest" }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook created. Secret is returned only once.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": { "data": { "$ref": "#/components/schemas/WebhookWithSecret" } }
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List webhook endpoints",
        "operationId": "listWebhooks",
        "tags": ["Webhooks"],
        "security": [{ "apiKey": ["webhook:read"] }],
        "responses": {
          "200": {
            "description": "List of webhook endpoints (secret not included)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": { "type": "array", "items": { "$ref": "#/components/schemas/WebhookEndpoint" } }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}": {
      "delete": {
        "summary": "Deactivate webhook endpoint",
        "operationId": "deleteWebhook",
        "tags": ["Webhooks"],
        "security": [{ "apiKey": ["webhook:write"] }],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Webhook deactivated" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/webhooks/{id}/deliveries": {
      "get": {
        "summary": "Get delivery log",
        "operationId": "getDeliveries",
        "tags": ["Webhooks"],
        "security": [{ "apiKey": ["webhook:read"] }],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Last 50 delivery attempts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": { "type": "array", "items": { "$ref": "#/components/schemas/WebhookDelivery" } }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}/test": {
      "post": {
        "summary": "Send test ping",
        "operationId": "testWebhook",
        "tags": ["Webhooks"],
        "security": [{ "apiKey": ["webhook:write"] }],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Test delivery result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "delivered": { "type": "boolean" },
                        "statusCode": { "type": "integer", "nullable": true },
                        "deliveryId": { "type": "string" },
                        "url": { "type": "string" }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key obtained from /api/keys. Format: pb_live_<64hex>"
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "required": ["code", "message"],
            "properties": {
              "code": { "type": "string", "example": "VALIDATION_ERROR" },
              "message": { "type": "string", "example": "Invalid RFQ data." },
              "details": { "type": "object" }
            }
          }
        }
      },
      "RFQSummary": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "example": "clx1abc123" },
          "rfqNumber": { "type": "string", "example": "RFQ-2026-00042" },
          "title": { "type": "string", "example": "SKF 6205 Bearings — 500pcs" },
          "category": { "type": "string", "example": "Bearings" },
          "status": { "type": "string", "enum": ["DRAFT", "OPEN", "UNDER_REVIEW", "AWARDED", "CLOSED", "CANCELLED"] },
          "urgency": { "type": "string", "enum": ["LOW", "NORMAL", "HIGH", "CRITICAL"] },
          "quantity": { "type": "number", "example": 500 },
          "unit": { "type": "string", "example": "PCS" },
          "budgetMin": { "type": "number", "nullable": true, "example": 15000 },
          "budgetMax": { "type": "number", "nullable": true, "example": 25000 },
          "currency": { "type": "string", "example": "SAR" },
          "deadline": { "type": "string", "format": "date-time" },
          "deliveryCountry": { "type": "string", "nullable": true, "example": "SA" },
          "createdAt": { "type": "string", "format": "date-time" },
          "company": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "country": { "type": "string" } } },
          "_count": { "type": "object", "properties": { "bids": { "type": "integer" }, "lineItems": { "type": "integer" } } }
        }
      },
      "RFQDetail": {
        "allOf": [
          { "$ref": "#/components/schemas/RFQSummary" },
          {
            "type": "object",
            "properties": {
              "lineItems": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": { "type": "string" },
                    "itemNumber": { "type": "integer" },
                    "description": { "type": "string" },
                    "partNumber": { "type": "string", "nullable": true },
                    "quantity": { "type": "number" },
                    "unit": { "type": "string" }
                  }
                }
              }
            }
          }
        ]
      },
      "CreateRFQRequest": {
        "type": "object",
        "required": ["title", "description", "category", "deadline", "parts"],
        "properties": {
          "title": { "type": "string", "example": "SKF 6205 Bearings" },
          "description": { "type": "string", "example": "Need 500pcs of SKF 6205-2RS deep groove ball bearings for industrial machinery." },
          "category": { "type": "string", "example": "Bearings" },
          "region": { "type": "string", "example": "SA" },
          "deadline": { "type": "string", "format": "date-time", "example": "2026-05-01T00:00:00Z" },
          "parts": {
            "type": "array",
            "items": {
              "type": "object",
              "required": ["description", "quantity"],
              "properties": {
                "partNumber": { "type": "string", "example": "SKF-6205-2RS" },
                "description": { "type": "string", "example": "Deep groove ball bearing 25x52x15mm" },
                "quantity": { "type": "number", "example": 500 },
                "unit": { "type": "string", "default": "PCS" }
              }
            }
          }
        }
      },
      "Bid": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "bidNumber": { "type": "string", "example": "BID-2026-00105" },
          "status": { "type": "string", "enum": ["PENDING", "SHORTLISTED", "AWARDED", "REJECTED", "WITHDRAWN"] },
          "totalPrice": { "type": "number", "example": 18750.00 },
          "currency": { "type": "string", "example": "SAR" },
          "deliveryDays": { "type": "integer", "example": 14 },
          "notes": { "type": "string", "nullable": true },
          "createdAt": { "type": "string", "format": "date-time" },
          "company": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" } } }
        }
      },
      "CreateBidRequest": {
        "type": "object",
        "required": ["price", "deliveryDays"],
        "properties": {
          "price": { "type": "number", "example": 18750.00, "description": "Total bid price in SAR" },
          "currency": { "type": "string", "default": "SAR" },
          "notes": { "type": "string", "example": "Genuine SKF, shipped from Jeddah warehouse." },
          "deliveryDays": { "type": "integer", "example": 14 }
        }
      },
      "SupplierSummary": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string", "example": "Gulf Parts Trading LLC" },
          "status": { "type": "string" },
          "country": { "type": "string", "example": "AE" },
          "city": { "type": "string", "nullable": true },
          "categories": { "type": "array", "items": { "type": "string" } },
          "supplierTier": { "type": "string", "nullable": true },
          "verifiedAt": { "type": "string", "format": "date-time", "nullable": true }
        }
      },
      "SupplierProfile": {
        "allOf": [
          { "$ref": "#/components/schemas/SupplierSummary" },
          {
            "type": "object",
            "properties": {
              "description": { "type": "string" },
              "website": { "type": "string" },
              "supplierScore": {
                "type": "object",
                "nullable": true,
                "properties": {
                  "overallScore": { "type": "number" },
                  "deliveryScore": { "type": "number" },
                  "qualityScore": { "type": "number" },
                  "responseScore": { "type": "number" },
                  "priceScore": { "type": "number" }
                }
              }
            }
          }
        ]
      },
      "CreateWebhookRequest": {
        "type": "object",
        "required": ["url", "events"],
        "properties": {
          "url": { "type": "string", "format": "uri", "example": "https://your-erp.com/webhooks/partsbid" },
          "events": {
            "type": "array",
            "items": { "type": "string", "enum": ["rfq.created", "rfq.published", "rfq.bid_received", "rfq.bid_accepted", "rfq.expired", "supplier.verified", "order.status_changed", "invoice.created", "escrow.released"] }
          },
          "name": { "type": "string", "example": "ERP Integration" }
        }
      },
      "WebhookEndpoint": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" },
          "url": { "type": "string" },
          "events": { "type": "array", "items": { "type": "string" } },
          "isActive": { "type": "boolean" },
          "lastFiredAt": { "type": "string", "format": "date-time", "nullable": true },
          "createdAt": { "type": "string", "format": "date-time" }
        }
      },
      "WebhookWithSecret": {
        "allOf": [
          { "$ref": "#/components/schemas/WebhookEndpoint" },
          {
            "type": "object",
            "properties": {
              "secret": { "type": "string", "description": "HMAC signing secret. Shown ONCE at creation." },
              "message": { "type": "string" }
            }
          }
        ]
      },
      "WebhookDelivery": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "event": { "type": "string", "example": "rfq.created" },
          "success": { "type": "boolean" },
          "responseStatus": { "type": "integer", "nullable": true },
          "attempt": { "type": "integer" },
          "deliveredAt": { "type": "string", "format": "date-time", "nullable": true },
          "createdAt": { "type": "string", "format": "date-time" }
        }
      },
      "WebhookEventPayload": {
        "type": "object",
        "description": "Standard webhook event payload",
        "required": ["event", "timestamp", "data"],
        "properties": {
          "event": { "type": "string", "example": "rfq.created" },
          "timestamp": { "type": "string", "format": "date-time" },
          "data": { "type": "object" }
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Invalid or missing API key",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
      },
      "Forbidden": {
        "description": "Missing required scope or wrong account type",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
      },
      "NotFound": {
        "description": "Resource not found",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
      },
      "ValidationError": {
        "description": "Request body validation failed",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
      },
      "RateLimited": {
        "description": "Rate limit exceeded (100 req/min per API key)",
        "headers": {
          "X-RateLimit-Limit": { "schema": { "type": "integer" } },
          "X-RateLimit-Remaining": { "schema": { "type": "integer" } },
          "X-RateLimit-Reset": { "schema": { "type": "integer" } },
          "Retry-After": { "schema": { "type": "integer" } }
        },
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
      }
    }
  }
}
