I think there should be made a distinction between external API communication and internal communication.
Internal communication is easy: The I want a token can trust each other, and probably no state changes are to be expected, I want a token tokens created during the initiation of the process are still valid during the calling of underlying systems and so don't need to be revalidated in the meantime.
External communication is harder: The systems can't trust each other, and you have no control over possible events between requests, like a logout action. So if you use tokens, which are provided by an authorization server and because of the signing the token itself can verified and trusted, you still have to check if the token hasn't been revoked because the user has been logged out in the meantime.
To solve this you can of course reduce the lifetime of the access-token, and use a refresh-token with a long lifetime to get a new access-token from the authentication-server, that in its turn can check if the user hasn't logged out in the meantime now this sounds like a session to me though.
Although it's not uncommon to use a refresh token, it does make things somewhat more complicated.
HTTP API Authorization
Another problem with the refresh-token is that you have to make sure that it doesn't get stolen, since else the bearer can of course gets its own access-tokens from the AS. The only advantage of tokens, compared to sessions, is that tokens can contain basic user info, that can be used by the client, although this information can just as easily be provided to the client by an API call.
So in my opinion it is not that bad to use session IDs with secure http-only cookies. Cookies are applied automatically by the user-agent when communicating with the services domain.
The client implementation gets much simpeler, and there are many well-known practices to secure session-IDs and cookies.