Quick start
Siga o exemplo e crie um fluxo de assinatura pela API
Nessa sessão você irá aprender como fazer login na API, subir um documento, iniciar um fluxo de assinatura com dois usuários de exemplo e verificar se a pessoa realizou a assinatura ou se o fluxo foi cancelado.
Todos o tutorial e exemplos nesta documentação faz referência ao ambiente de produção, mas no desenvolvimento da sua integração é importante que use o ambiente de homologação. São os links:
- API de homologação: https://api-v1-hom.assine.online
- Frontend de homologação: https://hom.assine.online
- API de produção: https://api-v1.assine.online
- Frontend de produção: https://app.assine.online
Para obtermos acesso aos endpoints da API, precisamos adquirir um token de acesso para autorizar as demais requisições. Utilizamos o método de
password
do OAuth2 para adquirir este token.Antes de tudo, garanta que tenha uma conta criada em nosso ambiente de sandbox, caso não tenha, faça o cadastro pela url: https://hom.assine.online/register. O domínio do ambiente sandbox é https://api-v1-hom.assine.online.
Quando for utilizar em produção, o domínio do frontend será https://app.assine.online e a api será https://api-v1.assine.online. Durante nossos tutoriais, usaremos o domínio de produção como exemplo.
Com o cadastro concluído, pegamos então o token de sessão:
cURL
JavaScript
curl -X POST -H "Content-Type: application/json" \
https://api-v1.assine.online/oauth -d '
{
"grant_type": "password",
"client_id": "app",
"client_secret": "app",
"username": "INFORME_USUARIO",
"password": "INFORME_SENHA"
}
'
const payload = {
grant_type:'password',
client_id: 'app',
client_secret: 'app',
username: 'INFORME_USUARIO',
password: 'INFORME_SENHA'
};
const response = await fetch('https://api.assine.online/oauth', {
method: 'POST',
body: JSON.stringify(payload),
headers: {
'Content-Type': 'application/json'
}
});
const data = await response.json();
Resposta:
{
"access_token": "41f7ff53c1dc5cf4f3db1f33e026b2908cdf88b4",
"expires_in": "86400",
"token_type": "Bearer",
"scope": "",
"refresh_token": "5fa76dd7427c6aa55cc7ca6297bbbb8c32d2d9d8"
}
Guarde o
access_token
pois com ele teremos autorização para utilizar os demais endpoints da API.Caso precise de um token de acesso com um tempo de vida maior, faça a geração de um token para aplicações.
Antes de iniciarmos um fluxo de assinatura, precisamos subir o arquivo que será assinado pelas pessoas.
Baixe aqui um pdf de exemplo ou defina um que desejar. Supondo que este documento esteja do mesmo diretório que o cursor, podemos usar o endpoint de upload com o verbo
POST
e passamos o token de acesso no header Authorization
no formato Authorization: Bearer <token>
:cURL
JavaScript
curl -X POST \
-H "Authorization: Bearer 41f7ff53c1dc5cf4f3db1f33e026b2908cdf88b4" \
-F "[email protected]" https://api-v1.assine.online/v1/file
const token = '41f7ff53c1dc5cf4f3db1f33e026b2908cdf88b4';
// Suponha que existe um campo de input[file] com o id "file"
const file = document.getElementById('file').files[0];
const response = await fetch('https://api.assine.online/v1/file', {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`
},
body: file
});
const data = await response.json();
Resposta:
{
"id": 5571,
"name": "file-sample.pdf",
"mimeType": "application/pdf",
"description": null,
"checksum": "6703901978dcb3dbf2d9915e1d3e066cfe712b0a",
"size": 142786,
"uuid": "e2dvb2RfbG9va137ImRhdGEiOnsidXVpZCI6IjBhYzM2ZTY0LTUzNTctMTFlYS05OWUzLTAyNDJhYzE0MDAwNyJ9LCJobWFjIjoiZGRjMGIxMDgzNzA5ZmI4MWNhNjI5MWEzOWNjZjA2NTdlNTBiMmIyNTNjMjM4N2YyNjdlOTJjMmNiZjJkMTU4MCIsIm5vbmNlIjoiODE3NDE1ODIxNDQzODkifQ==",
"_links": {
"self": {
"href": "https://api.assine.online/v1/file/5571"
}
}
}
A propriedade
uuid
é um token único para acesso futuro de forma pública ao arquivo, lembrando que nesse momento o arquivo não possui assinatura.Antes de criarmos o fluxo de assinatura e fazer a requisição ao backend, precisamos criar uma estrutura de JSON em que irá conter: uma mensagem de identificação do fluxo, a validade desse fluxo, os arquivos que devem ser assinados, os assinantes de cada arquivo e em que local do documento essa assinatura deve aparecer.
A estrutura final é relativamente grande e pode se tornar um pouco complexa de início, portanto vamos por partes.
Caso prefira, utilize nossa página que fornece um fluxo para integração facilitando a inclusão de campos e posições de assinatura clicando aqui.
Vamos começar criando a primeira parte do corpo do payload que iremos enviar, nele precisa conter na raiz as seguintes propriedades:
{
"autoRemind": 0,
"autoInitiate": 0,
"dueDate": "2023-01-01 00:00:00",
"message": "Uma mensagem de identificação",
"priority": 0,
"sla": 1,
"files": [...]
}
autoRemind
: Notificações de email quando está pendente de assinatura de alguém.0
desativa1
ativa.
autoInitiate
: Além de criar o fluxo, já também inicia o fluxo, fazendo os envios de emails para os assinantes.0
desativa;1
ativa.
dueDate
: Data de vencimento do fluxo, não será possível assinar os documentos após esta data definida.message
: Uma mensagem para identificar este fluxo.priority
: Simboliza uma prioridade para o fluxo.0
é prioridade normal;1
é alta e;2
muito alta.
sla
: Valor em horas em que será notificado a pendência de assinatura à pessoa. O valor1
significa uma hora,2
significa duas horas, sendo o valor máximo 720 horas (30 dias).files
: um array de arquivos que vamos escolher para este fluxo, faremos isso no próximo passo.
Continuamos então construindo nosso payload que iremos enviar para criar o fluxo, agora informando quais arquivos queremos utilizar. Definiremos o arquivo de id
5571
que fizemos upload no passo anterior, adicione o conteúdo dentro da propriedade files
do nosso payload:{
...
"files": [
{
"idFile": 5571,
"name": "Um documento de exemplo",
"specialFields": [],
"workflowSteps": [...]
}
]
}
idFile
: é o id do arquivo que nos foi retornado ao fazermos upload no passo anterior.name
(opcional) : Um nome para o documento como forma de identificação.specialFields
: São campos especiais que podemos colocar no documento que não dependem de um assinante específico. Um exemplo seria um campo de QR Code que possui um link em que valida se o documento é legitimo, outro exemplo é um campo de texto em que é possível preencher com dados da pessoa como CPF, datas de nascimento e etc. No nosso exemplo não usaremos estes campos, mas você pode conferir alguns exemplos de como utilizá-los neste link.workflowSteps
: Este define quem serão os nossos assinantes, na ordem que definimos e qual tipo de assinatura iremos pegar deste usuário, faremos isso no próximo passo.
Caso você queira informar uma pasta para este arquivo, você pode incluir a propriedade
idFolder
conforme:{
...
"files": [
{
"idFile": 5571,
"idFolder": 10,
[...]
}
]
}
Faremos um exemplo com dois assinantes: Jõao Carlos Santos e Maria das Neves. Vamos adicionar um workflowStep ao nosso array do payload com o João como primeiro assinante:
{
...
"files": [
{
...
"workflowSteps": [
{
"user": {
"name": "João Carlos Santos",
"email": "[email protected]"
},
"action": 0,
"signatureType": 0,
"fields": [...]
}
]
}
]
}
user
: Dados do assinantename
: Nome do assinante, este nome irá aparecer no email que a pessoa receberá.email
: Endereço de email da pessoa usado para enviar o documento pedindo a assinatura.
action
: Ação desta pessoa perante o documento, ou seja, se ela deve assinar, aprovar ou visualizar.0
define como pessoa assinante;1
como aprovador do documento;2
como visualizador.
signatureType
: Tipo de assinatura que queremos que essa pessoa faça, os tipos são:2
: Assinatura presencial, da qual se assemelha à eletrônica mas que é feita pelo aplicativo mobile.
field
: Campos para este usuário, ou seja, aqui vamos definir a posição em que a assinatura irá ficar dentro do documento, como também podemos definir outros campos para a pessoa preencher. Faremos isso no próximo passo.
No passo anterior definimos que João Carlos Santos será o primeiro assinante e que queremos uma assinatura eletrônica dele, agora precisamos definir em que lugar do documento essa assinatura ficará. Para isso definiremos a
field
que essa assinatura ficará:{
...
"files": [
{
...
"workflowSteps": [
{
...
"fields": [
{
"type": 8,
"x": 51,
"y": 29,
"height": 46,
"width": 200,
"page": 1
}
]
}
]
}
]
}
type
: O tipo do campo que estamos adicionando. Aqui vale algumas regras:- Para cada usuário adicionado, deve existir ao menos um
field
do tipo8
,16
ou17
, não podendo ter ambos e nem dois do mesmo tipo. - Os demais campos entre
0
e15
, exceto o8
, podem se repetir. - Os campos são:
0
: O nome do assinante;1
: O email do assinante;4
: Um campo de data;6
: Um campo de input de texto de preenchimento opcional;7
: Um campo de input de texto de preenchimento obrigatório;8
: A assinatura visível, ou seja, o desenho da assinatura da pessoa;11
: Um campo de data da assinatura;16
: Uma assinatura invisível, ou seja, que consta do documento final mas não existe uma representação visual no documento.17
: A assinatura visível, porém esta ficará na última página do documento na parte superior do lado esquerdo, com essa assinatura não é necessário informar os eixos x e y.
x
: Distância do eixo X em relação à página em que o campo deve aparecer;y
: Distância do eixo Y em relação à página em que o campo deve aparecer;height
: Altura que o campo terá em seu tamanho;width
: Largura que o campo terá em seu tamanho;page
: Em qual página do documento estará este campo.
Segue uma imagem de exemplo do que esses valores representam:

Posição da assinatura de João Carlos Santos
Aqui estamos dizendo que queremos um campo de assinatura eletrônica (type: 8), que esteja a 29 pixels do topo do documento (y: 29) e 51 pixels da esquerda do documento (x: 51). Tenha 200 pixels de largura (width: 200) e 46 pixels de altura (height: 46) e que queremos este campo na primeira página do documento (page: 1).
Com isso temos o nosso primeiro assinante definido, agora vamos duplicar e adicionar a Maria das Neves como segunda assinante.
Caso tenha dificuldades em definir as posições das assinaturas no documento, temos a opção de usar templates em uma página de configuração, veja neste link como você pode fazer isso.
Assim como o processo anterior, basta criar uma segunda posição no array com os dados de Maria:
{
...
"files": [
{
...
"workflowSteps": [
{
"user": {
"name": "João Carlos Santos",
"email": "[email protected]"
},
"action": 0,
"signatureType": 0,
"fields": [
{
"type": 8,
"x": 51,
"y": 29,
"height": 46,
"width": 200,
"page": 1
}
]
},
{
"user": {
"name": "Maria das Neves",
"email": "[email protected]"
},
"action": 0,
"signatureType": 0,
"fields": [
{
"type": 8,
"x": 490,
"y": 29,
"height": 46,
"width": 200,
"page": 1
}
]
}
]
}
]
}
Note que adicionamos também um campo do tipo assinatura eletrônica (type: 8) na mesma distância y da assinatura de João, porém colocamos que ela irá assinar mais para esquerda, à 490 pixels (x: 490).

Posição da assinatura de Maria das Neves
Com isso concluímos a construção do nosso payload e podemos então criar um fluxo, do qual nomeamos de workflow. Então o seu payload final será algo parecido com:
{
"autoRemind": 0,
"autoInitiate": 0,
"dueDate": "2023-01-01 00:00:00",
"message": "Uma mensagem de identificação",
"priority": 0,
"sla": 1,
"files": [
{
"idFile": 5571,
"name": "Um documento de exemplo",
"specialFields": [],
"workflowSteps": [
{
"user": {
"name": "João Carlos Santos",
"email": "[email protected]"
},
"action": 0,
"signatureType": 0,
"fields": [
{
"type": 8,
"x": 51,
"y": 29,
"height": 46,
"width": 200,
"page": 1
}
]
},
{
"user": {
"name": "Maria das Neves",
"email": "[email protected]"
},
"action": 0,
"signatureType": 0,
"fields": [
{
"type": 8,
"x": 490,
"y": 29,
"height": 46,
"width": 200,
"page": 1
}
]
}
]
}
]
}
Agora que temos nosso payload de workflow, vamos criá-lo:
cURL
JavaScript
PHP
curl -X POST \
-H 'Authorization: Bearer 41f7ff53c1dc5cf4f3db1f33e026b2908cdf88b4' \
-H "Content-Type: application/json" \
https://api.assine.online/v1/workflow -d '
{
"autoRemind": 0,
"autoInitiate": 0,
"dueDate": "2023-01-01 00:00:00",
"message": "Uma mensagem de identificação",
"priority": 0,
"sla": 1,
"files": [
{
"idFile": 5571,
"name": "Um documento de exemplo",
"specialFields": [],
"workflowSteps": [
{
"user": {
"name": "João Carlos Santos",
"email": "[email protected]"
},
"action": 0,
"signatureType": 0,
"fields": [
{
"type": 8,
"x": 51,
"y": 29,
"height": 46,
"width": 200,
"page": 1
}
]
},
{
"user": {
"name": "Maria das Neves",
"email": "[email protected]"
},
"action": 0,
"signatureType": 0,
"fields": [
{
"type": 8,
"x": 490,
"y": 29,
"height": 46,
"width": 200,
"page": 1
}
]
}
]
}
]
}
'
const token = '41f7ff53c1dc5cf4f3db1f33e026b2908cdf88b4';
const payload = {
autoRemind: 0,
autoInitiate: 0,
dueDate: '2023-01-01 00:00:00',
message: 'Uma mensagem de identificação',
priority: 0,
sla: 1,
files: [
{
idFile: 5571,
name: 'Um documento de exemplo',
specialFields: [],
workflowSteps: [
{
user: {
name: 'João Carlos Santos',
email: '[email protected]'
},
action: 0,
signatureType: 0,
fields: [
{
type: 8,
x: 51,
y: 29,
height: 46,
width: 200,
page: 1
}
]
},
{
user: {
name: 'Maria das Neves',
email: '[email protected]'
},
action: 0,
signatureType: 0,
fields: [
{
type: 8,
x: 490,
y: 29,
height: 46,
width: 200,
page: 1
}
]
}
]
}
]
};
const response = await fetch('https://api.assine.online/v1/workflow', {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(payload),
});
const data = await response.json();
$token = '41f7ff53c1dc5cf4f3db1f33e026b2908cdf88b4';
$client = new GuzzleHttp\Client();
$res = $client->request('POST', 'https://api.assine.online/v1/workflow', [
'headers' => [
'Authorization' => 'Bearer ' . $token
],
'json' => [
"autoRemind" => 0,
"autoInitiate" => 0,
"dueDate" => "2023-01-01 00:00:00",
"message" => "Uma mensagem de identificação",
"priority" => 0,
"sla" => 1,
"files" => [
[
"idFile" => 5571,
"name" => "Um documento de exemplo",
"specialFields" => [],
"workflowSteps" => [
[
"user" => [
"name" => "João Carlos Santos",
"email" => "[email protected]"
],
"action" => 0,
"signatureType" => 0,
"fields" => [
[
"type" => 8,
"x" => 51,
"y" => 29,
"height" => 46,
"width" => 200,
"page" => 1
]
]
],
[
"user" => [
"name" => "Maria das Neves",
"email" => "[email protected]"
],
"action" => 0,
"signatureType" => 0,
"fields" => [
[
"type" => 8,
"x" => 490,
"y" => 29,
"height" => 46,
"width" => 200,
"page" => 1
]
]
]
]
]
]
]
]);
echo $res->getBody();
Resposta:
{
"id": 1232,
"autoRemind": 0,
"dueDate": {
"date": "2023-01-01 00:00:00.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"name": null,
"message": "Uma mensagem de identificação",
"priority": 0,
"sla": 1,
"status": 0,
"_embedded": {
"user": {
"id": 474,
"username": "[email protected]",
"password": "$2y$10$Vw9uEiHuza.CaPHvmqXmi..PXIKQe/uyuDCnqkJOYWNpagU3X6IWm",
"status": "1",
"name": "Jhon Doe",
"email": "[email protected]",
"cellphone": "+5562991838359",
"document": "12312312312",
"country": "Brazil",
"state": "GO",
"city": "Goiânia",
"address": "Av 136, Ed. New York Square 19/20",
"zipCode": "74000000",
"dateCreated": {
"date": "2020-02-20 13:28:28.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"dateLastUpdated": {
"date": "2020-02-20 13:29:10.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"_embedded": {
"businessUnit": {
"id": 24,
"name": "Soluti Soluções em negocios inteligentes",
"document": "cnpj",
"status": null,
"country": "Brazil",
"state": "GO",
"city": "Goiânia",
"address": "Av 136, Ed. New York Square 19/20",
"zipCode": "74000000",
"_links": {
"self": {
"href": "https://api.assine.online/v1/business-unit/24"
}
}
}
},
"_links": {
"self": {
"href": "https://api.assine.online/v1/user/474"
}
}
}
},
"_links": {
"self": {
"href": "https://api.assine.online/v1/workflow/1232"
}
}
}
Muitas informações retornadas são configurações que foram feitas no momento da criação da qual nós mesmos definimos, mas vamos observar a propriedade
status
da qual foi retornada com o valor 0
, o que significa que este workflow de id 1232
ainda não foi iniciado. Os status que um workflow pode ter são:0
: Rascunho, ou seja, ainda não iniciou-se.1
: Circulando, ou seja, o fluxo se iniciou e está aguardando que as pessoas assinem.2
: Cancelado, ou seja, a pessoa que criou o fluxo cancelou.3
: Expirado, ou seja, o fluxo passou da data de vencimento definida.4
: Processando, ou seja, o documento está sendo processado com o cálculo de criptografia da assinatura.5
: Rejeitado, ou seja, algum dos assinantes rejeitou assinar este workflow.6
: Completado, ou seja, todos os assinantes efetuaram a assinatura e o documento está totalmente assinado.
Neste momento, o fluxo está apenas criado mas não iniciado, vamos então para o próximo passo que é de iniciar o workflow e aguardar as assinaturas.
Agora que temos nosso
id
do fluxo, ou workflow, vamos iniciá-lo para que o Assine Online comece a enviar os emails para os assinantes na ordem que definimos, alterando o status do workflow para 1 (Circulando):cURL
JavaScript
PHP
curl -X PATCH \
-H "Authorization: Bearer 41f7ff53c1dc5cf4f3db1f33e026b2908cdf88b4" \
-H "Content-Type: application/json" \
https://api.assine.online/v1/workflow/1232 -d '
{
"status": 1
}'
const token = '41f7ff53c1dc5cf4f3db1f33e026b2908cdf88b4';
const workflowId = 1232;
const payload = {
status: 1
};
const response = await fetch(`https://api.assine.online/v1/workflow/${workflowId}`, {
method: 'PATCH',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(payload),
});
const data = await response.json();
$token = '41f7ff53c1dc5cf4f3db1f33e026b2908cdf88b4';
$workflowId = 1232;
$client = new GuzzleHttp\Client();
$res = $client->request('PATCH', 'https://api.assine.online/v1/workflow/' . $workflowId, [
'headers' => [
'Authorization' => 'Bearer ' . $token
],
'json' => [
'status' => 1
]
]);
echo $res->getBody();
Resposta:
{
"id": 1232,
"autoRemind": 0,
"dueDate": {
"date": "2023-01-01 00:00:00.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"name": null,
"message": "Uma mensagem de identificação",
"priority": 0,
"sla": 1,
"status": 1,
"_embedded": {
"user": {
"id": 474,
"username": "[email protected]",
"status": "1",
"name": "Jhon Doe",
"email": "[email protected]",
"cellphone": "+5562991838359",
"document": "12312312312",
"country": "Brazil",
"state": "GO",
"city": "Goiânia",
"address": "Av 136, Ed. New York Square 19/20",
"zipCode": "74000000",
"dateCreated": {
"date": "2020-02-20 13:28:28.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"dateLastUpdated": {
"date": "2020-02-20 13:29:10.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"_embedded": {
"businessUnit": {
"id": 24,
"name": "Soluti Soluções em negocios inteligentes",
"document": "cnpj",
"status": null,
"country": "Brazil",
"state": "GO",
"city": "Goiânia",
"address": "Av 136, Ed. New York Square 19/20",
"zipCode": "74000000",
"_links": {
"self": {
"href": "https://api.assine.online/v1/business-unit/24"
}
}
}
},
"_links": {
"self": {
"href": "https://api.assine.online/v1/user/474"
}
}
}
},
"_links": {
"self": {
"href": "https://api.assine.online/v1/workflow/1232"
}
}
}
Notamos que a resposta é a mesma da criação do workflow, com a diferença que agora o status é 1. Se verificarmos a caixa de entrada de João, veremos que ele recebeu um pedido de assinatura:

Email recebido na caixa de entrada de João Carlos Santos
Perceba que estamos aguardando a assinatura de João e de Maria, porém Maria ainda não recebeu o pedido de assinatura, do qual será feito após João assinar.
Primeiramente, vamos pedir para a API nos trazer os detalhes de como está nosso workflow. Para isso fazemos:
cURL
JavaScript
PHP
curl -X GET \
-H "Authorization: Bearer 41f7ff53c1dc5cf4f3db1f33e026b2908cdf88b4" \
-H "Content-Type: application/json" \
https://api.assine.online/v1/workflow/1232
const token = '41f7ff53c1dc5cf4f3db1f33e026b2908cdf88b4';
const workflowId = 1232;
const response = await fetch(`https://api.assine.online/v1/workflow/${workflowId}`, {
method: 'GET',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
const data = await response.json();
$token = '41f7ff53c1dc5cf4f3db1f33e026b2908cdf88b4';
$workflowId = 1232;
$client = new GuzzleHttp\Client();
$res = $client->request('GET', 'https://api.assine.online/v1/workflow/' . $workflowId, [
'headers' => [
'Authorization' => 'Bearer ' . $token
]
]);
echo $res->getBody();