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

# Etiquetas de Anclaje

> Coloca campos automáticamente haciendo coincidir texto marcador literal en un PDF o DOCX subido, en lugar de especificar tú mismo las coordenadas en píxeles.

Las etiquetas de anclaje te permiten posicionar campos en un documento haciendo coincidir texto que ya está en el archivo, en lugar de calcular coordenadas x/y. Subes un PDF o DOCX que contiene texto marcador — comúnmente escrito como `{{SIGN_HERE}}` o similar, aunque funciona cualquier cadena literal — pasas un arreglo `anchor_tags` en tu solicitud de creación, y Firma busca cada cadena en el documento y coloca un campo donde encuentre una coincidencia.

<Note>
  Las etiquetas de anclaje solo funcionan con creación basada en documentos — una solicitud que incluye `document` (base64) o `document_id`. No tienen ningún efecto en las solicitudes basadas en `template_id`, porque el proceso de anclaje busca en el propio documento subido; los campos de una plantilla ya están posicionados.
</Note>

## Cómo funciona la coincidencia

`anchor_string` se compara como texto de subcadena literal, sin distinguir mayúsculas y minúsculas de forma predeterminada, en cualquier parte del documento — no se requiere ninguna sintaxis de delimitador. `{{...}}` es solo una convención que resulta visualmente fácil de detectar en un documento y poco probable que choque con contenido real; `"Sign Here:"` o `"X_____"` funcionan exactamente igual.

Cada etiqueta de anclaje admite:

| Propiedad               | Valor predeterminado | Efecto                                                                                                                             |
| :---------------------- | :------------------- | :--------------------------------------------------------------------------------------------------------------------------------- |
| `case_sensitive`        | `false`              | Si la coincidencia distingue mayúsculas y minúsculas                                                                               |
| `match_whole_word`      | `true`               | Requiere caracteres no alfanuméricos a ambos lados de la coincidencia                                                              |
| `occurrence`            | `0`                  | `0` coloca un campo en **cada** coincidencia; `1`, `2`, etc. colocan un campo solo en esa ocurrencia específica (indexada desde 1) |
| `ignore_if_not_present` | `false`              | Si no se encuentra la cadena: `true` la omite en silencio, `false` hace fallar toda la solicitud                                   |
| `x_offset` / `y_offset` | `0`                  | Desplaza el campo colocado respecto al texto encontrado                                                                            |
| `offset_units`          | `percent`            | `percent` de las dimensiones de la página, o `pixels` (puntos PDF, 72 DPI)                                                         |

<Warning>
  Si el documento no tiene ningún texto extraíble — un PDF escaneado o basado en imágenes, por ejemplo — ningún anclaje puede coincidir. Establece `ignore_if_not_present: true` si quieres que la solicitud continúe de todos modos (el campo simplemente nunca se coloca); de lo contrario, la solicitud falla la validación.
</Warning>

### Tamaños de campo predeterminados

Si no pasas `width`/`height` en una etiqueta de anclaje, el campo se dimensiona según el `type` (como un porcentaje de la página):

| Tipo                                                   | Ancho | Alto |
| :----------------------------------------------------- | :---- | :--- |
| `signature`                                            | 25%   | 5%   |
| `initial` / `initials`                                 | 10%   | 5%   |
| `date`                                                 | 20%   | 3%   |
| `text` / `textarea` / `text_area` / `dropdown` / `url` | 20%   | 3%   |
| `checkbox` / `radio` / `radio_buttons`                 | 3%    | 3%   |

<Warning>
  `stamp`, `file`, `approval_signature`, `approval_checkmark` y `approval_date` son todos aceptados por el servidor como valores de `type` para el anclaje, pero ninguno de los cinco tiene una entrada dedicada en esta tabla — todos recurren silenciosamente al valor predeterminado de `text` (20% × 3%). Eso suele ser demasiado pequeño para un sello, un cuadro de carga de archivos o una firma de aprobación. Pasa siempre `width`/`height` explícitos al anclar cualquiera de estos tipos.
</Warning>

## Ocultar el texto de anclaje

