Eu sou dev PHP, e já montei várias APIs usando Laravel. Mas não vou falar de linguagem ou tecnologia, apenas de conceito.

Uma coisa que é bem importante e eu não consigo desenvolver uma API sem isso, é autenticação por tokens JWT. Se você tiver funcionalidades restritas na sua API (ex.: gerenciamento de usuários), um jeito simples de fazer autenticação e validação dos usuários é com tokens JWT. Dá uma pesquisada sobre isso, é bem simples de entender, usar e implementar. E, com certeza, deve ter algum pacote pronto pra usar no Express (se já não tiver algo nativo rs).

Outra boa prática é se atentar bem aos códigos de status de retorno (200, 201, 400, 404, 422, 500 etc) para as respostas das chamadas na sua API, e também aos métodos usados para fazer as chamadas (GET, POST, PUT, PATCH e DELETE). Com esses dois "recursos" bem implementados, a validação dos retornos no front-end vai ser muito simples (e bonita), e documentações (seja uma collection no Postman ou uma interface com Swagger) vão ser bem mais simples de entender.

Espero que tenha contribuído com alguma coisa :)

Com certeza contribuiu algo. Sim, estou usando jwt para autenticação. Trazendo um exemplo:

Tenho uma rota DELETE /users/{userID}, a melhor forma de garantir que o usuário só pode deletar ele mesmo é checar o id do jwt com o id recebido como parametro?

Sobre os retornos, sim estou prezando bastante pelos códigos corretos. Retornar erro com 200 é triste kkkkkkkkk Acharia uma boa ter um padrão de retornar sempre no JSON a mensagem, o status (código), e o dado (data) ou somente retornar status e mensagem em caso de erro?

Sempre aconselhável fazer uma função handler de response. Eu curto sempre usar o HATEOAS para tornar a RESTful de fato... Pesquisa sobre error handler left/right, muito bom para os retornos e tratamentos de exceções.
eu gosto de retornar o código do status da requisição, para facilitar na chamada no front, e em algums tipos de requisição, como um post, gosto de retornar um json com um retorno, nem que seja um OK
Eu vejo em muitos lugares o retorno da própria entidade em caso de sucesso, inclusive já desenvolvi assim, mas nunca achei um consenso na comunidade sobre esse caso, qual a sua opinião?
Sobre o DELETE, eu faria exatamente como você mencionou, comparando o ID do usuário do JWT com o ID enviado na URL. Já vi pessoas com receio desse tipo de comparação por conta do JWT ser "visível" para o usuário (não diretamente, mas um curioso consegue ver ele no localStorage ou nas chamadas às APIs pelo DevTools do Chrome, por exemplo), mas como a estrutura dele envolve assinatura e etc, acaba sendo mais difícil de realmente comprometer a integridade dele, mesmo se alguém mudar o payload que é um simples base64. Se o seu back-end faz a validação certa do JWT, pode pegar as informações dele sem medo. Então, no seu caso, particularmente eu acho válido comparar o ID que vem no JWT com o ID informado na URL pra saber se o usuário tá fazendo "usuarisse" ou não kk Sobre o código de retorno, eu particularmente não costumo retornar ele no corpo da resposta, justamente porque ele já vem informado nos cabeçalhos das respostas (por exemplo, usando alguma biblioteca de ajax - como Axios, ou até mesmo a Fetch API, que não é uma biblioteca mas tem tudo que é necessário -, já é possível validar o código de status de uma request), então seria um tipo de redundância. Assim, você pode deixar o corpo da resposta somente com o dado que precisar retornar. E, em casos de erro, por exemplo, eu costumo retornar apenas um objeto`{message:"Mensagem descrevendo o erro"}` no body, assim posso mostrar alguma informação útil para o usuário, e não preciso deixar regra de negócio (como validar o motivo do erro) no front-end, porque o próprio back-end já vai me trazer uma mensagem descrevendo o que deu errado.
Eu particulamente gosto de devolver um json padronizado com algumas informações relevantes, como status da requisição, campo de erros, informações sbre paginação e outras informações relevantes. Uma boa API facilita muito a vida do front, geralmente, faço algo como o exemplo abaixo, imaginando um endpoint que devolveria uma lista de livros: ```json { "data": [ { "id": 1, "nome": "Entendendo algoritmos", } ... ], "meta": { "total": 1, "perPage": 10, "currentPage": 0, "nextPage": 1, "lastPage": null, "nextPageUrl": ... }, "error" : { "message": (alguma mensagem significativa para poder ser exibida no front), "debugMessage": (alguma mensagem que ajudasse a compreender a raíz do erro), "subErrors": [(em caso de múltiplos erros)], } } ```
Gostei muito desse "meta". Costumava trazer esse dados soltos, mas amei o padrão de metadados. Aderi!