> What you did not do is build an REST API. API means consumable by software and just formatting and rendering the response does not count as consumption by software, at least in my book. I want to get the data and compute some statistics on it. For that I need to know the structure of the data in advance, need to know which URLs to retrieve, which operations to perform, which data structures to expect. That is what WSDL, OpenAPI and friends are for. That I can understand XML, JSON or OData is not good enough.

I think you have some degree of confusion on what REST is in general, and HATEOAs in particular.

"Which URLs to retrieve" is provided by the hypermedia format you requested for a particular resource. There are many HATEOAS-based specifications for formats. Your client asks for the ones it supports when sending a request,and the server delivers one based on your request and what it supports.

"Which operations to perform" is also specified as part of the hypermedia format you requested. Your format specifies link relationships valid for a resource according to it's current state.

"Which data structure to expect" makes no sense and is a reflection of the degree of confusion you're in. Your client is responsible for specifying which media type it can consume. The "data structure to expect" is specified as part of the media type. If your client expects specific data structures, it needs to support specific media types that represents them. These media types are not application/json or application/xml. They are media types designed to reflect the format used to express your resource.

> what can I do except baking the structure into my code in one way or another?

You're missing the whole point. With REST, the "structure" that you "bake into your code" is not the URLs, operations, or data formats. You only need a single root resource as the entry point, and that resource expresses all link relations that you need to navigate towards your resource. The link relations provided by the resource already specify which other resources are available to your client, which also includes operations they currently support. Your client also has the responsibility of requesting the resources it wants expressed in the format it supports, which included the data format. I mean, if you write a Atom client you don't request application/xml. Instead, you request application/atom+xml.

If you need an analogy to understand the whole point, check how you navigate HackerNews with a browser. You open a resource representing the main page, and you're presented with a list of resources which include a collection of submissions, links to other collections reflecting specific queries such as new discussions, links to resources that allow you to login/logout or represent your user account. From that initial resource, you use the links provided in it to request other resources. If your current application state supports logging in, there will be a link to that. If your state is already logged in, there will be resources made available only in that state such as your account or logging out. If you opt to request a resource representing a submission, you'll get the submission text and/or link, along with comments. Each comment provides links to other resources such as individual comments, etc.

That's basically the whole point of REST. Do you hardcode references to each discussion or comment? No. you get them through links provided by other resources. Do you always get access to the resource representing your user account? No, that depends on the application state. Etc etc etc.