{"openapi":"3.1.0","info":{"title":"Agentanbud","version":"0.2.0"},"paths":{"/mcp":{"get":{"summary":"Mcp Get","description":"MCP server info — clients call this to discover capabilities.","operationId":"mcp_get_mcp_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Mcp Post","description":"Handle JSON-RPC 2.0 MCP requests.\n\nPer MCP spec, the request body is a single JSON-RPC object (not batched).\nResponses follow JSON-RPC 2.0:\n  - Success: { jsonrpc, id, result }\n  - Error:   { jsonrpc, id, error: { code, message, data? } }","operationId":"mcp_post_mcp_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"delete":{"summary":"Mcp Delete","description":"End a session (MCP Streamable HTTP).","operationId":"mcp_delete_mcp_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"options":{"summary":"Mcp Options","description":"CORS preflight.","operationId":"mcp_options_mcp_options","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/health":{"get":{"summary":"Health","operationId":"health_api_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Health Api Health Get"}}}}}}},"/api/stats":{"get":{"summary":"Stats","operationId":"stats_api_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Stats Api Stats Get"}}}}}}},"/api/tenders":{"get":{"summary":"List Tenders","operationId":"list_tenders_api_tenders_get","parameters":[{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}},{"name":"authority","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authority"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":25,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Tenders Api Tenders Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tenders/{tid}":{"get":{"summary":"Get Tender","operationId":"get_tender_api_tenders__tid__get","parameters":[{"name":"tid","in":"path","required":true,"schema":{"type":"integer","title":"Tid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Tender Api Tenders  Tid  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/sync":{"post":{"summary":"Trigger Sync","description":"Fire-and-forget: spawn the orchestrator in the background.","operationId":"trigger_sync_api_sync_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/backfill":{"post":{"summary":"Backfill","description":"Trigger a backfill with a longer lookback for TED EU.\nDefault: 90 days. Max: 365 days.\nTED has ~6500 SWE notices per 90 days.","operationId":"backfill_api_backfill_post","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":90,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/repair-links":{"post":{"summary":"Repair Links","description":"Repair tender links (2026-07 URL audit).\n\n1. ted / ted_awards / ted_pin: rebuild as /en/notice/-/detail/{nr}\n   — the only form that renders in a browser. Both /en/notice/{nr}\n   and /en/notice/{nr}/html bounce users to the TED homepage.\n2. mercell: delete all rows and re-sync. Old rows are keyed on\n   unstable search-index ids (duplicates after Mercell\n   re-indexes) and point at the dead /sv-SE/m/tender/ route.\n   The scraper now keys on repsNoticeId, links to /tender/{id}\n   and skips Mercell's TED mirrors.","operationId":"repair_links_api_repair_links_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/admin/query":{"post":{"summary":"Admin Query","description":"Read-only SQL access for maintenance and diagnostics.\n\nRequires ADMIN_API_KEY to be configured AND supplied — unlike the\nmutating endpoints this one fails closed when no key is set.\nSELECT/WITH single statements only; the connection is opened with\nPRAGMA query_only so writes are rejected at the SQLite level too.\n\nBody: {\"sql\": \"SELECT ...\", \"params\": [...]}\nReturns: {\"columns\": [...], \"rows\": [[...], ...], \"truncated\": bool}","operationId":"admin_query_api_admin_query_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/knowledge":{"get":{"summary":"List Knowledge","operationId":"list_knowledge_api_knowledge_get","parameters":[{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"criteria | questions","title":"Source"},"description":"criteria | questions"},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":25,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Knowledge Api Knowledge Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/knowledge/stats":{"get":{"summary":"Knowledge Stats","description":"Counts per source_system, and per top category.","operationId":"knowledge_stats_api_knowledge_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Knowledge Stats Api Knowledge Stats Get"}}}}}}}},"components":{"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}