Principios y prácticas para diseñar interfaces de programación claras, consistentes y evolucionables que faciliten la integración entre sistemas.
El diseño de APIs es la disciplina de crear interfaces programáticas que sean claras, consistentes y evolucionables. Una API bien diseñada actúa como un contrato entre sistemas, definiendo cómo los consumidores pueden interactuar con un servicio de manera predecible y confiable.
El diseño efectivo de APIs va más allá de simplemente exponer funcionalidad. Requiere considerar la experiencia del desarrollador, la evolución del sistema a largo plazo, y la integración con patrones arquitectónicos como microservicios y API Gateway. Una API bien diseñada reduce la fricción en la adopción, minimiza los errores de integración, y permite que los equipos trabajen de manera independiente.
El proceso de diseño debe ser iterativo y centrado en el usuario, comenzando con la definición del contrato antes de la implementación — un enfoque conocido como API-first que se alinea con el desarrollo dirigido por especificaciones.
| Estilo | Características | Casos de uso ideales | Complejidad |
|---|---|---|---|
| REST | Recursos, HTTP verbs, stateless | CRUD, APIs públicas, integraciones simples | Baja |
| GraphQL | Query language, schema tipado, single endpoint | Frontends complejos, agregación de datos | Media |
| gRPC | Protocol Buffers, streaming, type-safe | Microservicios internos, alta performance | Alta |
| WebSocket | Bidireccional, real-time, persistent connection | Chat, notificaciones, gaming | Media |
Una especificación OpenAPI define el contrato de una API REST de manera declarativa. Ejemplo para un endpoint de usuarios:
openapi: 3.0.3
info:
title: User Management API
version: 1.0.0
paths:
/users:
get:
summary: List users
parameters:
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: cursor
in: query
schema:
type: string
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/User'
pagination:
$ref: '#/components/schemas/CursorPagination'
components:
schemas:
User:
type: object
required: [id, email, created_at]
properties:
id:
type: string
format: uuid
email:
type: string
format: email
created_at:
type: string
format: date-time
CursorPagination:
type: object
properties:
next_cursor:
type: string
nullable: true
has_more:
type: boolean| Estrategia | Implementación | Ventajas | Desventajas |
|---|---|---|---|
| URL Path | /v1/users, /v2/users | Explícito, fácil routing | URLs múltiples, cache splitting |
| Query Parameter | /users?version=1 | Flexible, mismo endpoint | Fácil de omitir, menos explícito |
| Header | Accept: application/vnd.api+json;version=1 | Limpio, estándar HTTP | Menos visible, debugging complejo |
| Content Negotiation | Accept: application/vnd.myapi.v1+json | Estándar HTTP, granular | Configuración compleja |
{
"data": [...],
"pagination": {
"next_cursor": "eyJpZCI6MTIzfQ==",
"has_more": true,
"limit": 20
}
}Ventajas: Consistente con datos cambiantes, eficiente para datasets grandes Desventajas: No permite saltar a páginas específicas
{
"data": [...],
"pagination": {
"offset": 40,
"limit": 20,
"total": 1250,
"has_more": true
}
}Ventajas: Familiar, permite navegación directa Desventajas: Inconsistente con inserciones/eliminaciones, ineficiente en datasets grandes
Siguiendo RFC 9457 (Problem Details for HTTP APIs), que reemplaza al RFC 7807:
{
"type": "https://api.example.com/problems/validation-error",
"title": "Validation Error",
"status": 400,
"detail": "The request body contains invalid data",
"instance": "/users/create",
"errors": [
{
"field": "email",
"code": "INVALID_FORMAT",
"message": "Email must be a valid email address"
}
],
"trace_id": "abc123def456"
}| Algoritmo | Descripción | Casos de uso |
|---|---|---|
| Token Bucket | Tokens se regeneran a tasa fija | APIs con ráfagas permitidas |
| Fixed Window | Límite fijo por ventana de tiempo | Implementación simple |
| Sliding Window | Ventana deslizante más precisa | Balance entre precisión y performance |
| Leaky Bucket | Procesa requests a tasa constante | Suavizar tráfico irregular |
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 742
X-RateLimit-Reset: 1640995200
Retry-After: 3600
La integración con OAuth/OIDC es fundamental para APIs modernas. Consideraciones clave:
Las APIs deben integrarse nativamente con la observabilidad:
/health, /ready)Una API mal diseñada se convierte en deuda técnica permanente. Cada decisión de diseño — nomenclatura de recursos, estructura de respuestas, manejo de errores — se solidifica una vez que hay consumidores en producción. Cambiar una API pública requiere versionado, migración de clientes, y coordinación entre equipos.
El costo de rediseñar una API después del lanzamiento es exponencialmente mayor que invertir en diseño inicial. Una API bien diseñada reduce el tiempo de integración de semanas a días, minimiza tickets de soporte, y permite que los equipos de producto se muevan más rápido. En organizaciones con múltiples equipos, las APIs consistentes reducen la carga cognitiva y permiten reutilización de herramientas y patrones.
Metodología de desarrollo donde la especificación se escribe antes del código, sirviendo como contrato entre equipos y como fuente de verdad para la implementación.
Estilo arquitectónico que estructura una aplicación como colección de servicios pequeños, independientes y desplegables, cada uno con su propia lógica de negocio y datos.
Patrón que proporciona un punto de entrada único para múltiples microservicios, manejando routing, autenticación, rate limiting y agregación de respuestas.
Estándares de la industria para autorización delegada (OAuth 2.0) y autenticación federada (OpenID Connect), habilitando login con terceros y acceso seguro a APIs.
Capacidad de entender el estado interno de un sistema a partir de sus outputs externos: logs, métricas y traces, permitiendo diagnosticar problemas sin acceso directo al sistema.
Principios para diseñar kits de desarrollo que sean intuitivos, consistentes y faciliten la integración de servicios en múltiples lenguajes de programación.
Enfoque de diseño de software que centra el desarrollo en el dominio del negocio, usando un lenguaje ubicuo compartido entre desarrolladores y expertos de dominio.
Principios para diseñar interfaces de línea de comandos intuitivas, consistentes y productivas que los desarrolladores disfruten usar.
Patrón arquitectónico donde cada tipo de cliente tiene su propio backend dedicado que adapta las APIs de microservicios a las necesidades específicas de ese cliente.
Servicio managed de AWS para crear, publicar y gestionar APIs REST, HTTP y WebSocket que actúan como puerta de entrada a funciones Lambda y otros servicios backend.
Prácticas y herramientas para documentar APIs de forma clara, interactiva y mantenible, desde especificaciones OpenAPI hasta portales de documentación.