Cuando una UI muestra datos incorrectos, la pestaña Network en DevTools te dice si la API devolvió datos incorrectos (bug de backend) o si los datos correctos se mostraron de forma equivocada (bug de frontend). Ese único hábito de diagnóstico requiere entender cómo se estructuran las peticiones y respuestas REST. Este artículo cubre los métodos HTTP, los códigos de estado (incluyendo por qué un POST exitoso debería devolver 201 y no 200), los headers de autenticación, y cómo hacer llamadas directas a la API en tests de Playwright.
El concepto central: petición y respuesta
Una API (Application Programming Interface) es una forma en que dos piezas de software se comunican. Una API REST es un estilo específico de API que usa HTTP, el mismo protocolo que tu navegador usa para cargar sitios web.
La conversación siempre sigue el mismo patrón:
1. Tu código (o test) envía una petición
2. El servidor la procesa y devuelve una respuesta
Eso es todo. El resto son detalles sobre cómo se estructuran esas dos cosas.
Anatomía de una petición HTTP
Cada petición tiene cuatro partes:
1. Método (el verbo)
El método le dice al servidor qué quieres hacer:
| Método | Qué hace | Como decir |
|--------|---------|-----------|
| GET | Obtener datos | "Dame esta cosa" |
| POST | Crear algo nuevo | "Acá hay datos nuevos, guardalos" |
| PUT | Reemplazar algo completamente | "Reemplazá esto con mi nueva versión" |
| PATCH | Actualizar parte de algo | "Cambiá solo este campo" |
| DELETE | Eliminar algo | "Borrá esto" |
Un endpoint de reportes de bugs podría comportarse así:
GET /bugs→ listar todos los bugsGET /bugs/42→ obtener el bug #42POST /bugs→ crear un bug nuevoPATCH /bugs/42→ actualizar el estado del bug #42DELETE /bugs/42→ eliminar el bug #42
2. URL (la dirección)
La URL le dice al servidor con qué estás trabajando:
https://api.becomeqa.com/v1/users/123/ordersDesglosando esto:
https://api.becomeqa.com: el servidor/v1: versión de la API (común, no siempre presente)/users/123: el usuario específico con ID 123/orders: sus pedidos
Las partes después del dominio se llaman el path. Los números e IDs en el path (como 123) se llaman parámetros de path.
A veces los datos se pasan en la URL como parámetros de query:
GET /users?role=admin&active=true&page=2La parte ?role=admin&active=true&page=2 filtra y pagina los resultados sin cambiar de qué recurso estás hablando.
3. Headers
Los headers son metadatos enviados con la petición. Normalmente no los ves en el navegador (están en la pestaña Network). Los más comunes:
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Accept: application/jsonContent-Type le dice al servidor en qué formato está el cuerpo de tu petición. Authorization prueba quién eres (más sobre esto abajo). Accept le dice al servidor en qué formato quieres la respuesta.
4. Body
Las peticiones POST, PUT y PATCH generalmente incluyen un body, los datos reales que se envían. Las APIs REST casi siempre usan JSON:
{
"title": "El botón de login no funciona en mobile",
"severity": "high",
"steps": ["Abrir la app en mobile", "Tocar Login", "No pasa nada"]
}Las peticiones GET y DELETE típicamente no tienen body.
Anatomía de una respuesta HTTP
El servidor responde con:
1. Código de estado
Un número de 3 dígitos que te dice qué pasó:
| Rango | Categoría | Significado |
|-------|-----------|-------------|
| 2xx | Éxito | La petición funcionó |
| 3xx | Redirección | El recurso se movió, andá acá |
| 4xx | Error del cliente | Tu petición está mal |
| 5xx | Error del servidor | El servidor falló |
Los códigos más importantes para testing:
| Código | Nombre | Cuándo aparece |
|--------|--------|----------------|
| 200 | OK | Éxito estándar para GET |
| 201 | Created | POST que creó algo |
| 204 | No Content | Éxito pero nada que devolver (DELETE) |
| 400 | Bad Request | Entrada inválida (campo faltante, formato incorrecto) |
| 401 | Unauthorized | No autenticado (sin token o token inválido) |
| 403 | Forbidden | Autenticado pero sin permiso |
| 404 | Not Found | El recurso no existe |
| 422 | Unprocessable Entity | El JSON es válido pero falla la validación |
| 429 | Too Many Requests | Rate limiting |
| 500 | Internal Server Error | Crash no manejado del backend |
| 503 | Service Unavailable | El servidor está caído o sobrecargado |
2. Headers de respuesta
Similar a los headers de petición: metadatos sobre la respuesta:
Content-Type: application/json
X-Request-Id: abc-123-def
Cache-Control: no-cache3. Body de respuesta
Los datos reales devueltos, generalmente JSON:
{
"id": 42,
"title": "El botón de login no funciona en mobile",
"severity": "high",
"status": "open",
"created_at": "2026-05-17T10:30:00Z"
}O un error:
{
"error": "validation_failed",
"message": "El título es requerido",
"field": "title"
}Autenticación: cómo las APIs saben quién sos
La mayoría de las APIs requieren autenticación. Hay dos enfoques principales que vas a encontrar:
Bearer Token / JWT
Después del login, el servidor te da un token: una cadena larga que prueba tu identidad. Lo incluyes en cada petición posterior:
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjEyMywicm9sZSI6ImFkbWluIn0.abc123El servidor valida el token sin necesitar buscar tu sesión en una base de datos. Los tokens vencen (generalmente entre 15 minutos y 24 horas).
Sesiones basadas en cookies
Patrón más antiguo. Después del login, el servidor establece una cookie. El navegador la envía automáticamente con cada petición a ese dominio. No la ves en el body de la petición: el navegador la maneja.
API keys
Se usan para comunicación servidor a servidor. Una clave estática en el header:
X-API-Key: sk-1234567890abcdefCómo inspeccionar llamadas a la API en un navegador
Abre DevTools → pestaña Network → filtra por "Fetch/XHR". Cada llamada a la API que hace tu app aparecerá aquí.
Haz clic en cualquier petición para ver:
- Pestaña Headers: headers de petición, URL, método
- Pestaña Payload: body de la petición
- Pestaña Response: qué devolvió el servidor
- Código de estado: en la vista de lista, la columna del número
Aquí es donde depuras "¿es un bug de frontend o de backend?". Si la UI muestra datos incorrectos, verifica qué devolvió realmente la API. Si la API devolvió los datos correctos y la UI los muestra incorrectamente, es frontend. Si la API devolvió datos incorrectos, es backend.
Probar APIs: qué verificar
Al probar un endpoint de API (ya sea manualmente o con Playwright), verifica:
El código de estado coincide con la expectativa
- Crear un recurso →
201, no200 - Obtener un recurso →
200 - Delete exitoso sin contenido →
204 - Entrada inválida →
400o422, no500
El body de la respuesta es correcto
- Los campos requeridos están presentes
- Los tipos de datos son correctos (
"age": 25no"age": "25") - Los valores coinciden con lo que se envió
- No se filtraron datos sensibles (contraseñas, IDs internos)
Las respuestas de error son útiles
Los errores 400 deberían explicar qué fue inválido, los errores 404 deberían confirmar que el recurso no existe, y los errores 401 no deberían revelar información sensible de seguridad.
Los casos extremos se comportan correctamente
- Lista vacía: devuelve
[]nonull - ID inexistente: devuelve
404no500 - Body JSON inválido: devuelve
400no500 - Acción no autorizada: devuelve
403no200con body vacío
APIs REST en Playwright
Playwright puede hacer peticiones HTTP directamente, sin un navegador:
test('crear un usuario devuelve 201', async ({ request }) => {
const response = await request.post('https://api.becomeqa.com/users', {
data: {
name: 'Test User',
email: 'test@example.com',
role: 'member',
},
});
expect(response.status()).toBe(201);
const body = await response.json();
expect(body.id).toBeTruthy();
expect(body.email).toBe('test@example.com');
expect(body).not.toHaveProperty('password'); // sin filtración
});También puedes interceptar llamadas a la API hechas por el navegador durante tests E2E:
test('maneja el error de API de forma adecuada', async ({ page }) => {
// Forzar que la API devuelva un error
await page.route('**/api/users', (route) => {
route.fulfill({ status: 500, body: JSON.stringify({ error: 'server error' }) });
});
await page.goto('/users');
// La app debería mostrar el estado de error, no crashear
await expect(page.locator('[data-testid="error-banner"]')).toBeVisible();
});Resumen de vocabulario clave
| Término | Significado |
|---------|-------------|
| API | Interfaz para que el software se comunique |
| REST | Un estilo de API que usa HTTP |
| Endpoint | Una combinación específica de URL + método (GET /users) |
| Petición | Lo que enviás al servidor |
| Respuesta | Lo que el servidor devuelve |
| Código de estado | Número de 3 dígitos que indica éxito o fallo |
| JSON | El formato de datos que usan las APIs REST (basado en texto, pares clave-valor) |
| Header | Metadatos adjuntos a una petición o respuesta |
| Body | Los datos reales en una petición o respuesta |
| Bearer token | Credencial enviada en el header Authorization |
| Parámetro de path | Parte variable de la URL (/users/123, donde 123 es el parámetro) |
| Parámetro de query | Filtros en la URL después de ? (?page=2&sort=asc) |