Saltearse al contenido

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:

Ventana de terminal
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{
"email": "[email protected]",
"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:

Ventana de terminal
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:

Ventana de terminal
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{
"email": "[email protected]",
"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:

Ventana de terminal
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:

Ventana de terminal
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:

Ventana de terminal
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:

Ventana de terminal
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:

Ventana de terminal
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:

Ventana de terminal
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:

Ventana de terminal
curl -X GET http://localhost:3000/api/v1/api-keys \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

3. Añadir Permisos a Clave API

Ejemplo con cURL:

Ventana de terminal
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:

Ventana de terminal
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:

Ventana de terminal
curl -X GET http://localhost:3000/api/v1/roles \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

2. Crear un Nuevo Rol (Solo Administrador)

Ejemplo con cURL:

Ventana de terminal
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:

Ventana de terminal
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:

Ventana de terminal
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:

Ventana de terminal
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:

Ventana de terminal
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:

auth.js
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ón
type AuthClient struct {
BaseURL string
AccessToken string
RefreshToken string
HTTPClient *http.Client
}
// NewAuthClient crea un nuevo cliente de autenticación
func NewAuthClient(baseURL string) *AuthClient {
return &AuthClient{
BaseURL: baseURL,
HTTPClient: &http.Client{},
}
}
// TokenResponse representa la respuesta de los endpoints de login y refresh
type TokenResponse struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresIn int `json:"expires_in"`
}
// Login autentica a un usuario
func (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 autenticada
func (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 acceso
func (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 actual
func (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 uso
func main() {
client := NewAuthClient("http://localhost:3000/api/v1")
// Iniciar sesión
err := client.Login("[email protected]", "contraseñasegura123")
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)
}