# Entrantes

La API REST de Dinaup permite interactuar con tus datos de forma programática. Todos los endpoints se sirven desde `https://webhook.dinaup.com`.

***

## Autenticación

Todos los endpoints (excepto el ping) requieren una **Clave API de usuario** en el header HTTP:

```
Authorization: Bearer <clave-api>
```

Las claves API se generan desde **dinaup.com > Claves API**. Cada clave hereda los permisos del usuario al que pertenece, por lo que solo podrá acceder a los datos que ese usuario tiene permiso de ver.

→ Ver [Claves API](/administracion/claves-api.md)

{% hint style="warning" %}
Nunca compartas tus claves API en código público ni en el frontend de aplicaciones web. Úsalas exclusivamente en el backend.
{% endhint %}

***

## `GET /` — Ping

Verifica que el servidor de webhooks está operativo. No requiere autenticación.

**Request:**

```bash
curl -X GET "https://webhook.dinaup.com"
```

**Response:** `200 OK`

```
"Hola :)"
```

***

## `GET /api/whoami` — Información del usuario

Devuelve los datos del usuario asociado a la clave API. Útil para verificar que la autenticación funciona correctamente.

**Request:**

```bash
curl -X GET "https://webhook.dinaup.com/api/whoami" \
  -H "Authorization: Bearer <clave-api>"
```

**Response:** `200 OK` con los datos del usuario (nombre, email, permisos).

***

## Límites de tasa (Rate Limiting)

Cada endpoint tiene un límite de peticiones por tenant (identificado por el Bearer Token):

| Endpoint                 | Tokens | Reposición | Periodo |
| ------------------------ | ------ | ---------- | ------- |
| WriteOperations          | 30     | 5 tokens   | 10 seg  |
| Reports                  | 30     | 5 tokens   | 10 seg  |
| DynamicDocuments         | 30     | 5 tokens   | 10 seg  |
| Whoami                   | 60     | 10 tokens  | 10 seg  |
| Herramientas (AEAT/VIES) | 10     | 2 tokens   | 10 seg  |

Si excedes el límite, recibirás un error `429 Too Many Requests` con un header `Retry-After: 10`.

***

## `POST /api/reports` — Consultar informes

Ejecuta un [informe de Dinaup Flex](/desarrollo/flex/informes.md) y devuelve los resultados en formato JSON. Los informes se configuran previamente en Dinaup Flex con las columnas, filtros y agrupaciones deseadas.

**Parámetros (query string):**

| Parámetro         | Tipo | Obligatorio | Descripción                                                              |
| ----------------- | ---- | ----------- | ------------------------------------------------------------------------ |
| `id`              | UUID | Sí          | ID del informe a consultar                                               |
| `page`            | int  | No          | Número de página (por defecto: 1)                                        |
| `resultsPerPage`  | int  | No          | Resultados por página (por defecto: 10)                                  |
| `withFiles`       | bool | No          | Incluir URLs de archivos adjuntos (por defecto: false)                   |
| `safeColumnsName` | bool | No          | Usar GUIDs como nombres de columna para estabilidad (por defecto: false) |

**Body (opcional):** JSON con variables de filtro si el informe tiene preguntas dinámicas.

```json
{
  "variableFiltro1": "valor1",
  "variableFiltro2": "valor2"
}
```

**Request:**

```bash
curl -X POST "https://webhook.dinaup.com/api/reports?id=5b3b317c-0513-4ab8-9724-903100edea76&page=1&resultsPerPage=100&withFiles=false&safeColumnsName=false" \
  -H "Authorization: Bearer <clave-api>" \
  -H "Content-Type: application/json" \
  -d '{}'
```

**Response:**

```json
{
  "data": [
    {"columna1": "valor1", "columna2": "valor2"},
    {"columna1": "valor3", "columna2": "valor4"}
  ],
  "currentPage": 1,
  "totalPages": 5,
  "totalResults": 42,
  "files": []
}
```

{% hint style="info" %}
**Recomendaciones:**

* Activa `safeColumnsName=true` en producción para que los nombres de columna no cambien si se renombra un campo en Dinaup.
* Si el informe tiene **preguntas dinámicas**, puedes pasar los valores como parámetros adicionales en la URL para filtrar los resultados (por ejemplo, filtrar ventas por cliente o por rango de fechas).
* Los resultados están paginados. Usa `page` y `resultsPerPage` para iterar sobre conjuntos grandes de datos.
  {% endhint %}

***

## `POST /api/dynamicdocuments` — Documentos dinámicos

Genera un [documento dinámico](/desarrollo/flex/documentos-dinamicos.md) y devuelve su contenido renderizado. Los documentos dinámicos son plantillas que combinan datos de diferentes secciones en formatos como HTML, JSON o texto plano.

**Parámetros (query string):**

| Parámetro | Tipo | Obligatorio | Descripción               |
| --------- | ---- | ----------- | ------------------------- |
| `id`      | UUID | Sí          | ID del documento dinámico |

**Body (opcional):** JSON con variables para sustituir en la plantilla.

```json
{
  "nombreVariable1": "valor1",
  "nombreVariable2": "valor2"
}
```

**Request:**

```bash
curl -X POST "https://webhook.dinaup.com/api/dynamicdocuments?id=3db0df5f-af7f-4183-af9d-f561976fb61a" \
  -H "Authorization: Bearer <clave-api>" \
  -H "Content-Type: application/json" \
  -d '{"clienteId": "abc-123"}'
```

