API Response Standards

Códigos de Estado HTTP

2xx - Éxito

CódigoNombreUsoDescripción
200OKOperación exitosaRespuesta estándar para operaciones exitosas
201CreatedRecurso creadoCuando se crea un nuevo recurso
202AcceptedProcesamiento asíncronoOperación aceptada pero no completada
204No ContentSin contenidoOperación exitosa sin datos de respuesta

4xx - Errores del Cliente

CódigoNombreUsoDescripción
400Bad RequestSolicitud inválida Datos de entrada incorrectos o malformados
401UnauthorizedNo autenticado Token de acceso faltante o inválido
403ForbiddenSin permisos Token válido pero sin permisos para el recurso
404Not foundRecurso no encontrado El recurso solicitado no existe
409ConflictConflictoViolación de restricciones de negocio
422Unprocessable EntityDatos inválidosDatos válidos sintácticamente pero inválidos semánticamente
429Too Many RequestsLímite de velocidadDemasiadas solicitudes en un período de tiempo

5xx - Errores del Servidor

CódigoNombreUsoDescripción
500Internal Server ErrorError internoError inesperado del servidor
502 Bad GatewayError del gatewayError en servicio externo
503Service UnavailableServicio no disponibleServicio temporalmente no disponible

Formato de Respuesta Estándar

Respuesta Exitosa (200, 201, 202)

{
	"success": true,
	"data": {
		// Datos del recurso
	},
	"message": "Operación exitosa",
	"timestamp": "2024-01-15T10:30:00Z",
	"requestId": "req_123456789"
}

Respuesta de Lista/Paginación

{
	"success": true,
	"data": {
		"items": [
			// Array de elementos
		],
		"pagination": {
			"page": 1,
			"limit": 10,
			"total": 100,
			"totalPages": 10,
			"hasNext": true,
			"hasPrev": false
		}
	},
	"message": "Datos obtenidos exitosamente",
	"timestamp": "2024-01-15T10:30:00Z",
	"requestId": "req_123456789"
}

Manejo de Errores

Estructura de Error Estándar

{
	"success": false,
	"error": {
		"code": "VALIDATION_ERROR",
		"message": "Los datos proporcionados no son válidos",
		"details": [
			{
				"field": "email",
				"message": "El formato del email no es válido"
			},
			{
				"field": "password",
				"message": "La contraseña debe tener al menos 8 caracteres"
			}
		]
	},
	"timestamp": "2024-01-15T10:30:00Z",
	"requestId": "req_123456789"
}

Ejemplos de Respuestas de Error

400 - Bad Request

{
	"success": false,
	"error": {
		"code": "VALIDATION_ERROR",
		"message": "Los datos de la solicitud no son válidos",
		"details": [
			{
				"field": "email",
				"message": "El campo email es requerido"
			}
		]
	},
	"timestamp": "2024-01-15T10:30:00Z",
	"requestId": "req_123456789"
}

401 - Unauthorized

{
	"success": false,
	"error": {
		"code": "AUTHENTICATION_REQUIRED",
		"message": "Token de autenticación requerido",
		"details": null
	},
	"timestamp": "2024-01-15T10:30:00Z",
	"requestId": "req_123456789"
}

404 - Not Found

{
	"success": false,
	"error": {
		"code": "RESOURCE_NOT_FOUND",
		"message": "El usuario con ID 123 no fue encontrado",
		"details": null
	},
	"timestamp": "2024-01-15T10:30:00Z",
	"requestId": "req_123456789"
}
 
 

Ejemplos de Implementación

Backend (Node.js/Express)

// Middleware para respuestas exitosas
const successResponse = (
	res,
	data,
	message = "Operación exitosa",
	statusCode = 200
) => {
	return res.status(statusCode).json({
		success: true,
		data,
		message,
		timestamp: new Date().toISOString(),
		requestId: res.locals.requestId,
	});
};
 
// Middleware para respuestas de error
const errorResponse = (
	res,
	errorCode,
	message,
	details = null,
	statusCode = 400
) => {
	return res.status(statusCode).json({
		success: false,
		error: {
			code: errorCode,
			message,
			details,
		},
		timestamp: new Date().toISOString(),
		requestId: res.locals.requestId,
	});
};
 
// Uso en controladores
app.get("/api/users/:id", async (req, res) => {
	try {
		const user = await User.findById(req.params.id);
		if (!user) {
			return errorResponse(
				res,
				"RESOURCE_NOT_FOUND",
				"Usuario no encontrado",
				null,
				404
			);
		}
		return successResponse(res, user, "Usuario obtenido exitosamente");
	} catch (error) {
		return errorResponse(
			res,
			"INTERNAL_ERROR",
			"Error interno del servidor",
			null,
			500
		);
	}
});


Frontend (React/TypeScript)

// Tipos TypeScript
interface ApiResponse<T> {
  success: boolean;
  data?: T;
  message?: string;
  timestamp: string;
  requestId: string;
}
 
interface ApiError {
  success: false;
  error: {
    code: string;
    message: string;
    details?: Array<{
      field: string;
      message: string;
    }>;
  };
  timestamp: string;
  requestId: string;
}
 
// Hook para manejo de API
const useApi = () => {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
 
  const request = async <T>(
    url: string,
    options: RequestInit = {}
  ): Promise<ApiResponse<T> | null> => {
    setLoading(true);
    setError(null);
 
    try {
      const response = await fetch(url, {
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${getToken()}`,
          ...options.headers,
        },
        ...options,
      });
 
      const data = await response.json();
 
      if (!response.ok) {
        const errorData = data as ApiError;
        setError(errorData.error.message);
        return null;
      }
 
      return data as ApiResponse<T>;
    } catch (err) {
      setError('Error de conexión');
      return null;
    } finally {
      setLoading(false);
    }
  };
 
  return { request, loading, error };
};
 
// Uso en componentes
const UserProfile = ({ userId }: { userId: string }) => {
  const { request, loading, error } = useApi();
  const [user, setUser] = useState<User | null>(null);
 
  useEffect(() => {
    const fetchUser = async () => {
      const response = await request<User>(`/api/users/${userId}`);
      if (response?.success) {
        setUser(response.data);
      }
    };
 
    fetchUser();
  }, [userId]);
 
  if (loading) return <div>Cargando...</div>;
  if (error) return <div>Error: {error}</div>;
  if (!user) return <div>Usuario no encontrado</div>;
 
  return <div>{user.name}</div>;
};