Volver a Documentacion

Guia de Eventos en Tiempo Real (SSE)

Transmita precios FX en vivo, estados de transferencias, actualizaciones de ordenes y cambios de saldo a su aplicacion usando Server-Sent Events en lugar de polling.


Descripcion General

La plataforma ARi envia actualizaciones en tiempo real a su aplicacion a traves de una conexion HTTP persistente usando Server-Sent Events (SSE). En lugar de consultar endpoints cada pocos segundos, abra una sola conexion y reciba eventos en el instante en que ocurren — cambios de precio, transferencias completadas, ordenes ejecutadas y actualizaciones de saldo.

Caracteristica Detalles
Endpoint GET /api/v1/events/stream
Protocolo Server-Sent Events (text/event-stream)
Autenticacion Header Ocp-Apim-Subscription-Key
Eventos Broadcast price.update — cambios de tasa FX en vivo (todos los clientes)
Eventos por Usuario transfer.status, fxorder.status, balance.updated — actualizaciones por usuario
Reconexion Replay automatico via header Last-Event-ID

SSE vs Polling

SSE Polling
Latencia Push instantaneo Depende del intervalo de consulta
Ancho de Banda Una conexion abierta Solicitudes repetidas, mayormente vacias
Complejidad Manejar eventos entrantes Administrar timers y deduplicacion
Ideal para Dashboards en vivo, UIs de trading Integraciones simples, trabajos batch

Alcance de Eventos

Los eventos se dividen en dos categorias segun quien los recibe:

+---------------------------------------------------------------+
|                     ALCANCE DE EVENTOS                        |
+---------------------------------------------------------------+

     BROADCAST (price.update):
     ┌──────────────┐
     │   ARi API    │ ──> Cliente A
     │              │ ──> Cliente B     Todos los clientes
     │              │ ──> Cliente C     reciben el evento
     └──────────────┘

     POR USUARIO (transfer.status, fxorder.status, ...):
     ┌──────────────┐
     │   ARi API    │ ──> Cliente A  ✓  (externalUserId coincide)
     │              │     Cliente B  ✗  (usuario diferente)
     │              │     Cliente C  ✗  (usuario diferente)
     └──────────────┘

+---------------------------------------------------------------+
Alcance Eventos Entrega
Broadcast price.update Todos los clientes conectados
Por usuario transfer.status, fxorder.status, balance.updated, y mas Solo la conexion que coincide con el usuario destino

Para partners M2M, los eventos por usuario se filtran por el externalUserId configurado en su perfil de partner. Usted recibe unicamente eventos que pertenecen a su usuario.

¿Multiples usuarios? Si necesita eventos para multiples usuarios, abra una conexion SSE separada para cada externalUserId. Cada conexion tiene su propio alcance de eventos.


Inicio Rapido

Requisitos Previos

Antes de conectarse al stream de eventos, asegurese de tener:

  1. Clave de Suscripcion API — Obtenga desde el Portal de Desarrolladores
  2. Cliente HTTP con soporte de streamingcurl, fetch con ReadableStream, o requests con stream=True

Importante: La API nativa del navegador EventSource no puede enviar headers personalizados. Debe usar fetch o un cliente HTTP que soporte headers personalizados en solicitudes de streaming.

Pruebe ahora: Use el Tester de Stream SSE para probar su conexion directamente desde el portal — sin necesidad de codigo.

Prueba de Conexion en Sandbox

Abra una terminal y ejecute:

curl -N "https://sandbox-api.ariari.xyz/api/v1/events/stream" \
  -H "Ocp-Apim-Subscription-Key: SU_CLAVE" \
  -H "Accept: text/event-stream"

Deberia ver:

event: connected
data: {"status":"connected"}
id: conn-abc123

event: heartbeat
data:
id: hb-1

event: heartbeat
data:
id: hb-2

El evento connected confirma que su stream esta activo. Los heartbeats llegan cada 25 segundos para mantener la conexion viva.


Como Funciona SSE

