{"openapi":"3.0.3","info":{"title":"GeoAPI","version":"1.3.0","description":"Public catalog API. Send Authorization: Bearer geoapi_sk_\u2026 from your server. List responses keep data and meta, and add collection. limit defaults to 100 and cannot exceed 1000. per_page is an alias used only when limit is absent. Fuel consumption is litres per 100 km. The dimensions and performance groups are always null because this data is not collected yet. Colors returns every stored color with a verified flag. Models, generations, and colors have photo_url when a checked photo is stored, and GET \/api\/v1\/models\/{id}\/photo returns the image. Document version 1.3.0 matches the deployed catalog. The TypeScript SDK and the CLI (0.2.0) can be installed from https:\/\/geoapi.ge\/downloads. The MCP server is at https:\/\/geoapi.ge\/mcp (same key, limits, and quota). The host is https:\/\/geoapi.ge."},"servers":[{"url":"https:\/\/geoapi.ge"}],"tags":[{"name":"Catalog","description":"Public read-only vehicle catalog. GET only."}],"components":{"securitySchemes":{"secretKey":{"type":"http","scheme":"bearer","description":"Secret server key geoapi_sk_\u2026. geoapi_pk_, a key in the URL query, a cookie, and a cabinet session are not accepted."}},"parameters":{"page":{"name":"page","in":"query","description":"Page number. Default 1. Maximum 1000000.","schema":{"type":"integer","minimum":1,"maximum":1000000,"default":1}},"limit":{"name":"limit","in":"query","description":"Page size, from 1 to 1000. Default 100. per_page is ignored when limit is present.","schema":{"type":"integer","minimum":1,"maximum":1000,"default":100}},"perPage":{"name":"per_page","in":"query","description":"Alias of limit. Ignored when limit is present.","schema":{"type":"integer","minimum":1,"maximum":1000}},"direction":{"name":"direction","in":"query","description":"asc or desc. Default asc. Applied when sort is set.","schema":{"type":"string","enum":["asc","desc"],"default":"asc"}},"q":{"name":"q","in":"query","description":"Case-insensitive substring search, 1 to 100 characters. Brands and models: name or slug. Generations: name or chassis code. Modifications, engines, and fuel: the modification name. Bodies: the body type. Colors: the color name. Control characters are rejected. Not accepted on years.","schema":{"type":"string","minLength":1,"maxLength":100}},"include":{"name":"include","in":"query","description":"specs embeds each row's specs, the same object as \/modifications\/{id}\/specs, so one request returns a full list with specs. Only on modification lists.","schema":{"type":"string","enum":["specs"]}},"modifiedAfter":{"name":"modified_after","in":"query","description":"UTC timestamp. Returns rows whose modified value is newer. Example 2026-01-01T00:00:00Z. Not accepted on years or bodies.","schema":{"type":"string","format":"date-time"}},"yearFrom":{"name":"year_from","in":"query","description":"Inclusive. Matches rows whose year_start to year_end range reaches this year or later. Rows without years always match. Integer from 1886 to 2100. A filter, not a field.","schema":{"type":"integer","minimum":1886,"maximum":2100}},"yearTo":{"name":"year_to","in":"query","description":"Inclusive. Matches rows whose year_start to year_end range starts in this year or earlier. Works alone or with year_from. Rows without years always match. Integer from 1886 to 2100.","schema":{"type":"integer","minimum":1886,"maximum":2100}},"body":{"name":"body","in":"query","description":"Stored body type, up to 64 characters.","schema":{"type":"string","maxLength":64}},"fuel":{"name":"fuel","in":"query","description":"Stored fuel type, up to 64 characters.","schema":{"type":"string","maxLength":64}},"drive":{"name":"drive","in":"query","description":"Stored drive type, up to 64 characters.","schema":{"type":"string","maxLength":64}},"transmission":{"name":"transmission","in":"query","description":"Stored transmission, up to 64 characters.","schema":{"type":"string","maxLength":64}},"brandId":{"name":"brand_id","in":"query","description":"Positive integer id from a brand response. Zero is rejected.","schema":{"type":"integer","minimum":1}},"modelId":{"name":"model_id","in":"query","description":"Positive integer id from a model response. Zero is rejected.","schema":{"type":"integer","minimum":1}},"volumeFrom":{"name":"volume_from","in":"query","description":"Minimum engine volume in cubic centimetres, from 1 to 20000.","schema":{"type":"integer","minimum":1,"maximum":20000}},"volumeTo":{"name":"volume_to","in":"query","description":"Maximum engine volume in cubic centimetres, from 1 to 20000.","schema":{"type":"integer","minimum":1,"maximum":20000}}},"schemas":{"List":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object"}},"meta":{"type":"object","properties":{"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}}},"collection":{"type":"object","properties":{"count":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"},"next":{"type":"string","nullable":true},"prev":{"type":"string","nullable":true},"first":{"type":"string","nullable":true},"last":{"type":"string","nullable":true}}}}},"Error":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"type":"object","additionalProperties":false,"required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}},"Brand":{"type":"object","additionalProperties":false,"required":["id","slug","name","synonyms","is_lcv_or_commercial","logo_url_light","logo_url_dark","modified"],"properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"synonyms":{"type":"array","items":{"type":"string"}},"is_lcv_or_commercial":{"type":"boolean"},"logo_url_light":{"type":"string","nullable":true},"logo_url_dark":{"type":"string","nullable":true},"modified":{"type":"string","nullable":true}}},"Model":{"type":"object","additionalProperties":false,"required":["id","brand_id","slug","name","markets","has_generations","generations_count","photo_url","modified"],"properties":{"id":{"type":"string"},"brand_id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"markets":{"type":"array","items":{"type":"string"}},"has_generations":{"type":"boolean"},"generations_count":{"type":"integer"},"photo_url":{"type":"string","nullable":true,"description":"GET \/api\/v1\/models\/{id}\/photo with the same key returns the image. null when no checked photo is stored."},"modified":{"type":"string","nullable":true}}},"Generation":{"type":"object","additionalProperties":false,"required":["id","model_id","slug","name","year_start","year_end","period_text","body_type","body_types","chassis_code","steering_wheel","market","display_label","photo_url","modified"],"properties":{"id":{"type":"string"},"model_id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string","nullable":true},"year_start":{"type":"integer","nullable":true},"year_end":{"type":"integer","nullable":true},"period_text":{"type":"string","nullable":true},"body_type":{"type":"string","nullable":true,"description":"Set only when every row in the chassis group has the same body. Otherwise null; read body_types."},"body_types":{"type":"array","items":{"type":"string"},"description":"Every body type in the chassis group, sorted by name. Empty when no row has a body type."},"chassis_code":{"type":"string","nullable":true},"steering_wheel":{"type":"string","nullable":true},"market":{"type":"string","nullable":true,"description":"Always null for now."},"display_label":{"type":"string"},"photo_url":{"type":"string","nullable":true,"description":"Set only when the model photo was taken of this generation. GET it with the same key to receive the image."},"modified":{"type":"string","nullable":true}}},"Year":{"type":"object","additionalProperties":false,"required":["id","year"],"properties":{"id":{"type":"string"},"year":{"type":"integer"}}},"GenerationModification":{"type":"object","additionalProperties":false,"required":["id","generation_id","name","engine_volume_cc","transmission","drive_type","body_type","year_start","year_end","modified"],"properties":{"id":{"type":"string"},"generation_id":{"type":"string"},"name":{"type":"string"},"engine_volume_cc":{"type":"integer","nullable":true},"transmission":{"type":"string","nullable":true},"drive_type":{"type":"string","nullable":true},"body_type":{"type":"string","nullable":true},"year_start":{"type":"integer","nullable":true},"year_end":{"type":"integer","nullable":true},"modified":{"type":"string","nullable":true},"specs":{"allOf":[{"$ref":"#\/components\/schemas\/ModificationSpecs"}],"nullable":true,"description":"Present only with include=specs. Same object as GET \/api\/v1\/modifications\/{id}\/specs."}}},"ModificationSearch":{"type":"object","additionalProperties":false,"required":["id","name","brand_id","model_id","generation_id","engine_volume_cc","transmission","drive_type","body_type","fuel","year_start","year_end","modified"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"brand_id":{"type":"string"},"model_id":{"type":"string"},"generation_id":{"type":"string","nullable":true},"engine_volume_cc":{"type":"integer","nullable":true},"transmission":{"type":"string","nullable":true},"drive_type":{"type":"string","nullable":true},"body_type":{"type":"string","nullable":true},"fuel":{"type":"string","nullable":true},"year_start":{"type":"integer","nullable":true},"year_end":{"type":"integer","nullable":true},"modified":{"type":"string","nullable":true},"specs":{"allOf":[{"$ref":"#\/components\/schemas\/ModificationSpecs"}],"nullable":true,"description":"Present only with include=specs. Same object as GET \/api\/v1\/modifications\/{id}\/specs."}}},"Modification":{"type":"object","additionalProperties":false,"required":["id","name","engine_volume_cc","transmission","drive_type","body_type","year_start","year_end","brand","model","generation","modified"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"engine_volume_cc":{"type":"integer","nullable":true},"transmission":{"type":"string","nullable":true},"drive_type":{"type":"string","nullable":true},"body_type":{"type":"string","nullable":true},"year_start":{"type":"integer","nullable":true},"year_end":{"type":"integer","nullable":true},"brand":{"type":"object","additionalProperties":false,"required":["id","slug","name"],"properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"}}},"model":{"type":"object","additionalProperties":false,"required":["id","slug","name"],"properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"}}},"generation":{"type":"object","additionalProperties":false,"required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string","nullable":true}},"nullable":true},"modified":{"type":"string","nullable":true}}},"ModificationSpecs":{"type":"object","additionalProperties":false,"required":["modification_id","engine","transmission","dimensions","performance","consumption"],"properties":{"modification_id":{"type":"string"},"engine":{"type":"object","additionalProperties":false,"required":["volume_cc","fuel","power_hp"],"properties":{"volume_cc":{"type":"integer","nullable":true},"fuel":{"type":"string","nullable":true},"power_hp":{"type":"number","nullable":true}}},"transmission":{"type":"object","additionalProperties":false,"required":["type","drive"],"properties":{"type":{"type":"string","nullable":true},"drive":{"type":"string","nullable":true}}},"dimensions":{"type":"object","nullable":true,"description":"Always null. Dimensions are not collected yet."},"performance":{"type":"object","nullable":true,"description":"Always null. Performance data is not collected yet. power_hp is in engine."},"consumption":{"type":"object","additionalProperties":false,"required":["city_l","highway_l","combined_l","unit"],"properties":{"city_l":{"type":"number","nullable":true},"highway_l":{"type":"number","nullable":true},"combined_l":{"type":"number","nullable":true},"unit":{"type":"string"}}}}},"EquipmentItem":{"type":"object","additionalProperties":false,"required":["id","category","name","value"],"properties":{"id":{"type":"string"},"category":{"type":"string","nullable":true},"name":{"type":"string"},"value":{"type":"string","nullable":true}}},"ModificationEquipment":{"type":"object","additionalProperties":false,"required":["modification_id","standard","optional","not_available","unknown"],"properties":{"modification_id":{"type":"string"},"standard":{"type":"array","items":{"$ref":"#\/components\/schemas\/EquipmentItem"}},"optional":{"type":"array","items":{"$ref":"#\/components\/schemas\/EquipmentItem"}},"not_available":{"type":"array","items":{"$ref":"#\/components\/schemas\/EquipmentItem"}},"unknown":{"type":"array","items":{"$ref":"#\/components\/schemas\/EquipmentItem"}}}},"Engine":{"type":"object","additionalProperties":false,"required":["id","volume_cc","fuel","power_hp","brand_id","model_id","modified"],"properties":{"id":{"type":"string"},"volume_cc":{"type":"integer","nullable":true},"fuel":{"type":"string","nullable":true},"power_hp":{"type":"number","nullable":true},"brand_id":{"type":"string"},"model_id":{"type":"string"},"modified":{"type":"string","nullable":true}}},"Body":{"type":"object","additionalProperties":false,"required":["id","name","count","modified"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"count":{"type":"integer"},"modified":{"type":"string","nullable":true}}},"Fuel":{"type":"object","additionalProperties":false,"required":["id","fuel","city_l","highway_l","combined_l","brand_id","model_id","modified"],"properties":{"id":{"type":"string"},"fuel":{"type":"string","nullable":true},"city_l":{"type":"number","nullable":true},"highway_l":{"type":"number","nullable":true},"combined_l":{"type":"number","nullable":true},"brand_id":{"type":"string"},"model_id":{"type":"string"},"modified":{"type":"string","nullable":true}}},"Color":{"type":"object","additionalProperties":false,"required":["id","model_id","brand_id","name","verified","photo_url","modified"],"properties":{"id":{"type":"string","description":"The model id. Several colors of one model share it, so it is not unique."},"model_id":{"type":"string"},"brand_id":{"type":"string"},"name":{"type":"string"},"verified":{"type":"boolean"},"photo_url":{"type":"string","nullable":true,"description":"The photo with this color. null when verified is false or no image is stored."},"modified":{"type":"string","nullable":true}}},"Coverage":{"type":"object","additionalProperties":false,"required":["brands_count","models_count","generations_count","models_with_generations_count","models_without_generations_count","modifications_count","photos_count","generations_with_photo_urls_count","measured_at"],"properties":{"brands_count":{"type":"integer"},"models_count":{"type":"integer"},"generations_count":{"type":"integer","description":"Generations as the generation lists return them: one per chassis of a model. The same number appears on the home page."},"models_with_generations_count":{"type":"integer"},"models_without_generations_count":{"type":"integer"},"modifications_count":{"type":"integer"},"photos_count":{"type":"integer","description":"Checked photos that GET \/api\/v1\/models\/{id}\/photo serves. A model has at most one photo, so this is also the number of models whose photo_url is set."},"generations_with_photo_urls_count":{"type":"integer","description":"Generations whose photo_url is set. A photo marks at most one generation of its model, so this is never more than photos_count. A photo stored without a generation counts only in photos_count."},"measured_at":{"type":"string"}}}}},"security":[{"secretKey":[]}],"paths":{"\/api\/v1\/brands":{"get":{"tags":["Catalog"],"operationId":"listBrands","summary":"Brands","description":"Brand list. page defaults to 1. limit defaults to 100 and cannot exceed 1000. per_page is the same parameter when limit is omitted. sort is name, id, or modified. direction is asc or desc. q searches the name and the slug.\n\nPagination: page defaults to 1 (maximum 1000000). limit defaults to 100 and cannot exceed 1000. per_page is used only when limit is absent. direction defaults to asc and applies when sort is set. Without sort, this resource keeps its default order. REST year lists are ascending. The widget list starts with the newest year.\n\nAuthentication: send Authorization: Bearer geoapi_sk_\u2026 from your server. A key in the URL query, a cookie, or a cabinet session is not accepted. geoapi_pk_ is the widget key and does not work here. A cabinet personal access token with cars:read or * also needs X-GEOAPI-PROJECT with the id of one of your active projects. A secret key ignores X-GEOAPI-PROJECT. Before using a key, confirm your email. The Cars API is on by default; if you turned it off at \/account\/products, the key gets 403.\n\nError bodies are JSON with only error.code and error.message: 401 unauthorized, 403 forbidden, 404 not_found, 405 method_not_allowed, 422 invalid_parameter, 429 RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED, 503 unavailable. The key is checked before the method, so a non-GET request without a valid key returns 401, not 405. 405 is returned only after the key is accepted. Use GET or HEAD. One IP address may send 300 requests a minute. That limit is checked before the key, so it can return 429 before 401. Every response has an X-Request-Id header; send your own X-Request-Id to trace a request.\n\nLimits: one workspace subscription, one monthly quota, and one minute limit shared by all its projects and the widget. Free: 1 000 successful requests a month, 1 project, 15 requests a minute. Starter: 25 000 successful requests a month, 3 projects, 60 requests a minute. Growth: 150 000 successful requests a month, 10 projects, 120 requests a minute. The quota resets every billing month, including on a yearly payment. Prepaid packs (90 days) are spent after the quota and are included in X-Quota-Remaining. Older plans may still be unlimited and then send X-Quota-Limit: unlimited. A per-project cap is optional and returns PROJECT_CAP_EXCEEDED. There is no daily limit. If the request cannot be counted, the API returns 503.\n\nData: ids are strings. null means the value is unknown. dimensions and performance are always null. Colors include unchecked rows with verified false, and a color id is the model id. photo_url is set when a checked photo is stored; GET it with the same key to receive the image. VIN lookup is not available.\n\nVersion 1.3.0 at https:\/\/geoapi.ge. The TypeScript SDK and the CLI (0.2.0) can be installed from https:\/\/geoapi.ge\/downloads. The MCP server is at https:\/\/geoapi.ge\/mcp (same key, limits, and quota). The widget is the browser embed and uses geoapi_pk_.","parameters":[{"$ref":"#\/components\/parameters\/page"},{"$ref":"#\/components\/parameters\/limit"},{"$ref":"#\/components\/parameters\/perPage"},{"name":"sort","in":"query","description":"Optional. One of name, id, modified. direction applies when sort is set.","schema":{"type":"string","enum":["name","id","modified"]}},{"$ref":"#\/components\/parameters\/direction"},{"$ref":"#\/components\/parameters\/q"},{"$ref":"#\/components\/parameters\/modifiedAfter"}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"X-Quota-Limit":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Remaining":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Reset":{"schema":{"type":"integer"}}},"content":{"application\/json":{"schema":{"allOf":[{"$ref":"#\/components\/schemas\/List"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Brand"}}}}]}}}},"401":{"description":"The key is missing, unknown, revoked, or expired.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unauthorized","message":"\u2026"}}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"403":{"description":"The key is valid, but the project is disabled, the account is suspended, the email is not confirmed, or the Cars API is turned off.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"forbidden","message":"\u2026"}}}}},"404":{"description":"The record or the address was not found.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"not_found","message":"\u2026"}}}}},"405":{"description":"Use GET or HEAD.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"method_not_allowed","message":"\u2026"}}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"422":{"description":"A parameter is invalid or is not accepted on this route.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"invalid_parameter","message":"\u2026"}}}}},"429":{"description":"RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"\u2026"}}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"Retry-After":{"schema":{"type":"integer"}}}},"503":{"description":"The catalog or the request counter is temporarily unavailable.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unavailable","message":"\u2026"}}}}}},"x-codeSamples":[{"lang":"curl","source":"curl \"https:\/\/geoapi.ge\/api\/v1\/brands?limit=1\" \\\n  -H \"Authorization: Bearer geoapi_sk_\u2026\""},{"lang":"Node.js","source":"\/\/ Server-side only: a geoapi_sk_ key must never reach the browser. In a web page use the widget (geoapi_pk_).\nconst response = await fetch(\"https:\/\/geoapi.ge\/api\/v1\/brands?limit=1\", {\n  headers: { Authorization: 'Bearer geoapi_sk_\u2026' },\n});\nconsole.log(await response.json());"},{"lang":"Python","source":"import urllib.request\nrequest = urllib.request.Request(\"https:\/\/geoapi.ge\/api\/v1\/brands?limit=1\", headers={'Authorization': 'Bearer geoapi_sk_\u2026'})\nprint(urllib.request.urlopen(request).read().decode())"},{"lang":"PHP","source":"$ch = curl_init(\"https:\/\/geoapi.ge\/api\/v1\/brands?limit=1\");\ncurl_setopt_array($ch, [\n    CURLOPT_HTTPHEADER => ['Authorization: Bearer geoapi_sk_\u2026'],\n    CURLOPT_RETURNTRANSFER => true,\n]);\necho curl_exec($ch);"}],"x-geoapi-example":"\/api\/v1\/brands?limit=1","x-geoapi-kind":"brands","x-geoapi-mode":"list"}},"\/api\/v1\/brands\/{slug}\/models":{"get":{"tags":["Catalog"],"operationId":"listBrandModels","summary":"Models for one brand slug","description":"Models for one brand. The slug comes from the brands response. body filters by body type.\n\nPagination: page defaults to 1 (maximum 1000000). limit defaults to 100 and cannot exceed 1000. per_page is used only when limit is absent. direction defaults to asc and applies when sort is set. Without sort, this resource keeps its default order. REST year lists are ascending. The widget list starts with the newest year.\n\nAuthentication: send Authorization: Bearer geoapi_sk_\u2026 from your server. A key in the URL query, a cookie, or a cabinet session is not accepted. geoapi_pk_ is the widget key and does not work here. A cabinet personal access token with cars:read or * also needs X-GEOAPI-PROJECT with the id of one of your active projects. A secret key ignores X-GEOAPI-PROJECT. Before using a key, confirm your email. The Cars API is on by default; if you turned it off at \/account\/products, the key gets 403.\n\nError bodies are JSON with only error.code and error.message: 401 unauthorized, 403 forbidden, 404 not_found, 405 method_not_allowed, 422 invalid_parameter, 429 RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED, 503 unavailable. The key is checked before the method, so a non-GET request without a valid key returns 401, not 405. 405 is returned only after the key is accepted. Use GET or HEAD. One IP address may send 300 requests a minute. That limit is checked before the key, so it can return 429 before 401. Every response has an X-Request-Id header; send your own X-Request-Id to trace a request.\n\nLimits: one workspace subscription, one monthly quota, and one minute limit shared by all its projects and the widget. Free: 1 000 successful requests a month, 1 project, 15 requests a minute. Starter: 25 000 successful requests a month, 3 projects, 60 requests a minute. Growth: 150 000 successful requests a month, 10 projects, 120 requests a minute. The quota resets every billing month, including on a yearly payment. Prepaid packs (90 days) are spent after the quota and are included in X-Quota-Remaining. Older plans may still be unlimited and then send X-Quota-Limit: unlimited. A per-project cap is optional and returns PROJECT_CAP_EXCEEDED. There is no daily limit. If the request cannot be counted, the API returns 503.\n\nData: ids are strings. null means the value is unknown. dimensions and performance are always null. Colors include unchecked rows with verified false, and a color id is the model id. photo_url is set when a checked photo is stored; GET it with the same key to receive the image. VIN lookup is not available.\n\nVersion 1.3.0 at https:\/\/geoapi.ge. The TypeScript SDK and the CLI (0.2.0) can be installed from https:\/\/geoapi.ge\/downloads. The MCP server is at https:\/\/geoapi.ge\/mcp (same key, limits, and quota). The widget is the browser embed and uses geoapi_pk_.","parameters":[{"name":"slug","in":"path","required":true,"description":"Brand slug from the brands response. An unknown slug returns 404.","schema":{"type":"string"}},{"$ref":"#\/components\/parameters\/page"},{"$ref":"#\/components\/parameters\/limit"},{"$ref":"#\/components\/parameters\/perPage"},{"name":"sort","in":"query","description":"Optional. One of name, id, modified. direction applies when sort is set.","schema":{"type":"string","enum":["name","id","modified"]}},{"$ref":"#\/components\/parameters\/direction"},{"$ref":"#\/components\/parameters\/q"},{"$ref":"#\/components\/parameters\/modifiedAfter"},{"$ref":"#\/components\/parameters\/body"}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"X-Quota-Limit":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Remaining":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Reset":{"schema":{"type":"integer"}}},"content":{"application\/json":{"schema":{"allOf":[{"$ref":"#\/components\/schemas\/List"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Model"}}}}]}}}},"401":{"description":"The key is missing, unknown, revoked, or expired.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unauthorized","message":"\u2026"}}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"403":{"description":"The key is valid, but the project is disabled, the account is suspended, the email is not confirmed, or the Cars API is turned off.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"forbidden","message":"\u2026"}}}}},"404":{"description":"The record or the address was not found.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"not_found","message":"\u2026"}}}}},"405":{"description":"Use GET or HEAD.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"method_not_allowed","message":"\u2026"}}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"422":{"description":"A parameter is invalid or is not accepted on this route.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"invalid_parameter","message":"\u2026"}}}}},"429":{"description":"RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"\u2026"}}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"Retry-After":{"schema":{"type":"integer"}}}},"503":{"description":"The catalog or the request counter is temporarily unavailable.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unavailable","message":"\u2026"}}}}}},"x-codeSamples":[{"lang":"curl","source":"curl \"https:\/\/geoapi.ge\/api\/v1\/brands\/toyota\/models?limit=1\" \\\n  -H \"Authorization: Bearer geoapi_sk_\u2026\""},{"lang":"Node.js","source":"\/\/ Server-side only: a geoapi_sk_ key must never reach the browser. In a web page use the widget (geoapi_pk_).\nconst response = await fetch(\"https:\/\/geoapi.ge\/api\/v1\/brands\/toyota\/models?limit=1\", {\n  headers: { Authorization: 'Bearer geoapi_sk_\u2026' },\n});\nconsole.log(await response.json());"},{"lang":"Python","source":"import urllib.request\nrequest = urllib.request.Request(\"https:\/\/geoapi.ge\/api\/v1\/brands\/toyota\/models?limit=1\", headers={'Authorization': 'Bearer geoapi_sk_\u2026'})\nprint(urllib.request.urlopen(request).read().decode())"},{"lang":"PHP","source":"$ch = curl_init(\"https:\/\/geoapi.ge\/api\/v1\/brands\/toyota\/models?limit=1\");\ncurl_setopt_array($ch, [\n    CURLOPT_HTTPHEADER => ['Authorization: Bearer geoapi_sk_\u2026'],\n    CURLOPT_RETURNTRANSFER => true,\n]);\necho curl_exec($ch);"}],"x-geoapi-example":"\/api\/v1\/brands\/toyota\/models?limit=1","x-geoapi-kind":"models","x-geoapi-mode":"list"}},"\/api\/v1\/models\/{id}\/years":{"get":{"tags":["Catalog"],"operationId":"listModelYears","summary":"Years covered by one model. The list stops at the current UTC year.","description":"Years for one model, from the year_start and year_end of its generations and modifications. The list stops at the current UTC year. q, modified_after, year_from, and year_to return 422.\n\nPagination: page defaults to 1 (maximum 1000000). limit defaults to 100 and cannot exceed 1000. per_page is used only when limit is absent. direction defaults to asc and applies when sort is set. Without sort, this resource keeps its default order. REST year lists are ascending. The widget list starts with the newest year.\n\nAuthentication: send Authorization: Bearer geoapi_sk_\u2026 from your server. A key in the URL query, a cookie, or a cabinet session is not accepted. geoapi_pk_ is the widget key and does not work here. A cabinet personal access token with cars:read or * also needs X-GEOAPI-PROJECT with the id of one of your active projects. A secret key ignores X-GEOAPI-PROJECT. Before using a key, confirm your email. The Cars API is on by default; if you turned it off at \/account\/products, the key gets 403.\n\nError bodies are JSON with only error.code and error.message: 401 unauthorized, 403 forbidden, 404 not_found, 405 method_not_allowed, 422 invalid_parameter, 429 RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED, 503 unavailable. The key is checked before the method, so a non-GET request without a valid key returns 401, not 405. 405 is returned only after the key is accepted. Use GET or HEAD. One IP address may send 300 requests a minute. That limit is checked before the key, so it can return 429 before 401. Every response has an X-Request-Id header; send your own X-Request-Id to trace a request.\n\nLimits: one workspace subscription, one monthly quota, and one minute limit shared by all its projects and the widget. Free: 1 000 successful requests a month, 1 project, 15 requests a minute. Starter: 25 000 successful requests a month, 3 projects, 60 requests a minute. Growth: 150 000 successful requests a month, 10 projects, 120 requests a minute. The quota resets every billing month, including on a yearly payment. Prepaid packs (90 days) are spent after the quota and are included in X-Quota-Remaining. Older plans may still be unlimited and then send X-Quota-Limit: unlimited. A per-project cap is optional and returns PROJECT_CAP_EXCEEDED. There is no daily limit. If the request cannot be counted, the API returns 503.\n\nData: ids are strings. null means the value is unknown. dimensions and performance are always null. Colors include unchecked rows with verified false, and a color id is the model id. photo_url is set when a checked photo is stored; GET it with the same key to receive the image. VIN lookup is not available.\n\nVersion 1.3.0 at https:\/\/geoapi.ge. The TypeScript SDK and the CLI (0.2.0) can be installed from https:\/\/geoapi.ge\/downloads. The MCP server is at https:\/\/geoapi.ge\/mcp (same key, limits, and quota). The widget is the browser embed and uses geoapi_pk_.","parameters":[{"name":"id","in":"path","required":true,"description":"Positive model id. Zero or a non-numeric id returns 422. An unknown id returns 404.","schema":{"type":"integer","minimum":1}},{"$ref":"#\/components\/parameters\/page"},{"$ref":"#\/components\/parameters\/limit"},{"$ref":"#\/components\/parameters\/perPage"},{"name":"sort","in":"query","description":"Optional. One of year, id. direction applies when sort is set.","schema":{"type":"string","enum":["year","id"]}},{"$ref":"#\/components\/parameters\/direction"}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"X-Quota-Limit":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Remaining":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Reset":{"schema":{"type":"integer"}}},"content":{"application\/json":{"schema":{"allOf":[{"$ref":"#\/components\/schemas\/List"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Year"}}}}]}}}},"401":{"description":"The key is missing, unknown, revoked, or expired.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unauthorized","message":"\u2026"}}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"403":{"description":"The key is valid, but the project is disabled, the account is suspended, the email is not confirmed, or the Cars API is turned off.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"forbidden","message":"\u2026"}}}}},"404":{"description":"The record or the address was not found.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"not_found","message":"\u2026"}}}}},"405":{"description":"Use GET or HEAD.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"method_not_allowed","message":"\u2026"}}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"422":{"description":"A parameter is invalid or is not accepted on this route.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"invalid_parameter","message":"\u2026"}}}}},"429":{"description":"RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"\u2026"}}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"Retry-After":{"schema":{"type":"integer"}}}},"503":{"description":"The catalog or the request counter is temporarily unavailable.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unavailable","message":"\u2026"}}}}}},"x-codeSamples":[{"lang":"curl","source":"curl \"https:\/\/geoapi.ge\/api\/v1\/models\/690\/years?limit=1\" \\\n  -H \"Authorization: Bearer geoapi_sk_\u2026\""},{"lang":"Node.js","source":"\/\/ Server-side only: a geoapi_sk_ key must never reach the browser. In a web page use the widget (geoapi_pk_).\nconst response = await fetch(\"https:\/\/geoapi.ge\/api\/v1\/models\/690\/years?limit=1\", {\n  headers: { Authorization: 'Bearer geoapi_sk_\u2026' },\n});\nconsole.log(await response.json());"},{"lang":"Python","source":"import urllib.request\nrequest = urllib.request.Request(\"https:\/\/geoapi.ge\/api\/v1\/models\/690\/years?limit=1\", headers={'Authorization': 'Bearer geoapi_sk_\u2026'})\nprint(urllib.request.urlopen(request).read().decode())"},{"lang":"PHP","source":"$ch = curl_init(\"https:\/\/geoapi.ge\/api\/v1\/models\/690\/years?limit=1\");\ncurl_setopt_array($ch, [\n    CURLOPT_HTTPHEADER => ['Authorization: Bearer geoapi_sk_\u2026'],\n    CURLOPT_RETURNTRANSFER => true,\n]);\necho curl_exec($ch);"}],"x-geoapi-example":"\/api\/v1\/models\/690\/years?limit=1","x-geoapi-kind":"years","x-geoapi-mode":"list"}},"\/api\/v1\/models\/{id}\/generations":{"get":{"tags":["Catalog"],"operationId":"listModelGenerations","summary":"Generations grouped by chassis for one model id","description":"Generations for one model, grouped by chassis. The public id is the smallest id in the chassis group. Filter with year_from, year_to, and body.\n\nPagination: page defaults to 1 (maximum 1000000). limit defaults to 100 and cannot exceed 1000. per_page is used only when limit is absent. direction defaults to asc and applies when sort is set. Without sort, this resource keeps its default order. REST year lists are ascending. The widget list starts with the newest year.\n\nAuthentication: send Authorization: Bearer geoapi_sk_\u2026 from your server. A key in the URL query, a cookie, or a cabinet session is not accepted. geoapi_pk_ is the widget key and does not work here. A cabinet personal access token with cars:read or * also needs X-GEOAPI-PROJECT with the id of one of your active projects. A secret key ignores X-GEOAPI-PROJECT. Before using a key, confirm your email. The Cars API is on by default; if you turned it off at \/account\/products, the key gets 403.\n\nError bodies are JSON with only error.code and error.message: 401 unauthorized, 403 forbidden, 404 not_found, 405 method_not_allowed, 422 invalid_parameter, 429 RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED, 503 unavailable. The key is checked before the method, so a non-GET request without a valid key returns 401, not 405. 405 is returned only after the key is accepted. Use GET or HEAD. One IP address may send 300 requests a minute. That limit is checked before the key, so it can return 429 before 401. Every response has an X-Request-Id header; send your own X-Request-Id to trace a request.\n\nLimits: one workspace subscription, one monthly quota, and one minute limit shared by all its projects and the widget. Free: 1 000 successful requests a month, 1 project, 15 requests a minute. Starter: 25 000 successful requests a month, 3 projects, 60 requests a minute. Growth: 150 000 successful requests a month, 10 projects, 120 requests a minute. The quota resets every billing month, including on a yearly payment. Prepaid packs (90 days) are spent after the quota and are included in X-Quota-Remaining. Older plans may still be unlimited and then send X-Quota-Limit: unlimited. A per-project cap is optional and returns PROJECT_CAP_EXCEEDED. There is no daily limit. If the request cannot be counted, the API returns 503.\n\nData: ids are strings. null means the value is unknown. dimensions and performance are always null. Colors include unchecked rows with verified false, and a color id is the model id. photo_url is set when a checked photo is stored; GET it with the same key to receive the image. VIN lookup is not available.\n\nVersion 1.3.0 at https:\/\/geoapi.ge. The TypeScript SDK and the CLI (0.2.0) can be installed from https:\/\/geoapi.ge\/downloads. The MCP server is at https:\/\/geoapi.ge\/mcp (same key, limits, and quota). The widget is the browser embed and uses geoapi_pk_.","parameters":[{"name":"id","in":"path","required":true,"description":"Positive model id. Zero or a non-numeric id returns 422. An unknown id returns 404.","schema":{"type":"integer","minimum":1}},{"$ref":"#\/components\/parameters\/page"},{"$ref":"#\/components\/parameters\/limit"},{"$ref":"#\/components\/parameters\/perPage"},{"name":"sort","in":"query","description":"Optional. One of year_start, name, id, modified. direction applies when sort is set.","schema":{"type":"string","enum":["year_start","name","id","modified"]}},{"$ref":"#\/components\/parameters\/direction"},{"$ref":"#\/components\/parameters\/q"},{"$ref":"#\/components\/parameters\/modifiedAfter"},{"$ref":"#\/components\/parameters\/yearFrom"},{"$ref":"#\/components\/parameters\/yearTo"},{"$ref":"#\/components\/parameters\/body"}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"X-Quota-Limit":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Remaining":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Reset":{"schema":{"type":"integer"}}},"content":{"application\/json":{"schema":{"allOf":[{"$ref":"#\/components\/schemas\/List"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Generation"}}}}]}}}},"401":{"description":"The key is missing, unknown, revoked, or expired.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unauthorized","message":"\u2026"}}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"403":{"description":"The key is valid, but the project is disabled, the account is suspended, the email is not confirmed, or the Cars API is turned off.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"forbidden","message":"\u2026"}}}}},"404":{"description":"The record or the address was not found.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"not_found","message":"\u2026"}}}}},"405":{"description":"Use GET or HEAD.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"method_not_allowed","message":"\u2026"}}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"422":{"description":"A parameter is invalid or is not accepted on this route.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"invalid_parameter","message":"\u2026"}}}}},"429":{"description":"RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"\u2026"}}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"Retry-After":{"schema":{"type":"integer"}}}},"503":{"description":"The catalog or the request counter is temporarily unavailable.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unavailable","message":"\u2026"}}}}}},"x-codeSamples":[{"lang":"curl","source":"curl \"https:\/\/geoapi.ge\/api\/v1\/models\/690\/generations?limit=1\" \\\n  -H \"Authorization: Bearer geoapi_sk_\u2026\""},{"lang":"Node.js","source":"\/\/ Server-side only: a geoapi_sk_ key must never reach the browser. In a web page use the widget (geoapi_pk_).\nconst response = await fetch(\"https:\/\/geoapi.ge\/api\/v1\/models\/690\/generations?limit=1\", {\n  headers: { Authorization: 'Bearer geoapi_sk_\u2026' },\n});\nconsole.log(await response.json());"},{"lang":"Python","source":"import urllib.request\nrequest = urllib.request.Request(\"https:\/\/geoapi.ge\/api\/v1\/models\/690\/generations?limit=1\", headers={'Authorization': 'Bearer geoapi_sk_\u2026'})\nprint(urllib.request.urlopen(request).read().decode())"},{"lang":"PHP","source":"$ch = curl_init(\"https:\/\/geoapi.ge\/api\/v1\/models\/690\/generations?limit=1\");\ncurl_setopt_array($ch, [\n    CURLOPT_HTTPHEADER => ['Authorization: Bearer geoapi_sk_\u2026'],\n    CURLOPT_RETURNTRANSFER => true,\n]);\necho curl_exec($ch);"}],"x-geoapi-example":"\/api\/v1\/models\/690\/generations?limit=1","x-geoapi-kind":"generations","x-geoapi-mode":"list"}},"\/api\/v1\/models\/{id}\/photo":{"get":{"tags":["Catalog"],"operationId":"getModelPhoto","summary":"The checked photo of one model, as an image.","description":"The checked photo of one model. The response body is the image, without a watermark. A model without a checked photo returns 404. Take the URL from photo_url instead of building it, so you call it only when a photo exists. Each success counts as one request.\n\nThis route returns image bytes, not JSON. Content-Type is image\/jpeg, image\/png, image\/webp, or image\/gif. Errors are still JSON. Query parameters are ignored. ETag and If-None-Match work as on JSON routes.\n\nAuthentication: send Authorization: Bearer geoapi_sk_\u2026 from your server. A key in the URL query, a cookie, or a cabinet session is not accepted. geoapi_pk_ is the widget key and does not work here. A cabinet personal access token with cars:read or * also needs X-GEOAPI-PROJECT with the id of one of your active projects. A secret key ignores X-GEOAPI-PROJECT. Before using a key, confirm your email. The Cars API is on by default; if you turned it off at \/account\/products, the key gets 403.\n\nError bodies are JSON with only error.code and error.message: 401 unauthorized, 403 forbidden, 404 not_found, 405 method_not_allowed, 422 invalid_parameter, 429 RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED, 503 unavailable. The key is checked before the method, so a non-GET request without a valid key returns 401, not 405. 405 is returned only after the key is accepted. Use GET or HEAD. One IP address may send 300 requests a minute. That limit is checked before the key, so it can return 429 before 401. Every response has an X-Request-Id header; send your own X-Request-Id to trace a request.\n\nLimits: one workspace subscription, one monthly quota, and one minute limit shared by all its projects and the widget. Free: 1 000 successful requests a month, 1 project, 15 requests a minute. Starter: 25 000 successful requests a month, 3 projects, 60 requests a minute. Growth: 150 000 successful requests a month, 10 projects, 120 requests a minute. The quota resets every billing month, including on a yearly payment. Prepaid packs (90 days) are spent after the quota and are included in X-Quota-Remaining. Older plans may still be unlimited and then send X-Quota-Limit: unlimited. A per-project cap is optional and returns PROJECT_CAP_EXCEEDED. There is no daily limit. If the request cannot be counted, the API returns 503.\n\nData: ids are strings. null means the value is unknown. dimensions and performance are always null. Colors include unchecked rows with verified false, and a color id is the model id. photo_url is set when a checked photo is stored; GET it with the same key to receive the image. VIN lookup is not available.\n\nVersion 1.3.0 at https:\/\/geoapi.ge. The TypeScript SDK and the CLI (0.2.0) can be installed from https:\/\/geoapi.ge\/downloads. The MCP server is at https:\/\/geoapi.ge\/mcp (same key, limits, and quota). The widget is the browser embed and uses geoapi_pk_.","parameters":[{"name":"id","in":"path","required":true,"description":"Positive model id. Zero or a non-numeric id returns 422. An unknown id returns 404.","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"X-Quota-Limit":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Remaining":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Reset":{"schema":{"type":"integer"}}},"content":{"image\/jpeg":{"schema":{"type":"string","format":"binary"}},"image\/png":{"schema":{"type":"string","format":"binary"}},"image\/webp":{"schema":{"type":"string","format":"binary"}},"image\/gif":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"The key is missing, unknown, revoked, or expired.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unauthorized","message":"\u2026"}}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"403":{"description":"The key is valid, but the project is disabled, the account is suspended, the email is not confirmed, or the Cars API is turned off.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"forbidden","message":"\u2026"}}}}},"404":{"description":"The model is unknown or has no checked photo.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"not_found","message":"\u2026"}}}}},"405":{"description":"Use GET or HEAD.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"method_not_allowed","message":"\u2026"}}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"422":{"description":"A parameter is invalid or is not accepted on this route.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"invalid_parameter","message":"\u2026"}}}}},"429":{"description":"RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"\u2026"}}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"Retry-After":{"schema":{"type":"integer"}}}},"503":{"description":"The catalog or the request counter is temporarily unavailable.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unavailable","message":"\u2026"}}}}}},"x-codeSamples":[{"lang":"curl","source":"curl \"https:\/\/geoapi.ge\/api\/v1\/models\/690\/photo\" \\\n  -H \"Authorization: Bearer geoapi_sk_\u2026\" \\\n  -o photo.jpg"},{"lang":"Node.js","source":"\/\/ Server-side only. Fetch the photo with the secret key, then serve or store it yourself.\nconst response = await fetch(\"https:\/\/geoapi.ge\/api\/v1\/models\/690\/photo\", {\n  headers: { Authorization: 'Bearer geoapi_sk_\u2026' },\n});\nif (response.ok) {\n  const type = response.headers.get('Content-Type');\n  const bytes = Buffer.from(await response.arrayBuffer());\n}"},{"lang":"Python","source":"import urllib.request\nrequest = urllib.request.Request(\"https:\/\/geoapi.ge\/api\/v1\/models\/690\/photo\", headers={'Authorization': 'Bearer geoapi_sk_\u2026'})\nwith urllib.request.urlopen(request) as response:\n    open('photo.jpg', 'wb').write(response.read())"},{"lang":"PHP","source":"$ch = curl_init(\"https:\/\/geoapi.ge\/api\/v1\/models\/690\/photo\");\ncurl_setopt_array($ch, [\n    CURLOPT_HTTPHEADER => ['Authorization: Bearer geoapi_sk_\u2026'],\n    CURLOPT_RETURNTRANSFER => true,\n]);\nfile_put_contents('photo.jpg', curl_exec($ch));"}],"x-geoapi-example":"\/api\/v1\/models\/690\/photo","x-geoapi-kind":"model_photo","x-geoapi-mode":"photo"}},"\/api\/v1\/generations\/{id}\/modifications":{"get":{"tags":["Catalog"],"operationId":"listGenerationModifications","summary":"Modifications for one public generation id","description":"Modifications for one public generation id. Filters: year_from, year_to, body, fuel, drive, and transmission.\n\nPagination: page defaults to 1 (maximum 1000000). limit defaults to 100 and cannot exceed 1000. per_page is used only when limit is absent. direction defaults to asc and applies when sort is set. Without sort, this resource keeps its default order. REST year lists are ascending. The widget list starts with the newest year.\n\nAuthentication: send Authorization: Bearer geoapi_sk_\u2026 from your server. A key in the URL query, a cookie, or a cabinet session is not accepted. geoapi_pk_ is the widget key and does not work here. A cabinet personal access token with cars:read or * also needs X-GEOAPI-PROJECT with the id of one of your active projects. A secret key ignores X-GEOAPI-PROJECT. Before using a key, confirm your email. The Cars API is on by default; if you turned it off at \/account\/products, the key gets 403.\n\nError bodies are JSON with only error.code and error.message: 401 unauthorized, 403 forbidden, 404 not_found, 405 method_not_allowed, 422 invalid_parameter, 429 RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED, 503 unavailable. The key is checked before the method, so a non-GET request without a valid key returns 401, not 405. 405 is returned only after the key is accepted. Use GET or HEAD. One IP address may send 300 requests a minute. That limit is checked before the key, so it can return 429 before 401. Every response has an X-Request-Id header; send your own X-Request-Id to trace a request.\n\nLimits: one workspace subscription, one monthly quota, and one minute limit shared by all its projects and the widget. Free: 1 000 successful requests a month, 1 project, 15 requests a minute. Starter: 25 000 successful requests a month, 3 projects, 60 requests a minute. Growth: 150 000 successful requests a month, 10 projects, 120 requests a minute. The quota resets every billing month, including on a yearly payment. Prepaid packs (90 days) are spent after the quota and are included in X-Quota-Remaining. Older plans may still be unlimited and then send X-Quota-Limit: unlimited. A per-project cap is optional and returns PROJECT_CAP_EXCEEDED. There is no daily limit. If the request cannot be counted, the API returns 503.\n\nData: ids are strings. null means the value is unknown. dimensions and performance are always null. Colors include unchecked rows with verified false, and a color id is the model id. photo_url is set when a checked photo is stored; GET it with the same key to receive the image. VIN lookup is not available.\n\nVersion 1.3.0 at https:\/\/geoapi.ge. The TypeScript SDK and the CLI (0.2.0) can be installed from https:\/\/geoapi.ge\/downloads. The MCP server is at https:\/\/geoapi.ge\/mcp (same key, limits, and quota). The widget is the browser embed and uses geoapi_pk_.","parameters":[{"name":"id","in":"path","required":true,"description":"Positive public generation id. Another id from the same chassis group returns 404.","schema":{"type":"integer","minimum":1}},{"$ref":"#\/components\/parameters\/page"},{"$ref":"#\/components\/parameters\/limit"},{"$ref":"#\/components\/parameters\/perPage"},{"name":"sort","in":"query","description":"Optional. One of name, id, year_start, engine_volume_cc, modified. direction applies when sort is set.","schema":{"type":"string","enum":["name","id","year_start","engine_volume_cc","modified"]}},{"$ref":"#\/components\/parameters\/direction"},{"$ref":"#\/components\/parameters\/q"},{"$ref":"#\/components\/parameters\/modifiedAfter"},{"$ref":"#\/components\/parameters\/include"},{"$ref":"#\/components\/parameters\/yearFrom"},{"$ref":"#\/components\/parameters\/yearTo"},{"$ref":"#\/components\/parameters\/body"},{"$ref":"#\/components\/parameters\/fuel"},{"$ref":"#\/components\/parameters\/drive"},{"$ref":"#\/components\/parameters\/transmission"}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"X-Quota-Limit":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Remaining":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Reset":{"schema":{"type":"integer"}}},"content":{"application\/json":{"schema":{"allOf":[{"$ref":"#\/components\/schemas\/List"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/GenerationModification"}}}}]}}}},"401":{"description":"The key is missing, unknown, revoked, or expired.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unauthorized","message":"\u2026"}}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"403":{"description":"The key is valid, but the project is disabled, the account is suspended, the email is not confirmed, or the Cars API is turned off.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"forbidden","message":"\u2026"}}}}},"404":{"description":"The record or the address was not found.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"not_found","message":"\u2026"}}}}},"405":{"description":"Use GET or HEAD.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"method_not_allowed","message":"\u2026"}}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"422":{"description":"A parameter is invalid or is not accepted on this route.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"invalid_parameter","message":"\u2026"}}}}},"429":{"description":"RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"\u2026"}}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"Retry-After":{"schema":{"type":"integer"}}}},"503":{"description":"The catalog or the request counter is temporarily unavailable.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unavailable","message":"\u2026"}}}}}},"x-codeSamples":[{"lang":"curl","source":"curl \"https:\/\/geoapi.ge\/api\/v1\/generations\/100\/modifications?limit=1\" \\\n  -H \"Authorization: Bearer geoapi_sk_\u2026\""},{"lang":"Node.js","source":"\/\/ Server-side only: a geoapi_sk_ key must never reach the browser. In a web page use the widget (geoapi_pk_).\nconst response = await fetch(\"https:\/\/geoapi.ge\/api\/v1\/generations\/100\/modifications?limit=1\", {\n  headers: { Authorization: 'Bearer geoapi_sk_\u2026' },\n});\nconsole.log(await response.json());"},{"lang":"Python","source":"import urllib.request\nrequest = urllib.request.Request(\"https:\/\/geoapi.ge\/api\/v1\/generations\/100\/modifications?limit=1\", headers={'Authorization': 'Bearer geoapi_sk_\u2026'})\nprint(urllib.request.urlopen(request).read().decode())"},{"lang":"PHP","source":"$ch = curl_init(\"https:\/\/geoapi.ge\/api\/v1\/generations\/100\/modifications?limit=1\");\ncurl_setopt_array($ch, [\n    CURLOPT_HTTPHEADER => ['Authorization: Bearer geoapi_sk_\u2026'],\n    CURLOPT_RETURNTRANSFER => true,\n]);\necho curl_exec($ch);"}],"x-geoapi-example":"\/api\/v1\/generations\/100\/modifications?limit=1","x-geoapi-kind":"modifications","x-geoapi-mode":"list"}},"\/api\/v1\/modifications\/{id}\/specs":{"get":{"tags":["Catalog"],"operationId":"getModificationSpecs","summary":"Engine, transmission, and fuel consumption for one modification. Unknown specification keys are left out.","description":"Engine, transmission, and fuel consumption (L\/100 km) for one modification. Unknown values are null. dimensions and performance are always null. Unknown specification keys are left out.\n\nThis route returns one object in data. It has no pagination. Extra query parameters are ignored.\n\nAuthentication: send Authorization: Bearer geoapi_sk_\u2026 from your server. A key in the URL query, a cookie, or a cabinet session is not accepted. geoapi_pk_ is the widget key and does not work here. A cabinet personal access token with cars:read or * also needs X-GEOAPI-PROJECT with the id of one of your active projects. A secret key ignores X-GEOAPI-PROJECT. Before using a key, confirm your email. The Cars API is on by default; if you turned it off at \/account\/products, the key gets 403.\n\nError bodies are JSON with only error.code and error.message: 401 unauthorized, 403 forbidden, 404 not_found, 405 method_not_allowed, 422 invalid_parameter, 429 RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED, 503 unavailable. The key is checked before the method, so a non-GET request without a valid key returns 401, not 405. 405 is returned only after the key is accepted. Use GET or HEAD. One IP address may send 300 requests a minute. That limit is checked before the key, so it can return 429 before 401. Every response has an X-Request-Id header; send your own X-Request-Id to trace a request.\n\nLimits: one workspace subscription, one monthly quota, and one minute limit shared by all its projects and the widget. Free: 1 000 successful requests a month, 1 project, 15 requests a minute. Starter: 25 000 successful requests a month, 3 projects, 60 requests a minute. Growth: 150 000 successful requests a month, 10 projects, 120 requests a minute. The quota resets every billing month, including on a yearly payment. Prepaid packs (90 days) are spent after the quota and are included in X-Quota-Remaining. Older plans may still be unlimited and then send X-Quota-Limit: unlimited. A per-project cap is optional and returns PROJECT_CAP_EXCEEDED. There is no daily limit. If the request cannot be counted, the API returns 503.\n\nData: ids are strings. null means the value is unknown. dimensions and performance are always null. Colors include unchecked rows with verified false, and a color id is the model id. photo_url is set when a checked photo is stored; GET it with the same key to receive the image. VIN lookup is not available.\n\nVersion 1.3.0 at https:\/\/geoapi.ge. The TypeScript SDK and the CLI (0.2.0) can be installed from https:\/\/geoapi.ge\/downloads. The MCP server is at https:\/\/geoapi.ge\/mcp (same key, limits, and quota). The widget is the browser embed and uses geoapi_pk_.","parameters":[{"name":"id","in":"path","required":true,"description":"Positive modification id. Zero or a non-numeric id returns 422. An unknown id returns 404.","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"X-Quota-Limit":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Remaining":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Reset":{"schema":{"type":"integer"}}},"content":{"application\/json":{"schema":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"$ref":"#\/components\/schemas\/ModificationSpecs"}}}}}},"401":{"description":"The key is missing, unknown, revoked, or expired.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unauthorized","message":"\u2026"}}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"403":{"description":"The key is valid, but the project is disabled, the account is suspended, the email is not confirmed, or the Cars API is turned off.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"forbidden","message":"\u2026"}}}}},"404":{"description":"The record or the address was not found.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"not_found","message":"\u2026"}}}}},"405":{"description":"Use GET or HEAD.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"method_not_allowed","message":"\u2026"}}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"422":{"description":"A parameter is invalid or is not accepted on this route.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"invalid_parameter","message":"\u2026"}}}}},"429":{"description":"RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"\u2026"}}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"Retry-After":{"schema":{"type":"integer"}}}},"503":{"description":"The catalog or the request counter is temporarily unavailable.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unavailable","message":"\u2026"}}}}}},"x-codeSamples":[{"lang":"curl","source":"curl \"https:\/\/geoapi.ge\/api\/v1\/modifications\/1000\/specs\" \\\n  -H \"Authorization: Bearer geoapi_sk_\u2026\""},{"lang":"Node.js","source":"\/\/ Server-side only: a geoapi_sk_ key must never reach the browser. In a web page use the widget (geoapi_pk_).\nconst response = await fetch(\"https:\/\/geoapi.ge\/api\/v1\/modifications\/1000\/specs\", {\n  headers: { Authorization: 'Bearer geoapi_sk_\u2026' },\n});\nconsole.log(await response.json());"},{"lang":"Python","source":"import urllib.request\nrequest = urllib.request.Request(\"https:\/\/geoapi.ge\/api\/v1\/modifications\/1000\/specs\", headers={'Authorization': 'Bearer geoapi_sk_\u2026'})\nprint(urllib.request.urlopen(request).read().decode())"},{"lang":"PHP","source":"$ch = curl_init(\"https:\/\/geoapi.ge\/api\/v1\/modifications\/1000\/specs\");\ncurl_setopt_array($ch, [\n    CURLOPT_HTTPHEADER => ['Authorization: Bearer geoapi_sk_\u2026'],\n    CURLOPT_RETURNTRANSFER => true,\n]);\necho curl_exec($ch);"}],"x-geoapi-example":"\/api\/v1\/modifications\/1000\/specs","x-geoapi-kind":"ModificationSpecs","x-geoapi-mode":"one"}},"\/api\/v1\/modifications\/{id}\/equipment":{"get":{"tags":["Catalog"],"operationId":"getModificationEquipment","summary":"Equipment grouped as standard, optional, not_available, and unknown.","description":"Equipment for one modification in four groups: standard, optional, not_available, and unknown. Rows with the same category, name, and group are merged.\n\nThis route returns one object in data. It has no pagination. Extra query parameters are ignored.\n\nAuthentication: send Authorization: Bearer geoapi_sk_\u2026 from your server. A key in the URL query, a cookie, or a cabinet session is not accepted. geoapi_pk_ is the widget key and does not work here. A cabinet personal access token with cars:read or * also needs X-GEOAPI-PROJECT with the id of one of your active projects. A secret key ignores X-GEOAPI-PROJECT. Before using a key, confirm your email. The Cars API is on by default; if you turned it off at \/account\/products, the key gets 403.\n\nError bodies are JSON with only error.code and error.message: 401 unauthorized, 403 forbidden, 404 not_found, 405 method_not_allowed, 422 invalid_parameter, 429 RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED, 503 unavailable. The key is checked before the method, so a non-GET request without a valid key returns 401, not 405. 405 is returned only after the key is accepted. Use GET or HEAD. One IP address may send 300 requests a minute. That limit is checked before the key, so it can return 429 before 401. Every response has an X-Request-Id header; send your own X-Request-Id to trace a request.\n\nLimits: one workspace subscription, one monthly quota, and one minute limit shared by all its projects and the widget. Free: 1 000 successful requests a month, 1 project, 15 requests a minute. Starter: 25 000 successful requests a month, 3 projects, 60 requests a minute. Growth: 150 000 successful requests a month, 10 projects, 120 requests a minute. The quota resets every billing month, including on a yearly payment. Prepaid packs (90 days) are spent after the quota and are included in X-Quota-Remaining. Older plans may still be unlimited and then send X-Quota-Limit: unlimited. A per-project cap is optional and returns PROJECT_CAP_EXCEEDED. There is no daily limit. If the request cannot be counted, the API returns 503.\n\nData: ids are strings. null means the value is unknown. dimensions and performance are always null. Colors include unchecked rows with verified false, and a color id is the model id. photo_url is set when a checked photo is stored; GET it with the same key to receive the image. VIN lookup is not available.\n\nVersion 1.3.0 at https:\/\/geoapi.ge. The TypeScript SDK and the CLI (0.2.0) can be installed from https:\/\/geoapi.ge\/downloads. The MCP server is at https:\/\/geoapi.ge\/mcp (same key, limits, and quota). The widget is the browser embed and uses geoapi_pk_.","parameters":[{"name":"id","in":"path","required":true,"description":"Positive modification id. Zero or a non-numeric id returns 422. An unknown id returns 404.","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"X-Quota-Limit":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Remaining":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Reset":{"schema":{"type":"integer"}}},"content":{"application\/json":{"schema":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"$ref":"#\/components\/schemas\/ModificationEquipment"}}}}}},"401":{"description":"The key is missing, unknown, revoked, or expired.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unauthorized","message":"\u2026"}}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"403":{"description":"The key is valid, but the project is disabled, the account is suspended, the email is not confirmed, or the Cars API is turned off.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"forbidden","message":"\u2026"}}}}},"404":{"description":"The record or the address was not found.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"not_found","message":"\u2026"}}}}},"405":{"description":"Use GET or HEAD.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"method_not_allowed","message":"\u2026"}}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"422":{"description":"A parameter is invalid or is not accepted on this route.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"invalid_parameter","message":"\u2026"}}}}},"429":{"description":"RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"\u2026"}}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"Retry-After":{"schema":{"type":"integer"}}}},"503":{"description":"The catalog or the request counter is temporarily unavailable.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unavailable","message":"\u2026"}}}}}},"x-codeSamples":[{"lang":"curl","source":"curl \"https:\/\/geoapi.ge\/api\/v1\/modifications\/1000\/equipment\" \\\n  -H \"Authorization: Bearer geoapi_sk_\u2026\""},{"lang":"Node.js","source":"\/\/ Server-side only: a geoapi_sk_ key must never reach the browser. In a web page use the widget (geoapi_pk_).\nconst response = await fetch(\"https:\/\/geoapi.ge\/api\/v1\/modifications\/1000\/equipment\", {\n  headers: { Authorization: 'Bearer geoapi_sk_\u2026' },\n});\nconsole.log(await response.json());"},{"lang":"Python","source":"import urllib.request\nrequest = urllib.request.Request(\"https:\/\/geoapi.ge\/api\/v1\/modifications\/1000\/equipment\", headers={'Authorization': 'Bearer geoapi_sk_\u2026'})\nprint(urllib.request.urlopen(request).read().decode())"},{"lang":"PHP","source":"$ch = curl_init(\"https:\/\/geoapi.ge\/api\/v1\/modifications\/1000\/equipment\");\ncurl_setopt_array($ch, [\n    CURLOPT_HTTPHEADER => ['Authorization: Bearer geoapi_sk_\u2026'],\n    CURLOPT_RETURNTRANSFER => true,\n]);\necho curl_exec($ch);"}],"x-geoapi-example":"\/api\/v1\/modifications\/1000\/equipment","x-geoapi-kind":"ModificationEquipment","x-geoapi-mode":"one"}},"\/api\/v1\/modifications\/{id}":{"get":{"tags":["Catalog"],"operationId":"getModification","summary":"One modification","description":"One modification with its brand, model, and generation. modified is the time of the last change, in UTC.\n\nThis route returns one object in data. It has no pagination. Extra query parameters are ignored.\n\nAuthentication: send Authorization: Bearer geoapi_sk_\u2026 from your server. A key in the URL query, a cookie, or a cabinet session is not accepted. geoapi_pk_ is the widget key and does not work here. A cabinet personal access token with cars:read or * also needs X-GEOAPI-PROJECT with the id of one of your active projects. A secret key ignores X-GEOAPI-PROJECT. Before using a key, confirm your email. The Cars API is on by default; if you turned it off at \/account\/products, the key gets 403.\n\nError bodies are JSON with only error.code and error.message: 401 unauthorized, 403 forbidden, 404 not_found, 405 method_not_allowed, 422 invalid_parameter, 429 RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED, 503 unavailable. The key is checked before the method, so a non-GET request without a valid key returns 401, not 405. 405 is returned only after the key is accepted. Use GET or HEAD. One IP address may send 300 requests a minute. That limit is checked before the key, so it can return 429 before 401. Every response has an X-Request-Id header; send your own X-Request-Id to trace a request.\n\nLimits: one workspace subscription, one monthly quota, and one minute limit shared by all its projects and the widget. Free: 1 000 successful requests a month, 1 project, 15 requests a minute. Starter: 25 000 successful requests a month, 3 projects, 60 requests a minute. Growth: 150 000 successful requests a month, 10 projects, 120 requests a minute. The quota resets every billing month, including on a yearly payment. Prepaid packs (90 days) are spent after the quota and are included in X-Quota-Remaining. Older plans may still be unlimited and then send X-Quota-Limit: unlimited. A per-project cap is optional and returns PROJECT_CAP_EXCEEDED. There is no daily limit. If the request cannot be counted, the API returns 503.\n\nData: ids are strings. null means the value is unknown. dimensions and performance are always null. Colors include unchecked rows with verified false, and a color id is the model id. photo_url is set when a checked photo is stored; GET it with the same key to receive the image. VIN lookup is not available.\n\nVersion 1.3.0 at https:\/\/geoapi.ge. The TypeScript SDK and the CLI (0.2.0) can be installed from https:\/\/geoapi.ge\/downloads. The MCP server is at https:\/\/geoapi.ge\/mcp (same key, limits, and quota). The widget is the browser embed and uses geoapi_pk_.","parameters":[{"name":"id","in":"path","required":true,"description":"Positive modification id. Zero or a non-numeric id returns 422. An unknown id returns 404.","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"X-Quota-Limit":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Remaining":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Reset":{"schema":{"type":"integer"}}},"content":{"application\/json":{"schema":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"$ref":"#\/components\/schemas\/Modification"}}}}}},"401":{"description":"The key is missing, unknown, revoked, or expired.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unauthorized","message":"\u2026"}}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"403":{"description":"The key is valid, but the project is disabled, the account is suspended, the email is not confirmed, or the Cars API is turned off.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"forbidden","message":"\u2026"}}}}},"404":{"description":"The record or the address was not found.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"not_found","message":"\u2026"}}}}},"405":{"description":"Use GET or HEAD.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"method_not_allowed","message":"\u2026"}}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"422":{"description":"A parameter is invalid or is not accepted on this route.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"invalid_parameter","message":"\u2026"}}}}},"429":{"description":"RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"\u2026"}}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"Retry-After":{"schema":{"type":"integer"}}}},"503":{"description":"The catalog or the request counter is temporarily unavailable.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unavailable","message":"\u2026"}}}}}},"x-codeSamples":[{"lang":"curl","source":"curl \"https:\/\/geoapi.ge\/api\/v1\/modifications\/1000\" \\\n  -H \"Authorization: Bearer geoapi_sk_\u2026\""},{"lang":"Node.js","source":"\/\/ Server-side only: a geoapi_sk_ key must never reach the browser. In a web page use the widget (geoapi_pk_).\nconst response = await fetch(\"https:\/\/geoapi.ge\/api\/v1\/modifications\/1000\", {\n  headers: { Authorization: 'Bearer geoapi_sk_\u2026' },\n});\nconsole.log(await response.json());"},{"lang":"Python","source":"import urllib.request\nrequest = urllib.request.Request(\"https:\/\/geoapi.ge\/api\/v1\/modifications\/1000\", headers={'Authorization': 'Bearer geoapi_sk_\u2026'})\nprint(urllib.request.urlopen(request).read().decode())"},{"lang":"PHP","source":"$ch = curl_init(\"https:\/\/geoapi.ge\/api\/v1\/modifications\/1000\");\ncurl_setopt_array($ch, [\n    CURLOPT_HTTPHEADER => ['Authorization: Bearer geoapi_sk_\u2026'],\n    CURLOPT_RETURNTRANSFER => true,\n]);\necho curl_exec($ch);"}],"x-geoapi-example":"\/api\/v1\/modifications\/1000","x-geoapi-kind":"Modification","x-geoapi-mode":"one"}},"\/api\/v1\/modifications":{"get":{"tags":["Catalog"],"operationId":"listModifications","summary":"Modifications across brands, models, and generations","description":"Search modifications across brands, models, and generations. Filters: year_from, year_to, body, fuel, drive, transmission, brand_id, model_id, and q.\n\nPagination: page defaults to 1 (maximum 1000000). limit defaults to 100 and cannot exceed 1000. per_page is used only when limit is absent. direction defaults to asc and applies when sort is set. Without sort, this resource keeps its default order. REST year lists are ascending. The widget list starts with the newest year.\n\nAuthentication: send Authorization: Bearer geoapi_sk_\u2026 from your server. A key in the URL query, a cookie, or a cabinet session is not accepted. geoapi_pk_ is the widget key and does not work here. A cabinet personal access token with cars:read or * also needs X-GEOAPI-PROJECT with the id of one of your active projects. A secret key ignores X-GEOAPI-PROJECT. Before using a key, confirm your email. The Cars API is on by default; if you turned it off at \/account\/products, the key gets 403.\n\nError bodies are JSON with only error.code and error.message: 401 unauthorized, 403 forbidden, 404 not_found, 405 method_not_allowed, 422 invalid_parameter, 429 RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED, 503 unavailable. The key is checked before the method, so a non-GET request without a valid key returns 401, not 405. 405 is returned only after the key is accepted. Use GET or HEAD. One IP address may send 300 requests a minute. That limit is checked before the key, so it can return 429 before 401. Every response has an X-Request-Id header; send your own X-Request-Id to trace a request.\n\nLimits: one workspace subscription, one monthly quota, and one minute limit shared by all its projects and the widget. Free: 1 000 successful requests a month, 1 project, 15 requests a minute. Starter: 25 000 successful requests a month, 3 projects, 60 requests a minute. Growth: 150 000 successful requests a month, 10 projects, 120 requests a minute. The quota resets every billing month, including on a yearly payment. Prepaid packs (90 days) are spent after the quota and are included in X-Quota-Remaining. Older plans may still be unlimited and then send X-Quota-Limit: unlimited. A per-project cap is optional and returns PROJECT_CAP_EXCEEDED. There is no daily limit. If the request cannot be counted, the API returns 503.\n\nData: ids are strings. null means the value is unknown. dimensions and performance are always null. Colors include unchecked rows with verified false, and a color id is the model id. photo_url is set when a checked photo is stored; GET it with the same key to receive the image. VIN lookup is not available.\n\nVersion 1.3.0 at https:\/\/geoapi.ge. The TypeScript SDK and the CLI (0.2.0) can be installed from https:\/\/geoapi.ge\/downloads. The MCP server is at https:\/\/geoapi.ge\/mcp (same key, limits, and quota). The widget is the browser embed and uses geoapi_pk_.","parameters":[{"$ref":"#\/components\/parameters\/page"},{"$ref":"#\/components\/parameters\/limit"},{"$ref":"#\/components\/parameters\/perPage"},{"name":"sort","in":"query","description":"Optional. One of name, id, year_start, engine_volume_cc, modified. direction applies when sort is set.","schema":{"type":"string","enum":["name","id","year_start","engine_volume_cc","modified"]}},{"$ref":"#\/components\/parameters\/direction"},{"$ref":"#\/components\/parameters\/q"},{"$ref":"#\/components\/parameters\/modifiedAfter"},{"$ref":"#\/components\/parameters\/include"},{"$ref":"#\/components\/parameters\/yearFrom"},{"$ref":"#\/components\/parameters\/yearTo"},{"$ref":"#\/components\/parameters\/body"},{"$ref":"#\/components\/parameters\/fuel"},{"$ref":"#\/components\/parameters\/drive"},{"$ref":"#\/components\/parameters\/transmission"},{"$ref":"#\/components\/parameters\/brandId"},{"$ref":"#\/components\/parameters\/modelId"}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"X-Quota-Limit":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Remaining":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Reset":{"schema":{"type":"integer"}}},"content":{"application\/json":{"schema":{"allOf":[{"$ref":"#\/components\/schemas\/List"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/ModificationSearch"}}}}]}}}},"401":{"description":"The key is missing, unknown, revoked, or expired.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unauthorized","message":"\u2026"}}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"403":{"description":"The key is valid, but the project is disabled, the account is suspended, the email is not confirmed, or the Cars API is turned off.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"forbidden","message":"\u2026"}}}}},"404":{"description":"The record or the address was not found.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"not_found","message":"\u2026"}}}}},"405":{"description":"Use GET or HEAD.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"method_not_allowed","message":"\u2026"}}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"422":{"description":"A parameter is invalid or is not accepted on this route.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"invalid_parameter","message":"\u2026"}}}}},"429":{"description":"RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"\u2026"}}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"Retry-After":{"schema":{"type":"integer"}}}},"503":{"description":"The catalog or the request counter is temporarily unavailable.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unavailable","message":"\u2026"}}}}}},"x-codeSamples":[{"lang":"curl","source":"curl \"https:\/\/geoapi.ge\/api\/v1\/modifications?limit=1\" \\\n  -H \"Authorization: Bearer geoapi_sk_\u2026\""},{"lang":"Node.js","source":"\/\/ Server-side only: a geoapi_sk_ key must never reach the browser. In a web page use the widget (geoapi_pk_).\nconst response = await fetch(\"https:\/\/geoapi.ge\/api\/v1\/modifications?limit=1\", {\n  headers: { Authorization: 'Bearer geoapi_sk_\u2026' },\n});\nconsole.log(await response.json());"},{"lang":"Python","source":"import urllib.request\nrequest = urllib.request.Request(\"https:\/\/geoapi.ge\/api\/v1\/modifications?limit=1\", headers={'Authorization': 'Bearer geoapi_sk_\u2026'})\nprint(urllib.request.urlopen(request).read().decode())"},{"lang":"PHP","source":"$ch = curl_init(\"https:\/\/geoapi.ge\/api\/v1\/modifications?limit=1\");\ncurl_setopt_array($ch, [\n    CURLOPT_HTTPHEADER => ['Authorization: Bearer geoapi_sk_\u2026'],\n    CURLOPT_RETURNTRANSFER => true,\n]);\necho curl_exec($ch);"}],"x-geoapi-example":"\/api\/v1\/modifications?limit=1","x-geoapi-kind":"modification_search","x-geoapi-mode":"list"}},"\/api\/v1\/engines":{"get":{"tags":["Catalog"],"operationId":"listEngines","summary":"Engine volume, fuel, and power of each modification","description":"Engine volume, fuel, and power of each modification that has an engine volume or a fuel type. Filter with fuel, brand_id, model_id, volume_from, and volume_to.\n\nPagination: page defaults to 1 (maximum 1000000). limit defaults to 100 and cannot exceed 1000. per_page is used only when limit is absent. direction defaults to asc and applies when sort is set. Without sort, this resource keeps its default order. REST year lists are ascending. The widget list starts with the newest year.\n\nAuthentication: send Authorization: Bearer geoapi_sk_\u2026 from your server. A key in the URL query, a cookie, or a cabinet session is not accepted. geoapi_pk_ is the widget key and does not work here. A cabinet personal access token with cars:read or * also needs X-GEOAPI-PROJECT with the id of one of your active projects. A secret key ignores X-GEOAPI-PROJECT. Before using a key, confirm your email. The Cars API is on by default; if you turned it off at \/account\/products, the key gets 403.\n\nError bodies are JSON with only error.code and error.message: 401 unauthorized, 403 forbidden, 404 not_found, 405 method_not_allowed, 422 invalid_parameter, 429 RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED, 503 unavailable. The key is checked before the method, so a non-GET request without a valid key returns 401, not 405. 405 is returned only after the key is accepted. Use GET or HEAD. One IP address may send 300 requests a minute. That limit is checked before the key, so it can return 429 before 401. Every response has an X-Request-Id header; send your own X-Request-Id to trace a request.\n\nLimits: one workspace subscription, one monthly quota, and one minute limit shared by all its projects and the widget. Free: 1 000 successful requests a month, 1 project, 15 requests a minute. Starter: 25 000 successful requests a month, 3 projects, 60 requests a minute. Growth: 150 000 successful requests a month, 10 projects, 120 requests a minute. The quota resets every billing month, including on a yearly payment. Prepaid packs (90 days) are spent after the quota and are included in X-Quota-Remaining. Older plans may still be unlimited and then send X-Quota-Limit: unlimited. A per-project cap is optional and returns PROJECT_CAP_EXCEEDED. There is no daily limit. If the request cannot be counted, the API returns 503.\n\nData: ids are strings. null means the value is unknown. dimensions and performance are always null. Colors include unchecked rows with verified false, and a color id is the model id. photo_url is set when a checked photo is stored; GET it with the same key to receive the image. VIN lookup is not available.\n\nVersion 1.3.0 at https:\/\/geoapi.ge. The TypeScript SDK and the CLI (0.2.0) can be installed from https:\/\/geoapi.ge\/downloads. The MCP server is at https:\/\/geoapi.ge\/mcp (same key, limits, and quota). The widget is the browser embed and uses geoapi_pk_.","parameters":[{"$ref":"#\/components\/parameters\/page"},{"$ref":"#\/components\/parameters\/limit"},{"$ref":"#\/components\/parameters\/perPage"},{"name":"sort","in":"query","description":"Optional. One of volume_cc, id, power_hp, modified. direction applies when sort is set.","schema":{"type":"string","enum":["volume_cc","id","power_hp","modified"]}},{"$ref":"#\/components\/parameters\/direction"},{"$ref":"#\/components\/parameters\/q"},{"$ref":"#\/components\/parameters\/modifiedAfter"},{"$ref":"#\/components\/parameters\/fuel"},{"$ref":"#\/components\/parameters\/brandId"},{"$ref":"#\/components\/parameters\/modelId"},{"$ref":"#\/components\/parameters\/volumeFrom"},{"$ref":"#\/components\/parameters\/volumeTo"}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"X-Quota-Limit":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Remaining":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Reset":{"schema":{"type":"integer"}}},"content":{"application\/json":{"schema":{"allOf":[{"$ref":"#\/components\/schemas\/List"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Engine"}}}}]}}}},"401":{"description":"The key is missing, unknown, revoked, or expired.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unauthorized","message":"\u2026"}}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"403":{"description":"The key is valid, but the project is disabled, the account is suspended, the email is not confirmed, or the Cars API is turned off.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"forbidden","message":"\u2026"}}}}},"404":{"description":"The record or the address was not found.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"not_found","message":"\u2026"}}}}},"405":{"description":"Use GET or HEAD.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"method_not_allowed","message":"\u2026"}}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"422":{"description":"A parameter is invalid or is not accepted on this route.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"invalid_parameter","message":"\u2026"}}}}},"429":{"description":"RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"\u2026"}}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"Retry-After":{"schema":{"type":"integer"}}}},"503":{"description":"The catalog or the request counter is temporarily unavailable.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unavailable","message":"\u2026"}}}}}},"x-codeSamples":[{"lang":"curl","source":"curl \"https:\/\/geoapi.ge\/api\/v1\/engines?limit=1\" \\\n  -H \"Authorization: Bearer geoapi_sk_\u2026\""},{"lang":"Node.js","source":"\/\/ Server-side only: a geoapi_sk_ key must never reach the browser. In a web page use the widget (geoapi_pk_).\nconst response = await fetch(\"https:\/\/geoapi.ge\/api\/v1\/engines?limit=1\", {\n  headers: { Authorization: 'Bearer geoapi_sk_\u2026' },\n});\nconsole.log(await response.json());"},{"lang":"Python","source":"import urllib.request\nrequest = urllib.request.Request(\"https:\/\/geoapi.ge\/api\/v1\/engines?limit=1\", headers={'Authorization': 'Bearer geoapi_sk_\u2026'})\nprint(urllib.request.urlopen(request).read().decode())"},{"lang":"PHP","source":"$ch = curl_init(\"https:\/\/geoapi.ge\/api\/v1\/engines?limit=1\");\ncurl_setopt_array($ch, [\n    CURLOPT_HTTPHEADER => ['Authorization: Bearer geoapi_sk_\u2026'],\n    CURLOPT_RETURNTRANSFER => true,\n]);\necho curl_exec($ch);"}],"x-geoapi-example":"\/api\/v1\/engines?limit=1","x-geoapi-kind":"engines","x-geoapi-mode":"list"}},"\/api\/v1\/bodies":{"get":{"tags":["Catalog"],"operationId":"listBodies","summary":"Distinct body types used by models, generations, and modifications","description":"Distinct body types and how many records use each. q searches the name. modified_after returns 422.\n\nPagination: page defaults to 1 (maximum 1000000). limit defaults to 100 and cannot exceed 1000. per_page is used only when limit is absent. direction defaults to asc and applies when sort is set. Without sort, this resource keeps its default order. REST year lists are ascending. The widget list starts with the newest year.\n\nAuthentication: send Authorization: Bearer geoapi_sk_\u2026 from your server. A key in the URL query, a cookie, or a cabinet session is not accepted. geoapi_pk_ is the widget key and does not work here. A cabinet personal access token with cars:read or * also needs X-GEOAPI-PROJECT with the id of one of your active projects. A secret key ignores X-GEOAPI-PROJECT. Before using a key, confirm your email. The Cars API is on by default; if you turned it off at \/account\/products, the key gets 403.\n\nError bodies are JSON with only error.code and error.message: 401 unauthorized, 403 forbidden, 404 not_found, 405 method_not_allowed, 422 invalid_parameter, 429 RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED, 503 unavailable. The key is checked before the method, so a non-GET request without a valid key returns 401, not 405. 405 is returned only after the key is accepted. Use GET or HEAD. One IP address may send 300 requests a minute. That limit is checked before the key, so it can return 429 before 401. Every response has an X-Request-Id header; send your own X-Request-Id to trace a request.\n\nLimits: one workspace subscription, one monthly quota, and one minute limit shared by all its projects and the widget. Free: 1 000 successful requests a month, 1 project, 15 requests a minute. Starter: 25 000 successful requests a month, 3 projects, 60 requests a minute. Growth: 150 000 successful requests a month, 10 projects, 120 requests a minute. The quota resets every billing month, including on a yearly payment. Prepaid packs (90 days) are spent after the quota and are included in X-Quota-Remaining. Older plans may still be unlimited and then send X-Quota-Limit: unlimited. A per-project cap is optional and returns PROJECT_CAP_EXCEEDED. There is no daily limit. If the request cannot be counted, the API returns 503.\n\nData: ids are strings. null means the value is unknown. dimensions and performance are always null. Colors include unchecked rows with verified false, and a color id is the model id. photo_url is set when a checked photo is stored; GET it with the same key to receive the image. VIN lookup is not available.\n\nVersion 1.3.0 at https:\/\/geoapi.ge. The TypeScript SDK and the CLI (0.2.0) can be installed from https:\/\/geoapi.ge\/downloads. The MCP server is at https:\/\/geoapi.ge\/mcp (same key, limits, and quota). The widget is the browser embed and uses geoapi_pk_.","parameters":[{"$ref":"#\/components\/parameters\/page"},{"$ref":"#\/components\/parameters\/limit"},{"$ref":"#\/components\/parameters\/perPage"},{"name":"sort","in":"query","description":"Optional. One of name, id, count. direction applies when sort is set.","schema":{"type":"string","enum":["name","id","count"]}},{"$ref":"#\/components\/parameters\/direction"},{"$ref":"#\/components\/parameters\/q"}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"X-Quota-Limit":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Remaining":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Reset":{"schema":{"type":"integer"}}},"content":{"application\/json":{"schema":{"allOf":[{"$ref":"#\/components\/schemas\/List"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Body"}}}}]}}}},"401":{"description":"The key is missing, unknown, revoked, or expired.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unauthorized","message":"\u2026"}}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"403":{"description":"The key is valid, but the project is disabled, the account is suspended, the email is not confirmed, or the Cars API is turned off.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"forbidden","message":"\u2026"}}}}},"404":{"description":"The record or the address was not found.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"not_found","message":"\u2026"}}}}},"405":{"description":"Use GET or HEAD.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"method_not_allowed","message":"\u2026"}}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"422":{"description":"A parameter is invalid or is not accepted on this route.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"invalid_parameter","message":"\u2026"}}}}},"429":{"description":"RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"\u2026"}}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"Retry-After":{"schema":{"type":"integer"}}}},"503":{"description":"The catalog or the request counter is temporarily unavailable.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unavailable","message":"\u2026"}}}}}},"x-codeSamples":[{"lang":"curl","source":"curl \"https:\/\/geoapi.ge\/api\/v1\/bodies?limit=1\" \\\n  -H \"Authorization: Bearer geoapi_sk_\u2026\""},{"lang":"Node.js","source":"\/\/ Server-side only: a geoapi_sk_ key must never reach the browser. In a web page use the widget (geoapi_pk_).\nconst response = await fetch(\"https:\/\/geoapi.ge\/api\/v1\/bodies?limit=1\", {\n  headers: { Authorization: 'Bearer geoapi_sk_\u2026' },\n});\nconsole.log(await response.json());"},{"lang":"Python","source":"import urllib.request\nrequest = urllib.request.Request(\"https:\/\/geoapi.ge\/api\/v1\/bodies?limit=1\", headers={'Authorization': 'Bearer geoapi_sk_\u2026'})\nprint(urllib.request.urlopen(request).read().decode())"},{"lang":"PHP","source":"$ch = curl_init(\"https:\/\/geoapi.ge\/api\/v1\/bodies?limit=1\");\ncurl_setopt_array($ch, [\n    CURLOPT_HTTPHEADER => ['Authorization: Bearer geoapi_sk_\u2026'],\n    CURLOPT_RETURNTRANSFER => true,\n]);\necho curl_exec($ch);"}],"x-geoapi-example":"\/api\/v1\/bodies?limit=1","x-geoapi-kind":"bodies","x-geoapi-mode":"list"}},"\/api\/v1\/fuel":{"get":{"tags":["Catalog"],"operationId":"listFuel","summary":"Fuel consumption of each modification","description":"City, highway, and combined fuel consumption of each modification that has consumption data, in litres per 100 km. The modification search filters are accepted, including body, drive, and transmission.\n\nPagination: page defaults to 1 (maximum 1000000). limit defaults to 100 and cannot exceed 1000. per_page is used only when limit is absent. direction defaults to asc and applies when sort is set. Without sort, this resource keeps its default order. REST year lists are ascending. The widget list starts with the newest year.\n\nAuthentication: send Authorization: Bearer geoapi_sk_\u2026 from your server. A key in the URL query, a cookie, or a cabinet session is not accepted. geoapi_pk_ is the widget key and does not work here. A cabinet personal access token with cars:read or * also needs X-GEOAPI-PROJECT with the id of one of your active projects. A secret key ignores X-GEOAPI-PROJECT. Before using a key, confirm your email. The Cars API is on by default; if you turned it off at \/account\/products, the key gets 403.\n\nError bodies are JSON with only error.code and error.message: 401 unauthorized, 403 forbidden, 404 not_found, 405 method_not_allowed, 422 invalid_parameter, 429 RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED, 503 unavailable. The key is checked before the method, so a non-GET request without a valid key returns 401, not 405. 405 is returned only after the key is accepted. Use GET or HEAD. One IP address may send 300 requests a minute. That limit is checked before the key, so it can return 429 before 401. Every response has an X-Request-Id header; send your own X-Request-Id to trace a request.\n\nLimits: one workspace subscription, one monthly quota, and one minute limit shared by all its projects and the widget. Free: 1 000 successful requests a month, 1 project, 15 requests a minute. Starter: 25 000 successful requests a month, 3 projects, 60 requests a minute. Growth: 150 000 successful requests a month, 10 projects, 120 requests a minute. The quota resets every billing month, including on a yearly payment. Prepaid packs (90 days) are spent after the quota and are included in X-Quota-Remaining. Older plans may still be unlimited and then send X-Quota-Limit: unlimited. A per-project cap is optional and returns PROJECT_CAP_EXCEEDED. There is no daily limit. If the request cannot be counted, the API returns 503.\n\nData: ids are strings. null means the value is unknown. dimensions and performance are always null. Colors include unchecked rows with verified false, and a color id is the model id. photo_url is set when a checked photo is stored; GET it with the same key to receive the image. VIN lookup is not available.\n\nVersion 1.3.0 at https:\/\/geoapi.ge. The TypeScript SDK and the CLI (0.2.0) can be installed from https:\/\/geoapi.ge\/downloads. The MCP server is at https:\/\/geoapi.ge\/mcp (same key, limits, and quota). The widget is the browser embed and uses geoapi_pk_.","parameters":[{"$ref":"#\/components\/parameters\/page"},{"$ref":"#\/components\/parameters\/limit"},{"$ref":"#\/components\/parameters\/perPage"},{"name":"sort","in":"query","description":"Optional. One of combined_l, id, modified. direction applies when sort is set.","schema":{"type":"string","enum":["combined_l","id","modified"]}},{"$ref":"#\/components\/parameters\/direction"},{"$ref":"#\/components\/parameters\/q"},{"$ref":"#\/components\/parameters\/modifiedAfter"},{"$ref":"#\/components\/parameters\/yearFrom"},{"$ref":"#\/components\/parameters\/yearTo"},{"$ref":"#\/components\/parameters\/body"},{"$ref":"#\/components\/parameters\/fuel"},{"$ref":"#\/components\/parameters\/drive"},{"$ref":"#\/components\/parameters\/transmission"},{"$ref":"#\/components\/parameters\/brandId"},{"$ref":"#\/components\/parameters\/modelId"}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"X-Quota-Limit":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Remaining":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Reset":{"schema":{"type":"integer"}}},"content":{"application\/json":{"schema":{"allOf":[{"$ref":"#\/components\/schemas\/List"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Fuel"}}}}]}}}},"401":{"description":"The key is missing, unknown, revoked, or expired.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unauthorized","message":"\u2026"}}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"403":{"description":"The key is valid, but the project is disabled, the account is suspended, the email is not confirmed, or the Cars API is turned off.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"forbidden","message":"\u2026"}}}}},"404":{"description":"The record or the address was not found.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"not_found","message":"\u2026"}}}}},"405":{"description":"Use GET or HEAD.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"method_not_allowed","message":"\u2026"}}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"422":{"description":"A parameter is invalid or is not accepted on this route.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"invalid_parameter","message":"\u2026"}}}}},"429":{"description":"RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"\u2026"}}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"Retry-After":{"schema":{"type":"integer"}}}},"503":{"description":"The catalog or the request counter is temporarily unavailable.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unavailable","message":"\u2026"}}}}}},"x-codeSamples":[{"lang":"curl","source":"curl \"https:\/\/geoapi.ge\/api\/v1\/fuel?limit=1\" \\\n  -H \"Authorization: Bearer geoapi_sk_\u2026\""},{"lang":"Node.js","source":"\/\/ Server-side only: a geoapi_sk_ key must never reach the browser. In a web page use the widget (geoapi_pk_).\nconst response = await fetch(\"https:\/\/geoapi.ge\/api\/v1\/fuel?limit=1\", {\n  headers: { Authorization: 'Bearer geoapi_sk_\u2026' },\n});\nconsole.log(await response.json());"},{"lang":"Python","source":"import urllib.request\nrequest = urllib.request.Request(\"https:\/\/geoapi.ge\/api\/v1\/fuel?limit=1\", headers={'Authorization': 'Bearer geoapi_sk_\u2026'})\nprint(urllib.request.urlopen(request).read().decode())"},{"lang":"PHP","source":"$ch = curl_init(\"https:\/\/geoapi.ge\/api\/v1\/fuel?limit=1\");\ncurl_setopt_array($ch, [\n    CURLOPT_HTTPHEADER => ['Authorization: Bearer geoapi_sk_\u2026'],\n    CURLOPT_RETURNTRANSFER => true,\n]);\necho curl_exec($ch);"}],"x-geoapi-example":"\/api\/v1\/fuel?limit=1","x-geoapi-kind":"fuel","x-geoapi-mode":"list"}},"\/api\/v1\/colors":{"get":{"tags":["Catalog"],"operationId":"listColors","summary":"Colors of model photos","description":"Every color stored for a model photo. id is the model id, so it is not unique. verified is false when the photo was not checked, and those rows stay in the list. photo_url points to the image of a checked photo and is null otherwise.\n\nPagination: page defaults to 1 (maximum 1000000). limit defaults to 100 and cannot exceed 1000. per_page is used only when limit is absent. direction defaults to asc and applies when sort is set. Without sort, this resource keeps its default order. REST year lists are ascending. The widget list starts with the newest year.\n\nAuthentication: send Authorization: Bearer geoapi_sk_\u2026 from your server. A key in the URL query, a cookie, or a cabinet session is not accepted. geoapi_pk_ is the widget key and does not work here. A cabinet personal access token with cars:read or * also needs X-GEOAPI-PROJECT with the id of one of your active projects. A secret key ignores X-GEOAPI-PROJECT. Before using a key, confirm your email. The Cars API is on by default; if you turned it off at \/account\/products, the key gets 403.\n\nError bodies are JSON with only error.code and error.message: 401 unauthorized, 403 forbidden, 404 not_found, 405 method_not_allowed, 422 invalid_parameter, 429 RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED, 503 unavailable. The key is checked before the method, so a non-GET request without a valid key returns 401, not 405. 405 is returned only after the key is accepted. Use GET or HEAD. One IP address may send 300 requests a minute. That limit is checked before the key, so it can return 429 before 401. Every response has an X-Request-Id header; send your own X-Request-Id to trace a request.\n\nLimits: one workspace subscription, one monthly quota, and one minute limit shared by all its projects and the widget. Free: 1 000 successful requests a month, 1 project, 15 requests a minute. Starter: 25 000 successful requests a month, 3 projects, 60 requests a minute. Growth: 150 000 successful requests a month, 10 projects, 120 requests a minute. The quota resets every billing month, including on a yearly payment. Prepaid packs (90 days) are spent after the quota and are included in X-Quota-Remaining. Older plans may still be unlimited and then send X-Quota-Limit: unlimited. A per-project cap is optional and returns PROJECT_CAP_EXCEEDED. There is no daily limit. If the request cannot be counted, the API returns 503.\n\nData: ids are strings. null means the value is unknown. dimensions and performance are always null. Colors include unchecked rows with verified false, and a color id is the model id. photo_url is set when a checked photo is stored; GET it with the same key to receive the image. VIN lookup is not available.\n\nVersion 1.3.0 at https:\/\/geoapi.ge. The TypeScript SDK and the CLI (0.2.0) can be installed from https:\/\/geoapi.ge\/downloads. The MCP server is at https:\/\/geoapi.ge\/mcp (same key, limits, and quota). The widget is the browser embed and uses geoapi_pk_.","parameters":[{"$ref":"#\/components\/parameters\/page"},{"$ref":"#\/components\/parameters\/limit"},{"$ref":"#\/components\/parameters\/perPage"},{"name":"sort","in":"query","description":"Optional. One of name, id, modified. direction applies when sort is set.","schema":{"type":"string","enum":["name","id","modified"]}},{"$ref":"#\/components\/parameters\/direction"},{"$ref":"#\/components\/parameters\/q"},{"$ref":"#\/components\/parameters\/modifiedAfter"},{"$ref":"#\/components\/parameters\/brandId"},{"$ref":"#\/components\/parameters\/modelId"}],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"X-Quota-Limit":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Remaining":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Reset":{"schema":{"type":"integer"}}},"content":{"application\/json":{"schema":{"allOf":[{"$ref":"#\/components\/schemas\/List"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#\/components\/schemas\/Color"}}}}]}}}},"401":{"description":"The key is missing, unknown, revoked, or expired.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unauthorized","message":"\u2026"}}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"403":{"description":"The key is valid, but the project is disabled, the account is suspended, the email is not confirmed, or the Cars API is turned off.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"forbidden","message":"\u2026"}}}}},"404":{"description":"The record or the address was not found.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"not_found","message":"\u2026"}}}}},"405":{"description":"Use GET or HEAD.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"method_not_allowed","message":"\u2026"}}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"422":{"description":"A parameter is invalid or is not accepted on this route.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"invalid_parameter","message":"\u2026"}}}}},"429":{"description":"RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"\u2026"}}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"Retry-After":{"schema":{"type":"integer"}}}},"503":{"description":"The catalog or the request counter is temporarily unavailable.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unavailable","message":"\u2026"}}}}}},"x-codeSamples":[{"lang":"curl","source":"curl \"https:\/\/geoapi.ge\/api\/v1\/colors?limit=2\" \\\n  -H \"Authorization: Bearer geoapi_sk_\u2026\""},{"lang":"Node.js","source":"\/\/ Server-side only: a geoapi_sk_ key must never reach the browser. In a web page use the widget (geoapi_pk_).\nconst response = await fetch(\"https:\/\/geoapi.ge\/api\/v1\/colors?limit=2\", {\n  headers: { Authorization: 'Bearer geoapi_sk_\u2026' },\n});\nconsole.log(await response.json());"},{"lang":"Python","source":"import urllib.request\nrequest = urllib.request.Request(\"https:\/\/geoapi.ge\/api\/v1\/colors?limit=2\", headers={'Authorization': 'Bearer geoapi_sk_\u2026'})\nprint(urllib.request.urlopen(request).read().decode())"},{"lang":"PHP","source":"$ch = curl_init(\"https:\/\/geoapi.ge\/api\/v1\/colors?limit=2\");\ncurl_setopt_array($ch, [\n    CURLOPT_HTTPHEADER => ['Authorization: Bearer geoapi_sk_\u2026'],\n    CURLOPT_RETURNTRANSFER => true,\n]);\necho curl_exec($ch);"}],"x-geoapi-example":"\/api\/v1\/colors?limit=2","x-geoapi-kind":"colors","x-geoapi-mode":"list"}},"\/api\/v1\/coverage":{"get":{"tags":["Catalog"],"operationId":"getCoverage","summary":"Catalog counts.","description":"Catalog counts. They can be a few minutes old; measured_at is when they were counted. They are not your quota.\n\nThis route returns counts, not a list. Filters, q, sort, and modified_after return 422.\n\nAuthentication: send Authorization: Bearer geoapi_sk_\u2026 from your server. A key in the URL query, a cookie, or a cabinet session is not accepted. geoapi_pk_ is the widget key and does not work here. A cabinet personal access token with cars:read or * also needs X-GEOAPI-PROJECT with the id of one of your active projects. A secret key ignores X-GEOAPI-PROJECT. Before using a key, confirm your email. The Cars API is on by default; if you turned it off at \/account\/products, the key gets 403.\n\nError bodies are JSON with only error.code and error.message: 401 unauthorized, 403 forbidden, 404 not_found, 405 method_not_allowed, 422 invalid_parameter, 429 RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED, 503 unavailable. The key is checked before the method, so a non-GET request without a valid key returns 401, not 405. 405 is returned only after the key is accepted. Use GET or HEAD. One IP address may send 300 requests a minute. That limit is checked before the key, so it can return 429 before 401. Every response has an X-Request-Id header; send your own X-Request-Id to trace a request.\n\nLimits: one workspace subscription, one monthly quota, and one minute limit shared by all its projects and the widget. Free: 1 000 successful requests a month, 1 project, 15 requests a minute. Starter: 25 000 successful requests a month, 3 projects, 60 requests a minute. Growth: 150 000 successful requests a month, 10 projects, 120 requests a minute. The quota resets every billing month, including on a yearly payment. Prepaid packs (90 days) are spent after the quota and are included in X-Quota-Remaining. Older plans may still be unlimited and then send X-Quota-Limit: unlimited. A per-project cap is optional and returns PROJECT_CAP_EXCEEDED. There is no daily limit. If the request cannot be counted, the API returns 503.\n\nData: ids are strings. null means the value is unknown. dimensions and performance are always null. Colors include unchecked rows with verified false, and a color id is the model id. photo_url is set when a checked photo is stored; GET it with the same key to receive the image. VIN lookup is not available.\n\nVersion 1.3.0 at https:\/\/geoapi.ge. The TypeScript SDK and the CLI (0.2.0) can be installed from https:\/\/geoapi.ge\/downloads. The MCP server is at https:\/\/geoapi.ge\/mcp (same key, limits, and quota). The widget is the browser embed and uses geoapi_pk_.","parameters":[],"responses":{"200":{"description":"OK","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"X-Quota-Limit":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Remaining":{"description":"An integer, or the word unlimited on an unlimited plan.","schema":{"oneOf":[{"type":"integer"},{"type":"string","enum":["unlimited"]}]}},"X-Quota-Reset":{"schema":{"type":"integer"}}},"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Coverage"}}}},"401":{"description":"The key is missing, unknown, revoked, or expired.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unauthorized","message":"\u2026"}}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"403":{"description":"The key is valid, but the project is disabled, the account is suspended, the email is not confirmed, or the Cars API is turned off.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"forbidden","message":"\u2026"}}}}},"404":{"description":"The record or the address was not found.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"not_found","message":"\u2026"}}}}},"405":{"description":"Use GET or HEAD.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"method_not_allowed","message":"\u2026"}}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"422":{"description":"A parameter is invalid or is not accepted on this route.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"invalid_parameter","message":"\u2026"}}}}},"429":{"description":"RATE_LIMIT_EXCEEDED, MONTHLY_QUOTA_EXCEEDED, or PROJECT_CAP_EXCEEDED.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"RATE_LIMIT_EXCEEDED","message":"\u2026"}}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}},"Retry-After":{"schema":{"type":"integer"}}}},"503":{"description":"The catalog or the request counter is temporarily unavailable.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":{"code":"unavailable","message":"\u2026"}}}}}},"x-codeSamples":[{"lang":"curl","source":"curl \"https:\/\/geoapi.ge\/api\/v1\/coverage\" \\\n  -H \"Authorization: Bearer geoapi_sk_\u2026\""},{"lang":"Node.js","source":"\/\/ Server-side only: a geoapi_sk_ key must never reach the browser. In a web page use the widget (geoapi_pk_).\nconst response = await fetch(\"https:\/\/geoapi.ge\/api\/v1\/coverage\", {\n  headers: { Authorization: 'Bearer geoapi_sk_\u2026' },\n});\nconsole.log(await response.json());"},{"lang":"Python","source":"import urllib.request\nrequest = urllib.request.Request(\"https:\/\/geoapi.ge\/api\/v1\/coverage\", headers={'Authorization': 'Bearer geoapi_sk_\u2026'})\nprint(urllib.request.urlopen(request).read().decode())"},{"lang":"PHP","source":"$ch = curl_init(\"https:\/\/geoapi.ge\/api\/v1\/coverage\");\ncurl_setopt_array($ch, [\n    CURLOPT_HTTPHEADER => ['Authorization: Bearer geoapi_sk_\u2026'],\n    CURLOPT_RETURNTRANSFER => true,\n]);\necho curl_exec($ch);"}],"x-geoapi-example":"\/api\/v1\/coverage","x-geoapi-kind":"coverage","x-geoapi-mode":"coverage"}}}}