{"openapi":"3.1.0","info":{"title":"lovefengis public API","version":"1.0.0","description":"Catalog of the services and prices of lovefengis, a software studio in Izmir, Turkey. Prices come from the same source as the website (TRY, VAT included). No authentication, no personal data. Every operation is read-only: the two POST endpoints (/batch and /jobs) only run reads and compute exports, they store and change nothing. To start a project, book a call at /gorusme.\n\nPagination: list endpoints take limit (1-100, default 50) and an opaque cursor, and return next_cursor (null on the last page) and has_more.\n\nIdempotency: every POST accepts an Idempotency-Key header (1 to 255 printable ASCII characters). Operations are deterministic, so a repeated key with the same body returns the same result; the key is echoed in the response.\n\nSandbox: the second server serves the same API with fixture data (two fake services, ids starting with sandbox-). Responses carry X-Lovefengis-Environment: sandbox. The short form /api/sandbox/v1 also works.\n\nVersioning: the major version is in the path (/api/v1). Breaking changes ship as a new path; a deprecated endpoint keeps working for at least 6 months and announces itself with Deprecation, Sunset and Link headers. Policy: https://lovefengis.com/gelistirici/surum-politikasi","contact":{"name":"lovefengis","url":"https://lovefengis.com/gorusme"},"x-deprecation-policy":"https://lovefengis.com/gelistirici/surum-politikasi"},"externalDocs":{"description":"lovefengis developer docs","url":"https://lovefengis.com/gelistirici/api"},"servers":[{"url":"https://lovefengis.com","description":"Production"},{"url":"https://sandbox.lovefengis.com","description":"Sandbox server: same API paths with fake fixture data (also at ${SITE}/api/sandbox/v1)"}],"tags":[{"name":"Catalog","description":"Services and prices"},{"name":"Batch","description":"Several reads in one request"},{"name":"Jobs","description":"Asynchronous exports (202 Accepted, then poll)"}],"paths":{"/api/v1":{"get":{"operationId":"getApiIndex","tags":["Catalog"],"summary":"API index","description":"Returns the API name, version, documentation links and the list of available endpoints.","parameters":[{"name":"API-Version","in":"header","required":false,"description":"Pin the API version. Optional; the only version is 1. Any other value returns 400 unsupported_api_version. Policy: https://lovefengis.com/gelistirici/surum-politikasi","schema":{"type":"string","enum":["1"]}}],"responses":{"200":{"description":"API index","headers":{"API-Version":{"description":"Version that served the response.","schema":{"type":"string"}},"Deprecation":{"description":"RFC 9745. Present only on a deprecated endpoint: @ followed by the Unix time of deprecation.","schema":{"type":"string"}},"Sunset":{"description":"RFC 8594. Present only on a deprecated endpoint: HTTP date after which it may stop working.","schema":{"type":"string"}},"Link":{"description":"On a deprecated endpoint: the deprecation policy, rel=\"deprecation\".","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["name","version","openapi","docs","deprecation_policy","endpoints"],"properties":{"name":{"type":"string"},"version":{"type":"string"},"openapi":{"type":"string","format":"uri"},"docs":{"type":"string","format":"uri","description":"Developer documentation."},"deprecation_policy":{"type":"string","format":"uri"},"sandbox":{"type":"string","format":"uri","description":"Base URL of the sandbox that serves fixture data."},"endpoints":{"type":"array","items":{"type":"object","required":["method","path","description"],"properties":{"method":{"type":"string","enum":["GET","POST"]},"path":{"type":"string"},"description":{"type":"string"}}}}}}}}},"400":{"description":"A parameter or the API-Version header is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded; retry after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/status":{"get":{"operationId":"getStatus","tags":["Catalog"],"summary":"Health check","description":"Returns status ok, the API version and the server time. Never cached.","parameters":[{"name":"API-Version","in":"header","required":false,"description":"Pin the API version. Optional; the only version is 1. Any other value returns 400 unsupported_api_version. Policy: https://lovefengis.com/gelistirici/surum-politikasi","schema":{"type":"string","enum":["1"]}}],"responses":{"200":{"description":"Health status","headers":{"API-Version":{"description":"Version that served the response.","schema":{"type":"string"}},"Deprecation":{"description":"RFC 9745. Present only on a deprecated endpoint: @ followed by the Unix time of deprecation.","schema":{"type":"string"}},"Sunset":{"description":"RFC 8594. Present only on a deprecated endpoint: HTTP date after which it may stop working.","schema":{"type":"string"}},"Link":{"description":"On a deprecated endpoint: the deprecation policy, rel=\"deprecation\".","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["status","version","time"],"properties":{"status":{"type":"string","const":"ok"},"version":{"type":"string","example":"v1"},"time":{"type":"string","format":"date-time"}}}}}},"400":{"description":"A parameter or the API-Version header is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded; retry after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/hizmetler":{"get":{"operationId":"listServices","tags":["Catalog"],"summary":"List services","description":"Returns services with their id, page URL, Markdown URL and prices, one page at a time (limit, cursor).","parameters":[{"name":"limit","in":"query","required":false,"description":"Maximum items per page, 1 to 100. Default 50.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor. Pass the next_cursor value of the previous response of the same endpoint, unchanged, to get the next page.","schema":{"type":"string","maxLength":64}},{"name":"API-Version","in":"header","required":false,"description":"Pin the API version. Optional; the only version is 1. Any other value returns 400 unsupported_api_version. Policy: https://lovefengis.com/gelistirici/surum-politikasi","schema":{"type":"string","enum":["1"]}}],"responses":{"200":{"description":"Service list page","headers":{"API-Version":{"description":"Version that served the response.","schema":{"type":"string"}},"Deprecation":{"description":"RFC 9745. Present only on a deprecated endpoint: @ followed by the Unix time of deprecation.","schema":{"type":"string"}},"Sunset":{"description":"RFC 8594. Present only on a deprecated endpoint: HTTP date after which it may stop working.","schema":{"type":"string"}},"Link":{"description":"On a deprecated endpoint: the deprecation policy, rel=\"deprecation\".","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta","next_cursor","has_more"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ServiceSummary"}},"meta":{"$ref":"#/components/schemas/Meta"},"next_cursor":{"type":["string","null"],"description":"Pass as the cursor query parameter to get the next page. null on the last page."},"has_more":{"type":"boolean","description":"true when another page follows."}}}}}},"400":{"description":"A parameter or the API-Version header is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded; retry after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/hizmetler/{id}":{"get":{"operationId":"getService","tags":["Catalog"],"summary":"Get one service","description":"Returns one service with prices and, where the catalog has it, the scope list.","parameters":[{"name":"id","in":"path","required":true,"description":"Service id, the last segment of the service page path (for example kurumsal-ozel-yazilim).","schema":{"type":"string","pattern":"^[a-z0-9]+(-[a-z0-9]+)*$","maxLength":80}},{"name":"API-Version","in":"header","required":false,"description":"Pin the API version. Optional; the only version is 1. Any other value returns 400 unsupported_api_version. Policy: https://lovefengis.com/gelistirici/surum-politikasi","schema":{"type":"string","enum":["1"]}}],"responses":{"200":{"description":"Service","headers":{"API-Version":{"description":"Version that served the response.","schema":{"type":"string"}},"Deprecation":{"description":"RFC 9745. Present only on a deprecated endpoint: @ followed by the Unix time of deprecation.","schema":{"type":"string"}},"Sunset":{"description":"RFC 8594. Present only on a deprecated endpoint: HTTP date after which it may stop working.","schema":{"type":"string"}},"Link":{"description":"On a deprecated endpoint: the deprecation policy, rel=\"deprecation\".","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/Service"},"meta":{"$ref":"#/components/schemas/Meta"}}}}}},"400":{"description":"A parameter or the API-Version header is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No service has this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded; retry after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/fiyatlar":{"get":{"operationId":"listPrices","tags":["Catalog"],"summary":"List prices","description":"Returns a flat list of prices. Each price carries its service id. Filter by service id and billing period. Paged with limit and cursor.","parameters":[{"name":"service","in":"query","required":false,"description":"Only prices of this service id.","schema":{"type":"string","pattern":"^[a-z0-9]+(-[a-z0-9]+)*$","maxLength":80}},{"name":"period","in":"query","required":false,"description":"Only prices with this billing period.","schema":{"type":"string","enum":["one_time","monthly","yearly"]}},{"name":"limit","in":"query","required":false,"description":"Maximum items per page, 1 to 100. Default 50.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor. Pass the next_cursor value of the previous response of the same endpoint, unchanged, to get the next page.","schema":{"type":"string","maxLength":64}},{"name":"API-Version","in":"header","required":false,"description":"Pin the API version. Optional; the only version is 1. Any other value returns 400 unsupported_api_version. Policy: https://lovefengis.com/gelistirici/surum-politikasi","schema":{"type":"string","enum":["1"]}}],"responses":{"200":{"description":"Price list page","headers":{"API-Version":{"description":"Version that served the response.","schema":{"type":"string"}},"Deprecation":{"description":"RFC 9745. Present only on a deprecated endpoint: @ followed by the Unix time of deprecation.","schema":{"type":"string"}},"Sunset":{"description":"RFC 8594. Present only on a deprecated endpoint: HTTP date after which it may stop working.","schema":{"type":"string"}},"Link":{"description":"On a deprecated endpoint: the deprecation policy, rel=\"deprecation\".","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta","next_cursor","has_more"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PriceWithService"}},"meta":{"$ref":"#/components/schemas/Meta"},"next_cursor":{"type":["string","null"],"description":"Pass as the cursor query parameter to get the next page. null on the last page."},"has_more":{"type":"boolean","description":"true when another page follows."}}}}}},"400":{"description":"A parameter or the API-Version header is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded; retry after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/batch":{"post":{"operationId":"batchRead","tags":["Batch"],"summary":"Run several GET requests in one call","description":"Takes an array of up to 20 GET operations on /api/v1/ paths (not /batch or /jobs) and returns an array of { status, body } in the same order. Always 200 when the batch itself is valid; per-operation errors are in each status. Safe to repeat: same body, same result.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"name":"API-Version","in":"header","required":false,"description":"Pin the API version. Optional; the only version is 1. Any other value returns 400 unsupported_api_version. Policy: https://lovefengis.com/gelistirici/surum-politikasi","schema":{"type":"string","enum":["1"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchRequest"},"example":{"operations":[{"method":"GET","path":"/api/v1/hizmetler?limit=2"},{"method":"GET","path":"/api/v1/fiyatlar?period=monthly"}]}}}},"responses":{"200":{"description":"Results in request order.","headers":{"API-Version":{"description":"Version that served the response.","schema":{"type":"string"}},"Deprecation":{"description":"RFC 9745. Present only on a deprecated endpoint: @ followed by the Unix time of deprecation.","schema":{"type":"string"}},"Sunset":{"description":"RFC 8594. Present only on a deprecated endpoint: HTTP date after which it may stop working.","schema":{"type":"string"}},"Link":{"description":"On a deprecated endpoint: the deprecation policy, rel=\"deprecation\".","schema":{"type":"string"}},"Idempotency-Key":{"description":"Echo of the request header, when sent.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchResponse"}}}},"400":{"description":"A parameter or the API-Version header is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The request body is larger than 8192 bytes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The request body is not application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded; retry after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/jobs":{"post":{"operationId":"createJob","tags":["Jobs"],"summary":"Start an asynchronous price export","description":"Accepts a job and returns 202 with a Location header and status_url. Poll GET /api/v1/jobs/{id} until status is completed. The job id encodes the request, so no state is stored; repeating the same request returns the same id.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"name":"API-Version","in":"header","required":false,"description":"Pin the API version. Optional; the only version is 1. Any other value returns 400 unsupported_api_version. Policy: https://lovefengis.com/gelistirici/surum-politikasi","schema":{"type":"string","enum":["1"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobRequest"},"example":{"type":"price_export","period":"monthly"}}}},"responses":{"202":{"description":"Job accepted; poll status_url.","headers":{"API-Version":{"description":"Version that served the response.","schema":{"type":"string"}},"Deprecation":{"description":"RFC 9745. Present only on a deprecated endpoint: @ followed by the Unix time of deprecation.","schema":{"type":"string"}},"Sunset":{"description":"RFC 8594. Present only on a deprecated endpoint: HTTP date after which it may stop working.","schema":{"type":"string"}},"Link":{"description":"On a deprecated endpoint: the deprecation policy, rel=\"deprecation\".","schema":{"type":"string"}},"Location":{"description":"Path to poll for the job result.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before polling.","schema":{"type":"integer"}},"Idempotency-Key":{"description":"Echo of the request header, when sent.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["id","type","status","status_url"],"properties":{"id":{"type":"string"},"type":{"type":"string","enum":["price_export"]},"status":{"type":"string","enum":["queued"],"description":"Poll status_url (or the Location header) until status is completed."},"status_url":{"type":"string","format":"uri","description":"Absolute URL to poll with GET."}}}}}},"400":{"description":"A parameter or the API-Version header is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The request body is larger than 8192 bytes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The request body is not application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded; retry after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/jobs/{id}":{"get":{"operationId":"getJob","tags":["Jobs"],"summary":"Get a job and its result","description":"Returns the job with status completed and its result. An unknown or malformed id returns 404 job_not_found.","parameters":[{"name":"id","in":"path","required":true,"description":"Job id from POST /api/v1/jobs.","schema":{"type":"string","pattern":"^job_[A-Za-z0-9_-]+$","maxLength":304}},{"name":"API-Version","in":"header","required":false,"description":"Pin the API version. Optional; the only version is 1. Any other value returns 400 unsupported_api_version. Policy: https://lovefengis.com/gelistirici/surum-politikasi","schema":{"type":"string","enum":["1"]}}],"responses":{"200":{"description":"Job","headers":{"API-Version":{"description":"Version that served the response.","schema":{"type":"string"}},"Deprecation":{"description":"RFC 9745. Present only on a deprecated endpoint: @ followed by the Unix time of deprecation.","schema":{"type":"string"}},"Sunset":{"description":"RFC 8594. Present only on a deprecated endpoint: HTTP date after which it may stop working.","schema":{"type":"string"}},"Link":{"description":"On a deprecated endpoint: the deprecation policy, rel=\"deprecation\".","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["id","type","status","status_url","result","meta"],"properties":{"id":{"type":"string","description":"Job id. Stateless: it encodes the validated request, so it stays valid across restarts."},"type":{"type":"string","enum":["price_export"]},"status":{"type":"string","enum":["completed"]},"status_url":{"type":"string","format":"uri"},"result":{"type":"object","required":["service","period","count","prices"],"properties":{"service":{"type":["string","null"]},"period":{"type":["string","null"],"enum":["one_time","monthly","yearly",null]},"count":{"type":"integer"},"prices":{"type":"array","items":{"$ref":"#/components/schemas/PriceWithService"}}}},"meta":{"$ref":"#/components/schemas/Meta"}}}}}},"400":{"description":"A parameter or the API-Version header is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No job has this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded; retry after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"description":"Optional key (1 to 255 printable ASCII characters, for example a UUID) that identifies a retried request. These POST operations are read-only and deterministic, so the same key and body always return the same result. The key is echoed in the response; an invalid key returns 400 invalid_idempotency_key.","schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x21-\\x7E]{1,255}$"}}},"schemas":{"BatchRequest":{"type":"object","required":["operations"],"properties":{"operations":{"type":"array","minItems":1,"maxItems":20,"items":{"$ref":"#/components/schemas/BatchOperation"}}}},"BatchOperation":{"type":"object","required":["method","path"],"additionalProperties":false,"properties":{"method":{"type":"string","enum":["GET"]},"path":{"type":"string","pattern":"^/api/v1/","maxLength":300,"description":"A /api/v1/ path with optional query string, for example /api/v1/hizmetler/kurumsal-ozel-yazilim."}}},"BatchResponse":{"type":"object","required":["results"],"properties":{"results":{"type":"array","items":{"type":"object","required":["status","body"],"properties":{"status":{"type":"integer"},"body":{"type":"object","description":"The JSON body that the single request would have returned."}}}}}},"JobRequest":{"type":"object","required":["type"],"additionalProperties":false,"properties":{"type":{"type":"string","enum":["price_export"]},"service":{"type":"string","pattern":"^[a-z0-9]+(-[a-z0-9]+)*$","maxLength":80,"description":"Only prices of this service id."},"period":{"type":"string","enum":["one_time","monthly","yearly"]}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","hint"],"properties":{"code":{"type":"string","description":"Stable machine-readable code."},"message":{"type":"string"},"hint":{"type":"string","description":"How to fix the request."}}}}},"Price":{"type":"object","required":["id","label","amount_try","type","period","delivery","commitment_months"],"properties":{"id":{"type":"string"},"label":{"type":"string"},"amount_try":{"type":"integer","description":"Amount in Turkish lira, VAT included."},"type":{"type":"string","enum":["fixed","from"],"description":"\"from\" is a starting price; the final amount is fixed in a written offer."},"period":{"type":"string","enum":["one_time","monthly","yearly"]},"delivery":{"type":["string","null"],"description":"Delivery time as written on the site, or null."},"commitment_months":{"type":["integer","null"]}}},"PriceWithService":{"allOf":[{"$ref":"#/components/schemas/Price"},{"type":"object","required":["service_id","service_name","service_url"],"properties":{"service_id":{"type":"string"},"service_name":{"type":"string"},"service_url":{"type":"string","format":"uri"}}}]},"ServiceSummary":{"type":"object","required":["id","name","url","markdown_url","prices"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"markdown_url":{"type":"string","format":"uri"},"prices":{"type":"array","items":{"$ref":"#/components/schemas/Price"}}}},"Service":{"allOf":[{"$ref":"#/components/schemas/ServiceSummary"},{"type":"object","required":["scope"],"properties":{"scope":{"type":["array","null"],"items":{"type":"string"},"description":"What the service includes, when the catalog lists it."}}}]},"Meta":{"type":"object","required":["currency","vat_included","vat_note","from_means","fx","source"],"properties":{"currency":{"type":"string","const":"TRY"},"vat_included":{"type":"boolean"},"vat_note":{"type":"string"},"from_means":{"type":"string"},"fx":{"type":"object","required":["usd_try","as_of","source"],"properties":{"usd_try":{"type":"number"},"as_of":{"type":"string"},"source":{"type":"string"}}},"source":{"type":"string","format":"uri"},"environment":{"type":"string","const":"sandbox","description":"Present only in sandbox responses."},"note":{"type":"string","description":"Present only in sandbox responses: the data is fake."}}}}}}