@dereekb/zoho 13.3.0 → 13.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/nestjs/docs/zoho-sign-webhooks.md +202 -0
- package/nestjs/index.cjs.js +972 -130
- package/nestjs/index.esm.js +967 -133
- package/nestjs/package.json +8 -6
- package/nestjs/src/lib/sign/index.d.ts +1 -0
- package/nestjs/src/lib/sign/webhook/index.d.ts +6 -0
- package/nestjs/src/lib/sign/webhook/webhook.zoho.sign.config.d.ts +11 -0
- package/nestjs/src/lib/sign/webhook/webhook.zoho.sign.controller.d.ts +8 -0
- package/nestjs/src/lib/sign/webhook/webhook.zoho.sign.d.ts +124 -0
- package/nestjs/src/lib/sign/webhook/webhook.zoho.sign.module.d.ts +13 -0
- package/nestjs/src/lib/sign/webhook/webhook.zoho.sign.service.d.ts +16 -0
- package/nestjs/src/lib/sign/webhook/webhook.zoho.sign.verify.d.ts +45 -0
- package/package.json +7 -5
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# Zoho Sign Webhooks
|
|
2
|
+
|
|
3
|
+
This guide covers configuring Zoho Sign webhooks in the Zoho Sign dashboard and wiring up the `ZohoSignWebhookModule` in your NestJS application.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Create a Webhook in Zoho Sign
|
|
8
|
+
|
|
9
|
+
Navigate to **Settings > Developer Settings > Webhooks** in Zoho Sign, or go directly to `https://sign.zoho.com/zs/<YOUR_ORG_ID>#/devspace/webhooks/new`.
|
|
10
|
+
|
|
11
|
+
### Callback URL
|
|
12
|
+
|
|
13
|
+
Enter the public URL of your webhook endpoint. The NestJS controller registers at `/webhook/zoho/sign`, so the full URL will be something like:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
https://your-api-domain.com/api/webhook/zoho/sign
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Use the **"Test Url"** button to verify Zoho Sign can reach your endpoint.
|
|
20
|
+
|
|
21
|
+
### Name
|
|
22
|
+
|
|
23
|
+
Give the webhook a descriptive name (e.g. "Production API Webhook").
|
|
24
|
+
|
|
25
|
+
### Security Settings (HMAC)
|
|
26
|
+
|
|
27
|
+
Check **"Enable HMAC signature"** and either enter your own secret key or click **"Generate"** to create one.
|
|
28
|
+
|
|
29
|
+
> **Important:** Once saved, the secret key cannot be retrieved from Zoho Sign. Copy it immediately and store it in your environment variables as `ZOHO_SIGN_WEBHOOK_SECRET_TOKEN`.
|
|
30
|
+
|
|
31
|
+
When HMAC is enabled, Zoho Sign includes an `X-ZS-WEBHOOK-SIGNATURE` header on every webhook request. The signature is computed as `base64(HMAC-SHA256(payload, secret_key))`. The `ZohoSignWebhookModule` verifies this automatically.
|
|
32
|
+
|
|
33
|
+
### Callback Trigger Criteria (Optional)
|
|
34
|
+
|
|
35
|
+
You can optionally filter which documents trigger callbacks. For example, you can set criteria like "Document name Contains NDA" so that only matching documents fire the webhook. If no criteria is set, callbacks are triggered for all events selected below.
|
|
36
|
+
|
|
37
|
+
### Callback Events
|
|
38
|
+
|
|
39
|
+
Select which events should trigger the webhook. Events are split into two groups:
|
|
40
|
+
|
|
41
|
+
**Document events:**
|
|
42
|
+
|
|
43
|
+
| Event | Description |
|
|
44
|
+
|---|---|
|
|
45
|
+
| Sent | Documents are sent for signatures or approval |
|
|
46
|
+
| Completed by all | All recipients have signed and approved |
|
|
47
|
+
| Expires | Documents sent for signatures or approval expire |
|
|
48
|
+
| Recalled | Sender recalls the document |
|
|
49
|
+
|
|
50
|
+
**Recipient events:**
|
|
51
|
+
|
|
52
|
+
| Event | Description |
|
|
53
|
+
|---|---|
|
|
54
|
+
| Viewed | A recipient views the document |
|
|
55
|
+
| Signed by a recipient | A recipient signs the document |
|
|
56
|
+
| Approved by a recipient | A recipient approves the document |
|
|
57
|
+
| Declined | A recipient declines the document |
|
|
58
|
+
| Reassigned | A recipient reassigns to another person |
|
|
59
|
+
|
|
60
|
+
Click **"Save"** to create the webhook.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 2. Webhook Payload
|
|
65
|
+
|
|
66
|
+
Every webhook POST contains a JSON body with two top-level keys:
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"notifications": {
|
|
71
|
+
"performed_by_email": "signer@example.com",
|
|
72
|
+
"performed_by_name": "Jane Doe",
|
|
73
|
+
"performed_at": 1555062604837,
|
|
74
|
+
"reason": "",
|
|
75
|
+
"activity": "Document has been signed",
|
|
76
|
+
"operation_type": "RequestSigningSuccess",
|
|
77
|
+
"action_id": "1000000000090",
|
|
78
|
+
"ip_address": "192.168.100.100"
|
|
79
|
+
},
|
|
80
|
+
"requests": {
|
|
81
|
+
"request_name": "NDA Document",
|
|
82
|
+
"request_id": "1000000000000",
|
|
83
|
+
"request_status": "inprogress",
|
|
84
|
+
"org_id": "9876543210",
|
|
85
|
+
"request_type_id": "10000000011",
|
|
86
|
+
"document_ids": [
|
|
87
|
+
{
|
|
88
|
+
"document_name": "CommonNDA.pdf",
|
|
89
|
+
"document_id": "100000000000050"
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Operation Types
|
|
97
|
+
|
|
98
|
+
The `operation_type` field identifies the event:
|
|
99
|
+
|
|
100
|
+
| Operation Type | Trigger |
|
|
101
|
+
|---|---|
|
|
102
|
+
| `RequestSubmitted` | Document submitted for signature |
|
|
103
|
+
| `RequestViewed` | Document viewed by a recipient |
|
|
104
|
+
| `RequestSigningSuccess` | A signer completes signing |
|
|
105
|
+
| `RequestCompleted` | All signers/approvers complete |
|
|
106
|
+
| `RequestRejected` | A recipient declines |
|
|
107
|
+
| `RequestRecalled` | Sender recalls the document |
|
|
108
|
+
| `RequestForwarded` | A recipient forwards to another person |
|
|
109
|
+
| `RequestExpired` | Document expires |
|
|
110
|
+
|
|
111
|
+
> For signer-related actions (`RequestViewed`, `RequestSigningSuccess`, `RequestRejected`, `RequestForwarded`), the `action_id` of the signer is present in the `notifications` object.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## 3. Best Practices
|
|
116
|
+
|
|
117
|
+
- **Return HTTP 200 within 5 seconds.** Do not perform heavy processing before responding.
|
|
118
|
+
- After **10-15 consecutive failures**, Zoho Sign sends a warning email to the admin.
|
|
119
|
+
- After **20 consecutive failures**, the webhook is **automatically disabled**. The admin must re-enable it from the Zoho Sign web interface.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 4. NestJS Module Setup
|
|
124
|
+
|
|
125
|
+
### Environment Variable
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
ZOHO_SIGN_WEBHOOK_SECRET_TOKEN=<your-hmac-secret-key>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Import the Module
|
|
132
|
+
|
|
133
|
+
`ZohoSignWebhookModule` is a standalone module that reads the webhook secret from the environment. It does not depend on the Zoho Sign API module (`appZohoSignModuleMetadata`), since webhook verification only needs the HMAC secret.
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import { Module } from '@nestjs/common';
|
|
137
|
+
import { ZohoSignWebhookModule } from '@dereekb/zoho/nestjs';
|
|
138
|
+
|
|
139
|
+
@Module({
|
|
140
|
+
imports: [ZohoSignWebhookModule]
|
|
141
|
+
})
|
|
142
|
+
export class AppZohoSignWebhookModule {}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Import `AppZohoSignWebhookModule` in your API module alongside your other webhook modules.
|
|
146
|
+
|
|
147
|
+
### Handling Events
|
|
148
|
+
|
|
149
|
+
Inject `ZohoSignWebhookService` and use the `configure` accessor to register typed event handlers:
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
import { Injectable, OnModuleInit } from '@nestjs/common';
|
|
153
|
+
import { ZohoSignWebhookService } from '@dereekb/zoho/nestjs';
|
|
154
|
+
import { catchAllHandlerKey } from '@dereekb/util';
|
|
155
|
+
|
|
156
|
+
@Injectable()
|
|
157
|
+
export class MyZohoSignHandler implements OnModuleInit {
|
|
158
|
+
constructor(private readonly zohoSignWebhookService: ZohoSignWebhookService) {}
|
|
159
|
+
|
|
160
|
+
onModuleInit() {
|
|
161
|
+
this.zohoSignWebhookService.configure(this, (x) => {
|
|
162
|
+
x.handleRequestCompleted(this.handleCompleted);
|
|
163
|
+
x.handleRequestSigningSuccess(this.handleSigned);
|
|
164
|
+
x.handleRequestRejected(this.handleRejected);
|
|
165
|
+
x.set(catchAllHandlerKey(), this.handleAny);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async handleCompleted(event) {
|
|
170
|
+
const { request_id, request_name } = event.requests;
|
|
171
|
+
// All recipients have signed — process the completed document
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async handleSigned(event) {
|
|
175
|
+
const { action_id, performed_by_name } = event.notifications;
|
|
176
|
+
// A single recipient signed — update progress
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async handleRejected(event) {
|
|
180
|
+
const { reason, performed_by_name } = event.notifications;
|
|
181
|
+
// A recipient declined — notify the sender
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async handleAny(event) {
|
|
185
|
+
// Catch-all for any unhandled event types
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Register your handler service in the same module that imports `ZohoSignWebhookModule`:
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
@Module({
|
|
194
|
+
imports: [ZohoSignWebhookModule],
|
|
195
|
+
providers: [MyZohoSignHandler]
|
|
196
|
+
})
|
|
197
|
+
export class AppZohoSignWebhookModule {}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Webhook Middleware
|
|
201
|
+
|
|
202
|
+
The webhook controller is mounted at `/webhook/zoho/sign`. Your application must have webhook middleware enabled so the raw request body is preserved for HMAC verification. If using `@dereekb/firebase-server`, this is handled by setting `configureWebhooks: true` in your `nestServerInstance()` call. For plain NestJS apps, use `AppModuleWithWebhooksEnabled` or `consumeWebhooksWithRawBodyMiddleware()` from `@dereekb/nestjs`.
|