+---------------------------------------------------------------+
|                   FLUJO DE CONEXION SSE                       |
+---------------------------------------------------------------+

        Paso 1: EL CLIENTE ABRE LA CONEXION
        ┌──────────────┐                    ┌──────────────┐
        │    Cliente    │ ──GET /stream───> │   ARi API    │
        │   (Su App)    │                   │   Gateway    │
        └──────────────┘                    └──────┬───────┘
                                                   │
        Paso 2: EL SERVIDOR CONFIRMA               │
        ┌──────────────┐                    ┌──────┴───────┐
        │    Cliente    │ <──200 OK──────── │   ARi API    │
        │   (Su App)    │ text/event-stream │   Gateway    │
        └──────────────┘                    └──────┬───────┘
                                                   │
        Paso 3: EVENTOS EN TIEMPO REAL             │
        ┌──────────────┐                    ┌──────┴───────┐
        │    Cliente    │ <──price.update── │   ARi API    │
        │   (Su App)    │ <──heartbeat───── │   Gateway    │
        │               │ <──price.update── │              │
        └──────────────┘                    └──────────────┘

        La conexion permanece abierta hasta que usted la cierre,
        o un evento de ciclo de vida (auth_expired, server_shutdown)
        le indique reconectarse.

+---------------------------------------------------------------+

Formato de Eventos

Cada mensaje SSE tiene tres campos:

event: <tipo>
id: <id-unico>
data: <payload-json>

Los campos estan separados por saltos de linea. Cada mensaje termina con una linea en blanco. Ejemplo:

event: price.update
id: msg-a1b2c3d4-5678
data: {"event_type":"fx.rate_changed","buy":510.50,"sell":520.30}
Campo Descripcion
event Tipo de evento — determina que handler lo procesa
id Identificador unico — usado para replay en reconexion
data Payload JSON — el contenido del evento

Eventos Broadcast

Los eventos broadcast se entregan a todos los clientes conectados sin importar la identidad.

Actualizaciones de Precio

El evento price.update se dispara cada vez que las tasas FX cambian. Este es el evento principal para construir UIs de trading en tiempo real y pantallas de tasas.

Evento: `price.update`

Se dispara cuando una tasa FX cambia en la plataforma.

+------------------------------------------+
| event: price.update                      |
| id: msg-a1b2c3d4-5678                    |
| data: {                                  |
|   "event_type": "fx.rate_changed",       |
|   "buy": 510.50,                         |
|   "sell": 520.30                          |
| }                                        |
+------------------------------------------+
Campo Tipo Descripcion
event_type string Siempre "fx.rate_changed"
buy number Tasa de compra actual
sell number Tasa de venta actual

Como Usarlo

+---------------------------------------------------------------+
|              REEMPLAZAR POLLING CON SSE                        |
+---------------------------------------------------------------+

        ANTES (Polling):
        ┌──────────────┐           ┌──────────────┐
        │    Cliente    │ ─GET───> │  /getQuote   │
        │               │ <─200─── │              │   Cada 5s
        │               │ ─GET───> │              │   (desperdicio
        │               │ <─200─── │              │    cuando las tasas
        │               │ ─GET───> │              │    no cambian)
        │               │ <─200─── │              │
        └──────────────┘           └──────────────┘

        DESPUES (SSE):
        ┌──────────────┐           ┌──────────────┐
        │    Cliente    │ ─GET───> │  /stream     │
        │               │ <─200─── │              │   Una conexion,
        │               │          │              │   eventos enviados
        │               │ <─event─ │              │   solo cuando las
        │               │          │              │   tasas cambian
        │               │ <─event─ │              │
        └──────────────┘           └──────────────┘

+---------------------------------------------------------------+

Eventos por Usuario

Los eventos por usuario se entregan unicamente a la conexion cuyo externalUserId coincide con el usuario destino del evento. Estos eventos rastrean el ciclo de vida de sus transferencias, ordenes FX y saldos de cuenta.

Referencia de Tipos de Evento

Evento Descripcion
transfer.status Estado de transferencia cambio (PROCESSING, COMPLETED, FAILED)
transfer.completed Transferencia completada exitosamente
transfer.failed Transferencia fallida
transfer.leg_progress Progreso de tramo de transferencia
fxorder.status Estado de orden FX cambio
fxorder.created Nueva orden FX creada
balance.updated Saldo de cuenta cambio

Eventos de Transferencia

Los eventos de transferencia se disparan mientras sus transferencias avanzan por el pipeline de procesamiento.

Evento: `transfer.status`

Se dispara cuando una transferencia cambia de estado.

+------------------------------------------+
| event: transfer.status                   |
| id: msg-e5f6g7h8-9012                    |
| data: {                                  |
|   "reference_code": "TRF-20260310-001",  |
|   "status": "COMPLETED",                  |
|   "settled_amount": 500000,               |
|   "fee_amount": 2500,                     |
|   "completed_at": "2026-03-10T14:30:00Z"  |
| }                                        |
+------------------------------------------+
Campo Tipo Descripcion
reference_code string Codigo de referencia de la transferencia
status string Nuevo estado: PROCESSING, COMPLETED, FAILED
status_reason string? Razon del cambio de estado (si aplica)
settled_amount number? Monto liquidado final
fee_amount number? Comision cobrada
completed_at string? Timestamp de completado ISO 8601

Evento: `transfer.completed` / `transfer.failed`

Eventos terminales que indican el resultado final de una transferencia. El payload sigue la misma estructura que transfer.status.

Evento: `transfer.leg_progress`

Se dispara cuando una transferencia multi-tramo completa un paso de procesamiento.

Campo Tipo Descripcion
reference_code string Codigo de referencia de la transferencia
leg_number number Numero de tramo actual
total_legs number Total de tramos en la transferencia
leg_type string Tipo de tramo (ej., debito, credito, SINPE)
leg_status string Estado del tramo
timestamp string Timestamp ISO 8601

Eventos de Ordenes FX

Los eventos de ordenes FX se disparan mientras sus ordenes se procesan en la plataforma.

Evento: `fxorder.status`

Se dispara en cada transicion del estado de una orden FX.

+------------------------------------------+
| event: fxorder.status                    |
| id: msg-i9j0k1l2-3456                    |
| data: {                                  |
|   "reference_code": "FXT-20260310-000042",|
|   "status": "FILLED",                     |
|   "rate": "512.750000",                   |
|   "amount": "1000.00",                    |
|   "converted_amount": "512750.00"         |
| }                                        |
+------------------------------------------+
Campo Tipo Requerido Descripcion
reference_code string si Codigo de referencia de la orden. Formato: FXT-YYYYMMDD-NNNNNN.
status string si Nuevo estado. Uno de PENDING_NEW, NEW, ACCEPTED, FILLED, REJECTED, CANCELED (enum canonico `FxOrderStatus`).
rate string? no Tipo de cambio final con tier mezclado (6 decimales). Se completa cuando status=FILLED.
amount string? no Importe del lado origen.
converted_amount string? no Importe del lado destino. Se completa cuando status=FILLED.
Mapa de ciclo de vida → evento

Una sola orden FX emite un fxorder.created mas un fxorder.status por cada transicion. La cascada completa de la ruta feliz es:

solicitud createOrder
   │
   ├─ fxorder.created       (status=PENDING_NEW)
   ├─ fxorder.status NEW
   ├─ fxorder.status ACCEPTED
   ├─ fxorder.status FILLED ───┐
   └─ balance.updated  ────────┘  (debito origen + credito destino liquidados)

Las rutas de falla cortocircuitan la cascada:

Transicion Disparador Eventos subsiguientes
* → REJECTED Validacion o rechazo aguas arriba en cualquier estado pre-FILLED fxorder.status (REJECTED). Sin balance.updated.
* → CANCELED Llamada de cancelacion del socio o regla del sistema antes del fill fxorder.status (CANCELED). Sin balance.updated.

No existe estado EXPIRED — la expiracion de la cotizacion antes de createOrder se devuelve sincronicamente como `DB-FX-410`; una cotizacion que expira durante la ventana pre-fill de una orden se resuelve como REJECTED.

Evento: `fxorder.created`

Se dispara cuando se crea una nueva orden FX. El payload refleja la forma de respuesta de `FxOrder` createOrder (estado inicial status=PENDING_NEW, rate=null, converted_amount=null).

Eventos de Saldo

Evento: `balance.updated`

Se dispara cuando un saldo de cuenta cambia — tipicamente despues de una ejecucion de orden FX o completado de transferencia.

+------------------------------------------+
| event: balance.updated                   |
| id: msg-m3n4o5p6-7890                    |
| data: {                                  |
|   "event_type": "balance.updated",        |
|   "reference_code": "BAL-20260310-001"    |
| }                                        |
+------------------------------------------+

Use este evento como disparador para refrescar su pantalla de saldo llamando a la API de saldos.

