Webhooks
Receive events from your organization on Autentique through your webhook endpoints.
Why use Webhooks?
When building integrations with Autentique, it can be helpful for your applications to receive events as they happen in your organizations.
To start receiving webhooks, you need to register your endpoints in the dashboard. After registration, Autentique can send real-time event data to your webhook endpoints whenever events occur in your organization. Autentique uses HTTPS to send these events as a JSON payload, which includes an Event object.
Receiving webhook events is especially useful for tracking asynchronous events, such as when a signer signs a document, when a document is completed, or when actions related to document processing are finished.
Event Object
The following event shows an update to the name of a document.
{
"id": "MXwyMWZiY2VjOS1lMWI1LTRkY2EtYWZiYi0wMjIwNjFlOWVhODg=",
"object": "webhook",
"name": "test endpoint 2",
"format": "json",
"url": "https://this-url-doesn't-exist.autentique.com.br/webhooks",
"event": {
"id": "21fbcec9-e1b5-4dca-afbb-022061e9ea88",
"object": "event",
"organization": 1,
"type": "document.updated",
"data": {
"object": {
"id": "89c7d2ab31f9f5a13b3d20ecf53319af387e54d240ae7be993",
"name": "Updated name",
"refusable": true,
"stop_on_rejected": true,
"qualified": false,
"ignore_cpf": true,
"sortable": false,
"is_blocked": false,
"sandbox": 0,
"scrolling_required": 0,
"locale": {
"country": "BR",
"language": "pt-BR",
"timezone": "America/Sao_Paulo",
"date_format": "d/m/Y"
},
"created_at": "2024-08-26T18:02:26.000000Z",
"updated_at": "2024-08-26T18:03:27.000000Z",
"deleted_at": null,
"deadline_at": null,
"lifecycle_in": "2029-08-26T03:00:00.000000Z",
"email_template_id": null,
"expiration_at": null,
"notify_in": null,
"reminder": null,
"message": "I changed this message too",
"reply_to": null,
"signatures_count": 1,
"signed_count": 0,
"rejected_count": 0,
"object": "document",
"is_from_api": false,
"signatures": [
{
"public_id": "7f25d72b-6155-11ef-9dae-0242ac170004",
"name": "Felipe Autentique",
"company": null,
"email": "[email protected]",
"phone": null,
"cpf": "123.456.789-09",
"birthday": "1979-08-13",
"action": "Sign",
"viewed": "2024-08-26T18:02:27.000000Z",
"signed": null,
"rejected": null,
"validation_unapproved": null,
"validation_approved": null,
"validation_rejected": null,
"created_at": "2024-08-26T18:02:26.000000Z"
}
],
"author": {
"name": "Felipe Autentique",
"company": null,
"email": "[email protected]",
"phone": null,
"cpf": "123.456.789-09",
"birthday": "1979-08-13"
},
"files": {
"original": "https://storage.googleapis.com/f77/6e7a1fadeed9c56cf037b43a9cd0e6d1/o9baEgHHv1Tuf7AZttDqdL8vK68eUw56PaYXzRqV.original.pdf",
"signed": "https://painel.autentique.com.br/documentos/89c7d2ab31f95a13b3d20ecf53319af387e54d240ae7be993/assinado.pdf"
}
},
"previous_attributes": {
"name": "teste",
"refusable": false,
"updated_at": "2024-08-26T18:02:26.000000Z",
"message": "Please access and electronically sign the document by clicking the button above.",
"ignore_cpf": false
}
},
"created_at": "2024-08-26T18:03:27.387179Z"
}
}Type of Event
All webhooks sent are related to an event of a specific resource, which is indicated by the type field. Similarly, the data.object field corresponds to the resource of the event.
Data Object and previous_attributes
For *.updated events, the event payload includes the data.previous_attributes field, which allows you to inspect what changed in the related resource. In the example above, the document.updated event shows that the document previously had the name "teste".
How to Begin
Add your endpoint in the Autentique Developer Panel, selecting the events you want to listen to.
Set up an HTTPS function that accepts webhook requests with a POST method.
Process POST requests with a JSON payload consisting of an event object.
Quickly return a success status code (2xx) before any complex logic that may cause a timeout. For example, you need to return a 200 response before updating document data in your system.
If desired, you can verify that events are sent by Autentique before performing any manipulation with the payload.
Examples of endpoint:
$payload = @file_get_contents('php://input');
$webhook = null;
//Before processing the payload
try {
$webhook = json_decode($payload, true);
} catch(\UnexpectedValueException $e) {
// Invalid payload
http_response_code(400);
exit();
}
$event = $webhook['event'];
// Process the event
switch ($event['type']) {
case 'document.created':
$document = $event['data']['object']; // Contains a document object,
// define a method to process the document
// handleDocumentCreated($document);
break;
case 'signature.accepted':
$signature = $event['data']['object']; // Contains a signature object
// Define a method to process the signature
// handleSignatureAccepted($signature);
break;
// ... process other types of events
default:
echo 'Received unknown event type '.$event['type'];
}
http_response_code(200);package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
type WebhookPayload struct {
ID string `json:"id"`
Object string `json:"object"`
Name string `json:"name"`
Format string `json:"format"`
URL string `json:"url"`
Event Event `json:"event"`
}
type Event struct {
ID string `json:"id"`
Object string `json:"object"`
Organization int `json:"organization"`
Type string `json:"type"`
Data map[string]interface{} `json:"data"`
CreatedAt string `json:"created_at"`
}
func webhookHandler(w http.ResponseWriter, r *http.Request) {
payload, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, "Invalid payload", http.StatusBadRequest)
return
}
var webhook WebhookPayload
if err := json.Unmarshal(payload, &webhook); err != nil {
http.Error(w, "Invalid payload", http.StatusBadRequest)
return
}
event := webhook.Event
eventData := event.Data
eventObject := eventData["object"].(map[string]interface{})
switch event.Type {
case "document.created":
// handleDocumentCreated(eventObject)
fmt.Println("Document created:", eventObject)
case "document.updated":
// handleDocumentUpdated(eventObject)
fmt.Println("Document updated:", eventObject)
case "signature.accepted":
// handleSignatureAccepted(eventObject)
fmt.Println("Signature accepted:", eventObject)
default:
fmt.Printf("Received unknown event type: %s\n", event.Type)
}
w.WriteHeader(http.StatusOK)
}
func main() {
http.HandleFunc("/webhook", webhookHandler)
http.ListenAndServe(":8080", nil)
}import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatus;
import java.util.Map;
@RestController
@RequestMapping("/webhook")
public class WebhookController {
@PostMapping
public ResponseEntity<String> handleWebhook(@RequestBody Map<String, Object> payload) {
try {
Map<String, Object> event = (Map<String, Object>) payload.get("event");
String eventType = (String) event.get("type");
Map<String, Object> data = (Map<String, Object>) event.get("data");
Map<String, Object> eventObject = (Map<String, Object>) data.get("object");
switch (eventType) {
case "document.created":
// handleDocumentCreated(eventObject);
System.out.println("Document created: " + eventObject);
break;
case "document.updated":
// handleDocumentUpdated(eventObject);
System.out.println("Document updated: " + eventObject);
break;
case "signature.accepted":
// handleSignatureAccepted(eventObject);
System.out.println("Signature accepted: " + eventObject);
break;
default:
System.out.println("Received unknown event type: " + eventType);
}
return new ResponseEntity<>("Webhook received", HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>("Invalid payload", HttpStatus.BAD_REQUEST);
}
}
}const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
app.post('/webhook', (req, res) => {
try {
const payload = req.body;
const event = payload.event;
const eventType = event.type;
const eventData = event.data;
const eventObject = eventData.object;
switch (eventType) {
case 'document.created':
// handleDocumentCreated(eventObject);
console.log("Document created:", eventObject);
break;
case 'document.updated':
// handleDocumentUpdated(eventObject);
console.log("Document updated:", eventObject);
break;
case 'signature.accepted':
// handleSignatureAccepted(eventObject);
console.log("Signature accepted:", eventObject);
break;
default:
console.log(`Received unknown event type: ${eventType}`);
}
res.status(200).send('Webhook received');
} catch (error) {
res.status(400).send('Invalid payload');
}
});
app.listen(8080, () => {
console.log('Server is running on port 8080');
});from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def webhook():
try:
payload = request.json
event = payload['event']
event_type = event['type']
event_data = event['data']
event_object = event_data['object']
if event_type == 'document.created':
# handle_document_created(event_object)
print("Document created:", event_object)
elif event_type == 'document.updated':
# handle_document_updated(event_object)
print("Document updated:", event_object)
elif event_type == 'signature.accepted':
# handle_signature_accepted(event_object)
print("Signature accepted:", event_object)
else:
print(f"Received unknown event type: {event_type}")
return jsonify({"status": "success"}), 200
except Exception as e:
return jsonify({"error": "Invalid payload"}), 400
if __name__ == '__main__':
app.run(port=8080)class WebhooksController < ApplicationController
skip_before_action :verify_authenticity_token
def webhook
begin
payload = JSON.parse(request.body.read)
event = payload['event']
event_type = event['type']
event_data = event['data']
event_object = event_data['object']
case event_type
when 'document.created'
# handle_document_created(event_object)
puts "Document created: #{event_object}"
when 'document.updated'
# handle_document_updated(event_object)
puts "Document updated: #{event_object}"
when 'signature.accepted'
# handle_signature_accepted(event_object)
puts "Signature accepted: #{event_object}"
else
puts "Received unknown event type: #{event_type}"
end
render json: { status: 'success' }, status: :ok
rescue => e
render json: { error: 'Invalid payload' }, status: :bad_request
end
end
endEvent Order:
Autentique does not guarantee the delivery of events in the order they were generated. For example, the creation of a document may generate the following events:
document.updateddocument.createdsignature.createdsignature.viewed(if the author is a signer and in the document creation)
Your endpoint should not expect the delivery of these events in this order and should process them accordingly. You can also use the API to retrieve missing objects (for example, you can get signatures, folders, and organizations using the information from document.created if you receive that event first).
Best practices for Webhook usage
Review these best practices to ensure that your webhooks remain secure and work well with your integration.
Quickly Return a 2xx Response
The endpoint must quickly return a success status code (2xx) before any complex logic that could cause a timeout. For example, when receiving a document.finished event, you need to return a 200 response before updating the document data in your system.
Manage Events Asynchronously
Set up the handler to process received events with an asynchronous queue. Synchronously processing events can cause scalability issues, especially during peak webhook delivery times.
Using Queues: Use asynchronous queues to process events concurrently at a rate your system can handle.
Handle Duplicate Events
Occasionally, webhook endpoints may receive the same event more than once. To protect against receiving duplicate events:
Store Event IDs: Keep track of the event IDs you have processed and ignore already registered events.
Duplicate Identification: In some cases, two webhooks of the same event may be sent to your endpoint. Use the object ID in
event.dataalong with theevent.type.
Listen Only to Required Event Types
Configure your webhook endpoints to receive only the event types required by your integration. Listening for additional or all events can overload your server and is not recommended.
Event Configuration: You can change the events that a webhook endpoint receives in the Dashboard.
CSRF Protection-Free Webhook Route
If you're using frameworks like Rails, Django, or Laravel, your site may automatically check if each POST request contains a CSRF token. This is an important security feature that protects against cross-site request forgery attacks but may prevent your site from processing legitimate webhook events. To resolve this, you can exempt the webhook route from CSRF protection.
<?php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Middleware;
# On Laravel,
# you can add the webhook route as an exception
# middleware VerifyCsrfToken on the file `bootstrap/app.php`
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
channels: __DIR__.'/../routes/channels.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
$middleware->validateCsrfTokens(except: [
'webhooks/*' // <-- remove the validation route
]);
})->create();from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
# No Django, você pode isentar uma view específica
# da verificação CSRF sando o decorator @csrf_exempt
@csrf_exempt
@require_POST
def webhook_endpoint(request):
# Processar o webhook# No Rails, você pode isentar uma ação específica do protect_from_forgery
class WebhooksController < ApplicationController
protect_from_forgery except: :webhook
def webhook
# Process webhook data in `params`
end
endVerify if Events Are Sent by Autentique
To ensure that the events you receive truly come from Autentique, it's crucial to validate the HMAC signatures present in the webhook headers. Here are some examples of how to do this:
public function verifySignature(array $headers, string $payload, string $secret): bool
{
if (!isset($headers['x-autentique-signature'])) {
return false;
}
$signature = $headers['x-autentique-signature'];
$calculatedSignature = hash_hmac('sha256', $payload, $secret);
return hash_equals($calculatedSignature, $signature);
}const crypto = require('crypto');
function verifySignature(headers, payload, secret) {
const signature = headers['x-autentique-signature'];
if (!signature) {
return false;
}
const payloadJson = JSON.stringify(payload);
const calculatedSignature = crypto.createHmac('sha256', secret)
.update(payloadJson)
.digest('hex');
return crypto.timingSafeEqual(Buffer.from(calculatedSignature), Buffer.from(signature));
}import hmac
import hashlib
import json
def verify_signature(headers, payload, secret):
signature = headers.get('X-Autentique-Signature')
if not signature:
return False
payload_json = json.dumps(payload, separators=(',', ':')).encode('utf-8')
calculated_signature = hmac.new(secret.encode('utf-8'), payload_json, hashlib.sha256).hexdigest()
return hmac.compare_digest(calculated_signature, signature)require 'json'
require 'openssl'
require 'active_support/security_utils'
def verify_signature(headers, payload, secret)
signature = headers['X-Autentique-Signature']
return false unless signature
payload_json = payload.to_json
calculated_signature = OpenSSL::HMAC.hexdigest('SHA256', secret, payload_json)
ActiveSupport::SecurityUtils.secure_compare(calculated_signature, signature)
endimport javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
public class WebhookVerifier {
private String secret;
public WebhookVerifier(String secret) {
this.secret = secret;
}
public boolean verifySignature(String headerSignature, String payload) throws Exception {
String calculatedSignature = calculateSignature(payload);
return MessageDigest.isEqual(calculatedSignature.getBytes(StandardCharsets.UTF_8),
headerSignature.getBytes(StandardCharsets.UTF_8));
}
private String calculateSignature(String payload) throws Exception {
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
sha256_HMAC.init(secret_key);
byte[] hash = sha256_HMAC.doFinal(payload.getBytes(StandardCharsets.UTF_8));
return bytesToHex(hash);
}
private String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder(2 * bytes.length);
for (byte b : bytes) {
String hex = Integer.toHexString(0xff & b);
if(hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
}
}
Document Object
{
"id": "MXwwNmMzOGYyMS0zNjhjLTQyNmItOTM2Ny1iMzNhNzQ2NmY5MGM=",
"object": "webhook",
"name": "docs",
"format": "json",
"url": "https://this-url-does't-exist.autentique.com.br/webhooks",
"event": {
"id": "06c38f21-368c-426b-9367-b33a7466f90c",
"object": "event",
"organization": 1,
"type": "document.updated",
"data": {
"id": "1cf7d351a96696fdf450ba893f6720463599dd8c34e0aeda803d",
"object": "document",
"name": "test sddd",
"message": "Please access and electronically sign the document by clicking the button above.",
"refusable": true,
"author": {
"name": "Felipe Autentique",
"company": null,
"email": "[email protected]",
"phone": null,
"cpf": "03351152094",
"birthday": "2005-01-24"
},
"signatures": [
{
"public_id": "92b49dbe-df08-11ef-903c-0242ac140004",
"object": "signature",
"user": {
"name": "Felipe Autentique",
"company": null,
"email": "[email protected]",
"phone": null,
"cpf": "03351152094",
"birthday": "2005-01-24"
},
"document": "1cf7d351a96696450ba893f6720463599dd8c34e0aeda803d",
"action": "Sign",
"viewed": "2025-01-30T12:49:01.000000Z",
"signed": null,
"rejected": null,
"biometric_unapproved": null,
"biometric_approved": null,
"biometric_rejected": null,
"events": [],
"created_at": "2025-01-30T12:48:58.000000Z"
},
{
"public_id": "93115640-df08-11ef-903c-0242ac140004",
"object": "signature",
"user": {
"name": "Mateus Autentique",
"company": null,
"email": "[email protected]",
"phone": null,
"cpf": "189.614.966-03",
"birthday": "1979-04-19"
},
"document": "1cf7d351a96696450ba893f6720463599dd8c34e0aeda803d",
"action": "Sign",
"viewed": null,
"signed": null,
"rejected": null,
"biometric_unapproved": null,
"biometric_approved": null,
"biometric_rejected": null,
"events": [],
"created_at": "2025-01-30T12:48:59.000000Z"
}
],
"stop_on_rejected": true,
"qualified": false,
"ignore_cpf": false,
"sortable": false,
"is_blocked": false,
"sandbox": false,
"api": false,
"scrolling_required": false,
"locale": {
"country": "BR",
"language": "pt-BR",
"timezone": "America/Sao_Paulo",
"date_format": "d/m/Y"
},
"email_template_id": null,
"expiration_at": null,
"notify_in": null,
"reminder": null,
"reply_to": null,
"signatures_count": 2,
"signed_count": 0,
"rejected_count": 0,
"files": {
"original": "https://storage.googleapis.com/f77-dev/9be6ab49679f844230682d7335230029/3jTmKFWps4mIaMByzrj7zmFywm4a6LYIjUDfNhZ7.original.pdf",
"signed": "https://painel.autentique.com.br/documentos/1cf7d351a96696450ba893f6720463599dd8c34e0aeda803d/assinado.pdf"
},
"created_at": "2025-01-30T12:48:58.000000Z",
"updated_at": "2025-01-30T12:49:56.000000Z",
"deleted_at": null,
"deadline_at": null,
"lifecycle_in": "2030-01-30T03:00:00.000000Z"
},
"previous_attributes": {
"signatures_count": 3
},
"created_at": "2025-01-30T12:49:56.342822Z"
}
}Signature Object
{
"id": "MjV8OTQ4OGNlMTEtNzBiZi00ZGI3LTg1OGItZDc2ZjFkZDI5MGRj",
"object": "webhook",
"name": "sig",
"format": "json",
"url": "https://this-url-does't-exist.autentique.com.br/webhooks",
"event": {
"id": "9488ce11-70bf-4db7-858b-d76f1dd290dc",
"object": "event",
"organization": 1519203,
"type": "signature.accepted",
"data": {
"public_id": "f8911dcd-dfcd-11ef-9465-42010a2b610e",
"object": "signature",
"user": {
"name": "Felipe Autentique",
"company": null,
"email": "[email protected]",
"phone": null,
"cpf": "03351152094",
"birthday": "2002-03-04"
},
"mail": {
"sent": "2025-04-09 09:21:35",
"opened": "2025-04-09 09:25:35",
"refused": null,
"delivered": null,
"reason": null
},
"document": "f48a8b465d02dd87559e08f06c41e3b6d548c4d7ad835eb0f",
"action": "Sign",
"viewed": "2025-01-31T12:22:01.000000Z",
"signed": "2025-01-31T12:22:30.000000Z",
"rejected": null,
"biometric_unapproved": null,
"biometric_approved": null,
"biometric_rejected": null,
"events": [
{
"type": "viewed", // Can be: viewed, accepted, rejected, biometric_approved, biometric_rejected, biometric_unapproved
"document": "f48a8b465d02dd87559e08f06c41e3b6d548c4d7ad835eb0f",
"user": {
"uuid": "ebcca9bc391a60336e777a23d32ada4410fe8b",
"name": null,
"email": "[email protected]",
"cpf": null,
"birthday": null
},
"geolocation": {
"country": "Brazil",
"countryISO": "BR",
"state": "Rio Grande do Sul",
"stateISO": "RS",
"city": "Erechim",
"zipcode": "99704094",
"latitude": -27.6767,
"longitude": -52.2559
},
"reason": null,
"ip": "192.168.65.1",
"port": 29317,
"created_at": "2025-03-18T16:22:49.000000Z"
},
...
]
"created_at": "2025-01-31T12:22:00.000000Z"
},
"previous_attributes": [],
"created_at": "2025-01-31T12:22:30.495056Z"
}
}Member Object
{
"id": "MjZ8NzY1MjY1NTAtNzg3YS00YjU3LTk2MWYtN2EwMThlOTFkOGRj",
"object": "webhook",
"name": "memb",
"format": "json",
"url": "https://this-url-does't-exist.autentique.com.br/webhooks",
"event": {
"id": "76526550-787a-4b57-961f-7a018e91d8dc",
"object": "event",
"organization": 1519203,
"type": "member.created",
"data": {
"user": {
"name": "Felipe Autentique",
"company": null,
"email": "[email protected]",
"phone": null,
"cpf": "03351152094",
"birthday": "2002-03-04"
},
"group": {
"uuid": "96d50d5a-b69c-4c84-b2d9-3f37c227cebf",
"name": "Administrador",
"organization": 1519203,
"permissions": {
"overwrite_permissions": true,
"create_documents": true,
"sign_documents": true,
"delete_documents": true,
"archive_documents": true,
"view_documents_gr": true,
"view_folders_gr": true,
"actions_folders_gr": true,
"actions_documents_gr": true,
"actions_templates_gr": true,
"actions_members_oz": true,
"actions_groups_oz": true,
"actions_webhooks_oz": true,
"view_documents_oz": true,
"view_member_documents_oz": true,
"view_group_documents_oz": true,
"view_folders_oz": true,
"view_member_folders_oz": true,
"view_group_folders_oz": true,
"actions_documents_oz": true,
"view_invoices_oz": true,
"change_plan_oz": true,
"actions_folders_oz": true,
"change_appearances_oz": true,
"change_whitelabel_oz": false,
"enterprise_access": false
},
"configs": {
"geral": false,
"sobrescrever_modelos": false,
"overwrite_template_group": false,
"sobrescrever_organizacao": false
}
},
"permissions": {
"overwrite_permissions": false,
"create_documents": true,
"sign_documents": true,
"delete_documents": true,
"archive_documents": true,
"view_documents_gr": true,
"view_folders_gr": true,
"actions_folders_gr": false,
"actions_documents_gr": false,
"actions_templates_gr": false,
"actions_members_oz": false,
"actions_groups_oz": false,
"actions_webhooks_oz": false,
"view_documents_oz": true,
"view_member_documents_oz": false,
"view_group_documents_oz": false,
"view_folders_oz": true,
"view_member_folders_oz": false,
"view_group_folders_oz": false,
"actions_documents_oz": false,
"view_invoices_oz": true,
"change_plan_oz": false,
"actions_folders_oz": false,
"change_appearances_oz": false,
"change_whitelabel_oz": false,
"enterprise_access": false
}
},
"previous_attributes": [],
"created_at": "2025-01-31T12:24:48.477885Z"
}
}Types of events
Autentique's API uses specific events triggered when certain actions occur.
All webhooks sent are related to an event of a specific resource, defined by the "type" field. The content of the webhooks only varies between different event types.
These events are classified into three main categories
Document: Events related to the creation, modification, and completion of documents.
Signature: Events related to the signature flow in documents.
Member: Events related to the members of the organization.
Document Events
document.created
Triggered when a new document is created in the application.
document.updated
Triggered when an existing document is updated or edited (e.g., changes to additional settings).
document.deleted
Triggered when a document is permanently deleted from the application.
document.finished
Triggered when all signatures or steps associated with the document are successfully completed.
Signature Events
signature.created
Triggered when a new signature request is created for a signer in a document.
signature.updated
Triggered when there is a change or update to the signature request, such as a change in conditions or the signature status (e.g., placing an invisible signature).
signature.deleted
Triggered when a pending signer is removed from the document.
signature.viewed
Triggered when the signer views the document for the first time, indicating they accessed the content but have not taken any further action.
signature.accepted
Triggered when the signer successfully completes the signature process.
signature.rejected
Triggered when the signer explicitly declines the signature.
signature.biometric_approved
Triggered when the signer's biometric verification is successfully validated by the document creator or through automatic validation.
signature.biometric_unapproved
Triggered when a document's signature has pending checks, such as manual validation that remains in an approval state and needs to be completed by the document owner.
signature.biometric_rejected
Triggered when the biometric verification is rejected by the document author.
Member Events
member.created
Triggered when a new member joins the organization
member.deleted
Triggered when a member is removed from the organization
Webhooks that failed
When a webhook is sent but not successfully received by the registered endpoint, it is added to the list of undelivered webhooks in the error log, available on our webhook endpoint registration page.
Webhooks on this list will undergo up to three additional delivery attempts, made after 60, 120, and 300 seconds. If all attempts fail, the event will remain on the list for up to 14 days.
Last updated
Was this helpful?