# Meta Ads

> Piloto privado en preparación para consultar el gasto diario de una cuenta publicitaria de Meta, al total de la cuenta y por campaña. Solo lectura; pendiente de validación real y aún no habilitado para conectar cuentas.



**Piloto privado en preparación.** La integración está pendiente de completar su validación con Meta real y aún no está habilitada para conectar cuentas. Esta guía describe el funcionamiento previsto para cuando se abra el piloto.

`meta_ads` está diseñado para leer el **gasto y la entrega diarios** de una cuenta publicitaria de Meta (Facebook e Instagram), al total de la cuenta y por campaña, y guardarlos en Connect para consultarlos sin volver a llamar a Meta. Cada conexión tendrá un `conn_…` que identifica la cuenta y viaja en toda llamada (en REST, el header `X-Connect-Connection`).

Una vez validado, Emisso podrá habilitar el piloto por organización. El conector solo estará disponible en el catálogo, el alta y la ejecución de las organizaciones invitadas.

**El alcance previsto es solo lectura.** Las herramientas del conector no crean, editan, pausan ni publican anuncios, campañas, presupuestos, públicos ni píxeles, y no administran la facturación de la cuenta publicitaria.

**El gasto es una métrica publicitaria estimada, no un comprobante.** Es la cifra que Meta informa en sus estadísticas de anuncios: no son facturas, recibos, cobros ni impuestos de Meta, y no sirve como respaldo contable.

## Qué necesitarás al habilitarse el piloto [#qué-necesitarás-al-habilitarse-el-piloto]

Para participar en el piloto, **necesitas una cuenta en Meta (Facebook) con acceso a la cuenta publicitaria que quieres leer, y tu usuario debe tener permiso sobre ella.** Autorizarás con ese usuario: Connect no creará cuentas publicitarias ni las administrará.

El formulario previsto pedirá **dos datos, y ninguno es un secreto**:

| Campo                        | Qué es                                                                                                      |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------- |
| RUT de la empresa            | La empresa a la que pertenece la cuenta publicitaria. Lo declaras tú.                                       |
| ID de la cuenta publicitaria | El identificador de la cuenta en Meta, con o sin el prefijo `act_`. Lo ves en el Administrador de anuncios. |

**Meta no confirma ese RUT.** Su autorización no informa a qué contribuyente pertenece la cuenta publicitaria, así que Connect no tiene contra qué compararlo: el RUT queda como lo escribiste. Si conectas varias empresas, revisa que cada conexión lleve el RUT correcto.

En el flujo previsto del piloto, el navegador sale a Meta para que apruebes el acceso y vuelve a Connect. **Connect no te pedirá tu contraseña de Facebook.** Guardará cifrado el permiso emitido, sin mostrarlo al agente.

## Permisos previstos [#permisos-previstos]

Para activar una conexión del piloto, Connect pedirá y exigirá un solo permiso de Meta: **lectura de anuncios** (`ads_read`), que permite leer las estadísticas de las cuentas publicitarias a las que tiene acceso quien autoriza. No pide permisos de gestión de anuncios ni de administración del negocio.

Revisa los permisos que muestra Meta antes de autorizar. Si no concedes la lectura de anuncios, o la concesión trae algún permiso que Connect no reconoce, la autorización será rechazada y la conexión no se activará.

### La cuenta publicitaria queda fijada [#la-cuenta-publicitaria-queda-fijada]

Al autorizar, Connect comprueba que la persona que autoriza pueda leer la cuenta publicitaria indicada y recién entonces la fija a la conexión. Una conexión lee **una sola cuenta publicitaria** y no cambia de cuenta: para leer otra, conéctala en una conexión aparte.

### El permiso vence [#el-permiso-vence]

La vigencia del permiso la determina Meta y no se renueva automáticamente. Cuando vence, la sincronización responde `connection_credential_required` y hay que volver a autorizar.

### Revocar el acceso [#revocar-el-acceso]

Una vez conectada la cuenta, podrás revocar el acceso de dos formas:

* **Desde Meta:** en la configuración de tu cuenta de Facebook, donde aparecen las integraciones comerciales con acceso, quita la aplicación de Connect. Desde ese momento Meta rechaza el permiso y la próxima sincronización responde `connection_credential_required`.
* **Desde Connect:** elimina la conexión. Eso detiene la sincronización; para que Meta también deje de reconocer el permiso, revócalo además desde tu cuenta.

