Flujos S2S de SKAdNetwork: Cómo verificar postbacks de redes publicitarias

opoinstall
2026-08-21
5 min read

¿Cómo gestionan las DSP los postbacks de SKAdNetwork? Las plataformas del lado de la demanda (DSP) y las redes publicitarias gestionan los postbacks de SKAdNetwork estableciendo puntos de entrada de ingesta HTTP POST seguros, construyendo la cadena de mensajes UTF-8 serializada mediante el delimitador U+2063, verificando la firma criptográfica ECDSA P-256 de Apple frente a su clave pública publicada, y registrando los ID de transacción verificados para prevenir el procesamiento duplicado antes de actualizar los modelos de puja.

Un postback de validación de instalación de SKAdNetwork es una notificación HTTPS POST firmada por Apple que el sistema operativo envía a una red publicitaria elegible y, en el caso de atribuciones ganadoras, opcionalmente al punto de recepción configurado del desarrollador de la aplicación anunciada. Para garantizar la integridad de los datos, los sistemas de ingesta backend deben verificar la firma ECDSA P-256 de Apple, validar la serialización de parámetros y aplicar la desduplicación a nivel de transacción.

Término Definición
SKAdNetwork El marco a nivel de plataforma de Apple para la atribución de campañas publicitarias con preservación de la privacidad.
Postback de validación de instalación Una carga útil JSON firmada por Apple que contiene metadatos de validación de instalación y atribución tras una conversión publicitaria elegible.
ECDSA P-256 El algoritmo criptográfico de curva elíptica utilizado por Apple para firmar los postbacks de validación de instalación.
ID de transacción Un identificador de validación único que los receptores utilizan como clave de idempotencia para la detección de duplicados.

La arquitectura de ingesta de postbacks de SKAdNetwork para DSP y redes publicitarias

La canalización de doble ingesta: entrega directa a la red publicitaria frente a puntos de recepción del desarrollador

Cuando se produce la instalación de una aplicación de iOS atribuida, el subsistema de atribución de Apple envía postbacks de validación de instalación mediante HTTPS POST:

  • Ingesta de la red publicitaria: El dispositivo entrega el postback ganador principal (did-win: true) directamente a la URL del servidor registrada bajo el ad-network-id correspondiente en el registro de Apple.
  • Ingesta de copia para el desarrollador: Si la aplicación anunciada especifica la clave NSAdvertisingAttributionReportEndpoint en su archivo Info.plist, el dispositivo envía simultáneamente una copia exacta del postback ganador directamente al servidor del desarrollador.
  • Enrutamiento de postbacks no ganadores: A partir de SKAdNetwork 3.0, si varias redes publicitarias cumplían los requisitos para la atribución pero no resultaron ganadoras, el dispositivo envía hasta cinco postbacks no ganadores (did-win: false) directamente a esas redes secundarias elegibles. Los postbacks no ganadores no se envían al punto de recepción de copias del desarrollador.

Los puntos de recepción de la ingesta backend deben responder con un código HTTP 200 OK. Si el dispositivo no recibe una respuesta 200, puede reintentar la entrega hasta nueve veces en un plazo máximo de nueve días.

Flujo de ingesta y verificación de postbacks de SKAdNetwork

El papel de NSAdvertisingAttributionReportEndpoint en la auditoría del desarrollador

El parámetro NSAdvertisingAttributionReportEndpoint permite a los desarrolladores de aplicaciones recibir copias directas de los postbacks ganadores de forma independiente al reenvío de la red publicitaria:

  • Auditoría independiente: Los desarrolladores reciben copias exactas de todos los postbacks ganadores generados para su aplicación, lo que permite la validación interna de los informes de las redes publicitarias.
  • Ruta de punto de recepción dedicada: El servidor del desarrollador debe alojar el punto de recepción en https://<domain>/.well-known/skadnetwork/report-attribution/.
  • Distinción de AdAttributionKit: Para AdAttributionKit, Apple define una configuración de enrutamiento separada en https://<domain>/.well-known/appattribution/report-attribution/, la cual utiliza una arquitectura de verificación de Firma Web JSON (JWS).

Cómo los MMP ingieren, agregan y normalizan flujos de eventos S2S de múltiples redes

