{
  "openapi": "3.1.0",
  "info": {
    "title": "Tender Agents API",
    "version": "0.1.0",
    "description": "EU public tenders as structured data. Free preview without a key; a free API key raises rate limits (60 req/h), paid tiers (Pro 600 req/h, Agent 3,600 req/h) unlock full-text search and higher limits. Auth: Authorization: Bearer sk_...",
    "contact": {
      "email": "hi@tender-agents.com",
      "url": "https://www.tender-agents.com/developers"
    }
  },
  "servers": [
    {
      "url": "https://www.tender-agents.com"
    }
  ],
  "paths": {
    "/api/tenders-public": {
      "get": {
        "summary": "Search live tender previews",
        "operationId": "searchTenders",
        "parameters": [
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Free-text term matched against title/description (language-sensitive)"
          },
          {
            "name": "country",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "ISO 3166-1 alpha-3 buyer country, e.g. DEU, FRA, ESP. Omit for all EU."
          },
          {
            "name": "cpv",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "CPV code prefix. Full 8-digit codes match exactly; shorter numeric prefixes (e.g. '45') match whole CPV divisions."
          },
          {
            "name": "min_score",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            },
            "description": "Minimum relevance score"
          },
          {
            "name": "deadline_within_days",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "minimum_value_eur",
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "maximum_value_eur",
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 6,
              "maximum": 25
            },
            "description": "Free tier caps at 25"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "summary_lang",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "de"
              ]
            },
            "description": "Attach cached AI summaries (title + max two sentences) in this language; labelled as AI-generated, the original notice prevails. Generated lazily and cached; may be null on first requests."
          }
        ],
        "responses": {
          "200": {
            "description": "Array of tender previews",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Tender"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        }
      }
    },
    "/api/source-status": {
      "get": {
        "summary": "Live source coverage and freshness",
        "operationId": "sourceStatus",
        "responses": {
          "200": {
            "description": "Per-source status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SourceStatus"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/signup": {
      "post": {
        "summary": "Create a free API key (self-serve)",
        "operationId": "signupFree",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Key created; also sent by email",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "email": {
                      "type": "string"
                    },
                    "tier": {
                      "type": "string"
                    },
                    "api_key": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Email already registered"
          },
          "429": {
            "description": "Signup rate limit (10/hour)"
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "summary": "MCP endpoint (JSON-RPC 2.0)",
        "operationId": "mcp",
        "description": "Model Context Protocol over HTTP. Methods: initialize, tools/list, tools/call. Tools: agentleads.search_tenders (free), agentleads.fulltext_search (Pro/Agent key). Optional Authorization: Bearer sk_...",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC response"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "sk_..."
      }
    },
    "schemas": {
      "Tender": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "source_url": {
            "type": "string",
            "format": "uri"
          },
          "title": {
            "type": "string"
          },
          "buyer_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "buyer_country": {
            "type": "string",
            "description": "ISO 3166-1 alpha-3"
          },
          "cpv_main": {
            "type": [
              "string",
              "null"
            ]
          },
          "published_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "deadline_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "estimated_value_eur": {
            "type": [
              "number",
              "null"
            ]
          },
          "verticals": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "relevance_score": {
            "type": [
              "integer",
              "null"
            ]
          },
          "summary": {
            "type": [
              "object",
              "null"
            ],
            "description": "Cached AI summary in the requested summary_lang ({title, summary, label, model, generated_at}); null unless requested and available."
          }
        }
      },
      "SourceStatus": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string"
          },
          "implementation_status": {
            "type": "string",
            "enum": [
              "live",
              "stub"
            ]
          },
          "last_attempt_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_success_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "fetched": {
            "type": [
              "integer",
              "null"
            ]
          },
          "stored": {
            "type": [
              "integer",
              "null"
            ]
          }
        }
      }
    }
  }
}