Eventos de Trading (Avanzado)

Estos eventos estan disponibles para partners con integracion de trading habilitada.

Evento Descripcion
trading_order.status Estado de orden de trading cambio
trading.order_filled Orden completamente ejecutada
trading.order_rejected Orden rechazada
trading.order_canceled Orden cancelada
trading.order_expired Orden expirada
trading.order_partially_filled Orden parcialmente ejecutada

Los eventos de ordenes de trading llevan order_id, reference_code, status y (para fills) filled_qty + filled_avg_price. A diferencia de los eventos de ordenes FX — que describen una sola conversion — los payloads de trading rastrean fills parciales contra una cantidad, por lo que el conjunto de campos es distinto por diseno.


Eventos de Ciclo de Vida

Estos eventos gestionan el ciclo de vida de la conexion. No son datos de negocio — manejelos para mantener su conexion saludable.

Evento Data Accion del Cliente
connected {"status":"connected"} El stream esta activo. Comience a procesar eventos.
heartbeat (vacio) No se requiere accion. Mantiene la conexion viva a traves de proxies.
auth_expired {"reason":"token_expired"} Refresque sus credenciales y reconectese.
server_shutdown {"reason":"shutdown"} Reconectese inmediatamente — el servidor se esta reiniciando.

Flujo de Ciclo de Vida

+---------------------------------------------------------------+
|                CICLO DE VIDA DE CONEXION                      |
+---------------------------------------------------------------+

     CONECTAR ──> connected ──> heartbeat (25s) ──> heartbeat ...
                                    │
                                    ├──> price.update (broadcast)
                                    ├──> transfer.status (por usuario)
                                    ├──> fxorder.status (por usuario)
                                    ├──> balance.updated (por usuario)
                                    │
                                    ├──> auth_expired ──> RECONECTAR
                                    │                     (con clave nueva)
                                    │
                                    └──> server_shutdown ──> RECONECTAR
                                                             (inmediatamente)

+---------------------------------------------------------------+

Reconexion y Replay

Si su conexion se interrumpe, reconectese con el header Last-Event-ID para reproducir eventos perdidos. El servidor almacena en buffer los ultimos 100 eventos.

+---------------------------------------------------------------+
|                RECONEXION CON REPLAY                          |
+---------------------------------------------------------------+

        1. La conexion se interrumpe (red, reinicio de servidor, etc.)

        ┌──────────────┐
        │    Cliente    │ ──X── (desconectado)
        └──────────────┘

        2. El cliente se reconecta con el ultimo ID de evento conocido

        ┌──────────────┐                    ┌──────────────┐
        │    Cliente    │ ──GET /stream───> │   ARi API    │
        │               │  Last-Event-ID:   │              │
        │               │  msg-a1b2c3d4     │              │
        └──────────────┘                    └──────┬───────┘
                                                   │
        3. El servidor reproduce eventos perdidos, luego reanuda en vivo

        ┌──────────────┐                    ┌──────┴───────┐
        │    Cliente    │ <──evt perdido──── │   ARi API    │
        │               │ <──evt perdido──── │              │
        │               │ <──connected────── │              │
        │               │ <──eventos vivos── │              │
        └──────────────┘                    └──────────────┘

+---------------------------------------------------------------+

cURL: Reconectar con Last-Event-ID

curl -N "https://sandbox-api.ariari.xyz/api/v1/events/stream" \
  -H "Ocp-Apim-Subscription-Key: SU_CLAVE" \
  -H "Accept: text/event-stream" \
  -H "Last-Event-ID: msg-a1b2c3d4-5678"

Nota: El buffer de replay almacena hasta 100 eventos. Si estuvo desconectado por mas tiempo, algunos eventos pueden haberse perdido. Use un fallback de polling para datos criticos que no deben perderse.


Limites de Conexion y Rate Limits

Limite Valor Descripcion
Conexiones por usuario 3 Maximo de conexiones SSE concurrentes por clave de suscripcion
Tasa de reconexion 10/min Maximo de intentos de reconexion por minuto
Intervalo de heartbeat 25 segundos Senal de keep-alive
Buffer de replay 100 eventos Eventos disponibles para replay via Last-Event-ID

Exceder el limite de conexiones retorna 429 Too Many Requests.


Headers Requeridos