Según las integraciones comerciales, los socios de medición móvil (MMP) pueden ingerir datos de SKAdNetwork a través del reenvío del lado del desarrollador, integraciones con redes publicitarias o flujos de servidores asociados personalizados:

  • Ingesta de múltiples fuentes: Ingesta de datos de postbacks verificados reenviados desde los puntos de recepción de los desarrolladores junto con los flujos de informes directos de las redes publicitarias.
  • Desduplicación entre flujos: Normalización y desduplicación de registros utilizando el transaction-id único a través de las copias compartidas de la red publicitaria y del desarrollador.
  • Normalización para BI posterior: Mapeo de los valores de conversión de grano grueso y fino a los modelos de ingresos y eventos de embudo definidos por el cliente.

Véase también: SKAdNetwork ──> Modelo de atribución móvil

Verificación criptográfica: validación de la firma ECDSA P-256 de Apple

Comprender la pila criptográfica: curva NIST P-256 (secp256r1) con SHA-256

Cada postback de SKAdNetwork incluye un campo attribution-signature. Esta firma criptográfica es generada por Apple utilizando el Algoritmo de Firma Digital de Curva Elíptica (ECDSA) con la curva NIST P-256 (secp256r1) y un resumen SHA-256.

La firma valida dos propiedades de seguridad fundamentales:

  • Autenticidad: El postback fue generado directamente por el subsistema de la plataforma de Apple en un dispositivo verificado, y no falsificado por un cliente o proxy malintencionado.
  • Integridad: Los parámetros cubiertos por la firma no han sido alterados durante el tránsito.

Uso de la clave pública publicada de SKAdNetwork de Apple

Para verificar la firma, el servidor de ingesta debe cargar la clave pública oficial de Apple. Para SKAdNetwork 2.1 y versiones posteriores, Apple publica una clave pública NIST P-256 dedicada en su documentación para desarrolladores:

  • Inicialización de la clave: La clave pública se carga en la memoria como un objeto de clave pública X.509/DER estándar durante el inicio del servidor.
  • Comprobación de firma asimétrica: El motor de verificación reconstruye la cadena de mensajes serializada en UTF-8 exacta, calcula el hash SHA-256 y verifica la firma attribution-signature decodificada en Base64 frente al mensaje reconstruido.

[Device / Subsystem] ──► [Dispatches Signed JSON Postback]
                                     │
                                     ▼
                  [DSP / Ad Network Ingestion Endpoint]
                  (HTTPS POST to registered postback URL)
                                     │
                                     ▼
                  [Parse JSON & Reconstruct Message String]
                  (Concatenate UTF-8 fields with \u2063)
                                     │
                                     ▼
                  [ECDSA P-256 Public Key Signature Verification]
                                     │
                      ┌──────────────┴──────────────┐
                      ▼                                                          ▼
               [Signature Valid]                                         [Signature Invalid]
                      │                                                          │
                      ▼                                                          ▼
            [Atomic Deduplication]                                       [Log Error & Discard]
            (Check transaction-id)
                      │
                      ▼
            [Process Attribution]
Flujo de verificación de firma ECDSA P 256 en SKAdNetwork

Por qué un hash por sí solo no es suficiente: verificación de firma asimétrica

Debido a que Apple firma la carga útil utilizando su clave privada y no distribuye un secreto compartido, no se puede utilizar la validación simétrica (como HMAC-SHA256). Los motores de ingesta deben implementar la verificación estándar de firmas asimétricas de clave pública utilizando bibliotecas criptográficas estándar (como OpenSSL, crypto de Node.js o cryptography de Python).

Construcción de la cadena de mensajes para la verificación de firmas

El protocolo de serialización estricto: el papel del separador invisible (\u2063)

Apple especifica un formato exacto de serialización de bytes UTF-8 para construir la cadena de mensajes para la validación de la firma. Los parámetros deben concatenarse en una secuencia precisa, separados por el carácter Unicode invisible \u2063 (separador invisible U+2063, secuencia de bytes UTF-8 0xE2 0x81 0xA3):

Message=Param1    "2˘063"    Param2    "2˘063"  Paramn\text{Message} = \text{Param}_1 \;\|\; \text{"\u2063"} \;\|\; \text{Param}_2 \;\|\; \text{"\u2063"} \dots \|\; \text{Param}_n