Para volver a leer la cuenta después de revocar o de que venza el permiso, entra a **Ajustes** de la conexión y usa **Volver a autorizar**. La conexión conserva sus datos y su cuenta publicitaria; la persona que autoriza tiene que seguir teniendo acceso a esa misma cuenta.

## El alcance [#el-alcance]

El piloto contempla un alcance, `gasto`, con el permiso `meta_ads:read`. Una sola sincronización traerá los dos niveles mediante estas herramientas:

| Tool                                | Qué hace                                                                                                            |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `meta_ads.conexion.sincronizar`     | Trae de Meta el gasto diario de la cuenta y por campaña y lo guarda. Es el único camino que llama a Meta por datos. |
| `meta_ads.conexion.verificar`       | Comprueba que la autorización siga vigente y que la cuenta fijada siga legible. No trae gasto.                      |
| `meta_ads.gasto_cuenta.consultar`   | Lee el gasto ya guardado del total de la cuenta publicitaria, un día por fila: gasto, impresiones, alcance y clics. |
| `meta_ads.gasto_campanas.consultar` | Lee el gasto ya guardado por campaña, un día de una campaña por fila, con las mismas métricas.                      |

## Sincronizar [#sincronizar]

Ejemplo previsto para una conexión del piloto habilitada:

```bash
curl -X POST https://connect.emisso.ai/api/v1/tools/meta_ads.conexion.sincronizar/execute \
  -H "Authorization: Bearer connect_sk_..." \
  -H "X-Connect-Connection: conn_9tKfR2mQx4Vb" \
  -H "Content-Type: application/json" \
  -d '{"input":{}}'
```

Respuesta ilustrativa:

```json
{
  "data": { "periodo": "2026-10", "estado": "encolado", "jobId": "sjb_3h5j7k9m1n2p4q6r8s0t1", "yaEnCurso": false },
  "meta": { "request_id": "req_...", "tool_id": "meta_ads.conexion.sincronizar", "plane": "read" }
}
```

La llamada está diseñada para responder con `estado: "encolado"` y un `jobId`; el resultado de la corrida llegará por [webhook](/docs/operar/webhooks) o en el estado de la conexión. La cadencia automática prevista es cada cuatro horas.

El sync no trabaja por mes: relee los últimos 28 días, porque Meta corrige cifras recientes, y completa hacia atrás unos 13 meses de historial por tramos. `periodo` es opcional y solo organiza la ejecución; un período que no es el corriente no vuelve a consultar Meta. Cada ejecución guarda los tramos completos y, si quedan pendientes, termina con estado `partial` y un `detalle` que los explica. La capacidad para cuentas con muchas campañas aún debe validarse antes de ampliar el piloto.

## Consultar [#consultar]

Ejemplo previsto para una conexión del piloto habilitada, con datos ya sincronizados:

```bash
curl -X POST https://connect.emisso.ai/api/v1/tools/meta_ads.gasto_cuenta.consultar/execute \
  -H "Authorization: Bearer connect_sk_..." \
  -H "X-Connect-Connection: conn_9tKfR2mQx4Vb" \
  -H "Content-Type: application/json" \
  -d '{"input":{"desde":"2026-10-01","hasta":"2026-10-20"}}'
```

Respuesta (datos ficticios):

```json
{
  "data": {
    "cuenta": { "cuentaId": "1234567890123456", "moneda": "CLP", "zonaHoraria": "America/Santiago" },
    "filas": [{
      "fecha": "2026-10-19",
      "moneda": "CLP",
      "zonaHoraria": "America/Santiago",
      "gasto": "48250",
      "impresiones": 61234,
      "alcance": 30211,
      "clics": 1402,
      "clicsEnlace": 988,
      "diaCerrado": true,
      "versionApi": "v26.0",
      "sincronizadoEn": "2026-10-20T16:00:02.000Z"
    }],
    "cobertura": {
      "desde": "2025-09-21",
      "hasta": "2026-10-20",
      "completa": true,
      "diasSinLeer": [],
      "pendiente": null,
      "sincronizadoEn": "2026-10-20T16:00:02.000Z"
    },
    "cursor": null
  },
  "meta": { "request_id": "req_...", "tool_id": "meta_ads.gasto_cuenta.consultar", "plane": "action" }
}
```

