# OpenAPI Callbacks
Podrías crear una API con una *path operation* que podría desencadenar un request a una *API externa* creada por alguien más (probablemente el mismo desarrollador que estaría *usando* tu API).
El proceso que ocurre cuando tu aplicación API llama a la *API externa* se llama un "callback". Porque el software que escribió el desarrollador externo envía un request a tu API y luego tu API *responde*, enviando un request a una *API externa* (que probablemente fue creada por el mismo desarrollador).
En este caso, podrías querer documentar cómo esa API externa *debería* verse. Qué *path operation* debería tener, qué cuerpo debería esperar, qué response debería devolver, etc.
## Una aplicación con callbacks
Veamos todo esto con un ejemplo.
Imagina que desarrollas una aplicación que permite crear facturas.
Estas facturas tendrán un `id`, `title` (opcional), `customer`, y `total`.
El usuario de tu API (un desarrollador externo) creará una factura en tu API con un request POST.
Luego tu API (imaginemos):
* Enviará la factura a algún cliente del desarrollador externo.
* Recogerá el dinero.
* Enviará una notificación de vuelta al usuario de la API (el desarrollador externo).
* Esto se hará enviando un request POST (desde *tu API*) a alguna *API externa* proporcionada por ese desarrollador externo (este es el "callback").
## La aplicación normal de **FastAPI**
Primero veamos cómo sería la aplicación API normal antes de agregar el callback.
Tendrá una *path operation* que recibirá un cuerpo `Invoice`, y un parámetro de query `callback_url` que contendrá la URL para el callback.
Esta parte es bastante normal, probablemente ya estés familiarizado con la mayor parte del código:
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[9:13,36:53] *}
/// tip | Consejo
El parámetro de query `callback_url` utiliza un tipo Url de Pydantic.
///
Lo único nuevo es el `callbacks=invoices_callback_router.routes` como un argumento para el *decorador de path operation*. Veremos qué es eso a continuación.
## Documentar el callback
El código real del callback dependerá mucho de tu propia aplicación API.
Y probablemente variará mucho de una aplicación a otra.
Podría ser solo una o dos líneas de código, como:
```Python
callback_url = "https://example.com/api/v1/invoices/events/"
httpx.post(callback_url, json={"description": "Invoice paid", "paid": True})
```
Pero posiblemente la parte más importante del callback es asegurarse de que el usuario de tu API (el desarrollador externo) implemente la *API externa* correctamente, de acuerdo con los datos que *tu API* va a enviar en el request body del callback, etc.
Entonces, lo que haremos a continuación es agregar el código para documentar cómo debería verse esa *API externa* para recibir el callback de *tu API*.
Esa documentación aparecerá en la Swagger UI en `/docs` en tu API, y permitirá a los desarrolladores externos saber cómo construir la *API externa*.
Este ejemplo no implementa el callback en sí (eso podría ser solo una línea de código), solo la parte de documentación.
/// tip | Consejo
El callback real es solo un request HTTP.
Cuando implementes el callback tú mismo, podrías usar algo como HTTPX o Requests.
///
## Escribir el código de documentación del callback
Este código no se ejecutará en tu aplicación, solo lo necesitamos para *documentar* cómo debería verse esa *API externa*.
Pero, ya sabes cómo crear fácilmente documentación automática para una API con **FastAPI**.
Así que vamos a usar ese mismo conocimiento para documentar cómo debería verse la *API externa*... creando la(s) *path operation(s)* que la API externa debería implementar (las que tu API va a llamar).
/// tip | Consejo
Cuando escribas el código para documentar un callback, podría ser útil imaginar que eres ese *desarrollador externo*. Y que actualmente estás implementando la *API externa*, no *tu API*.
Adoptar temporalmente este punto de vista (del *desarrollador externo*) puede ayudarte a sentir que es más obvio dónde poner los parámetros, el modelo de Pydantic para el body, para el response, etc. para esa *API externa*.
///
### Crear un `APIRouter` de callback
Primero crea un nuevo `APIRouter` que contendrá uno o más callbacks.
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[3,25] *}
### Crear la *path operation* del callback
Para crear la *path operation* del callback utiliza el mismo `APIRouter` que creaste anteriormente.
Debería verse como una *path operation* normal de FastAPI:
* Probablemente debería tener una declaración del body que debería recibir, por ejemplo `body: InvoiceEvent`.
* Y también podría tener una declaración del response que debería devolver, por ejemplo `response_model=InvoiceEventReceived`.
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[16:18,21:22,28:32] *}
Hay 2 diferencias principales respecto a una *path operation* normal:
* No necesita tener ningún código real, porque tu aplicación nunca llamará a este código. Solo se usa para documentar la *API externa*. Así que, la función podría simplemente tener `pass`.
* El *path* puede contener una expresión OpenAPI 3 (ver más abajo) donde puede usar variables con parámetros y partes del request original enviado a *tu API*.
### La expresión del path del callback
El *path* del callback puede tener una expresión OpenAPI 3 que puede contener partes del request original enviado a *tu API*.
En este caso, es el `str`:
```Python
"{$callback_url}/invoices/{$request.body.id}"
```
Entonces, si el usuario de tu API (el desarrollador externo) envía un request a *tu API* a:
```
https://yourapi.com/invoices/?callback_url=https://www.external.org/events
```
con un JSON body de:
```JSON
{
"id": "2expen51ve",
"customer": "Mr. Richie Rich",
"total": "9999"
}
```
luego *tu API* procesará la factura, y en algún momento después, enviará un request de callback al `callback_url` (la *API externa*):
```
https://www.external.org/events/invoices/2expen51ve
```
con un JSON body que contiene algo como:
```JSON
{
"description": "Payment celebration",
"paid": true
}
```
y esperaría un response de esa *API externa* con un JSON body como:
```JSON
{
"ok": true
}
```
/// tip | Consejo
Observa cómo la URL del callback utilizada contiene la URL recibida como parámetro de query en `callback_url` (`https://www.external.org/events`) y también el `id` de la factura desde dentro del JSON body (`2expen51ve`).
///
### Agregar el router de callback
En este punto tienes las *path operation(s)* del callback necesarias (las que el *desarrollador externo* debería implementar en la *API externa*) en el router de callback que creaste antes.
Ahora usa el parámetro `callbacks` en el *decorador de path operation de tu API* para pasar el atributo `.routes` (que en realidad es solo un `list` de rutas/*path operations*) de ese router de callback:
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[35] *}
/// tip | Consejo
Observa que no estás pasando el router en sí (`invoices_callback_router`) a `callback=`, sino el atributo `.routes`, como en `invoices_callback_router.routes`.
///
### Revisa la documentación
Ahora puedes iniciar tu aplicación e ir a http://127.0.0.1:8000/docs.
Verás tu documentación incluyendo una sección de "Callbacks" para tu *path operation* que muestra cómo debería verse la *API externa*: