Guias

Adicionar automaticamente campos de assinatura com etiquetas âncora: Posicionamento de campos baseado em texto

Escrito por

Conteúdo

Se já posicionou campos de assinatura calculando coordenadas x/y num PDF, sabe o quão entediante isso se torna em escala. Altere o esquema do documento, e todas as coordenadas quebram. Adicione uma segunda página, e estará a recalcular desvios para metade dos seus campos.

As etiquetas de ancoragem resolvem isto. Incorpore marcadores de texto como {{SIGN_HERE}} ou {{DATE}} diretamente no seu modelo de PDF, e o Firma.dev deteta-os automaticamente e coloca os tipos de campo corretos nesses locais. Os marcadores são removidos do documento final, para que os signatários nunca os vejam. Uma chamada de API, sem matemática de coordenadas.

As etiquetas de ancoragem foram lançadas na v1.11.0 e suportam todos os tipos de campo, regras de correspondência flexíveis e até 100 etiquetas por pedido de assinatura.

Início Rápido

A forma mais rápida de colocar as etiquetas de ancoragem a funcionar: incorpore um marcador no seu PDF e, em seguida, crie um pedido de assinatura com um array anchor_tags.

Passo 1: Adicione o texto {{SIGN_HERE}} em algum lugar no seu PDF onde deseja que o campo de assinatura apareça. Pode fazê-lo em qualquer ferramenta que gere os seus documentos, quer seja um modelo do Word, uma biblioteca de PDF ou um serviço de geração de documentos.

Passo 2: Crie um pedido de assinatura baseado em documento com a definição da etiqueta de ancoragem:

const response = await fetch(
  'https://api.firma.dev/functions/v1/signing-request-api/signing-requests',
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.FIRMA_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      workspace_id: workspaceId,
      document: documentBase64,
      name: 'NDA - Acme Corp',
      anchor_tags: [
        {
          anchor_string: '{{SIGN_HERE}}',
          type: 'signature',
          recipient_id: 'temp_1',
          required: true
        }
      ],
      recipients: [
        {
          id: 'temp_1',
          first_name: 'Jane',
          last_name: 'Smith',
          email: 'jane@example.com',
          designation: 'Signer',
          order: 1
        }
      ]
    })
  }
);

const signingRequest = await response.json();
const response = await fetch(
  'https://api.firma.dev/functions/v1/signing-request-api/signing-requests',
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.FIRMA_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      workspace_id: workspaceId,
      document: documentBase64,
      name: 'NDA - Acme Corp',
      anchor_tags: [
        {
          anchor_string: '{{SIGN_HERE}}',
          type: 'signature',
          recipient_id: 'temp_1',
          required: true
        }
      ],
      recipients: [
        {
          id: 'temp_1',
          first_name: 'Jane',
          last_name: 'Smith',
          email: 'jane@example.com',
          designation: 'Signer',
          order: 1
        }
      ]
    })
  }
);

const signingRequest = await response.json();
const response = await fetch(
  'https://api.firma.dev/functions/v1/signing-request-api/signing-requests',
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.FIRMA_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      workspace_id: workspaceId,
      document: documentBase64,
      name: 'NDA - Acme Corp',
      anchor_tags: [
        {
          anchor_string: '{{SIGN_HERE}}',
          type: 'signature',
          recipient_id: 'temp_1',
          required: true
        }
      ],
      recipients: [
        {
          id: 'temp_1',
          first_name: 'Jane',
          last_name: 'Smith',
          email: 'jane@example.com',
          designation: 'Signer',
          order: 1
        }
      ]
    })
  }
);

const signingRequest = await response.json();

O Firma.dev analisa o PDF em busca de {{SIGN_HERE}}, coloca um campo de assinatura nesse local, atribui-o ao destinatário e remove o texto do marcador do documento. É só isso.

Note que as etiquetas de ancoragem apenas funcionam com a criação de pedidos de assinatura baseados em documentos, não baseados em modelos. Está a enviar o PDF original e a deixar que o sistema de ancoragem trate do posicionamento dos campos.

Tipos de Campo Suportados

As etiquetas de ancoragem suportam todos os tipos de campo disponíveis no Firma.dev. Defina a propriedade type em cada etiqueta de ancoragem para um destes valores:

signature para campos de assinatura, initials para campos de rubrica, text para introdução de texto de linha única, textarea para introdução de texto multilinha, date para campos de data, checkbox para caixas de seleção, radio para grupos de botões de rádio, dropdown para seleções suspensas, url para campos de URL, stamp para campos de carimbo e file para campos de carregamento de ficheiros.

Cada tipo apresenta o widget de campo apropriado na experiência de assinatura. Uma etiqueta de ancoragem de date cria um selecionador de data, um dropdown cria um menu de seleção e assim por diante.

Opções de Correspondência e Posicionamento

O comportamento de correspondência padrão funciona na maioria dos casos, mas pode refinar a forma como o Firma.dev encontra e posiciona os campos criados por ancoragem.

Sensibilidade a maiúsculas e minúsculas: Defina case_sensitive para true ou false (o padrão é false). Com a correspondência insensível a maiúsculas, tanto {{sign_here}} como {{SIGN_HERE}} correspondem.

Correspondência de palavra inteira: Defina whole_word para true para evitar correspondências parciais. Se a sua string de ancoragem for SIGN e whole_word for false, também corresponderia a SIGNATURE ou COSIGN. Definir para true garante que apenas corresponde à palavra exata.

Segmentação de ocorrências específicas: Se o seu PDF contiver a mesma string de ancoragem várias vezes, pode segmentar ocorrências específicas com occurrence. Defina como 1 para a primeira correspondência, 2 para a segunda e assim por diante. Omita-o ou defina match_all como true para colocar campos em todas as ocorrências.

Posicionamento de desvio: Ajuste com precisão onde o campo fica em relação ao texto de ancoragem utilizando offset_x e offset_y. Pode especificar desvios em percentagens (relativas às dimensões da página) ou píxeis. Isto é útil quando deseja que o campo seja posicionado ligeiramente abaixo ou à direita do marcador, em vez de diretamente em cima dele.

Tratamento suave de âncoras em falta: Defina ignore_if_not_present para true se a string de ancoragem puder não existir em todos os documentos. Sem isto, uma âncora em falta devolve um erro. Com isto ativado, o Firma.dev ignora silenciosamente essa etiqueta e processa o resto.

Configuração Avançada

Eis um exemplo mais completo que combina múltiplas etiquetas de ancoragem com diferentes tipos de campo, dimensões personalizadas e desvios de posicionamento:

const response = await fetch(
  'https://api.firma.dev/functions/v1/signing-request-api/signing-requests',
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.FIRMA_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      workspace_id: workspaceId,
      document: documentBase64,
      name: 'Employment Agreement',
      anchor_tags: [
        {
          anchor_string: '{{EMPLOYEE_SIGNATURE}}',
          type: 'signature',
          recipient_id: 'temp_1',
          required: true,
          width: 30,
          height: 8,
          offset_y: 2
        },
        {
          anchor_string: '{{EMPLOYEE_DATE}}',
          type: 'date',
          recipient_id: 'temp_1',
          required: true
        },
        {
          anchor_string: '{{EMPLOYEE_INITIALS}}',
          type: 'initials',
          recipient_id: 'temp_1',
          required: true,
          match_all: true
        },
        {
          anchor_string: '{{MANAGER_SIGNATURE}}',
          type: 'signature',
          recipient_id: 'temp_2',
          required: true
        },
        {
          anchor_string: '{{BENEFITS_OPT_IN}}',
          type: 'checkbox',
          recipient_id: 'temp_1',
          required: false,
          ignore_if_not_present: true
        }
      ],
      recipients: [
        {
          id: 'temp_1',
          first_name: 'Sarah',
          last_name: 'Chen',
          email: 'sarah@example.com',
          designation: 'Signer',
          order: 1
        },
        {
          id: 'temp_2',
          first_name: 'Mike',
          last_name: 'Torres',
          email: 'mike@example.com',
          designation: 'Signer',
          order: 2
        }
      ]
    })
  }
);
const response = await fetch(
  'https://api.firma.dev/functions/v1/signing-request-api/signing-requests',
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.FIRMA_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      workspace_id: workspaceId,
      document: documentBase64,
      name: 'Employment Agreement',
      anchor_tags: [
        {
          anchor_string: '{{EMPLOYEE_SIGNATURE}}',
          type: 'signature',
          recipient_id: 'temp_1',
          required: true,
          width: 30,
          height: 8,
          offset_y: 2
        },
        {
          anchor_string: '{{EMPLOYEE_DATE}}',
          type: 'date',
          recipient_id: 'temp_1',
          required: true
        },
        {
          anchor_string: '{{EMPLOYEE_INITIALS}}',
          type: 'initials',
          recipient_id: 'temp_1',
          required: true,
          match_all: true
        },
        {
          anchor_string: '{{MANAGER_SIGNATURE}}',
          type: 'signature',
          recipient_id: 'temp_2',
          required: true
        },
        {
          anchor_string: '{{BENEFITS_OPT_IN}}',
          type: 'checkbox',
          recipient_id: 'temp_1',
          required: false,
          ignore_if_not_present: true
        }
      ],
      recipients: [
        {
          id: 'temp_1',
          first_name: 'Sarah',
          last_name: 'Chen',
          email: 'sarah@example.com',
          designation: 'Signer',
          order: 1
        },
        {
          id: 'temp_2',
          first_name: 'Mike',
          last_name: 'Torres',
          email: 'mike@example.com',
          designation: 'Signer',
          order: 2
        }
      ]
    })
  }
);
const response = await fetch(
  'https://api.firma.dev/functions/v1/signing-request-api/signing-requests',
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.FIRMA_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      workspace_id: workspaceId,
      document: documentBase64,
      name: 'Employment Agreement',
      anchor_tags: [
        {
          anchor_string: '{{EMPLOYEE_SIGNATURE}}',
          type: 'signature',
          recipient_id: 'temp_1',
          required: true,
          width: 30,
          height: 8,
          offset_y: 2
        },
        {
          anchor_string: '{{EMPLOYEE_DATE}}',
          type: 'date',
          recipient_id: 'temp_1',
          required: true
        },
        {
          anchor_string: '{{EMPLOYEE_INITIALS}}',
          type: 'initials',
          recipient_id: 'temp_1',
          required: true,
          match_all: true
        },
        {
          anchor_string: '{{MANAGER_SIGNATURE}}',
          type: 'signature',
          recipient_id: 'temp_2',
          required: true
        },
        {
          anchor_string: '{{BENEFITS_OPT_IN}}',
          type: 'checkbox',
          recipient_id: 'temp_1',
          required: false,
          ignore_if_not_present: true
        }
      ],
      recipients: [
        {
          id: 'temp_1',
          first_name: 'Sarah',
          last_name: 'Chen',
          email: 'sarah@example.com',
          designation: 'Signer',
          order: 1
        },
        {
          id: 'temp_2',
          first_name: 'Mike',
          last_name: 'Torres',
          email: 'mike@example.com',
          designation: 'Signer',
          order: 2
        }
      ]
    })
  }
);

Algumas coisas a notar neste exemplo. A etiqueta {{EMPLOYEE_INITIALS}} utiliza match_all: true, por isso se o PDF tiver marcadores de rubricas nas páginas 1, 5 e 12, as três recebem campos. A caixa de seleção {{BENEFITS_OPT_IN}} utiliza ignore_if_not_present: true porque nem todas as versões do contrato de trabalho incluem essa secção. E o offset_y: 2 no campo de assinatura desvia-o ligeiramente para baixo em relação à posição do texto de ancoragem.

As dimensões (width e height) seguem o mesmo sistema de coordenadas baseado em percentagens utilizado por campos posicionados manualmente. As etiquetas de ancoragem e os campos manuais funcionam em conjunto, pelo que pode utilizar âncoras para a maior parte dos seus campos e continuar a adicionar campos baseados em coordenadas manuais no mesmo pedido para casos excecionais.