Sustituir los espacios en blanco, la puntuación estándar o los separadores Unicode alternativos provocará un fallo en la verificación criptográfica.

Orden de parámetros específico de la versión para SKAN 4.0

Según la documentación para desarrolladores de Apple sobre la verificación de postbacks de validación de instalación, los parámetros para los postbacks de SKAdNetwork 4.0 deben serializarse exactamente en el siguiente orden:

  1. version (p. ej., "4.0")
  2. ad-network-id (p. ej., "example123.skadnetwork")
  3. source-identifier (p. ej., "4821")
  4. app-id (p. ej., 1234567890)
  5. transaction-id (p. ej., "6a8b1c2d-3e4f-5a6b-7c8d-9e0f1a2b3c4d")
  6. redownload (p. ej., "true" o "false" como cadena en minúsculas)
  7. source-app-id (para anuncios de aplicación a aplicación) O source-domain (para anuncios de web a aplicación en Safari), incluido solo si está presente en el postback
  8. fidelity-type (p. ej., 1 para anuncios renderizados por StoreKit o anuncios web atribuidos por SKAdNetwork; 0 para anuncios de visualización)
  9. did-win (p. ej., "true" o "false" como cadena en minúsculas)
  10. postback-sequence-index (p. ej., 0, 1 o 2)

Especificación crucial de SKAN 4: Los valores de conversión están excluidos de la firma

En SKAdNetwork 4.0, la firma de Apple no incluye conversion-value ni coarse-conversion-value, incluso cuando uno de esos campos está presente en la carga útil JSON. La cadena serializada para SKAN 4 termina con postback-sequence-index. Intentar añadir valores de conversión a la cadena de mensajes hará que la verificación falle.

La carga útil JSON a continuación ilustra un esquema completo de postback de SKAdNetwork 4.0. La firma que se muestra a continuación es un marcador de posición ilustrativo y no superará la verificación criptográfica; para las pruebas unitarias, utilice los ejemplos firmados de Apple de la documentación oficial de verificación:

{
  "version": "4.0",
  "ad-network-id": "example123.skadnetwork",
  "source-identifier": "4821",
  "app-id": 1234567890,
  "transaction-id": "6a8b1c2d-3e4f-5a6b-7c8d-9e0f1a2b3c4d",
  "redownload": false,
  "source-app-id": 9876543210,
  "fidelity-type": 1,
  "did-win": true,
  "postback-sequence-index": 0,
  "conversion-value": 47,
  "attribution-signature": "MEQCIFz8...SAMPLE_CRYPTOGRAPHIC_SIGNATURE...=="
}

Serialización del mensaje de firma de SKAN 4 con U 2063

Gestión de cargas útiles multi-ventana de SKAN 4.0 y puntos de recepción del desarrollador

Análisis de postback-sequence-index en ventanas de conversión secuenciales

En SKAdNetwork 4.0, las conversiones generan postbacks a partir de ventanas de conversión que abarcan hasta 35 días después del primer lanzamiento de la aplicación, y la entrega real ocurre después de los retrasos aleatorios posteriores a la ventana establecidos por Apple. Los sistemas de ingesta backend analizan el campo postback-sequence-index para asignar los datos de conversión a la ventana del ciclo de vida correcta:

  • Índice 0 (Ventana 1: Días 0–2): Contiene un valor de conversión de grano fino (0–63), un valor de conversión de grano grueso (low, medium, high), o el campo está ausente.
  • Índice 1 (Ventana 2: Días 3–7): Para los niveles de datos de postback 1–3, puede revelar un coarse-conversion-value (low, medium, high) cuando se proporciona; el nivel 0 no es elegible para segundo o tercer postback.
  • Índice 2 (Ventana 3: Días 8–35): Para los niveles de datos de postback 1–3, puede revelar un coarse-conversion-value (low, medium, high) cuando se proporciona; el nivel 0 no es elegible para segundo o tercer postback.

Gestión de valores de conversión de grano fino frente a grano grueso

Los decodificadores de ingesta deben tener en cuenta la variabilidad de la carga útil:

  • Exclusión mutua: Apple especifica que un postback de validación de instalación puede contener un conversion-value o un coarse-conversion-value, pero nunca ambos simultáneamente.
  • Valores de conversión ausentes: Si el nivel de datos de postback asignado es bajo (Nivel 0), los campos de valor de conversión se omiten de la carga útil JSON.

Defensa contra ataques de repetición y cargas útiles de conversión suplantadas

El papel del transaction-id como clave de desduplicación

Cada postback de SKAdNetwork contiene un UUID transaction-id único. La documentación de Apple aconseja a los receptores utilizar este identificador como clave de idempotencia para detectar y descartar postbacks de conversión duplicados.

Dado que los receptores de postbacks son puntos de recepción HTTPS accesibles públicamente, los actores malintencionados podrían intentar ataques de repetición capturando un postback válido y reteniéndolo o reenviándolo repetidamente para inflar artificialmente las métricas de conversión.

Implementación de almacenamiento en caché distribuido en memoria y registros persistentes

Apple no prescribe un período universal de retención de desduplicación. Los receptores en producción deben mantener un registro de idempotencia duradero para los ID de transacción verificados de acuerdo con sus requisitos de conciliación y defensa contra repeticiones; el TTL de Redis puede utilizarse como una optimización de caché rápida en lugar de ser el único registro autorizado de duplicados:

  1. Verificación criptográfica primero: Verifique completamente la firma ECDSA frente a la clave pública de Apple antes de comprometer el ID de transacción en el almacenamiento.
  2. Desduplicación atómica: Realice una operación de escritura atómica (p. ej., Redis SET key value NX EX <seconds>) respaldada por una restricción de unicidad en una base de datos relacional o de documentos persistente.
  3. Horizonte de desduplicación: Establezca una ventana de retención operativa en la capa de caché que cubra la entrega esperada de postbacks, los reintentos de red (Apple reintenta las entregas fallidas hasta por 9 días) y la conciliación posterior.

Canalización de defensa contra repeticiones y desduplicación en SKAdNetwork


La implementación de backend a continuación demuestra la validación de firmas, la validación de esquemas y la desduplicación atómica en Python:

import base64
import json
import redis
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.serialization import load_der_public_key
from cryptography.exceptions import InvalidSignature

# Initialize Redis client for hot-cache transaction deduplication
redis_client = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)

# Official Apple SKAdNetwork 2.1+ Public Key (Base64 DER encoded, published by Apple)
APPLE_SKAN_PUBLIC_KEY_B64 = (
    "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWdp8GPcGqmhgzEFj9Z2nSpQVdday"
    "aPe4FMzqM9wib1+aHaaIzoHoLN9zW4K8y4SPykE3YVK3sVqW6Af0lfx3gg=="
)

# Exact Apple-specified invisible separator: U+2063 INVISIBLE SEPARATOR (UTF-8: 0xE2 0x81 0xA3)
SEPARATOR = "\u2063"

def construct_skan4_message_bytes(payload: dict) -> bytes:
    """
    Constructs the serialized UTF-8 message string for SKAN 4.0 signature verification.
    Apple specification explicitly EXCLUDES conversion-value and coarse-conversion-value from the signature.
    """
    parts = [
        str(payload["version"]),
        str(payload["ad-network-id"]),
        str(payload["source-identifier"]),
        str(payload["app-id"]),
        str(payload["transaction-id"]),
        "true" if payload["redownload"] is True else "false"
    ]

    # Include source-app-id (app ad) OR source-domain (web ad) if present
    if payload.get("source-app-id") is not None:
        parts.append(str(payload["source-app-id"]))
    elif payload.get("source-domain") is not None:
        parts.append(str(payload["source-domain"]))

    parts.append(str(payload["fidelity-type"]))
    parts.append("true" if payload["did-win"] is True else "false")
    parts.append(str(payload["postback-sequence-index"]))

    # Join with U+2063 separator and encode to UTF-8
    message_string = SEPARATOR.join(parts)
    return message_string.encode('utf-8')