Header Requerido Descripcion
Ocp-Apim-Subscription-Key Si Su clave de suscripcion API
Accept Recomendado text/event-stream
Last-Event-ID No Ultimo ID de evento recibido — activa replay de eventos perdidos

Manejo de Errores

Errores Comunes

Estado Error Causa Solucion
401 Unauthorized Clave de suscripcion faltante o invalida Verifique su clave en el Portal de Desarrolladores
429 Too Many Requests Limite de conexiones excedido (3/usuario) o tasa de reconexion excedida (10/min) Cierre conexiones no utilizadas; use backoff exponencial

Formato de Respuesta de Error

Los errores siguen RFC 7807 Problem Details:

{
  "type": "about:blank",
  "title": "Too Many Requests",
  "status": 429,
  "detail": "Maximum concurrent connections exceeded",
  "trace_id": "0HN4G6LJN5FT0:00000001"
}

Tip: Guarde el trace_id al contactar soporte.


Ejemplos de Codigo

cURL: Abrir Stream

curl -N "https://api.ariari.com/api/v1/events/stream" \
  -H "Ocp-Apim-Subscription-Key: SU_CLAVE" \
  -H "Accept: text/event-stream"

JavaScript: Fetch + ReadableStream

async function connectSSE(apiKey) {
  let lastEventId = '';

  async function connect() {
    const headers = {
      'Ocp-Apim-Subscription-Key': apiKey,
      'Accept': 'text/event-stream',
    };
    if (lastEventId) {
      headers['Last-Event-ID'] = lastEventId;
    }

    const response = await fetch(
      'https://api.ariari.com/api/v1/events/stream',
      { headers }
    );

    if (!response.ok) {
      throw new Error(`Conexion SSE fallida: ${response.status}`);
    }

    const reader = response.body.getReader();
    const decoder = new TextDecoder();
    let buffer = '';

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;

      buffer += decoder.decode(value, { stream: true });
      const messages = buffer.split('\n\n');
      buffer = messages.pop(); // Mantener mensaje incompleto en buffer

      for (const message of messages) {
        const event = parseSSE(message);
        if (!event) continue;

        if (event.id) lastEventId = event.id;

        switch (event.type) {
          case 'price.update':
            console.log('Tasa cambio:', event.data);
            // Actualice su UI con event.data.buy / event.data.sell
            break;
          case 'transfer.status':
          case 'transfer.completed':
          case 'transfer.failed':
            console.log(`Transferencia ${event.data.reference_code}: ${event.data.status}`);
            // Actualice el estado de la transferencia en su UI
            break;
          case 'fxorder.status':
            console.log(`Orden FX ${event.data.reference_code}: ${event.data.status}`);
            break;
          case 'balance.updated':
            console.log('Saldo cambio — refrescando...');
            // Dispare un refresh de saldo desde la API
            break;
          case 'auth_expired':
            console.warn('Auth expirado — reconectando...');
            reader.cancel();
            return connect(); // Reconectar con credenciales frescas
          case 'server_shutdown':
            console.warn('Servidor reiniciando — reconectando...');
            reader.cancel();
            return connect();
        }
      }
    }

    // Conexion cerrada — reconectar con backoff
    setTimeout(connect, 1000);
  }

  connect();
}

function parseSSE(raw) {
  const lines = raw.split('\n');
  const event = {};
  for (const line of lines) {
    if (line.startsWith('event: ')) event.type = line.slice(7);
    else if (line.startsWith('id: ')) event.id = line.slice(4);
    else if (line.startsWith('data: ')) {
      try {
        event.data = JSON.parse(line.slice(6));
      } catch {
        event.data = line.slice(6);
      }
    }
  }
  return event.type ? event : null;
}

Python: requests con Streaming

import requests
import json
import time