Migração de Outras Plataformas

Se está a migrar de outro fornecedor de assinatura eletrónica que utiliza posicionamento de campos baseado em texto, os conceitos mapeiam-se diretamente. A sintaxe da string de ancoragem e os nomes das propriedades diferem, mas o mecanismo subjacente é o mesmo: incorpore um marcador, defina o tipo de campo e deixe a API tratar do posicionamento.

De DocuSign Auto-Place: O DocuSign utiliza anchorString, anchorXOffset, anchorYOffset e tipos específicos de separador como signHereTabs. No Firma.dev, isto torna-se anchor_string, offset_x, offset_y e o campo universal type. O anchorIgnoreIfNotPresent do DocuSign mapeia para ignore_if_not_present. O anchorCaseSensitive do DocuSign mapeia para case_sensitive. A principal diferença estrutural é que o Firma.dev utiliza um único array anchor_tags com uma propriedade type, em vez de arrays separados para cada tipo de separador.

De Yousign Smart Anchors: O conceito de "âncoras inteligentes" do Yousign com deteção do tipo de campo traduz-se diretamente. As opções de correspondência e posicionamento são comparáveis, embora os nomes das propriedades utilizem a convenção snake_case do Firma.dev.

O limite é de 100 etiquetas de ancoragem por pedido de assinatura, o que cobre confortavelmente a maioria dos fluxos de trabalho de documentos. Se estiver a processar documentos que necessitem genuinamente de mais de 100 campos, considere dividir em múltiplos pedidos de assinatura ou utilizar uma combinação de etiquetas de ancoragem e definições de campo baseadas em modelos.

Referência da API

O array anchor_tags está disponível no endpoint de criação de pedidos de assinatura baseados em documentos (POST /signing-requests). Cada item no array é um objeto AnchorTag com cerca de 25 propriedades configuráveis.

As propriedades chave:

anchor_string (obrigatório) é o marcador de texto a pesquisar no PDF. type (obrigatório) é o tipo de campo a criar. recipient_id atribui o campo a um destinatário específico utilizando o seu ID ou ID temporário. required marca o campo como obrigatório ou opcional. offset_x e offset_y ajustam a posição do campo em relação ao local da âncora. width e height definem dimensões personalizadas para o campo. case_sensitive controla se a correspondência é sensível a maiúsculas e minúsculas. whole_word evita correspondências parciais de texto. occurrence visa uma instância específica quando a âncora aparece várias vezes. match_all coloca campos em todas as ocorrências. ignore_if_not_present ignora a etiqueta sem erro se o texto de ancoragem não for encontrado no documento.

Para o esquema completo com todas as propriedades e respetivos tipos, consulte o registo de alterações da API para a v1.11.0.

Próximos Passos

As etiquetas de ancoragem funcionam muito bem com a geração programática de documentos. Se a sua aplicação gera contratos, acordos de confidencialidade ou documentos de integração a partir de modelos, pode incorporar strings de ancoragem durante a geração e deixar que o Firma.dev trate do posicionamento dos campos automaticamente em cada pedido.

Comece a utilizar o Firma.dev gratuitamente, sem necessidade de cartão de crédito.

  1. Cabeçalho

Imagem de Fundo

Pronto para adicionar assinaturas eletrónicas à sua aplicação?

Comece gratuitamente. Não é necessário cartão de crédito. Pague apenas 0,049 € por envelope quando estiver pronto para começar.

Imagem de Fundo

Pronto para adicionar assinaturas eletrónicas à sua aplicação?

Comece gratuitamente. Não é necessário cartão de crédito. Pague apenas 0,049 € por envelope quando estiver pronto para começar.

Imagem de Fundo

Pronto para adicionar assinaturas eletrónicas à sua aplicação?

Comece gratuitamente. Não é necessário cartão de crédito. Pague apenas 0,049 € por envelope quando estiver pronto para começar.