def verify_and_ingest_skan4_postback(postback_json_str: str) -> dict:
    """
    Validates payload schema, verifies the ECDSA P-256 signature against Apple's public key,
    and performs atomic transaction-id deduplication.
    """
    try:
        payload = json.loads(postback_json_str)
    except Exception:
        return {"status": "REJECTED", "reason": "INVALID_JSON_FORMAT"}

    # Version Gate: Enforce SKAN 4.0 payload handling
    if payload.get("version") != "4.0":
        return {"status": "REJECTED", "reason": "UNSUPPORTED_SKAN_VERSION"}

    # Schema Validation: Required fields for SKAN 4.0
    required_fields = [
        "version", "ad-network-id", "source-identifier", "app-id",
        "transaction-id", "redownload", "fidelity-type", "did-win",
        "postback-sequence-index", "attribution-signature"
    ]
    for field in required_fields:
        if field not in payload:
            return {"status": "REJECTED", "reason": f"MISSING_REQUIRED_FIELD_{field.upper()}"}

    # Strict Type Validation
    if not isinstance(payload["redownload"], bool):
        return {"status": "REJECTED", "reason": "INVALID_TYPE_REDOWNLOAD"}
    if not isinstance(payload["did-win"], bool):
        return {"status": "REJECTED", "reason": "INVALID_TYPE_DID_WIN"}
    if payload["postback-sequence-index"] not in (0, 1, 2):
        return {"status": "REJECTED", "reason": "INVALID_SEQUENCE_INDEX"}
    if payload["fidelity-type"] not in (0, 1):
        return {"status": "REJECTED", "reason": "INVALID_FIDELITY_TYPE"}

    # Enforce mutual exclusivity between source-app-id and source-domain
    has_source_app = payload.get("source-app-id") is not None
    has_source_domain = payload.get("source-domain") is not None
    if has_source_app and has_source_domain:
        return {"status": "REJECTED", "reason": "CONFLICTING_SOURCE_FIELDS"}

    signature_b64 = payload["attribution-signature"]
    transaction_id = payload["transaction-id"]

    try:
        # Step 1: Reconstruct the exact UTF-8 serialized message
        message_bytes = construct_skan4_message_bytes(payload)
        signature_der = base64.b64decode(signature_b64, validate=True)

        # Step 2: Verify ECDSA P-256 / SHA-256 signature using Apple's published public key
        apple_public_key = load_der_public_key(base64.b64decode(APPLE_SKAN_PUBLIC_KEY_B64))
        apple_public_key.verify(
            signature_der,
            message_bytes,
            ec.ECDSA(hashes.SHA256())
        )
    except InvalidSignature:
        return {"status": "REJECTED", "reason": "INVALID_CRYPTOGRAPHIC_SIGNATURE"}
    except Exception as e:
        return {"status": "ERROR", "reason": f"VERIFICATION_FAILED: {str(e)}"}

    # Step 3: Atomic Deduplication via Redis (Hot cache layer)
    # Note: In production, pair this hot cache with a persistent unique database constraint.
    # 14-day TTL (1,209,600 seconds) serves as an illustrative receiver cache policy covering retries.
    is_new = redis_client.set(f"skan_tx:{transaction_id}", "1", nx=True, ex=1209600)
    if not is_new:
        return {"status": "DUPLICATE", "reason": "TRANSACTION_ALREADY_PROCESSED"}

    return {
        "status": "VERIFIED",
        "transaction_id": transaction_id,
        "sequence_index": payload["postback-sequence-index"],
        "did_win": payload["did-win"]
    }

Ingesta de postbacks en modelos de pujas en tiempo real y optimizadores de CPA

Desacoplamiento de la ingesta en el extremo frente al procesamiento asíncrono

Las DSP de alto volumen procesan importantes volúmenes de postbacks durante los periodos pico de las campañas. El procesamiento sincrónico posterior puede introducir cuellos de botella por latencia.

Las arquitecturas empresariales implementan una canalización asíncrona:

  1. Receptor en el extremo (Edge Receiver): Acepta el HTTP POST entrante, verifica la autenticidad de la firma, ejecuta la desduplicación atómica en el transaction-id y devuelve inmediatamente un código HTTP 200 OK.
  2. Cola de eventos: Publica la carga útil verificada en un intermediario de eventos distribuido (p. ej., Apache Kafka o AWS SQS).
  3. Workers de pujas y análisis: Consumen el flujo de eventos, mapean los valores de conversión a métricas de ingresos y actualizan los modelos de CPA objetivo de pujas en tiempo real (RTB).

Uso del identificador de fuente jerárquico

