I tend to prefer a simple JSON object that wraps any response...
{ data: any, error: object }
So that only the presence of an error needs to be checked... within the error should always be a friendly message property and optionally a numeric code, that mirrors the response code (404), etc.
{ error: { code:404, message: 'Not found' } }
This tends to work well with error traps in server-side workflows... As to the data/result etc, it can be whatever is needed as a response to the client. For paged results, data/nextToken or something similar are perfectly serviceable imho.
To me an error should be top-level in the response object, as well as meta, and the data itself should be a consistent property and nested as such. Other platforms add their own wrappers which include the headers with the response object. ymmv.
//use CamelCasePropertyNamesContractResolver
public class ApiResponse<T> {
public T Data { get; set; }
public Exception Error { get; set; }
public ApiResponse(T data) {
this.Data = data;
}
public ApiResponse(Exception error) {
this.Error = error;
}
}
In this way, all API requests return ApiResponse<TypeOfData>
To me an error should be top-level in the response object, as well as meta, and the data itself should be a consistent property and nested as such. Other platforms add their own wrappers which include the headers with the response object. ymmv.