Нет, не "должен", но может. Лично я пришел к такой схеме:
- 200-ые статус коды отправляются ТОЛЬКО тогда, когда все прошло успешно. В таком случае не будет никаких success: true или response: {} - а нужные данные, прямо на первом уровне нестинга. Собственно если взять за правило, что 200-ые коды возвращаются когда все ок, то можно полностью избавлятся от этих плохих проверок на наличие ключа в респонсе.
- 400-ые и 500-ые будут попадать в отдельный колбек/реджектить промис, опять же избавляя от нужды проверять какие-то ключи. Для всех кодов ответов, кроме 400 и 422 - в ответе нету нихрена. Ни code, ни message, ни response. Вообще ничего. Вся инфа находится в самом http status коде. Для 400 и 422 прибавляется параметр code, который является номером ВНУТРЕННЕЙ ошибки (ну, например, есть какие-то предусловия для выполнения запроса - уникальность эмейл адреса при регистрации как пример) - по ней фронт может показывать отдельные ошибки либо выполнять какую-то логику.
Плюс ко всему этому у себя локально и на сервере для фронта включен дебаг, добавляющий некий параметр _debug к каждому ответу. В нем может хранится любая инфа - сообщение с ошибкой (даже если ее можно понять по http коду или внутреннему), стак трэйс 500-ой ошибки и тд.