El primer postback ganador puede exponer dos, tres o cuatro dígitos del source-identifier jerárquico, según el nivel de datos del postback. El significado semántico de esos dígitos está definido por la propia taxonomía de identificadores de fuente de la red publicitaria. Los sistemas de pujas deben resolver el identificador de fuente recibido frente a los metadatos de campaña de la red en lugar de asumir un mapeo universal entre la longitud de los dígitos y una ubicación específica o la granularidad de los creativos.

Matriz comparativa: Entrega directa de Apple frente a ingesta S2S del MMP

Dimensión funcional Entrega directa de Apple (Red publicitaria) Punto de recepción del desarrollador (NSAdvertising...) Canalización de ingesta S2S del MMP
Destinatario Red publicitaria registrada Desarrollador de la aplicación anunciada Socio de medición móvil (MMP)
Alcance de la atribución Postbacks ganadores para esa red Copia de los postbacks ganadores para la aplicación Vista agregada de múltiples redes
Validación de firmas Ejecutada por el backend de la red publicitaria Ejecutada por el backend del desarrollador Dependiente de la implementación (Flujos del socio)
Postbacks no ganadores Recibidos si califica (did-win: false) No se entregan al punto de recepción del desarrollador Pueden estar disponibles a través de flujos de socios
Caso de uso principal Optimizador directo de pujas y CPA objetivo Auditoría y verificación interna de almacén de datos Panel de rendimiento multicanal

Preguntas frecuentes (FAQ)

¿Qué clave pública se utiliza para verificar la firma del postback de Apple?
Apple publica la clave pública oficial NIST P-256 utilizada para la validación de instalaciones de SKAdNetwork 2.1+ en su documentación para desarrolladores. Los servidores de ingesta cargan esta clave pública en formato X.509/DER para verificar las firmas entrantes.
¿Por qué un postback válido de SKAdNetwork falla en la verificación de la firma?
Los fallos en la verificación de firmas suelen deberse a errores de serialización: usar el carácter separador incorrecto (utilizar `\u2060` en lugar de `\u2063`), un orden incorrecto de los parámetros, añadir erróneamente valores de conversión a las cadenas de mensajes de SKAN 4, o gestionar incorrectamente las codificaciones de cadenas booleanas (`"true"` frente a `"false"`).
¿Puede el punto de recepción del desarrollador de la aplicación anunciada recibir postbacks no ganadores de SKAdNetwork?
No. El punto de recepción de copias del desarrollador recibe copias de los postbacks ganadores de validación de instalación cuando está configurado. Se envían hasta cinco postbacks no ganadores (`did-win: false`) directamente a otras redes publicitarias que cumplan los requisitos, y no al punto de recepción del desarrollador.

Resumen y marco de decisiones

La gestión de postbacks de SKAdNetwork a escala requiere combinar la ingesta en el extremo de baja latencia con una rigurosa validación criptográfica y la desduplicación a nivel de transacción. Debido a que los postbacks de Apple influyen directamente en la asignación de presupuestos y en los algoritmos de puja, validar las firmas ECDSA y aplicar la idempotencia del transaction-id protege las canalizaciones de ingesta contra postbacks falsificados o alterados y contra el procesamiento de reproducciones duplicadas.

Para complementar los informes de SKAdNetwork mediados por la plataforma con la incorporación de usuarios a nivel micro y el enrutamiento instantáneo mediante enlaces profundos (deep links), los equipos de ingeniería despliegan arquitecturas de enrutamiento de origen directo junto con las API de la plataforma.

Para obtener más información sobre cómo configurar los postbacks de atribución del lado del servidor y las canalizaciones de enlaces profundos, consulte la documentación de OpoInstall.

Materiales relacionados

  • Conceptos: Postbacks S2S, Verificación criptográfica, ECDSA P-256, Defensa contra ataques de repetición, Desduplicación de transacciones

  • Tecnologías: Apple SKAdNetwork, Apple AdAttributionKit, Caché en memoria de Redis, SDK móvil de OpoInstall

  • Estándares: IETF RFC 8259 (Intercambio de datos JSON), RFC 5480 (Criptografía de curva elíptica)

  • API: API de StoreKit SKAdNetwork, Especificación de entrega de postbacks S2S de Apple, API S2S de OpoInstall

Documentación oficial

Share this article