**Response:**

```json
{
  "document": "Contenido renderizado del documento...",
  "data": {
    "clienteId": "abc-123"
  }
}
```

***

## `POST /api/writeoperations` — Escribir datos

Crea, edita o elimina registros en cualquier sección de Dinaup.

**Parámetros (query string):**

| Parámetro      | Tipo   | Obligatorio | Descripción                                                               |
| -------------- | ------ | ----------- | ------------------------------------------------------------------------- |
| `sectionId`    | UUID   | Sí          | ID de la sección donde escribir                                           |
| `FieldPrimary` | string | Sí          | Nombre del campo clave para identificar registros                         |
| `scripts`      | bool   | No          | Ejecutar scripts del servidor asociados a la sección (por defecto: false) |

**Headers:**

```
Authorization: Bearer <clave-api>
Content-Type: application/json
```

### Crear, editar y eliminar

La operación se determina por el valor del campo `id`:

| Valor de `id`       | Operación  | Descripción                                                     |
| ------------------- | ---------- | --------------------------------------------------------------- |
| `""` (cadena vacía) | **Crear**  | Se crea un nuevo registro. Dinaup genera el ID automáticamente. |
| UUID existente      | **Editar** | Se actualizan los campos enviados del registro con ese ID.      |
| UUID inexistente    | **Error**  | Devuelve error. No se puede editar un registro que no existe.   |

Para **eliminar** un registro, envía una operación de edición con el campo `eliminado` establecido a `1`:

```json
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "eliminado": "1"
}
```

{% hint style="info" %}
No existe un endpoint DELETE separado. La eliminación es lógica (soft delete) y se realiza mediante WriteOperations.
{% endhint %}

### Nombres de campo (`pr_*`)

Los campos se identifican por su columna PostgreSQL, que tiene formato `pr_XXXXXXXXX`. Puedes consultar los nombres de campo de cada sección desde:

* **Play Dinaup** → módulo Desarrollo → Esquema
* **Dinaup Desktop** (app Windows) → configuración de la sección
* **doc-flex.dinaup.com** → referencia completa de todas las secciones
* **SDK .NET (MyDinaup)** → todos los campos están tipados con nombres legibles

### Formato 1: Objeto simple

Envía un solo registro como diccionario de campos:

```json
{
  "id": "",
  "pr_60040105651": "id-del-cliente",
  "pr_500401055323": "100.00"
}
```

> `"id": ""` → crea un nuevo registro. Para editar, usa el UUID del registro existente.

### Formato 2: Objeto con lista (padre + hijos)

Para secciones que tienen una sección lista asociada (ej: Factura + Líneas de factura):

```json
{
  "Main": {
    "id": "",
    "pr_60040105651": "id-del-cliente"
  },
  "List": [
    {"pr_item": "producto-1", "pr_cantidad": "10"},
    {"pr_item": "producto-2", "pr_cantidad": "20"}
  ]
}
```

### Formato 3: Lote de objetos

Envía múltiples registros en una sola petición:

```json
[
  {"id": "", "pr_campo1": "valor1"},
  {"id": "", "pr_campo1": "valor2"}
]
```

### Formato 4: Lote de objetos con listas

Múltiples registros padre-hijo en una sola petición:

```json
[
  {
    "Main": {"id": "", "pr_campo": "valor1"},
    "List": [{"pr_item": "val1"}]
  },
  {
    "Main": {"id": "", "pr_campo": "valor2"},
    "List": [{"pr_item": "val2"}]
  }
]
```

**Ejemplo completo (crear un registro):**

```bash
curl -X POST "https://webhook.dinaup.com/api/writeoperations?sectionId=0ce4c6ac-54aa-488d-b8b8-e3a20d79f7a4&FieldPrimary=id&scripts=true" \
  -H "Authorization: Bearer <clave-api>" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "",
    "pr_60040105651": "id-del-cliente",
    "pr_500401055323": "100.00"
  }'
```

{% hint style="warning" %}
Las operaciones de escritura respetan los permisos del usuario asociado a la clave API. Si el usuario no tiene permiso de escritura en una sección, la operación fallará.
{% endhint %}

***

## Herramientas auxiliares

### `GET /api/tools/aeat` — Validación NIF/CIF

Valida un NIF o CIF contra el censo de la Agencia Estatal de Administración Tributaria (AEAT).

### `GET /api/tools/vies` — Validación VIES

Valida un número de identificación fiscal intracomunitario contra el sistema VIES de la Unión Europea. Útil para verificar que un cliente es operador intracomunitario antes de emitir una factura con IVA al 0%.

***

## Códigos de respuesta

| Código | Significado                                                          |
| ------ | -------------------------------------------------------------------- |
| `200`  | Operación exitosa                                                    |
| `401`  | Clave API inválida o ausente                                         |
| `403`  | El usuario no tiene permisos para esta operación                     |
| `404`  | Recurso no encontrado (informe, documento, sección)                  |
| `422`  | Datos de entrada inválidos (campos obligatorios, formato incorrecto) |
| `500`  | Error interno del servidor                                           |

***

## Playground

Prueba todos los endpoints directamente desde Dinaup sin configurar herramientas externas:

[Abrir Playground de Webhooks](https://play.dinaup.com/App/Dev/IncomingWebhooks)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://doc.dinaup.com/integraciones/webhook/entrantes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
