{
    "openapi": "3.0.3",
    "info": {
        "title": "Conference Partner API",
        "description": "Read-only REST API over the Conference Partner dataset: academic conferences and journals with CFPs, deadlines, locations, and CCF / CORE / QUALIS rankings. See https://www.myhuiban.com/methodology for ranking definitions and update cadence.",
        "version": "1.0.0",
        "contact": {
            "name": "Conference Partner",
            "url": "https://www.myhuiban.com/",
            "email": "admin@myhuiban.com"
        }
    },
    "servers": [
        {
            "url": "https://www.myhuiban.com",
            "description": "Current environment"
        },
        {
            "url": "https://www.myhuiban.com",
            "description": "Production"
        }
    ],
    "components": {
        "securitySchemes": {
            "bearerAuth": {
                "type": "http",
                "scheme": "bearer",
                "bearerFormat": "JWT",
                "description": "JWT issued by POST /api/login. Send as `Authorization: Bearer <token>`."
            }
        },
        "schemas": {
            "ApiSuccess": {
                "type": "object",
                "properties": {
                    "success": {
                        "type": "boolean",
                        "example": true
                    },
                    "code": {
                        "type": "integer",
                        "example": 200
                    },
                    "data": {
                        "type": "object"
                    }
                },
                "required": [
                    "success",
                    "code"
                ]
            },
            "ApiError": {
                "type": "object",
                "properties": {
                    "success": {
                        "type": "boolean",
                        "example": false
                    },
                    "code": {
                        "type": "integer",
                        "example": 400
                    },
                    "message": {
                        "type": "string"
                    },
                    "errors": {
                        "type": "object",
                        "additionalProperties": true
                    }
                },
                "required": [
                    "success",
                    "code",
                    "message"
                ]
            },
            "LoginRequest": {
                "type": "object",
                "required": [
                    "email",
                    "password"
                ],
                "properties": {
                    "email": {
                        "type": "string",
                        "format": "email"
                    },
                    "password": {
                        "type": "string",
                        "format": "password"
                    }
                }
            },
            "LoginResponse": {
                "type": "object",
                "properties": {
                    "token": {
                        "type": "string",
                        "description": "JWT bearer token"
                    },
                    "expires_in": {
                        "type": "integer",
                        "description": "Seconds until expiration"
                    },
                    "user": {
                        "type": "object"
                    }
                }
            },
            "Conference": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "shortName": {
                        "type": "string",
                        "example": "ICML"
                    },
                    "fullName": {
                        "type": "string",
                        "example": "International Conference on Machine Learning"
                    },
                    "website": {
                        "type": "string",
                        "format": "uri"
                    },
                    "submissionDate": {
                        "type": "string",
                        "format": "date",
                        "nullable": true
                    },
                    "notificationDate": {
                        "type": "string",
                        "format": "date",
                        "nullable": true
                    },
                    "conferenceDate": {
                        "type": "string",
                        "format": "date",
                        "nullable": true
                    },
                    "location": {
                        "type": "string"
                    },
                    "years": {
                        "type": "integer"
                    },
                    "ccf": {
                        "type": "string",
                        "enum": [
                            "a",
                            "b",
                            "c",
                            "x"
                        ],
                        "description": "CCF rank, x means not ranked"
                    },
                    "act": {
                        "type": "string",
                        "description": "CORE rank, 0 means A*"
                    },
                    "qualis": {
                        "type": "string",
                        "description": "QUALIS rank"
                    },
                    "extended": {
                        "type": "integer",
                        "enum": [
                            0,
                            1
                        ]
                    }
                }
            },
            "Journal": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "shortName": {
                        "type": "string",
                        "nullable": true
                    },
                    "fullName": {
                        "type": "string"
                    },
                    "website": {
                        "type": "string",
                        "format": "uri"
                    },
                    "impactFactor": {
                        "type": "string",
                        "nullable": true
                    },
                    "publisher": {
                        "type": "string"
                    },
                    "issn": {
                        "type": "string"
                    },
                    "ccf": {
                        "type": "string"
                    }
                }
            }
        }
    },
    "paths": {
        "/api/login": {
            "post": {
                "operationId": "login",
                "summary": "Exchange email/password for a JWT bearer token",
                "tags": [
                    "Auth"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/LoginRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Token issued",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/ApiSuccess"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/LoginResponse"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Invalid credentials",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/conferences": {
            "get": {
                "operationId": "searchConferences",
                "summary": "Search academic conferences",
                "description": "Filter by name, ranking, and date ranges. Requires JWT.",
                "tags": [
                    "Conferences"
                ],
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "parameters": [
                    {
                        "name": "query",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Keyword matched against short name and full name (case-insensitive)."
                    },
                    {
                        "name": "ccf_rank",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "enum": [
                                "a",
                                "b",
                                "c"
                            ]
                        }
                    },
                    {
                        "name": "core_rank",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string"
                        },
                        "description": "CORE rank: A* / A / B / C (use raw value)."
                    },
                    {
                        "name": "qualis_rank",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "submission_date_start",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "submission_date_end",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "conference_date_start",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "conference_date_end",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "default": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100,
                            "default": 10
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Paged list of conferences",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/ApiSuccess"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object",
                                                    "properties": {
                                                        "items": {
                                                            "type": "array",
                                                            "items": {
                                                                "$ref": "#/components/schemas/Conference"
                                                            }
                                                        },
                                                        "total": {
                                                            "type": "integer"
                                                        },
                                                        "page": {
                                                            "type": "integer"
                                                        },
                                                        "per_page": {
                                                            "type": "integer"
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Validation error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing/invalid JWT",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limit exceeded",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/journals": {
            "get": {
                "operationId": "searchJournals",
                "summary": "Search academic journals",
                "tags": [
                    "Journals"
                ],
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "parameters": [
                    {
                        "name": "query",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Keyword matched against journal full/short name."
                    },
                    {
                        "name": "ccf_rank",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "enum": [
                                "a",
                                "b",
                                "c"
                            ]
                        }
                    },
                    {
                        "name": "issn",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "default": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100,
                            "default": 10
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Paged list of journals",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/ApiSuccess"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "object",
                                                    "properties": {
                                                        "items": {
                                                            "type": "array",
                                                            "items": {
                                                                "$ref": "#/components/schemas/Journal"
                                                            }
                                                        },
                                                        "total": {
                                                            "type": "integer"
                                                        },
                                                        "page": {
                                                            "type": "integer"
                                                        },
                                                        "per_page": {
                                                            "type": "integer"
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Validation error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing/invalid JWT",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limit exceeded",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ApiError"
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "externalDocs": {
        "description": "LLM-oriented site description",
        "url": "https://www.myhuiban.com/llms.txt"
    }
}