{"openapi":"3.1.0","info":{"title":"Stanovina API","version":"1.0.0","description":"Publish and manage property listings on stanovina.me. Authenticate with an API key issued in the dashboard; the endpoints the website's own pages call are not part of this contract and are not supported for integrations. The same operations are available to AI assistants as an MCP server at /mcp, with the same key."},"servers":[{"url":"https://stanovina.me"}],"components":{"securitySchemes":{"ApiKey":{"type":"http","scheme":"bearer","description":"Authorization: Bearer <key>"}},"schemas":{"ListingCreate":{"type":"object","required":["title","description","propertyType","listingType","countryId","area"],"properties":{"title":{"type":"string","description":"Primary language (Montenegrin). Required."},"description":{"type":"string","description":"Primary language. Required."},"titleEn":{"type":"string"},"titleRu":{"type":"string"},"descriptionEn":{"type":"string"},"descriptionRu":{"type":"string"},"propertyType":{"type":"string","enum":["APARTMENT","HOUSE","VILLA","STUDIO","PENTHOUSE","LAND","COMMERCIAL","OFFICE","GARAGE","HOTEL"]},"listingType":{"type":"string","enum":["SALE","LONG_TERM_RENT","SHORT_TERM_RENT","DAILY_RENT"]},"furnishing":{"type":"string","enum":["FURNISHED","SEMI_FURNISHED","UNFURNISHED"]},"price":{"type":"number","exclusiveMinimum":0},"priceOnRequest":{"type":"boolean","description":"Withhold the price; then price is not required."},"area":{"type":"number","exclusiveMinimum":0},"countryId":{"type":"string","description":"From /api/v1/reference/countries."},"cityId":{"type":"string","description":"Optional: settlement coverage is partial by design."},"districtId":{"type":"string"},"latitude":{"type":"number"},"longitude":{"type":"number"},"buildStage":{"type":["string","null"],"enum":["NEW_BUILD","UNDER_CONSTRUCTION",null],"description":"New builds: NEW_BUILD or UNDER_CONSTRUCTION; null for an existing building. Listings are returned with this field."},"completionYear":{"type":["integer","null"],"description":"Expected completion year, only kept with UNDER_CONSTRUCTION (otherwise stored as null): from last year to six years ahead of the current year. In a PATCH send it together with buildStage."},"completionQuarter":{"type":["integer","null"],"minimum":1,"maximum":4,"description":"Expected completion quarter, only kept with UNDER_CONSTRUCTION. In a PATCH send it together with buildStage."}}},"ListingPatch":{"type":"object","properties":{"title":{"type":"string","description":"Primary language (Montenegrin). Required."},"description":{"type":"string","description":"Primary language. Required."},"titleEn":{"type":"string"},"titleRu":{"type":"string"},"descriptionEn":{"type":"string"},"descriptionRu":{"type":"string"},"propertyType":{"type":"string","enum":["APARTMENT","HOUSE","VILLA","STUDIO","PENTHOUSE","LAND","COMMERCIAL","OFFICE","GARAGE","HOTEL"]},"listingType":{"type":"string","enum":["SALE","LONG_TERM_RENT","SHORT_TERM_RENT","DAILY_RENT"]},"furnishing":{"type":"string","enum":["FURNISHED","SEMI_FURNISHED","UNFURNISHED"]},"price":{"type":"number","exclusiveMinimum":0},"priceOnRequest":{"type":"boolean","description":"Withhold the price; then price is not required."},"area":{"type":"number","exclusiveMinimum":0},"countryId":{"type":"string","description":"From /api/v1/reference/countries."},"cityId":{"type":"string","description":"Optional: settlement coverage is partial by design."},"districtId":{"type":"string"},"latitude":{"type":"number"},"longitude":{"type":"number"},"buildStage":{"type":["string","null"],"enum":["NEW_BUILD","UNDER_CONSTRUCTION",null],"description":"New builds: NEW_BUILD or UNDER_CONSTRUCTION; null for an existing building. Listings are returned with this field."},"completionYear":{"type":["integer","null"],"description":"Expected completion year, only kept with UNDER_CONSTRUCTION (otherwise stored as null): from last year to six years ahead of the current year. In a PATCH send it together with buildStage."},"completionQuarter":{"type":["integer","null"],"minimum":1,"maximum":4,"description":"Expected completion quarter, only kept with UNDER_CONSTRUCTION. In a PATCH send it together with buildStage."}}}}},"paths":{"/api/v1/listings":{"get":{"summary":"Your listings, newest first.","security":[{"ApiKey":["listings:read"]}],"parameters":[{"name":"status","in":"query","required":false,"description":"Any listing status; omit for all of them.","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Page size, at most 100.","schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"400":{"description":"A field is missing or invalid; the body names it."},"401":{"description":"No key, or the key lacks the scope."}}},"post":{"summary":"Create a listing. It starts as a DRAFT and is published separately.","security":[{"ApiKey":["listings:write"]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingCreate"}}}},"responses":{"200":{"description":"OK"},"400":{"description":"A field is missing or invalid; the body names it."},"401":{"description":"No key, or the key lacks the scope."}}}},"/api/v1/listings/{id}":{"get":{"summary":"One listing of yours, in full.","security":[{"ApiKey":["listings:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"400":{"description":"A field is missing or invalid; the body names it."},"401":{"description":"No key, or the key lacks the scope."}}},"patch":{"summary":"Change some fields. Anything you send must still be valid on its own.","security":[{"ApiKey":["listings:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingPatch"}}}},"responses":{"200":{"description":"OK"},"400":{"description":"A field is missing or invalid; the body names it."},"401":{"description":"No key, or the key lacks the scope."}}},"delete":{"summary":"Archive a listing. Nothing is erased.","security":[{"ApiKey":["listings:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"400":{"description":"A field is missing or invalid; the body names it."},"401":{"description":"No key, or the key lacks the scope."}}}},"/api/v1/listings/{id}/publish":{"post":{"summary":"Submit a draft for publication, once it has everything a published listing needs.","security":[{"ApiKey":["listings:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"400":{"description":"A field is missing or invalid; the body names it."},"401":{"description":"No key, or the key lacks the scope."}}}},"/api/v1/listings/{id}/status":{"post":{"summary":"Mark a listing sold, rented, or back on the market.","security":[{"ApiKey":["listings:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"400":{"description":"A field is missing or invalid; the body names it."},"401":{"description":"No key, or the key lacks the scope."}}}},"/api/v1/listings/{id}/images":{"get":{"summary":"The listing's photos, in the order they are shown.","security":[{"ApiKey":["listings:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"400":{"description":"A field is missing or invalid; the body names it."},"401":{"description":"No key, or the key lacks the scope."}}},"post":{"summary":"Add a photo.","security":[{"ApiKey":["listings:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"400":{"description":"A field is missing or invalid; the body names it."},"401":{"description":"No key, or the key lacks the scope."}}},"patch":{"summary":"Reorder the photos.","security":[{"ApiKey":["listings:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"400":{"description":"A field is missing or invalid; the body names it."},"401":{"description":"No key, or the key lacks the scope."}}}},"/api/v1/listings/{id}/images/{imageId}":{"delete":{"summary":"Remove one photo.","security":[{"ApiKey":["listings:write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"imageId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"400":{"description":"A field is missing or invalid; the body names it."},"401":{"description":"No key, or the key lacks the scope."}}}},"/api/v1/me":{"get":{"summary":"The account the key belongs to.","security":[{"ApiKey":["profile:read"]}],"parameters":[],"responses":{"200":{"description":"OK"},"400":{"description":"A field is missing or invalid; the body names it."},"401":{"description":"No key, or the key lacks the scope."}}},"patch":{"summary":"Update your contact details.","security":[{"ApiKey":["profile:write"]}],"parameters":[],"responses":{"200":{"description":"OK"},"400":{"description":"A field is missing or invalid; the body names it."},"401":{"description":"No key, or the key lacks the scope."}}}},"/api/v1/reference/countries":{"get":{"summary":"Countries, with the ids a listing refers to.","security":[{"ApiKey":[]}],"parameters":[],"responses":{"200":{"description":"OK"},"400":{"description":"A field is missing or invalid; the body names it."},"401":{"description":"No key, or the key lacks the scope."}}}},"/api/v1/reference/municipalities":{"get":{"summary":"Municipalities.","security":[{"ApiKey":[]}],"parameters":[{"name":"country","in":"query","required":false,"description":"Country code or slug.","schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"400":{"description":"A field is missing or invalid; the body names it."},"401":{"description":"No key, or the key lacks the scope."}}}},"/api/v1/reference/cities":{"get":{"summary":"Settlements — the level a listing is filed under.","security":[{"ApiKey":[]}],"parameters":[{"name":"country","in":"query","required":false,"description":"Country code or slug.","schema":{"type":"string"}},{"name":"municipality","in":"query","required":false,"description":"Municipality slug.","schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"400":{"description":"A field is missing or invalid; the body names it."},"401":{"description":"No key, or the key lacks the scope."}}}},"/api/v1/reference/districts":{"get":{"summary":"Quarters of one settlement.","security":[{"ApiKey":[]}],"parameters":[{"name":"city","in":"query","required":false,"description":"City slug.","schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"400":{"description":"A field is missing or invalid; the body names it."},"401":{"description":"No key, or the key lacks the scope."}}}},"/api/v1/reference/enums":{"get":{"summary":"The accepted values for every enumerated field.","security":[{"ApiKey":[]}],"parameters":[],"responses":{"200":{"description":"OK"},"400":{"description":"A field is missing or invalid; the body names it."},"401":{"description":"No key, or the key lacks the scope."}}}}}}