> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tryprofound.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Convenciones y errores comunes

> Léelo una vez, pégalo en tu asistente de IA y evita los errores más comunes del primer día.

## Autenticación

Cada solicitud necesita tu clave de API en el encabezado `X-API-Key`. El SDK
de Python la lee de la variable de entorno `PROFOUND_API_KEY`.

<CodeGroup>
  ```python Python theme={null}
  import os
  from profound import Profound

  client = Profound(api_key=os.environ["PROFOUND_API_KEY"])
  categories = client.organizations.categories.list()
  ```

  ```bash curl theme={null}
  curl https://api.tryprofound.com/v1/org/categories \
    -H "X-API-Key: your_api_key_here"
  ```
</CodeGroup>

Genera una clave en la aplicación, en **Settings → API Keys**. Trátala como
una contraseña: tiene acceso de lectura completo a los datos de análisis de tu organización.

## Límite de solicitudes

**600 solicitudes por hora, por clave.** Cualquier exceso devuelve `429 Too Many
Requests`. Almacena las respuestas en caché siempre que puedas y agrupa las
consultas de comparación entre períodos o de varios activos en lugar de
dispersarlas en muchas llamadas.

## `end_date` es exclusivo: suma un día

`end_date` se interpreta al **inicio** de ese día en **hora del Este (ET)**,
por lo que queda excluido de la respuesta. Para incluir todo el `May 10`, envía
`end_date="2026-05-11"`.

| Ventana que quieres mostrar | Qué enviar |
| - | - |
| `May 4 → May 10` (7 días, inclusivo) | `start_date="2026-05-04", end_date="2026-05-11"` |
| `April 1 → April 30` (mes completo) | `start_date="2026-04-01", end_date="2026-05-01"` |

Los intervalos de `date_interval` (`"day"` / `"week"` / `"month"`) también se
calculan en ET.

## Lee las posiciones de las columnas en `info.query`, no en tu solicitud

Cada fila de la respuesta agrupa sus `metrics` y `dimensions` como arreglos.
El orden de los valores en esos arreglos proviene de `info.query.metrics` y
`info.query.dimensions`, **no** del orden que enviaste en la solicitud.
Búscalo siempre:

```python theme={null}
order   = res.info.query["metrics"]
i_score = order.index("visibility_score")
score   = res.data[0].metrics[i_score]
```

Una respuesta siempre tiene este aspecto:

```json theme={null}
{
  "info": {
    "total_rows": 12345,
    "query": {
      "metrics": ["visibility_score", "share_of_voice"],
      "dimensions": ["asset_name"]
    }
  },
  "data": [
    { "metrics": [0.42, 0.17], "dimensions": ["<your-asset>"] }
  ]
}
```

## Las variaciones entre períodos se calculan del lado del cliente

La API no devuelve el cambio frente al período anterior. Ejecuta la misma
llamada dos veces (ventana actual y una ventana anterior de igual duración) y resta.

## No promedies filas diarias para obtener una puntuación del período

Una llamada con `dimensions=["date"]` devuelve una fila por día. Una llamada sin
`date` devuelve una fila para toda la ventana. Son **números diferentes**: la
puntuación del período está ponderada por tráfico, y un promedio de filas
diarias no lo está. Usa la llamada sin `date` para los valores principales y la
llamada con `date` para los gráficos. Nunca derives uno del otro.

## Paginación

El valor predeterminado de `pagination.limit` es `100`. El máximo es `50,000`. Usa
`info.total_rows` (que se devuelve en cada respuesta) para decidir si necesitas
paginar. Casi todas las consultas caben en una sola página de 50k; solo las
consultas de citas pesadas con `dimensions=["url", ...]` suelen necesitar una segunda página.

```python theme={null}
pagination={"limit": 50000, "offset": 0}
```

Si necesitas más, incrementa `offset` en `limit` hasta cubrir
`total_rows`.

## Filtros

Cada endpoint de informes acepta un arreglo `filters` de objetos `{field, operator,
value}`:

```json theme={null}
{ "field": "asset_name", "operator": "is", "value": "<your-asset-name>" }
```

| Operador | Qué hace |
| - | - |
| `is` | Coincidencia exacta (valor escalar) |
| `not_is` | No es igual |
| `in` | Coincide con cualquier valor de un arreglo |
| `not_in` | No coincide con ninguno de los valores de un arreglo |
| `contains` | Coincidencia de subcadena (distingue mayúsculas y minúsculas) |
| `contains_case_insensitive` | Coincidencia de subcadena (no distingue mayúsculas y minúsculas) |
| `matches` | Coincidencia con expresión regular |

`prompt_type` (con valores como `"visibility"`) corresponde a los selectores de
vista de la aplicación. Envía `prompt_type=visibility` en las consultas de
Citations / Visibility para reflejar el alcance predeterminado de la interfaz.

## Respuestas de error

| Estado | Significado | Qué revisar |
| - | - | - |
| `400` | Error de validación | El campo `detail` / `errors` del cuerpo de la respuesta. |
| `401` | Clave de API ausente o no válida | El encabezado `X-API-Key`; si la clave fue revocada. |
| `403` | Clave válida, pero sin acceso | Es posible que el `category_id` pertenezca a otra organización. |
| `404` | Ruta incorrecta | Error tipográfico o versión de la API incorrecta. |
| `429` | Límite de solicitudes alcanzado | Espera y reduce el ritmo a ≤600/h. |
| `5xx` | Error del servidor | Reintenta con retroceso exponencial. |

## Zonas horarias

Toda la agrupación por intervalos se realiza en **hora del Este (ET)**. Un rango
de "últimos 7 días" anclado a tu reloj local puede caer en un día ET distinto
del que esperas. Ancla los trabajos programados a ET:

```python theme={null}
from datetime import datetime
from zoneinfo import ZoneInfo

today_et = datetime.now(ZoneInfo("America/New_York")).date()
```
