Common use cases
- Send internal notifications when documents are signed
- Update your database when signing requests are completed
- Trigger downstream workflows (invoicing, provisioning, etc.)
- Track signing request status changes in real-time
Event types
Firma sends the following event types:Signing Request Events
signing_request.created- New signing request createdsigning_request.sent- Signing request sent to recipientssigning_request.viewed- Recipient viewed the documentsigning_request.completed- All recipients finished signingsigning_request.expired- Signing request expiredsigning_request.cancelled- Signing request was cancelledsigning_request.updated- Signing request metadata updatedsigning_request.certificate.generated- Signing certificate generatedsigning_request.reminder.sent- Reminder sent to recipientssigning_request.field.filled- A field was filled by a recipientsigning_request.document.updated- Document was updated
Recipient Events
signing_request.recipient.added- Recipient added to signing requestsigning_request.recipient.signed- Recipient completed signingsigning_request.recipient.declined- Recipient declined to signsigning_request.recipient.updated- Recipient details updatedsigning_request.recipient.identity_changed- Recipient changed their identity (name, company, etc.) during signing
Template Events
template.created- New template createdtemplate.updated- Template modifiedtemplate.deleted- Template deletedtemplate.field.added- Field added to templatetemplate.used- Template used to create a signing request
Workspace Events
workspace.created- New workspace createdworkspace.updated- Workspace modifiedworkspace.deleted- Workspace deleted
Domain Events
domain.verified- Domain verified successfullydomain.verification.failed- Domain verification failed
Creating a webhook
Create webhooks via the API or dashboard:Your webhook URL must use HTTPS and respond within 5 seconds. Firma will send a test event during creation to verify the endpoint.
Webhook payload structure
All webhook events follow this standard structure:Security: Signature verification (Required)
Firma signs all webhook requests using HMAC SHA-256. Your webhook endpoint receives these headers:X-Firma-Signature- HMAC signature using current signing secretX-Firma-Signature-Old- HMAC signature using previous secret (during 24-hour rotation grace period)X-Firma-Event- Event type (e.g.,signing_request.completed)X-Firma-Delivery- Unique delivery attempt ID
Signature format
Firma uses a timestamped signature header:- Header:
X-Firma-Signature: t=1707500000,v1=abc123def456... t= Unix timestamp (seconds) when the signature was generatedv1= HMAC-SHA256 hex digest- Signed payload format:
{timestamp}.{json_body}
Get your signing secret
- Navigate to your Firma dashboard
- View webhook details to retrieve the signing secret
- Store the secret securely (environment variable or secrets manager)
Verification example — Node.js (Express)
Verification example — Python (Flask)
Handling secret rotation
When you rotate your webhook signing secret:- Firma generates a new secret
- For 24 hours, Firma sends both signatures:
X-Firma-Signature(new secret)X-Firma-Signature-Old(previous secret)
- After 24 hours, only
X-Firma-Signatureis sent
X-Firma-Signature first. If verification fails and X-Firma-Signature-Old exists, verify against the old secret.
Retry behavior
Firma automatically retries failed webhook deliveries:- Retry schedule: 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours
- Total attempts: Up to 5 retries per event
- Timeout: Your endpoint must respond within 5 seconds
- Success: Any 2xx status code indicates success
- Auto-disable: After 50 consecutive failures, the webhook is automatically disabled
Idempotency
Always handle duplicate events using the eventid:
Monitoring webhook health
Monitor your webhook’s health by checking the webhook details:consecutive_failures- Number of consecutive failed deliverieslast_failure_at- Timestamp of most recent failureenabled- Whether webhook is active (auto-disabled after 50 failures)last_success_at- Timestamp of most recent successful delivery
Rate limit: GET webhook requests support 60 requests per minute per API key.
Troubleshooting
Common issues
401 Unauthorized / Invalid signature- Verify you’re using the correct signing secret
- Check that you’re hashing the raw request body (not parsed JSON)
- Ensure you’re using HMAC SHA-256, not other hash algorithms
- Respond with 200 immediately, process asynchronously
- Check your endpoint responds within 5 seconds
- Use background jobs/queues for heavy processing
- Implement idempotency using the event
id - Store processed event IDs in your database
- Check
consecutive_failuresand recent event logs - Fix endpoint issues, then re-enable webhook via API or dashboard
Testing webhooks locally
Use a tunnel service like ngrok for local development:Production checklist
- Verify HMAC signatures on all webhook requests
- Handle signature rotation (check both
X-Firma-SignatureandX-Firma-Signature-Old) - Respond with 200 within 5 seconds
- Process events asynchronously (queues/background jobs)
- Implement idempotency using the event
id - Store signing secret securely (env var or secrets manager)
- Monitor
consecutive_failuresmetric via GET webhook endpoint - Set up alerts for webhook failures
- Log all webhook events for debugging
- Test with all subscribed event types
- Stay within rate limits (See Rate Limit Guide)
Next steps
- Create a webhook via API
- Test your webhook before going live
- Update webhook settings as needed