def connect_sse(api_key, base_url="https://api.ariari.com"):
    last_event_id = None
    backoff = 1

    while True:
        headers = {
            "Ocp-Apim-Subscription-Key": api_key,
            "Accept": "text/event-stream",
        }
        if last_event_id:
            headers["Last-Event-ID"] = last_event_id

        try:
            with requests.get(
                f"{base_url}/api/v1/events/stream",
                headers=headers,
                stream=True,
                timeout=(10, None),  # 10s conexion, sin timeout de lectura
            ) as resp:
                resp.raise_for_status()
                backoff = 1  # Resetear en conexion exitosa

                buffer = ""
                for chunk in resp.iter_content(decode_unicode=True):
                    buffer += chunk
                    while "\n\n" in buffer:
                        message, buffer = buffer.split("\n\n", 1)
                        event = parse_sse(message)
                        if not event:
                            continue

                        if event.get("id"):
                            last_event_id = event["id"]

                        if event["type"] == "price.update":
                            print(f"Tasa: compra={event['data']['buy']}, venta={event['data']['sell']}")
                        elif event["type"] in ("transfer.status", "transfer.completed", "transfer.failed"):
                            print(f"Transferencia {event['data']['reference_code']}: {event['data']['status']}")
                        elif event["type"] == "fxorder.status":
                            print(f"Orden FX {event['data']['reference_code']}: {event['data']['status']}")
                        elif event["type"] == "balance.updated":
                            print("Saldo cambio — refrescando...")
                        elif event["type"] == "auth_expired":
                            print("Auth expirado — reconectando...")
                            break
                        elif event["type"] == "server_shutdown":
                            print("Servidor reiniciando — reconectando...")
                            break

        except requests.exceptions.RequestException as e:
            print(f"Error de conexion: {e}")

        # Backoff exponencial: 1s, 2s, 4s, ... max 30s
        time.sleep(min(backoff, 30))
        backoff *= 2


def parse_sse(raw):
    event = {}
    for line in raw.strip().split("\n"):
        if line.startswith("event: "):
            event["type"] = line[7:]
        elif line.startswith("id: "):
            event["id"] = line[4:]
        elif line.startswith("data: "):
            try:
                event["data"] = json.loads(line[6:])
            except json.JSONDecodeError:
                event["data"] = line[6:]
    return event if "type" in event else None

Mejores Practicas

  1. Implemente backoff exponencial en reconexion (1s, 2s, 4s... max 30s)
  2. Rastree Last-Event-ID — persista el ultimo ID recibido para poder reproducir eventos perdidos al reconectar
  3. Deduplique por ID de evento despues de reconexion — el buffer de replay puede solaparse con eventos que ya proceso
  4. NO use la API nativa EventSource — no puede enviar headers personalizados (Ocp-Apim-Subscription-Key)
  5. Maneje eventos de ciclo de vidaauth_expired significa refrescar credenciales, server_shutdown significa reconectar inmediatamente
  6. Mantenga un fallback de polling — para datos criticos, consulte endpoints de estado (/transfers/{id}, /fxorder/{id}) periodicamente como red de seguridad
  7. Limite conexiones abiertas — tiene 3 maximo por clave de suscripcion; cierre streams no utilizados
  8. Filtre por dominio de evento — si solo le interesan transferencias, verifique event.type.startsWith('transfer.') e ignore el resto
  9. Una conexion por usuario — partners M2M que necesiten eventos para multiples usuarios deben abrir conexiones separadas por externalUserId
  10. Ignore heartbeat en logica de negocio — los heartbeats son senales de infraestructura, no datos de negocio

Flujo de Decision: SSE vs Webhooks vs Polling

+---------------------------------------------------------------+
|              ¿QUE PATRON DE INTEGRACION?                      |
+---------------------------------------------------------------+

                            Inicio
                              |
                              v
               +-----------------------------+
               |  ¿Necesita actualizaciones  |
               |  en tiempo real en un       |
               |  navegador o dashboard?     |
               +-----------------------------+
                      |             |
                      SI            NO
                      |             |
                      v             v
               +------------+  +-----------------------------+
               |    Use     |  |  ¿Necesita notificaciones   |
               |    SSE     |  |  push servidor-a-servidor?  |
               +------------+  +-----------------------------+
                                      |             |
                                      SI            NO
                                      |             |
                                      v             v
                               +------------+  +------------+
                               |    Use     |  |    Use     |
                               |  Webhooks  |  |  Polling   |
                               +------------+  +------------+

+---------------------------------------------------------------+
|  SSE: Streaming en tiempo real a navegadores/apps & M2M       |
|       (esta guia)                                             |
|  Webhooks: Push a su endpoint de servidor (/docs/webhooks)    |
|  Polling: Solicitudes GET con timer (/apisuite)               |
+---------------------------------------------------------------+

Proximos Pasos