Skip to main content

Callbacks

Documentación Oficial

Documentación Swagger

Un callback es como dejar tu número de teléfono en el restaurante para que te llamen cuando la comida esté lista. En el mundo de las APIs, funciona así:

  1. Tú (cliente) quieres hacer un pedido pero no quieres esperar. Le das al restaurante (servidor) el número de tu teléfono (una "dirección de callback") al hacer el pedido.
  2. El restaurante comienza a preparar la comida. Esto puede tomar algún tiempo. El restaurante no te va a hacer esperar allí parado.
  3. El restaurante te llama cuando la comida está lista. Esa llamada es el callback.

¿Cómo Funciona Esto en la API?

Haces una solicitud al servidor pidiendo algo, como "avísame cuando mi pedido esté listo". También informas dónde el servidor debe avisarte (como una URL, que sería equivalente a tu número de teléfono en el ejemplo anterior). El servidor envía un mensaje a esa URL en el futuro, cuando la tarea esté completada.

Esta funcionalidad (introducida en OpenAPI 3.0) es una evolución importante para APIs modernas que requieren comunicación bidireccional u orientada a eventos.

Beneficios del Callback

  • Modelar notificaciones asíncronas: Útil para APIs que siguen patrones basados en Webhooks.
  • Documentación completa: Permite describir todo el ciclo de vida de la interacción entre cliente y servidor.
  • Flexibilidad: El camino del callback puede ser dinámico, adaptado a la solicitud del cliente.
  • Performance: Disminuye el tráfico y el procesamiento innecesario.

Estos escenarios son comunes en APIs que implementan notificaciones asíncronas o eventos basados en Webhooks.

¿Cuándo Usar?

  • Webhooks: Notificaciones para eventos específicos, como actualizaciones de estado, alertas o mensajes.
  • Procesos asíncronos: Cuando el cliente necesita ser notificado después de que una tarea de larga duración sea completada.
  • Integraciones en tiempo real: Como sistemas de pago, notificaciones de entrega o actualizaciones de estado.

No es muy usado así, pero es bueno conocer cómo funciona.


Imaginemos que cuando recibimos una solicitud en una api necesitamos enviar a otro sistema (que tiene otra api) que notificará al usuario. Es claro que necesitamos conocer la otra api también.

openapi: 3.0.2
info:
#...
paths:
#...
/v1/customers/{customerId}/orders: # Observa que el path tiene un parámetro necesario
post:
tags:
- Order Service
description: Place Order
parameters:
- name: customerId # No usamos el id anterior porque cambiamos la definición aquí.
in: path
description: Customer Id
required: true
style: simple # Este es el estándar
explode: false # Este es el estándar
schema:
type: string
format: uuid
requestBody: # En el body esperamos la orden con el objeto BeerOrder
content:
application/json:
schema:
$ref: '#/components/schemas/BeerOrder'
required: false # El objeto no es obligatorio ser pasado.
responses:
201:
description: Order Created
headers:
Location:
description: Reference to created Order
style: simple # Este es el estándar
explode: false # Este es el estándar
schema:
type: string
format: uri
400:
description: Bad Reqeust
404:
description: Not Found
409:
description: Conflict
callbacks: # Además de recibir la solicitud ya estamos preparando otra para otro sistema.
orderStatusChange: # Nombre del evento
${request.body#/orderStatusCallbackUrl}:
description: Webhook for order status change notifications
post: # Si el servidor está enviando datos, ¿tiene sentido ser otra cosa?
# Sí es posible que sea, pero son situaciones muy raras.
requestBody: # Es necesario que se conozca la estructura que la url anterior creará.
content:
application/json:
schema:
type: object
properties:
orderId:
type: string
format: uuid
orderStatus:
type: string
responses:
200:
description: Okay
#...
components:
schemas:
#...
BeerList:
type: array
items:
$ref: '#/components/schemas/Beer'
BeerOrder:
required:
- customerId
type: object
properties:
id:
type: string
format: uuid
nullable: true #???
readOnly: true # Solo va a aparecer en el response, no en el request
customerId:
type: string
format: uuid
customerRef:
type: string
nullable: true
beerOrderLines:
type: array
items:
$ref: '#/components/schemas/BeerOrderLine'
orderStatusCallbackUrl: # Va a ser usado en el callback
type: string
format: uri
BeerOrderLine:
required:
- orderQuantity
- upc
type: object
properties:
id:
type: string
format: uuid
nullable: true
readOnly: true
beerId:
type: string
format: uuid
readOnly: true
upc:
type: string
orderQuantity:
maximum: 999
minimum: 1
type: integer
quantityAllocated:
type: integer
nullable: true
readOnly: true
parameters:
#...