Dos opciones independientes y combinables controlan qué sucede con el texto marcador y el área a su alrededor una vez que se coloca un campo:

| Opción                 | Valor predeterminado | Qué hace realmente                                                                                                                                                                                                                                     |
| :--------------------- | :------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `remove_anchor_text`   | `true`               | Establece los glifos de la cadena de anclaje en **modo de renderizado de texto invisible de PDF**, en el mismo lugar. Los caracteres permanecen en el flujo de contenido (así el texto circundante no se reorganiza) pero no se pinta nada para ellos. |
| `add_white_background` | `false`              | Dibuja un **rectángulo blanco opaco** sobre todo el cuadro delimitador del campo, cubriendo cualquier contenido del documento que haya debajo — no solo la cadena de anclaje.                                                                          |

<Warning>
  La referencia pública de la API actualmente describe `remove_anchor_text` como que "dibuja un rectángulo blanco sobre" el texto de anclaje. Esa descripción está desactualizada — corresponde a una implementación anterior. El comportamiento actual es el renderizado de texto invisible (descrito arriba), que deja los glifos en su lugar en lugar de pintar sobre ellos. Dibujar un rectángulo es lo que hace `add_white_background`, y actúa sobre todo el cuadro del campo, no específicamente sobre la cadena de anclaje.
</Warning>

Como `remove_anchor_text` solo cambia la forma en que se *pinta* el texto, nunca elimina la cadena de la capa de texto del documento:

<Note>
  Un documento procesado con `remove_anchor_text: true` (el valor predeterminado) parece que el texto de anclaje desapareció en cualquier visor de PDF — pero al ejecutar extracción de texto (`pdftotext`, el `extractText` de una librería de PDF, etc.) contra el mismo archivo, se sigue devolviendo la cadena de anclaje literal. Esto también aplica al documento final firmado, no solo a la versión previa a la firma. Si ves un reporte de soporte donde se dice que el texto de anclaje "sigue ahí" después del procesamiento, esta es casi siempre la explicación: el texto es invisible, no está eliminado, y la firma en sí es una capa de imagen separada colocada en las coordenadas del anclaje.
</Note>

Si necesitas que el área detrás de un campo quede visualmente en blanco (por ejemplo, para cubrir un cuadro de marcador de posición impreso, no solo el texto marcador dentro de él), combina ambas opciones — `remove_anchor_text` oculta los glifos del marcador, `add_white_background` cubre toda la superficie del campo.

## Documentos DOCX

No existe una lógica de coincidencia de anclaje específica para DOCX. Un archivo DOCX subido se convierte completamente a PDF primero, y luego se ejecuta exactamente el mismo proceso de búsqueda de texto descrito arriba contra el PDF resultante:

1. Se inspeccionan los primeros bytes del archivo subido para detectar si es DOCX (un archivo en formato ZIP) o PDF.
2. Un DOCX se convierte mediante `mammoth` (DOCX → HTML) y luego se vuelve a maquetar desde cero en una página A4 fija, con márgenes fijos y una tabla de tamaños de fuente fija — **no** es una rasterización de la paginación original de Word.
3. La coincidencia de anclaje se ejecuta contra este PDF recién generado.

<Warning>
  Como la conversión DOCX→PDF vuelve a maquetar el contenido en lugar de conservar el diseño original de Word, la posición de un anclaje después de la conversión depende de dónde coloca ese texto el propio renderizador del conversor — no de dónde aparecía en el documento Word original. Los saltos de página y de línea pueden cambiar. **Las imágenes incrustadas en el DOCX se descartan por completo durante la conversión** — el paso de análisis de HTML solo maneja encabezados, párrafos, listas y tablas, sin soporte para imágenes. Si un anclaje está cerca de una imagen en tu DOCX de origen, espera que la imagen esté ausente del documento de firma, no solo reposicionada.
</Warning>

Los tipos de campo admitidos son idénticos a los de los anclajes en PDF — para cuando se ejecuta la coincidencia de anclaje, el archivo ya es un PDF, así que no hay ninguna restricción específica de DOCX sobre qué valores de `type` puedes usar.

## Documentos PDF

