Ejemplos de Uso de la API
Este documento proporciona ejemplos prácticos de escenarios comunes de uso de la API utilizando diversas herramientas como cURL, JavaScript y Go.
Flujo de Autenticación
1. Registrar un Nuevo Usuario
Ejemplo con cURL:
curl -X POST http://localhost:3000/api/v1/auth/register \ -H "Content-Type: application/json" \ -d '{ "email": "[email protected]", "password": "contraseñasegura123", "first_name": "Juan", "last_name": "Pérez" }'
Ejemplo con JavaScript (Fetch API):
fetch('http://localhost:3000/api/v1/auth/register', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ password: 'contraseñasegura123', first_name: 'Juan', last_name: 'Pérez' }),}).then(response => response.json()).then(data => console.log(data)).catch(error => console.error('Error:', error));
Ejemplo con Go:
package main
import ( "bytes" "encoding/json" "fmt" "net/http")
func main() { // Crear cuerpo de la solicitud requestBody, err := json.Marshal(map[string]string{ "password": "contraseñasegura123", "first_name": "Juan", "last_name": "Pérez", }) if err != nil { fmt.Println("Error al crear el cuerpo de la solicitud:", err) return }
// Realizar la solicitud resp, err := http.Post( "http://localhost:3000/api/v1/auth/register", "application/json", bytes.NewBuffer(requestBody), ) if err != nil { fmt.Println("Error al realizar la solicitud:", err) return } defer resp.Body.Close()
// Analizar la respuesta var result map[string]interface{} json.NewDecoder(resp.Body).Decode(&result) fmt.Println("Respuesta:", result)}
2. Verificar Email
Después del registro, el usuario recibirá un token de verificación. Utilízalo para verificar su email:
Ejemplo con cURL:
curl -X POST http://localhost:3000/api/v1/auth/verify-email \ -H "Content-Type: application/json" \ -d '{ "token": "token-de-verificacion-recibido-via-email" }'
3. Iniciar Sesión
Ejemplo con cURL:
curl -X POST http://localhost:3000/api/v1/auth/login \ -H "Content-Type: application/json" \ -d '{ "email": "[email protected]", "password": "contraseñasegura123" }'
Respuesta:
{ "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "bearer", "expires_in": 900}
Ejemplo con JavaScript (Fetch API):
fetch('http://localhost:3000/api/v1/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ password: 'contraseñasegura123' }),}).then(response => response.json()).then(data => { // Almacenar tokens en localStorage o de forma segura en memoria localStorage.setItem('access_token', data.access_token); localStorage.setItem('refresh_token', data.refresh_token); console.log('Autenticación exitosa:', data);}).catch(error => console.error('Error:', error));
Ejemplo con Go:
package main
import ( "bytes" "encoding/json" "fmt" "net/http")
func main() { // Crear cuerpo de la solicitud requestBody, err := json.Marshal(map[string]string{ "password": "contraseñasegura123", }) if err != nil { fmt.Println("Error al crear el cuerpo de la solicitud:", err) return }
// Realizar la solicitud resp, err := http.Post( "http://localhost:3000/api/v1/auth/login", "application/json", bytes.NewBuffer(requestBody), ) if err != nil { fmt.Println("Error al realizar la solicitud:", err) return } defer resp.Body.Close()
// Analizar la respuesta var result map[string]interface{} json.NewDecoder(resp.Body).Decode(&result) fmt.Println("Token de Acceso:", result["access_token"]) fmt.Println("Token de Refresco:", result["refresh_token"])}
4. Renovar Token
Cuando el token de acceso expire, utiliza el token de refresco para obtener un nuevo par:
Ejemplo con cURL:
curl -X POST http://localhost:3000/api/v1/auth/refresh \ -H "Content-Type: application/json" \ -d '{ "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." }'
Ejemplo con JavaScript:
fetch('http://localhost:3000/api/v1/auth/refresh', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ refresh_token: localStorage.getItem('refresh_token') }),}).then(response => response.json()).then(data => { // Actualizar tokens en almacenamiento localStorage.setItem('access_token', data.access_token); localStorage.setItem('refresh_token', data.refresh_token); console.log('Tokens renovados exitosamente');}).catch(error => console.error('Error al renovar tokens:', error));
5. Cerrar Sesión
Ejemplo con cURL:
curl -X POST http://localhost:3000/api/v1/auth/logout \ -H "Content-Type: application/json" \ -d '{ "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." }'
Ejemplo con JavaScript:
fetch('http://localhost:3000/api/v1/auth/logout', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ refresh_token: localStorage.getItem('refresh_token') }),}).then(response => { if (response.ok) { // Eliminar tokens del almacenamiento localStorage.removeItem('access_token'); localStorage.removeItem('refresh_token'); console.log('Sesión cerrada exitosamente'); } else { console.error('Error al cerrar sesión'); }}).catch(error => console.error('Error durante el cierre de sesión:', error));
Gestión de Usuarios
1. Obtener Perfil de Usuario Actual
Ejemplo con cURL:
curl -X GET http://localhost:3000/api/v1/users/me \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Ejemplo con JavaScript:
fetch('http://localhost:3000/api/v1/users/me', { method: 'GET', headers: { 'Authorization': `Bearer ${localStorage.getItem('access_token')}`, },}).then(response => response.json()).then(data => console.log('Perfil de usuario:', data)).catch(error => console.error('Error al obtener perfil:', error));
2. Actualizar Perfil de Usuario
Ejemplo con cURL:
curl -X PUT http://localhost:3000/api/v1/users/me \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \ -H "Content-Type: application/json" \ -d '{ "first_name": "Actualizado", "last_name": "Apellido" }'
Ejemplo con JavaScript:
fetch('http://localhost:3000/api/v1/users/me', { method: 'PUT', headers: { 'Authorization': `Bearer ${localStorage.getItem('access_token')}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ first_name: 'Actualizado', last_name: 'Apellido' }),}).then(response => response.json()).then(data => console.log('Perfil actualizado:', data)).catch(error => console.error('Error al actualizar perfil:', error));
3. Listar Todos los Usuarios (Solo Administrador)
Ejemplo con cURL:
curl -X GET "http://localhost:3000/api/v1/users?page=1&per_page=20" \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Ejemplo con JavaScript:
fetch('http://localhost:3000/api/v1/users?page=1&per_page=20', { method: 'GET', headers: { 'Authorization': `Bearer ${localStorage.getItem('access_token')}`, },}).then(response => response.json()).then(data => console.log('Lista de usuarios:', data)).catch(error => console.error('Error al obtener usuarios:', error));
Gestión de Claves API
1. Crear una Clave API
Ejemplo con cURL:
curl -X POST http://localhost:3000/api/v1/api-keys \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \ -H "Content-Type: application/json" \ -d '{ "name": "Clave API para Mi Servicio", "expires_at": "2025-12-31T23:59:59Z" }'
Respuesta:
{ "id": "8a7b6c5d-4e3f-2a1b-0c9d-8e7f6a5b4c3d", "user_id": "5f8d0d55-8b96-4536-8c34-781a9a3e9a9b", "name": "Clave API para Mi Servicio", "key": "sk-Avery1LongRandomAPIKeyStringThatShouldBeStoredSafely", "prefix": "sk-Avery", "is_active": true, "expires_at": "2025-12-31T23:59:59Z", "created_at": "2023-06-01T12:34:56Z", "updated_at": "2023-06-01T12:34:56Z"}
Importante: La clave API completa (campo key
) solo se devuelve una vez al crearla. Guárdala de forma segura ya que no podrás recuperarla más tarde.
2. Listar tus Claves API
Ejemplo con cURL:
curl -X GET http://localhost:3000/api/v1/api-keys \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
3. Añadir Permisos a Clave API
Ejemplo con cURL:
curl -X POST http://localhost:3000/api/v1/api-keys/8a7b6c5d-4e3f-2a1b-0c9d-8e7f6a5b4c3d/permissions \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \ -H "Content-Type: application/json" \ -d '{ "permission_id": "5f8d0d55-8b96-4536-8c34-781a9a3e9a9b" }'
4. Usar una Clave API para Autenticación
En lugar de usar tokens JWT, puedes autenticarte con una clave API:
Ejemplo con cURL:
curl -X GET http://localhost:3000/api/v1/users/me \ -H "X-API-Key: sk-Avery1LongRandomAPIKeyStringThatShouldBeStoredSafely"
Ejemplo con JavaScript:
fetch('http://localhost:3000/api/v1/users/me', { method: 'GET', headers: { 'X-API-Key': 'sk-Avery1LongRandomAPIKeyStringThatShouldBeStoredSafely', },}).then(response => response.json()).then(data => console.log('Perfil de usuario:', data)).catch(error => console.error('Error al obtener perfil:', error));
Gestión de Roles y Permisos
1. Listar Todos los Roles
Ejemplo con cURL:
curl -X GET http://localhost:3000/api/v1/roles \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
2. Crear un Nuevo Rol (Solo Administrador)
Ejemplo con cURL:
curl -X POST http://localhost:3000/api/v1/roles \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \ -H "Content-Type: application/json" \ -d '{ "name": "editor", "description": "Puede editar contenido pero no gestionar usuarios" }'
3. Añadir Permiso a Rol (Solo Administrador)
Ejemplo con cURL:
curl -X POST http://localhost:3000/api/v1/roles/8a7b6c5d-4e3f-2a1b-0c9d-8e7f6a5b4c3d/permissions \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \ -H "Content-Type: application/json" \ -d '{ "permission_id": "5f8d0d55-8b96-4536-8c34-781a9a3e9a9b" }'
4. Asignar Rol a Usuario (Solo Administrador)
Ejemplo con cURL:
curl -X POST http://localhost:3000/api/v1/users/8a7b6c5d-4e3f-2a1b-0c9d-8e7f6a5b4c3d/roles \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \ -H "Content-Type: application/json" \ -d '{ "role_id": "5f8d0d55-8b96-4536-8c34-781a9a3e9a9b" }'
Ejemplos de Manejo de Errores
1. Error de Validación
Solicitud:
curl -X POST http://localhost:3000/api/v1/auth/register \ -H "Content-Type: application/json" \ -d '{ "email": "email-invalido", "password": "corta", "first_name": "Juan", "last_name": "Pérez" }'
Respuesta:
{ "error": "Validación fallida", "fields": { "email": "debe ser una dirección de email válida", "password": "debe tener al menos 8 caracteres" }}
2. Error de Autenticación
Solicitud:
curl -X GET http://localhost:3000/api/v1/users/me
Respuesta:
{ "error": "No autorizado: falta token de autenticación", "status": 401}
3. Error de Límite de Tasa
Cuando se exceden los límites de tasa:
Respuesta:
{ "error": "Límite de tasa excedido", "status": 429}
Utilidades de Ayuda
Utilidad de Autenticación JavaScript
Aquí hay una utilidad JavaScript simple para manejar la autenticación:
class AuthService { constructor(apiUrl) { this.apiUrl = apiUrl; this.accessToken = localStorage.getItem('access_token'); this.refreshToken = localStorage.getItem('refresh_token'); }
isAuthenticated() { return !!this.accessToken; }
async login(email, password) { const response = await fetch(`${this.apiUrl}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ email, password }), });
if (!response.ok) { const error = await response.json(); throw new Error(error.error || 'Error al iniciar sesión'); }
const data = await response.json(); this.accessToken = data.access_token; this.refreshToken = data.refresh_token;
localStorage.setItem('access_token', this.accessToken); localStorage.setItem('refresh_token', this.refreshToken);
return data; }
async logout() { if (!this.refreshToken) return;
try { await fetch(`${this.apiUrl}/auth/logout`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ refresh_token: this.refreshToken }), }); } catch (error) { console.error('Error al cerrar sesión:', error); } finally { // Eliminar tokens independientemente del éxito al cerrar sesión this.accessToken = null; this.refreshToken = null; localStorage.removeItem('access_token'); localStorage.removeItem('refresh_token'); } }
async refreshAccessToken() { if (!this.refreshToken) throw new Error('No hay token de refresco disponible');
const response = await fetch(`${this.apiUrl}/auth/refresh`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ refresh_token: this.refreshToken }), });
if (!response.ok) { // Si la renovación falla, cerrar sesión this.logout(); throw new Error('Error al renovar token'); }
const data = await response.json(); this.accessToken = data.access_token; this.refreshToken = data.refresh_token;
localStorage.setItem('access_token', this.accessToken); localStorage.setItem('refresh_token', this.refreshToken);
return data; }
async fetchWithAuth(url, options = {}) { const headers = { ...options.headers, 'Authorization': `Bearer ${this.accessToken}`, };
let response = await fetch(url, { ...options, headers });
// Si no está autorizado, intentar renovar token y reintentar la solicitud if (response.status === 401 && this.refreshToken) { try { await this.refreshAccessToken(); // Actualizar encabezados con nuevo token headers.Authorization = `Bearer ${this.accessToken}`; // Reintentar la solicitud response = await fetch(url, { ...options, headers }); } catch (error) { console.error('Error al renovar token:', error); throw error; } }
return response; }}
// Uso:const auth = new AuthService('http://localhost:3000/api/v1');
async function loginUser(email, password) { try { await auth.login(email, password); console.log('Inicio de sesión exitoso'); } catch (error) { console.error('Error al iniciar sesión:', error); }}
async function getUserProfile() { try { const response = await auth.fetchWithAuth(`${auth.apiUrl}/users/me`); if (!response.ok) throw new Error('Error al obtener perfil'); const profile = await response.json(); console.log('Perfil de usuario:', profile); return profile; } catch (error) { console.error('Error al obtener perfil:', error); }}
Ejemplo de Cliente Go
Aquí hay un cliente Go simple para la API:
package main
import ( "bytes" "encoding/json" "errors" "fmt" "net/http")
// AuthClient representa un cliente para la API de autenticacióntype AuthClient struct { BaseURL string AccessToken string RefreshToken string HTTPClient *http.Client}
// NewAuthClient crea un nuevo cliente de autenticaciónfunc NewAuthClient(baseURL string) *AuthClient { return &AuthClient{ BaseURL: baseURL, HTTPClient: &http.Client{}, }}
// TokenResponse representa la respuesta de los endpoints de login y refreshtype TokenResponse struct { AccessToken string `json:"access_token"` RefreshToken string `json:"refresh_token"` ExpiresIn int `json:"expires_in"`}
// Login autentica a un usuariofunc (c *AuthClient) Login(email, password string) error { // Crear cuerpo de la solicitud requestBody, err := json.Marshal(map[string]string{ "email": email, "password": password, }) if err != nil { return err }
// Realizar la solicitud resp, err := c.HTTPClient.Post( c.BaseURL+"/auth/login", "application/json", bytes.NewBuffer(requestBody), ) if err != nil { return err } defer resp.Body.Close()
if resp.StatusCode != http.StatusOK { var errorResp map[string]interface{} json.NewDecoder(resp.Body).Decode(&errorResp) return fmt.Errorf("error al iniciar sesión: %v", errorResp["error"]) }
// Analizar la respuesta var tokenResp TokenResponse if err := json.NewDecoder(resp.Body).Decode(&tokenResp); err != nil { return err }
// Guardar tokens c.AccessToken = tokenResp.AccessToken c.RefreshToken = tokenResp.RefreshToken return nil}
// AuthenticatedRequest realiza una solicitud autenticadafunc (c *AuthClient) AuthenticatedRequest(method, path string, body interface{}) (*http.Response, error) { if c.AccessToken == "" { return nil, errors.New("no autenticado") }
var bodyReader *bytes.Buffer if body != nil { bodyData, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewBuffer(bodyData) }
// Crear solicitud req, err := http.NewRequest(method, c.BaseURL+path, bodyReader) if err != nil { return nil, err }
// Establecer encabezados req.Header.Set("Authorization", "Bearer "+c.AccessToken) if body != nil { req.Header.Set("Content-Type", "application/json") }
// Realizar la solicitud resp, err := c.HTTPClient.Do(req) if err != nil { return nil, err }
// Si no está autorizado, intentar renovar token if resp.StatusCode == http.StatusUnauthorized && c.RefreshToken != "" { resp.Body.Close() // Cerrar la respuesta 401
// Intentar renovar token err = c.RefreshTokens() if err != nil { return nil, fmt.Errorf("error al renovar token: %w", err) }
// Reintentar la solicitud con nuevo token req.Header.Set("Authorization", "Bearer "+c.AccessToken) return c.HTTPClient.Do(req) }
return resp, nil}
// RefreshTokens renueva el token de accesofunc (c *AuthClient) RefreshTokens() error { if c.RefreshToken == "" { return errors.New("no hay token de refresco disponible") }
// Crear cuerpo de la solicitud requestBody, err := json.Marshal(map[string]string{ "refresh_token": c.RefreshToken, }) if err != nil { return err }
// Realizar la solicitud resp, err := c.HTTPClient.Post( c.BaseURL+"/auth/refresh", "application/json", bytes.NewBuffer(requestBody), ) if err != nil { return err } defer resp.Body.Close()
if resp.StatusCode != http.StatusOK { // Limpiar tokens en caso de error de renovación c.AccessToken = "" c.RefreshToken = "" var errorResp map[string]interface{} json.NewDecoder(resp.Body).Decode(&errorResp) return fmt.Errorf("error al renovar token: %v", errorResp["error"]) }
// Analizar la respuesta var tokenResp TokenResponse if err := json.NewDecoder(resp.Body).Decode(&tokenResp); err != nil { return err }
// Guardar nuevos tokens c.AccessToken = tokenResp.AccessToken c.RefreshToken = tokenResp.RefreshToken return nil}
// GetUserProfile obtiene el perfil del usuario actualfunc (c *AuthClient) GetUserProfile() (map[string]interface{}, error) { resp, err := c.AuthenticatedRequest("GET", "/users/me", nil) if err != nil { return nil, err } defer resp.Body.Close()
if resp.StatusCode != http.StatusOK { var errorResp map[string]interface{} json.NewDecoder(resp.Body).Decode(&errorResp) return nil, fmt.Errorf("error al obtener perfil: %v", errorResp["error"]) }
var profile map[string]interface{} if err := json.NewDecoder(resp.Body).Decode(&profile); err != nil { return nil, err }
return profile, nil}
// Ejemplo de usofunc main() { client := NewAuthClient("http://localhost:3000/api/v1")
// Iniciar sesión if err != nil { fmt.Println("Error de inicio de sesión:", err) return }
// Obtener perfil profile, err := client.GetUserProfile() if err != nil { fmt.Println("Error al obtener perfil:", err) return }
fmt.Println("Perfil de usuario:", profile)}