https://example.com/messages?posted-2020-01-01/content~Bob
would compile to SQL like select *
from messages
where posted < '2020-01-01' or content like '%Bob%'
It's a little bit constrained by the the characters that can appear unescaped in the query component of a URL, which is why it uses '-' instead of '<' for less-than and '/' for 'or'. But there are enough characters to allow a range of operators, and parenthesis is allowed for grouping. Also it's a super set of the usual way that browsers encode forms, so that '=' and '&' work the way you'd expect.It works pretty well!
The next step up is something like OpenAPI which is still REST but at least it encodes what result you could expect and how the objects are related to each other.
Another step and you've got GraphQL which doesn't just enforce the schema but actually generates your entire API from it (just the interface though not the implementation). It goes from 'this endpoint returns data conforming to this definition' to 'these are the objects I can return and these are their properties'.
By allowing more flexible queries it is possible to encode information into these objects that is impossible to fit in a single JSON (consider e.g. a simple user-management API that returns for each user a list of all the groups they're in and for each group a list of all its users).