Para un PDF nativo subido, la coincidencia de anclaje se ejecuta directamente contra el documento: el texto posicionado se extrae página por página, los fragmentos de texto adyacentes en la misma línea se combinan (así una cadena de anclaje dividida entre distintos operadores de despliegue de texto del PDF por el productor original del PDF sigue encontrándose como una sola coincidencia), y cada coincidencia se convierte de puntos PDF a una posición porcentual relativa a la página para el nuevo campo.

<Note>
  La posición de la coincidencia se aproxima de forma proporcional a partir del índice de caracteres dentro de una cadena de texto, no del kerning exacto por glifo. En fuentes proporcionales (no monoespaciadas), un campo colocado puede quedar muy ligeramente descentrado respecto al texto de anclaje exacto. Esto rara vez es visible en tamaños de campo normales, pero vale la pena saberlo si necesitas precisión de colocación a nivel de subpíxel.
</Note>

### PDF frente a DOCX de un vistazo

|                            | PDF                                                            | DOCX                                                                              |
| :------------------------- | :------------------------------------------------------------- | :-------------------------------------------------------------------------------- |
| Diseño original conservado | Sí — la coincidencia se ejecuta sobre el archivo subido exacto | No — el archivo se reajusta a un diseño A4 fijo antes de ejecutar la coincidencia |
| Imágenes                   | Intactas por el procesamiento de anclaje                       | Se descartan durante la conversión DOCX→PDF                                       |
| Proceso de coincidencia    | Se ejecuta directamente                                        | Se ejecuta contra el PDF convertido (lógica idéntica)                             |

## Ejemplo completo

