{"openapi": "3.1.0", "info": {"title": "UK.app Developer APIs", "version": "1.0.0", "description": "Weather and IP APIs with shared per-account, per-service UTC calendar-month quotas. Successful weather responses cost one unit; IP requests cost one unit per address. No automatic paid overages. Project keys are scoped, expiring and revocable. Header quota values account for in-flight reservations.", "contact": {"email": "support@uk.app"}}, "servers": [{"url": "https://dev.uk.app/api/v1"}], "security": [{"bearerAuth": []}], "components": {"securitySchemes": {"bearerAuth": {"type": "http", "scheme": "bearer", "description": "Create a key at https://dev.uk.app/account/#keys. Send it only in the Authorization header."}}}, "paths": {"/ip/lookup": {"get": {"operationId": "ipLookup", "summary": "Look up a public IPv4 or IPv6 address", "tags": ["IP"], "parameters": [{"name": "ip", "in": "query", "required": true, "schema": {"type": "string"}, "example": "1.1.1.1"}, {"name": "lang", "in": "query", "schema": {"type": "string", "enum": ["en", "uk", "de", "fr", "es", "pt"], "default": "en"}}, {"name": "Idempotency-Key", "in": "header", "schema": {"type": "string", "minLength": 8, "maxLength": 100}, "description": "Optional retry protection. Responses are encrypted at rest and replayable for ten minutes."}], "responses": {"200": {"description": "Result including DB-IP Lite attribution"}, "400": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}, "401": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}, "403": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}, "409": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}, "429": {"description": "Monthly quota or account rate limit reached. See Retry-After."}, "503": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}}}}, "/ip/me": {"get": {"operationId": "ipMe", "summary": "Look up the caller IP", "tags": ["IP"], "parameters": [{"name": "lang", "in": "query", "schema": {"type": "string", "enum": ["en", "uk", "de", "fr", "es", "pt"], "default": "en"}}, {"name": "Idempotency-Key", "in": "header", "schema": {"type": "string", "minLength": 8, "maxLength": 100}, "description": "Optional retry protection. Responses are encrypted at rest and replayable for ten minutes."}], "responses": {"200": {"description": "Result including DB-IP Lite attribution"}, "400": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}, "401": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}, "403": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}, "409": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}, "429": {"description": "Monthly quota or account rate limit reached. See Retry-After."}, "503": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}}}}, "/ip/bulk": {"post": {"operationId": "ipBulk", "summary": "Look up 1\u201350 public IP addresses", "tags": ["IP"], "parameters": [{"name": "lang", "in": "query", "schema": {"type": "string", "enum": ["en", "uk", "de", "fr", "es", "pt"], "default": "en"}}, {"name": "Idempotency-Key", "in": "header", "schema": {"type": "string", "minLength": 8, "maxLength": 100}, "description": "Optional retry protection. Responses are encrypted at rest and replayable for ten minutes."}], "responses": {"200": {"description": "Result including DB-IP Lite attribution"}, "400": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}, "401": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}, "403": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}, "409": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}, "429": {"description": "Monthly quota or account rate limit reached. See Retry-After."}, "503": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": false, "required": ["ips"], "properties": {"ips": {"type": "array", "minItems": 1, "maxItems": 50, "items": {"type": "string"}}}}}}}}}, "/weather/current": {"get": {"operationId": "weatherCurrent", "summary": "Current weather", "tags": ["Weather"], "parameters": [{"name": "lat", "in": "query", "required": true, "schema": {"type": "number", "minimum": -90, "maximum": 90}}, {"name": "lon", "in": "query", "required": true, "schema": {"type": "number", "minimum": -180, "maximum": 180}}, {"name": "days", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 16, "default": 7}}, {"name": "timezone", "in": "query", "schema": {"type": "string", "default": "UTC"}, "description": "IANA timezone or auto"}, {"name": "current", "in": "query", "schema": {"type": "string"}, "description": "Comma-separated weather variables, at most twelve."}, {"name": "hourly", "in": "query", "schema": {"type": "string"}}, {"name": "daily", "in": "query", "schema": {"type": "string"}}, {"name": "temperature_unit", "in": "query", "schema": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, {"name": "wind_speed_unit", "in": "query", "schema": {"type": "string", "enum": ["kmh", "ms", "mph", "kn"]}}, {"name": "precipitation_unit", "in": "query", "schema": {"type": "string", "enum": ["mm", "inch"]}}], "responses": {"200": {"description": "Open-Meteo weather data and source attribution"}, "400": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}, "401": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}, "403": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}, "429": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}, "503": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}}}}, "/weather/forecast": {"get": {"operationId": "weatherForecast", "summary": "Weather forecast up to 16 days", "tags": ["Weather"], "parameters": [{"name": "lat", "in": "query", "required": true, "schema": {"type": "number", "minimum": -90, "maximum": 90}}, {"name": "lon", "in": "query", "required": true, "schema": {"type": "number", "minimum": -180, "maximum": 180}}, {"name": "days", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 16, "default": 7}}, {"name": "timezone", "in": "query", "schema": {"type": "string", "default": "UTC"}, "description": "IANA timezone or auto"}, {"name": "current", "in": "query", "schema": {"type": "string"}, "description": "Comma-separated weather variables, at most twelve."}, {"name": "hourly", "in": "query", "schema": {"type": "string"}}, {"name": "daily", "in": "query", "schema": {"type": "string"}}, {"name": "temperature_unit", "in": "query", "schema": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, {"name": "wind_speed_unit", "in": "query", "schema": {"type": "string", "enum": ["kmh", "ms", "mph", "kn"]}}, {"name": "precipitation_unit", "in": "query", "schema": {"type": "string", "enum": ["mm", "inch"]}}], "responses": {"200": {"description": "Open-Meteo weather data and source attribution"}, "400": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}, "401": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}, "403": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}, "429": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}, "503": {"description": "Request rejected. Invalid and failed requests do not consume monthly units."}}}}}}