Wraps fetch, parses JSON, and throws ApiError{code,message,status} on non-2xx. Degrades to {code:'unknown'} when the error body is not the expected envelope shape.