API
Criar envelope
Cria um novo envelope com um documento e signatários.
POST
/
v1
/
envelopes
Criar envelope
curl --request POST \
--url https://api.valid.com/v1/envelopes \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"title": "<string>",
"signingMode": {},
"document": {
"url": "<string>",
"content": "<string>",
"filename": "<string>"
},
"signers": [
{
"name": "<string>",
"email": "<string>",
"cpf": "<string>",
"phoneCountryCode": "<string>",
"phoneNumber": "<string>",
"queueOrder": 123,
"livenessSessionId": "<string>"
}
],
"externalCode": "<string>",
"templateId": "<string>",
"dueDate": "<string>",
"urlOrigin": "<string>",
"urlNotification": "<string>",
"auth": {
"mfaTransactionId": "<string>"
}
}
'import requests
url = "https://api.valid.com/v1/envelopes"
payload = {
"title": "<string>",
"signingMode": {},
"document": {
"url": "<string>",
"content": "<string>",
"filename": "<string>"
},
"signers": [
{
"name": "<string>",
"email": "<string>",
"cpf": "<string>",
"phoneCountryCode": "<string>",
"phoneNumber": "<string>",
"queueOrder": 123,
"livenessSessionId": "<string>"
}
],
"externalCode": "<string>",
"templateId": "<string>",
"dueDate": "<string>",
"urlOrigin": "<string>",
"urlNotification": "<string>",
"auth": { "mfaTransactionId": "<string>" }
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
title: '<string>',
signingMode: {},
document: {url: '<string>', content: '<string>', filename: '<string>'},
signers: [
{
name: '<string>',
email: '<string>',
cpf: '<string>',
phoneCountryCode: '<string>',
phoneNumber: '<string>',
queueOrder: 123,
livenessSessionId: '<string>'
}
],
externalCode: '<string>',
templateId: '<string>',
dueDate: '<string>',
urlOrigin: '<string>',
urlNotification: '<string>',
auth: {mfaTransactionId: '<string>'}
})
};
fetch('https://api.valid.com/v1/envelopes', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.valid.com/v1/envelopes",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'title' => '<string>',
'signingMode' => [
],
'document' => [
'url' => '<string>',
'content' => '<string>',
'filename' => '<string>'
],
'signers' => [
[
'name' => '<string>',
'email' => '<string>',
'cpf' => '<string>',
'phoneCountryCode' => '<string>',
'phoneNumber' => '<string>',
'queueOrder' => 123,
'livenessSessionId' => '<string>'
]
],
'externalCode' => '<string>',
'templateId' => '<string>',
'dueDate' => '<string>',
'urlOrigin' => '<string>',
'urlNotification' => '<string>',
'auth' => [
'mfaTransactionId' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.valid.com/v1/envelopes"
payload := strings.NewReader("{\n \"title\": \"<string>\",\n \"signingMode\": {},\n \"document\": {\n \"url\": \"<string>\",\n \"content\": \"<string>\",\n \"filename\": \"<string>\"\n },\n \"signers\": [\n {\n \"name\": \"<string>\",\n \"email\": \"<string>\",\n \"cpf\": \"<string>\",\n \"phoneCountryCode\": \"<string>\",\n \"phoneNumber\": \"<string>\",\n \"queueOrder\": 123,\n \"livenessSessionId\": \"<string>\"\n }\n ],\n \"externalCode\": \"<string>\",\n \"templateId\": \"<string>\",\n \"dueDate\": \"<string>\",\n \"urlOrigin\": \"<string>\",\n \"urlNotification\": \"<string>\",\n \"auth\": {\n \"mfaTransactionId\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.valid.com/v1/envelopes")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"title\": \"<string>\",\n \"signingMode\": {},\n \"document\": {\n \"url\": \"<string>\",\n \"content\": \"<string>\",\n \"filename\": \"<string>\"\n },\n \"signers\": [\n {\n \"name\": \"<string>\",\n \"email\": \"<string>\",\n \"cpf\": \"<string>\",\n \"phoneCountryCode\": \"<string>\",\n \"phoneNumber\": \"<string>\",\n \"queueOrder\": 123,\n \"livenessSessionId\": \"<string>\"\n }\n ],\n \"externalCode\": \"<string>\",\n \"templateId\": \"<string>\",\n \"dueDate\": \"<string>\",\n \"urlOrigin\": \"<string>\",\n \"urlNotification\": \"<string>\",\n \"auth\": {\n \"mfaTransactionId\": \"<string>\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.valid.com/v1/envelopes")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"title\": \"<string>\",\n \"signingMode\": {},\n \"document\": {\n \"url\": \"<string>\",\n \"content\": \"<string>\",\n \"filename\": \"<string>\"\n },\n \"signers\": [\n {\n \"name\": \"<string>\",\n \"email\": \"<string>\",\n \"cpf\": \"<string>\",\n \"phoneCountryCode\": \"<string>\",\n \"phoneNumber\": \"<string>\",\n \"queueOrder\": 123,\n \"livenessSessionId\": \"<string>\"\n }\n ],\n \"externalCode\": \"<string>\",\n \"templateId\": \"<string>\",\n \"dueDate\": \"<string>\",\n \"urlOrigin\": \"<string>\",\n \"urlNotification\": \"<string>\",\n \"auth\": {\n \"mfaTransactionId\": \"<string>\"\n }\n}"
response = http.request(request)
puts response.read_bodyHTTP/1.1 201 Created
Content-Type: application/json
{
"envelopeUuid": "550e8400-e29b-41d4-a716-446655440000",
"fileUuid": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
"signers": [
{
"signerUuid": "6ba7b811-9dad-11d1-80b4-00c04fd430c8",
"sessionToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"signUrl": "https://seu-app.com/sign?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
},
{
"signerUuid": "6ba7b812-9dad-11d1-80b4-00c04fd430c8",
"sessionToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"signUrl": "https://seu-app.com/sign?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
],
"state": "CREATED",
"createdAt": "2025-07-27T10:30:00.000Z"
}
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"statusCode": 400,
"message": "Unique constraint violation on field(s): externalCode"
}
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"statusCode": 401,
"message": "Invalid or expired API key"
}
Cria um novo envelope, abre sessões de assinatura para cada signatário e retorna as URLs/tokens para compartilhamento.
string
required
Título do envelope (ex:
"Contrato de Serviços 2025").enum
required
Modo de assinatura:
sequential (signatários assinam um de cada vez) ou parallel (todos podem assinar simultaneamente).object
required
array
required
Lista de signatários.
Show Propriedades de signers[]
Show Propriedades de signers[]
string
required
Nome completo do signatário.
string
required
E-mail do signatário (recebe link para assinar).
string
required
CPF do signatário (11 dígitos, sem formatação).
string
Código de país do telefone (ex:
"55" para Brasil).string
Número de telefone (ex:
"11987654321").integer
Ordem na fila (apenas para
signingMode: sequential). Signatários com ordem menor assinam primeiro.string
ID de uma sessão de liveness já realizada (para PAdES avançado). Opcional.
string
Código único externo do seu sistema (ex:
"FAT-2025-001"). Deve ser único por projeto. Opcional.string
UUID de um template para usar como base. Se enviado, o documento do template é ignorado; use o documento enviado aqui ou deixe vazio para usar o do template.
string
Data/hora limite para assinatura (ISO 8601, ex:
"2025-12-31T23:59:59Z"). Signatários que não acessarem até essa data verão 410 Gone.string
URL origem do seu app (ex:
"https://app.seu-dominio.com"). Usado para construir links no e-mail de convite.string
URL webhook para notificação de mudanças de estado (ex:
"https://seu-backend.com/webhooks/status"). Opcional. Veja Notificações via webhook.object
Dados de autenticação/verificação (usado para escolher estratégia de assinatura).
Show Propriedades de auth
Show Propriedades de auth
string
ID de uma transação MFA já aprovada (para assinatura eletrônica simples, não PAdES).
Respostas
string
UUID único do envelope criado.
string
UUID do arquivo (PDF) do envelope.
array
string
Estado inicial do envelope:
CREATED.string
Timestamp de criação (ISO 8601).
Erros comuns
Veja Autenticação e erros para detalhes sobre401, 400, 409, etc.
- 400: CPF inválido, email malformado, documento não encontrado (URL inválida).
- 401: API key inválida ou expirada.
- 409:
externalCodeduplicado no projeto.
HTTP/1.1 201 Created
Content-Type: application/json
{
"envelopeUuid": "550e8400-e29b-41d4-a716-446655440000",
"fileUuid": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
"signers": [
{
"signerUuid": "6ba7b811-9dad-11d1-80b4-00c04fd430c8",
"sessionToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"signUrl": "https://seu-app.com/sign?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
},
{
"signerUuid": "6ba7b812-9dad-11d1-80b4-00c04fd430c8",
"sessionToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"signUrl": "https://seu-app.com/sign?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
],
"state": "CREATED",
"createdAt": "2025-07-27T10:30:00.000Z"
}
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"statusCode": 400,
"message": "Unique constraint violation on field(s): externalCode"
}
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"statusCode": 401,
"message": "Invalid or expired API key"
}
Exemplo completo
curl -X POST "https://signer.vcc-service.com/v1/envelopes" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Contrato de Serviços",
"signingMode": "sequential",
"externalCode": "CONT-2025-001",
"document": {
"url": "https://exemplo.com/contrato.pdf",
"filename": "contrato.pdf"
},
"signers": [
{
"name": "João Silva",
"email": "joao@empresa.com",
"cpf": "12345678901",
"phoneCountryCode": "55",
"phoneNumber": "11987654321"
},
{
"name": "Maria Santos",
"email": "maria@empresa.com",
"cpf": "98765432100",
"phoneCountryCode": "55",
"phoneNumber": "11912345678"
}
],
"dueDate": "2025-12-31T23:59:59Z",
"urlOrigin": "https://seu-app.com",
"urlNotification": "https://seu-backend.com/webhooks/envelope-status"
}'
Próximas etapas
- Compartilhe os links: Envie cada
signUrlpara o signatário correspondente (ou extraia osessionTokene construa seu próprio link). - Signatário assina: Veja
GET /v1/sign/:sessionTokenpara entender o fluxo do signatário. - Acompanhe o status: Use
GET /v1/envelopes/:uuidpara verificar mudanças de estado.
⌘I
Criar envelope
curl --request POST \
--url https://api.valid.com/v1/envelopes \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"title": "<string>",
"signingMode": {},
"document": {
"url": "<string>",
"content": "<string>",
"filename": "<string>"
},
"signers": [
{
"name": "<string>",
"email": "<string>",
"cpf": "<string>",
"phoneCountryCode": "<string>",
"phoneNumber": "<string>",
"queueOrder": 123,
"livenessSessionId": "<string>"
}
],
"externalCode": "<string>",
"templateId": "<string>",
"dueDate": "<string>",
"urlOrigin": "<string>",
"urlNotification": "<string>",
"auth": {
"mfaTransactionId": "<string>"
}
}
'import requests
url = "https://api.valid.com/v1/envelopes"
payload = {
"title": "<string>",
"signingMode": {},
"document": {
"url": "<string>",
"content": "<string>",
"filename": "<string>"
},
"signers": [
{
"name": "<string>",
"email": "<string>",
"cpf": "<string>",
"phoneCountryCode": "<string>",
"phoneNumber": "<string>",
"queueOrder": 123,
"livenessSessionId": "<string>"
}
],
"externalCode": "<string>",
"templateId": "<string>",
"dueDate": "<string>",
"urlOrigin": "<string>",
"urlNotification": "<string>",
"auth": { "mfaTransactionId": "<string>" }
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
title: '<string>',
signingMode: {},
document: {url: '<string>', content: '<string>', filename: '<string>'},
signers: [
{
name: '<string>',
email: '<string>',
cpf: '<string>',
phoneCountryCode: '<string>',
phoneNumber: '<string>',
queueOrder: 123,
livenessSessionId: '<string>'
}
],
externalCode: '<string>',
templateId: '<string>',
dueDate: '<string>',
urlOrigin: '<string>',
urlNotification: '<string>',
auth: {mfaTransactionId: '<string>'}
})
};
fetch('https://api.valid.com/v1/envelopes', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.valid.com/v1/envelopes",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'title' => '<string>',
'signingMode' => [
],
'document' => [
'url' => '<string>',
'content' => '<string>',
'filename' => '<string>'
],
'signers' => [
[
'name' => '<string>',
'email' => '<string>',
'cpf' => '<string>',
'phoneCountryCode' => '<string>',
'phoneNumber' => '<string>',
'queueOrder' => 123,
'livenessSessionId' => '<string>'
]
],
'externalCode' => '<string>',
'templateId' => '<string>',
'dueDate' => '<string>',
'urlOrigin' => '<string>',
'urlNotification' => '<string>',
'auth' => [
'mfaTransactionId' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.valid.com/v1/envelopes"
payload := strings.NewReader("{\n \"title\": \"<string>\",\n \"signingMode\": {},\n \"document\": {\n \"url\": \"<string>\",\n \"content\": \"<string>\",\n \"filename\": \"<string>\"\n },\n \"signers\": [\n {\n \"name\": \"<string>\",\n \"email\": \"<string>\",\n \"cpf\": \"<string>\",\n \"phoneCountryCode\": \"<string>\",\n \"phoneNumber\": \"<string>\",\n \"queueOrder\": 123,\n \"livenessSessionId\": \"<string>\"\n }\n ],\n \"externalCode\": \"<string>\",\n \"templateId\": \"<string>\",\n \"dueDate\": \"<string>\",\n \"urlOrigin\": \"<string>\",\n \"urlNotification\": \"<string>\",\n \"auth\": {\n \"mfaTransactionId\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.valid.com/v1/envelopes")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"title\": \"<string>\",\n \"signingMode\": {},\n \"document\": {\n \"url\": \"<string>\",\n \"content\": \"<string>\",\n \"filename\": \"<string>\"\n },\n \"signers\": [\n {\n \"name\": \"<string>\",\n \"email\": \"<string>\",\n \"cpf\": \"<string>\",\n \"phoneCountryCode\": \"<string>\",\n \"phoneNumber\": \"<string>\",\n \"queueOrder\": 123,\n \"livenessSessionId\": \"<string>\"\n }\n ],\n \"externalCode\": \"<string>\",\n \"templateId\": \"<string>\",\n \"dueDate\": \"<string>\",\n \"urlOrigin\": \"<string>\",\n \"urlNotification\": \"<string>\",\n \"auth\": {\n \"mfaTransactionId\": \"<string>\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.valid.com/v1/envelopes")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"title\": \"<string>\",\n \"signingMode\": {},\n \"document\": {\n \"url\": \"<string>\",\n \"content\": \"<string>\",\n \"filename\": \"<string>\"\n },\n \"signers\": [\n {\n \"name\": \"<string>\",\n \"email\": \"<string>\",\n \"cpf\": \"<string>\",\n \"phoneCountryCode\": \"<string>\",\n \"phoneNumber\": \"<string>\",\n \"queueOrder\": 123,\n \"livenessSessionId\": \"<string>\"\n }\n ],\n \"externalCode\": \"<string>\",\n \"templateId\": \"<string>\",\n \"dueDate\": \"<string>\",\n \"urlOrigin\": \"<string>\",\n \"urlNotification\": \"<string>\",\n \"auth\": {\n \"mfaTransactionId\": \"<string>\"\n }\n}"
response = http.request(request)
puts response.read_bodyHTTP/1.1 201 Created
Content-Type: application/json
{
"envelopeUuid": "550e8400-e29b-41d4-a716-446655440000",
"fileUuid": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
"signers": [
{
"signerUuid": "6ba7b811-9dad-11d1-80b4-00c04fd430c8",
"sessionToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"signUrl": "https://seu-app.com/sign?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
},
{
"signerUuid": "6ba7b812-9dad-11d1-80b4-00c04fd430c8",
"sessionToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"signUrl": "https://seu-app.com/sign?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
],
"state": "CREATED",
"createdAt": "2025-07-27T10:30:00.000Z"
}
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"statusCode": 400,
"message": "Unique constraint violation on field(s): externalCode"
}
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"statusCode": 401,
"message": "Invalid or expired API key"
}