{
    "openapi": "3.0.3",
    "info": {
        "title": "AppShovel API",
        "description": "Keyword popularity and recommendation data from the Apple App Store. Use these endpoints to look up search-popularity scores and discover related keywords for App Store Optimization (ASO).",
        "version": "1.0.0",
        "contact": {
            "name": "AppShovel",
            "url": "https://appshovel.com"
        }
    },
    "servers": [
        {
            "url": "https://appshovel.com",
            "description": "Production"
        }
    ],
    "security": [
        {
            "BearerAuth": []
        }
    ],
    "paths": {
        "/api/v1/keywords/popularities": {
            "post": {
                "operationId": "getKeywordPopularities",
                "summary": "Get keyword popularities",
                "description": "Returns popularity and difficulty scores for up to 100 keywords in a given country and platform.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PopularitiesRequest"
                            },
                            "example": {
                                "terms": ["fitness tracker", "workout app"],
                                "country": "us",
                                "platform": "iphone"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Popularity scores for the requested keywords.",
                        "headers": {
                            "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" },
                            "X-RateLimit-Remaining": { "$ref": "#/components/headers/X-RateLimit-Remaining" },
                            "X-RateLimit-Reset": { "$ref": "#/components/headers/X-RateLimit-Reset" }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/PopularityResult"
                                    }
                                },
                                "example": [
                                    {
                                        "term": "fitness tracker",
                                        "country": "us",
                                        "platform": "iphone",
                                        "popularity": 62,
                                        "difficulty": 45
                                    },
                                    {
                                        "term": "workout app",
                                        "country": "us",
                                        "platform": "iphone",
                                        "popularity": 55,
                                        "difficulty": null
                                    }
                                ]
                            }
                        }
                    },
                    "400": {
                        "description": "Validation error — invalid or missing parameters.",
                        "content": {
                            "application/json": {
                                "schema": { "$ref": "#/components/schemas/Error" },
                                "examples": {
                                    "missingTerms": {
                                        "summary": "Missing terms",
                                        "value": { "error": "Invalid or missing 'terms' parameter. Expected a non-empty array of strings." }
                                    },
                                    "tooManyTerms": {
                                        "summary": "Too many terms",
                                        "value": { "error": "Too many terms. Maximum is 100 per request." }
                                    },
                                    "emptyStrings": {
                                        "summary": "Empty string terms",
                                        "value": { "error": "All terms must be non-empty strings." }
                                    },
                                    "invalidCountry": {
                                        "summary": "Invalid country",
                                        "value": { "error": "Invalid or missing 'country' parameter." }
                                    },
                                    "invalidPlatform": {
                                        "summary": "Invalid platform",
                                        "value": { "error": "Invalid or missing 'platform' parameter." }
                                    }
                                }
                            }
                        }
                    },
                    "401": { "$ref": "#/components/responses/Unauthorized" },
                    "402": { "$ref": "#/components/responses/PaymentRequired" },
                    "429": { "$ref": "#/components/responses/TooManyRequests" }
                }
            }
        },
        "/api/v1/keywords/recommendations": {
            "post": {
                "operationId": "getKeywordRecommendations",
                "summary": "Get keyword recommendations",
                "description": "Returns related keyword suggestions for a single keyword in a given country and platform.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/RecommendationsRequest"
                            },
                            "example": {
                                "term": "fitness tracker",
                                "country": "us",
                                "platform": "iphone"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Recommended keywords related to the input term.",
                        "headers": {
                            "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" },
                            "X-RateLimit-Remaining": { "$ref": "#/components/headers/X-RateLimit-Remaining" },
                            "X-RateLimit-Reset": { "$ref": "#/components/headers/X-RateLimit-Reset" }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/RecommendationsResult"
                                },
                                "example": {
                                    "term": "fitness tracker",
                                    "country": "us",
                                    "platform": "iphone",
                                    "recommendations": [
                                        { "name": "fitness app", "popularity": 58 },
                                        { "name": "health tracker", "popularity": 47 }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Validation error — invalid or missing parameters.",
                        "content": {
                            "application/json": {
                                "schema": { "$ref": "#/components/schemas/Error" },
                                "examples": {
                                    "missingTerm": {
                                        "summary": "Missing term",
                                        "value": { "error": "Invalid or missing 'term' parameter. Expected a non-empty string." }
                                    },
                                    "invalidCountry": {
                                        "summary": "Invalid country",
                                        "value": { "error": "Invalid or missing 'country' parameter." }
                                    },
                                    "invalidPlatform": {
                                        "summary": "Invalid platform",
                                        "value": { "error": "Invalid or missing 'platform' parameter." }
                                    }
                                }
                            }
                        }
                    },
                    "401": { "$ref": "#/components/responses/Unauthorized" },
                    "402": { "$ref": "#/components/responses/PaymentRequired" },
                    "404": {
                        "description": "Keyword not found after sync.",
                        "content": {
                            "application/json": {
                                "schema": { "$ref": "#/components/schemas/Error" },
                                "example": { "error": "Keyword not found." }
                            }
                        }
                    },
                    "429": { "$ref": "#/components/responses/TooManyRequests" }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "BearerAuth": {
                "type": "http",
                "scheme": "bearer",
                "description": "API key passed as a Bearer token. Generate one from your account settings at https://appshovel.com/settings."
            }
        },
        "headers": {
            "X-RateLimit-Limit": {
                "description": "Maximum requests allowed per window (60).",
                "schema": { "type": "integer", "example": 60 }
            },
            "X-RateLimit-Remaining": {
                "description": "Requests remaining in the current window.",
                "schema": { "type": "integer", "example": 57 }
            },
            "X-RateLimit-Reset": {
                "description": "Seconds until the oldest request in the window expires.",
                "schema": { "type": "integer", "example": 42 }
            }
        },
        "schemas": {
            "Country": {
                "type": "string",
                "description": "Two-letter country code.",
                "enum": [
                    "al",
                    "dz",
                    "ar",
                    "am",
                    "au",
                    "at",
                    "az",
                    "bh",
                    "be",
                    "bo",
                    "br",
                    "bg",
                    "kh",
                    "ca",
                    "cl",
                    "cn",
                    "co",
                    "cr",
                    "hr",
                    "cy",
                    "cz",
                    "dk",
                    "do",
                    "ec",
                    "eg",
                    "sv",
                    "ee",
                    "fi",
                    "fr",
                    "de",
                    "gh",
                    "gr",
                    "gt",
                    "hn",
                    "hk",
                    "hu",
                    "is",
                    "in",
                    "id",
                    "iq",
                    "ie",
                    "il",
                    "it",
                    "jp",
                    "jo",
                    "kz",
                    "ke",
                    "kw",
                    "kg",
                    "lv",
                    "lb",
                    "lu",
                    "mo",
                    "my",
                    "mx",
                    "mn",
                    "ma",
                    "np",
                    "nl",
                    "nz",
                    "no",
                    "om",
                    "pa",
                    "py",
                    "pe",
                    "ph",
                    "pl",
                    "pt",
                    "qa",
                    "ro",
                    "ru",
                    "sa",
                    "sg",
                    "sk",
                    "si",
                    "za",
                    "kr",
                    "es",
                    "lk",
                    "se",
                    "ch",
                    "tw",
                    "th",
                    "tr",
                    "ua",
                    "ae",
                    "gb",
                    "us",
                    "uz",
                    "vn"
                ]
            },
            "Platform": {
                "type": "string",
                "description": "Target App Store platform.",
                "enum": ["iphone", "ipad"]
            },
            "PopularitiesRequest": {
                "type": "object",
                "required": ["terms", "country", "platform"],
                "properties": {
                    "terms": {
                        "type": "array",
                        "items": { "type": "string", "minLength": 1 },
                        "minItems": 1,
                        "maxItems": 100,
                        "description": "Keywords to look up (1–100)."
                    },
                    "country": { "$ref": "#/components/schemas/Country" },
                    "platform": { "$ref": "#/components/schemas/Platform" }
                }
            },
            "PopularityResult": {
                "type": "object",
                "properties": {
                    "term": { "type": "string", "description": "The keyword." },
                    "country": { "$ref": "#/components/schemas/Country" },
                    "platform": { "$ref": "#/components/schemas/Platform" },
                    "popularity": {
                        "type": "integer",
                        "nullable": true,
                        "minimum": 0,
                        "maximum": 100,
                        "description": "Search popularity score (0–100), or null if unavailable."
                    },
                    "difficulty": {
                        "type": "integer",
                        "nullable": true,
                        "minimum": 0,
                        "maximum": 100,
                        "description": "Competition difficulty score (0–100), or null if unavailable."
                    }
                }
            },
            "RecommendationsRequest": {
                "type": "object",
                "required": ["term", "country", "platform"],
                "properties": {
                    "term": {
                        "type": "string",
                        "minLength": 1,
                        "description": "A single keyword to get recommendations for."
                    },
                    "country": { "$ref": "#/components/schemas/Country" },
                    "platform": { "$ref": "#/components/schemas/Platform" }
                }
            },
            "RecommendationsResult": {
                "type": "object",
                "properties": {
                    "term": { "type": "string", "description": "The input keyword." },
                    "country": { "$ref": "#/components/schemas/Country" },
                    "platform": { "$ref": "#/components/schemas/Platform" },
                    "recommendations": {
                        "type": "array",
                        "items": { "$ref": "#/components/schemas/Recommendation" },
                        "description": "Related keywords."
                    }
                }
            },
            "Recommendation": {
                "type": "object",
                "properties": {
                    "name": { "type": "string", "description": "Recommended keyword." },
                    "popularity": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 100,
                        "description": "Popularity score (0–100)."
                    }
                }
            },
            "Error": {
                "type": "object",
                "properties": {
                    "error": { "type": "string", "description": "Human-readable error message." }
                },
                "required": ["error"]
            }
        },
        "responses": {
            "Unauthorized": {
                "description": "Missing or invalid API key.",
                "content": {
                    "application/json": {
                        "schema": { "$ref": "#/components/schemas/Error" },
                        "examples": {
                            "missingHeader": {
                                "summary": "Missing Authorization header",
                                "value": { "error": "Missing or invalid Authorization header. Expected: Bearer <api_key>" }
                            },
                            "invalidKey": {
                                "summary": "Invalid API key",
                                "value": { "error": "Invalid API key." }
                            }
                        }
                    }
                }
            },
            "PaymentRequired": {
                "description": "No active subscription.",
                "content": {
                    "application/json": {
                        "schema": { "$ref": "#/components/schemas/Error" },
                        "example": { "error": "User has no active subscription." }
                    }
                }
            },
            "TooManyRequests": {
                "description": "Rate limit exceeded (60 requests per 60-second window).",
                "headers": {
                    "X-RateLimit-Limit": { "$ref": "#/components/headers/X-RateLimit-Limit" },
                    "X-RateLimit-Remaining": { "$ref": "#/components/headers/X-RateLimit-Remaining" },
                    "X-RateLimit-Reset": { "$ref": "#/components/headers/X-RateLimit-Reset" }
                },
                "content": {
                    "application/json": {
                        "schema": { "$ref": "#/components/schemas/Error" },
                        "example": { "error": "Too many requests. Please try again later." }
                    }
                }
            }
        }
    }
}
