OpenAPI Callbacks
Um callback é como deixar seu número de telefone no restaurante para que eles te liguem quando a comida estiver pronta. No mundo das APIs, funciona assim:
- Você (cliente) quer fazer um pedido mas não quer esperar. Você dá ao restaurante (servidor) o número do seu telefone (um "endereço de callback") ao fazer o pedido.
- O restaurante começa a preparar a comida. Isso pode levar algum tempo. O restaurante não vai te fazer esperar lá parado.
- O restaurante te liga quando a comida está pronta. Essa ligação é o callback.
Como Isso Funciona na API?
Você faz uma requisição para o servidor pedindo alguma coisa, como "me avise quando meu pedido estiver pronto". Você também informa onde o servidor deve te avisar (como um URL, que seria equivalente ao seu número de telefone no exemplo anterior). O servidor envia uma mensagem para esse URL no futuro, quando a tarefa estiver concluída.
Essa funcionalidade (introduzida na OpenAPI 3.0) é uma evolução importante para APIs modernas que requerem comunicação bidirecional ou orientada a eventos.
Benefícios do Callback
- Modelar notificações assíncronas: Útil para APIs que seguem padrões baseados em Webhooks.
- Documentação completa: Permite descrever todo o ciclo de vida da interação entre cliente e servidor.
- Flexibilidade: O caminho do callback pode ser dinâmico, adaptado à solicitação do cliente.
- Performance: Diminui o tráfego e o processamento desnecessário.
Esses cenários são comuns em APIs que implementam notificações assíncronas ou eventos baseados em Webhooks.
Quando Usar?
- Webhooks: Notificações para eventos específicos, como atualizações de status, alertas ou mensagens.
- Processos assíncronos: Quando o cliente precisa ser notificado após uma tarefa de longa duração ser concluída.
- Integrações em tempo real: Como sistemas de pagamento, notificações de entrega ou atualizações de estado.
Não é muito usado assim, mas é bom conhecer como funciona.
Imaginemos que quando recebemos uma requisição em uma api precisamos enviar para outro sistema (que tem outra api) que notificará o usuário. É claro que precisamos conhecer a outra api também.
openapi: 3.0.2
info:
#...
paths:
#...
/v1/customers/{customerId}/orders: #Observe que o path tem um parametro necessário
post:
tags:
- Order Service
description: Place Order
parameters:
- name: customerId # Não usamos o id anterior por que mudamos a definição aqui.
in: path
description: Customer Id
required: true
style: simple # Esse é o padrão
explode: false # Esse é o padrão
schema:
type: string
format: uuid
requestBody: # No body esperamos a ordem com o objeto BeerOrder
content:
application/json:
schema:
$ref: '#/components/schemas/BeerOrder'
required: false # O objeto não é obrigatório ser passado.
responses:
201:
description: Order Created
headers:
Location:
description: Reference to created Order
style: simple # Esse é o padrão
explode: false # Esse é o padrão
schema:
type: string
format: uri
400:
description: Bad Reqeust
404:
description: Not Found
409:
description: Conflict
callbacks: # Além de receber a requisição já estamos preparando outra para outro sistema.
orderStatusChange: # Nome do evento
${request.body#/orderStatusCallbackUrl}:
description: Webhook for order status change notifications
post: # Se o servidor esta enviando dados, faz sentido ser outra coisa?
# Até é possível que seja, mas são situações muito raras.
requestBody: # É necessário que se conheça a estrutura que a url acima irá criar.
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 # Só vai aparede no response, não no request
customerId:
type: string
format: uuid
customerRef:
type: string
nullable: true
beerOrderLines:
type: array
items:
$ref: '#/components/schemas/BeerOrderLine'
orderStatusCallbackUrl: # Vai ser usado no 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:
#...