Los filtros `desde` y `hasta` son días (`AAAA-MM-DD`) en la zona horaria de la cuenta publicitaria. `meta_ads.gasto_campanas.consultar` acepta además `campanaId` para traer una sola campaña. Para seguir con la página siguiente, reenvía el `cursor` tal cual.

### El gasto es texto, con su moneda [#el-gasto-es-texto-con-su-moneda]

`gasto` viene como **decimal en texto** (`"48250"`, `"12.34"`) en la moneda de la cuenta publicitaria, que cada fila repite en `moneda`. No lo conviertas a un número de coma flotante para sumarlo, y **no sumes gastos de monedas distintas**: si la cuenta cambia de moneda, Connect vuelve a leer el historial desde cero.

### Los días son los de la cuenta publicitaria [#los-días-son-los-de-la-cuenta-publicitaria]

Meta corta los días en la zona horaria de la cuenta (`zonaHoraria`), que puede no ser la de Chile. Un día con `diaCerrado` en `false` todavía no terminaba al leerlo y sus cifras pueden crecer en la próxima sincronización.

### Cuenta y campañas no se suman [#cuenta-y-campañas-no-se-suman]

Las filas de `meta_ads.gasto_cuenta.consultar` ya son el total de la cuenta: no les sumes las de campañas. Tampoco supongas que la suma de las campañas cuadra con la cuenta, porque Meta puede no informar campañas eliminadas. El `alcance` (personas únicas) no se suma entre días ni entre campañas, y un `null&#x60; significa que Meta no lo informó: **`null` no es cero**.

## Verdades operativas [#verdades-operativas]

### `cobertura` dice qué está guardado [#cobertura-dice-qué-está-guardado]

Las dos tools de consulta devuelven `cobertura`. Dentro de `desde` y `hasta`, un día sin fila es un día en que Meta no informó entrega, salvo que caiga en `diasSinLeer`: ahí el gasto es desconocido, no cero. `completa` es `true` solo si el historial llegó a unos 13 meses, no quedó ningún tramo sin leer y la última sincronización no quedó a medias. **Con `completa` en `false`, una lista vacía no prueba que no hubo gasto.**

### Lo que este conector no es [#lo-que-este-conector-no-es]

* **No son facturas ni cobros.** Connect no lee facturas, recibos, métodos de pago ni impuestos de Meta.
* **No mide resultados de negocio.** No trae conversiones, ventas ni retorno de la inversión publicitaria; solo gasto, impresiones, alcance y clics.
* **No es en tiempo real.** Lo guardado es lo que leyó la última sincronización, y Meta puede corregir cifras de hasta 28 días atrás.
* **No baja de campaña.** Esta versión no trae conjuntos de anuncios ni anuncios individuales.

## Errores previstos [#errores-previstos]

| Código                               | Qué significa                                                                                                                                  | Qué hacer                                                                                               |
| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `428 connection_credential_required` | Meta ya no acepta el permiso: venció, se revocó, no incluye la lectura de anuncios o quien autorizó perdió el acceso a la cuenta publicitaria. | En **Ajustes** de la conexión, usa **Volver a autorizar** con un usuario que tenga acceso a esa cuenta. |
| `409 connection_identity_mismatch`   | La cuenta publicitaria que respondió no es la fijada a la conexión.                                                                            | Avísanos: la conexión no se usará con otra cuenta.                                                      |
| `502 upstream_error`                 | Meta no respondió a tiempo o limitó las consultas.                                                                                             | Reintenta más tarde. La sincronización programada lo reintenta sola y conserva lo ya guardado.          |
| `502 upstream_unexpected_response`   | Meta rechazó una consulta o respondió con una forma que Connect no reconoce.                                                                   | Avísanos: hay que revisar la aplicación de Connect o el conector.                                       |

Cuando la autorización deja de valer, la sincronización responde `connection_credential_required`; una caída o un límite de Meta responde `upstream_error` y no invalida la autorización. El envelope de cada código está en el [catálogo de errores](/docs/operar/errores).

## Próximos pasos [#próximos-pasos]

* Las cuatro tools, con contrato completo: [referencia de `meta_ads`](/docs/referencia/meta_ads).
* La separación entre escribir la caché y leerla: [Sincronizar y consultar](/docs/conceptos/sincronizar-consultar).