Esta solicitud crea y envía un documento con tres campos colocados mediante anclaje: una firma, una fecha que toma como predeterminado el día de la firma, y un campo de texto de solo lectura que toma su valor de un valor fijo.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.firma.dev/functions/v1/signing-request-api/signing-requests/create-and-send" \
    -H "Authorization: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Employment Contract",
      "document_id": "c251c2c0-a184-4f8c-8e65-be433e6a714a",
      "recipients": [
        {
          "first_name": "Alice",
          "last_name": "Johnson",
          "email": "alice@example.com",
          "designation": "Signer"
        }
      ],
      "anchor_tags": [
        {
          "anchor_string": "{{SIGN_HERE}}",
          "type": "signature",
          "recipient_id": "temp_1"
        },
        {
          "anchor_string": "{{DATE}}",
          "type": "date",
          "recipient_id": "temp_1",
          "date_signing_default": true
        },
        {
          "anchor_string": "{{CONTRACT_REF}}",
          "type": "text",
          "recipient_id": "temp_1",
          "read_only": true,
          "read_only_value": "Contract #12345"
        }
      ]
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch(
    'https://api.firma.dev/functions/v1/signing-request-api/signing-requests/create-and-send',
    {
      method: 'POST',
      headers: {
        'Authorization': process.env.FIRMA_API_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        name: 'Employment Contract',
        document_id: 'c251c2c0-a184-4f8c-8e65-be433e6a714a',
        recipients: [
          {
            first_name: 'Alice',
            last_name: 'Johnson',
            email: 'alice@example.com',
            designation: 'Signer'
          }
        ],
        anchor_tags: [
          {
            anchor_string: '{{SIGN_HERE}}',
            type: 'signature',
            recipient_id: 'temp_1'
          },
          {
            anchor_string: '{{DATE}}',
            type: 'date',
            recipient_id: 'temp_1',
            date_signing_default: true
          },
          {
            anchor_string: '{{CONTRACT_REF}}',
            type: 'text',
            recipient_id: 'temp_1',
            read_only: true,
            read_only_value: 'Contract #12345'
          }
        ]
      })
    }
  )

  const result = await response.json()
  ```

  ```python Python theme={null}
  import os
  import requests

  response = requests.post(
      'https://api.firma.dev/functions/v1/signing-request-api/signing-requests/create-and-send',
      headers={
          'Authorization': os.environ['FIRMA_API_KEY'],
          'Content-Type': 'application/json'
      },
      json={
          'name': 'Employment Contract',
          'document_id': 'c251c2c0-a184-4f8c-8e65-be433e6a714a',
          'recipients': [
              {
                  'first_name': 'Alice',
                  'last_name': 'Johnson',
                  'email': 'alice@example.com',
                  'designation': 'Signer'
              }
          ],
          'anchor_tags': [
              {
                  'anchor_string': '{{SIGN_HERE}}',
                  'type': 'signature',
                  'recipient_id': 'temp_1'
              },
              {
                  'anchor_string': '{{DATE}}',
                  'type': 'date',
                  'recipient_id': 'temp_1',
                  'date_signing_default': True
              },
              {
                  'anchor_string': '{{CONTRACT_REF}}',
                  'type': 'text',
                  'recipient_id': 'temp_1',
                  'read_only': True,
                  'read_only_value': 'Contract #12345'
              }
          ]
      }
  )

  result = response.json()
  ```
</CodeGroup>

<Note>
  `recipient_id` usa aquí un id temporal (`temp_1`) porque el destinatario se define en la misma solicitud (creación basada en documento). Los campos resueltos a partir de las etiquetas de anclaje se combinan con cualquier `fields` especificado manualmente en la misma solicitud, y una vez creados son filas de campo ordinarias — la respuesta no distingue un campo colocado por anclaje de uno posicionado manualmente, ni expone qué cadena de anclaje u ocurrencia lo produjo.
</Note>

## Problemas conocidos

### El texto de anclaje eliminado se oculta, no se borra — prepárate para que aparezca en la extracción

Como se explicó arriba, `remove_anchor_text` nunca elimina caracteres del PDF; solo hace que dejen de pintarse. Si tus propios requisitos de cumplimiento o redacción exigen que una cadena marcadora nunca pueda aparecer en una extracción de texto programática del documento final firmado, las etiquetas de anclaje tal como están implementadas hoy no pueden satisfacer eso — elige cadenas de anclaje con las que te sientas cómodo teniendo presentes de forma permanente (de manera invisible) en el archivo, o no dependas de esta API para eliminarlas.

### Reprocesar un documento ya anclado vuelve a coincidir con los mismos anclajes

Como el texto de anclaje solo se oculta visualmente, un documento que ya pasó por el procesamiento de etiquetas de anclaje sigue coincidiendo con los mismos valores de `anchor_string` si lo vuelves a pasar (o una copia de él) a una *nueva* solicitud de creación con los mismos `anchor_tags`. El texto invisible es indistinguible del texto visible para el paso de coincidencia. Ejecuta siempre las etiquetas de anclaje contra tu documento de origen original, sin procesar — no contra un documento que ya generaste a partir de una solicitud de anclaje anterior.

### El estilo de fuente de las etiquetas de anclaje mayormente no persiste

Una etiqueta de anclaje acepta `font_family`, `font_size`, `font_color` y `text_align`. Solo `font_size` llega realmente al campo creado — se combina en `format_rules.fontSize` (limitado entre 8 y 48). `font_family`, `font_color` y `text_align` se resuelven internamente pero se descartan antes de que se guarde el campo, así que establecerlos en una etiqueta de anclaje no tiene efecto visible.

### Los tipos de anclaje `stamp`, `file` y `approval_*` necesitan dimensionamiento explícito

`stamp`, `file`, `approval_signature`, `approval_checkmark` y `approval_date` pasan todos la validación del lado del servidor como valores de `type` de anclaje, pero ninguno tiene una entrada dedicada de dimensiones predeterminadas, así que los cinco heredan silenciosamente el valor predeterminado de `text` (20% × 3%). Pasa `width` y `height` de forma explícita para estos tipos.

## Próximos pasos

* [Envío de una solicitud de firma](/guides/sending-signing-request) para conocer el flujo completo de creación de destinatarios y campos
* [Precarga de campos](/guides/field-prefilling) — el comportamiento de `read_only`/`read_only_value`/`format_rules.prefilledData` que también siguen los campos colocados por anclaje una vez creados
* [Webhooks](/guides/webhooks) — suscríbete a `signing_request.field.filled` para reaccionar a medida que se completan los campos colocados por anclaje
