@assinafy/sdk 2.0.0 → 2.1.1

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/dist/index.d.ts CHANGED
@@ -36,20 +36,26 @@ interface AssinafyClientOptions {
36
36
  /** Assinafy API key. Preferred authentication method (sends `X-Api-Key` header). */
37
37
  apiKey?: string;
38
38
  /**
39
- * Legacy access token. If provided (and `apiKey` is not), the client will send
40
- * `Authorization: Bearer <token>` instead. Kept for backwards compatibility.
39
+ * Access token. If provided (and `apiKey` is not), the client will send
40
+ * `Authorization: Bearer <token>` instead.
41
41
  */
42
42
  token?: string;
43
43
  /** Default account (workspace) ID applied to account-scoped endpoints. */
44
44
  accountId?: string;
45
45
  /** Override the API base URL. Defaults to https://api.assinafy.com.br/v1. */
46
46
  baseUrl?: string;
47
- /** Secret used to verify webhook payload signatures (HMAC-SHA256). */
47
+ /**
48
+ * Secret for an opt-in HMAC-SHA256 convention implemented by your own
49
+ * gateway. The public Assinafy contract does not currently define a
50
+ * platform webhook-signature header or shared-secret exchange.
51
+ */
48
52
  webhookSecret?: string;
49
53
  /** Request timeout in milliseconds. Defaults to 30_000. */
50
54
  timeout?: number;
51
55
  /**
52
56
  * Max automatic retries on HTTP 429 (rate limit), honoring `Retry-After`.
57
+ * Automatic retries are limited to idempotent GET, HEAD, OPTIONS, PUT, and
58
+ * DELETE requests, plus requests carrying an explicit `Idempotency-Key`.
53
59
  * Defaults to `2`. Set to `0` to disable retrying.
54
60
  */
55
61
  maxRetries?: number;
@@ -59,17 +65,18 @@ interface AssinafyClientOptions {
59
65
  /**
60
66
  * Payload for creating a signer.
61
67
  *
62
- * `email` is optional: the API accepts a signer with only a
63
- * `whatsapp_phone_number`. At least one of the two must be supplied.
68
+ * The official schema requires only `full_name`. Contact fields are optional;
69
+ * name-only signers cannot receive a signing notification until updated.
64
70
  */
65
71
  interface ICreateSignerPayload {
66
72
  full_name: string;
67
73
  email?: string;
68
74
  whatsapp_phone_number?: string;
69
- /** PHP SDK compatibility alias for `whatsapp_phone_number`. */
75
+ /** Compatibility alias normalized to `whatsapp_phone_number` before sending. */
70
76
  phone?: string;
71
- /** Brazilian tax ID (CPF). Non-digits are stripped before sending. */
77
+ /** Unverified request extension. Brazilian CPF; non-digits are stripped. */
72
78
  cpf?: string;
79
+ /** Unverified request extension retained for existing integrations. */
73
80
  metadata?: Record<string, unknown>;
74
81
  }
75
82
  /** Payload for updating a signer. */
@@ -77,9 +84,9 @@ interface IUpdateSignerPayload {
77
84
  full_name?: string;
78
85
  email?: string;
79
86
  whatsapp_phone_number?: string;
80
- /** PHP SDK compatibility alias for `whatsapp_phone_number`. */
87
+ /** Compatibility alias normalized to `whatsapp_phone_number` before sending. */
81
88
  phone?: string;
82
- /** Brazilian tax ID (CPF). Non-digits are stripped before sending. */
89
+ /** Unverified request extension. Brazilian CPF; non-digits are stripped. */
83
90
  cpf?: string;
84
91
  }
85
92
  /** Signer object as returned by the API. */
@@ -99,8 +106,56 @@ interface ISigner {
99
106
  has_signature?: boolean;
100
107
  /** Only returned by `GET /signers/self`. */
101
108
  has_initial?: boolean;
109
+ /** Only returned by `GET /signers/self`. */
110
+ is_signature_reusable?: boolean;
102
111
  metadata?: Record<string, unknown>;
103
112
  }
113
+ /** Signer profile returned by the signer-code-authenticated `GET /signers/self`. */
114
+ interface ISignerSelf extends ISigner {
115
+ has_signature: boolean;
116
+ has_initial: boolean;
117
+ is_signature_reusable: boolean;
118
+ }
119
+ /** Official identity fields accepted by the signer `confirm-data` operation. */
120
+ interface IConfirmSignerDataPayload {
121
+ /** Signer's full name as it should appear on the signed document. */
122
+ full_name?: string;
123
+ email?: string;
124
+ /** Government-issued identifier recorded with the signature. */
125
+ government_id?: string;
126
+ }
127
+ /**
128
+ * Compatibility input retained for integrations written against older
129
+ * Assinafy deployments. Neither extra property belongs to the current
130
+ * `confirm-data` request schema.
131
+ */
132
+ interface ILegacyConfirmSignerDataPayload extends IConfirmSignerDataPayload {
133
+ /**
134
+ * @deprecated Unverified legacy field. Prefer updating the account signer
135
+ * record before starting the signing flow.
136
+ */
137
+ whatsapp_phone_number?: string;
138
+ /**
139
+ * @deprecated Unverified legacy pass-through. It does not replace the
140
+ * official `acceptTerms()` operation and must not be treated as proof of
141
+ * legal consent.
142
+ */
143
+ has_accepted_terms?: boolean;
144
+ }
145
+ /** Official options for uploading the PNG signature image described by OpenAPI. */
146
+ interface IUploadSignatureOptions {
147
+ imageType?: 'signature' | 'initial';
148
+ /** Persist this image so it is reused on future documents. */
149
+ reuse?: boolean;
150
+ }
151
+ /** Source-compatible options for older deployments that accepted other media types. */
152
+ interface ILegacyUploadSignatureOptions extends IUploadSignatureOptions {
153
+ /**
154
+ * @deprecated The current API contract accepts only `image/png`. Non-PNG
155
+ * values are retained as an unverified compatibility escape hatch.
156
+ */
157
+ contentType?: string;
158
+ }
104
159
  type ICreateSignerResponse = ISigner;
105
160
  /** Pagination metadata extracted from `X-Pagination-*` response headers. */
106
161
  interface PaginationMeta {
@@ -137,8 +192,7 @@ interface ICreateAssignmentPayload {
137
192
  method?: AssignmentMethod;
138
193
  /**
139
194
  * List of signers. Each entry may be a signer id string, or an object with
140
- * `id` / `signer_id`. For cost estimation, entries may omit the ID and
141
- * specify only `verification_method` / `notification_methods`.
195
+ * `id` / `signer_id`.
142
196
  *
143
197
  * The SDK normalises them to the docs-sanctioned `signers: [{ ... }]`
144
198
  * shape before sending.
@@ -166,17 +220,60 @@ interface ICreateAssignmentPayload {
166
220
  */
167
221
  copy_receivers?: string[];
168
222
  /** Field placement entries used when `method` is `collect`. */
169
- entries?: unknown[];
223
+ entries?: IAssignmentEntry[];
224
+ }
225
+ /**
226
+ * A field-placement entry for a `collect`-method assignment: one page and the
227
+ * per-signer fields positioned on it.
228
+ */
229
+ interface IAssignmentEntry {
230
+ page_id: string;
231
+ fields: Array<{
232
+ signer_id: string;
233
+ field_id: string;
234
+ /**
235
+ * Opaque, server-defined placement settings (position, size, …). Left
236
+ * loosely typed: the spec models it as a bare object and the live API
237
+ * returns an unstable shape (an empty array on assignment items).
238
+ */
239
+ display_settings?: Record<string, unknown>;
240
+ }>;
241
+ }
242
+ /** Channel descriptor accepted by assignment cost estimation. */
243
+ interface IAssignmentCostSigner {
244
+ verification_method?: AssignmentVerificationMethod;
245
+ notification_methods?: AssignmentNotificationMethod[];
246
+ }
247
+ /**
248
+ * Official request body for
249
+ * `POST /documents/{documentId}/assignments/estimate-cost`.
250
+ */
251
+ interface IEstimateAssignmentCostPayload {
252
+ method?: AssignmentMethod;
253
+ /** Required for `virtual`; `{}` prices the default Email channel. */
254
+ signers?: IAssignmentCostSigner[];
255
+ /** Required for `collect`; signer descriptors are optional in that mode. */
256
+ entries?: IAssignmentEntry[];
170
257
  }
171
258
  /** A signer as embedded inside an assignment (richer than the bare {@link ISigner}). */
172
259
  interface IAssignmentSigner extends ISigner {
173
- completed: boolean;
174
- notification_history: unknown[];
175
- verification_method: AssignmentVerificationMethod;
176
- notification_methods: AssignmentNotificationMethod[];
260
+ /** Only present in account-owner contexts; omitted from signer-code responses. */
261
+ completed?: boolean | null;
262
+ notification_history: INotificationHistoryEntry[] | null;
263
+ verification_method: AssignmentVerificationMethod | null;
264
+ notification_methods: AssignmentNotificationMethod[] | null;
177
265
  /** 1-based signing order. See {@link SignerReference.step}. */
178
- step: number;
179
- notified: boolean;
266
+ step: number | null;
267
+ notified: boolean | null;
268
+ }
269
+ /** Per-channel notification delivery history embedded in an assignment signer. */
270
+ interface INotificationHistoryEntry {
271
+ event: string;
272
+ status: 'sent' | 'failed';
273
+ error_code: string | null;
274
+ error_message: string | null;
275
+ sent_at: string | null;
276
+ failed_at: string | null;
180
277
  }
181
278
  /** A placed field/item within an assignment (one row per signer × field). */
182
279
  interface IAssignmentItem {
@@ -189,8 +286,9 @@ interface IAssignmentItem {
189
286
  download_url: string;
190
287
  } | null;
191
288
  signer: ISigner;
192
- field: IFieldDefinition;
193
- value: string | null;
289
+ field: IFieldDefinition | null;
290
+ /** Captured field value; its wire type depends on the field definition. */
291
+ value: unknown | null;
194
292
  completed?: boolean;
195
293
  [key: string]: unknown;
196
294
  }
@@ -202,9 +300,10 @@ interface IAssignment {
202
300
  method: AssignmentMethod;
203
301
  expires_at?: string | null;
204
302
  expiration?: string;
205
- message?: string;
303
+ message?: string | null;
206
304
  signers: IAssignmentSigner[];
207
- copy_receivers?: string[];
305
+ /** Expanded copy-receiver objects returned by the API. */
306
+ copy_receivers?: Array<Record<string, unknown>>;
208
307
  items?: IAssignmentItem[];
209
308
  summary?: {
210
309
  signer_count: number;
@@ -221,9 +320,9 @@ interface IAssignment {
221
320
  }
222
321
  type ICreateAssignmentResponse = IAssignment;
223
322
  interface IResendEmailResponse {
224
- is_sent?: boolean;
225
- document_id?: string;
226
- signer_id?: string;
323
+ is_sent: boolean;
324
+ document_id: string;
325
+ signer_id: string;
227
326
  }
228
327
  /**
229
328
  * Credit/document cost estimate returned by `assignments.estimateCost` and
@@ -249,8 +348,15 @@ interface ICostEstimate {
249
348
  blocking_reason: string | null;
250
349
  message: string | null;
251
350
  }
252
- /** Cost estimate returned by `assignments.estimateResendCost`. */
253
- interface IResendCostEstimate {
351
+ /**
352
+ * Legacy resend-cost payload still returned by some Assinafy environments.
353
+ *
354
+ * The current OpenAPI contract declares {@link ICostEstimate} for this route,
355
+ * while the sandbox has also returned this smaller, resend-specific shape.
356
+ * The SDK models both wire formats instead of promising fields that may be
357
+ * absent at runtime.
358
+ */
359
+ interface ILegacyResendCostEstimate {
254
360
  total: number;
255
361
  breakdown: Array<{
256
362
  code: string;
@@ -260,17 +366,23 @@ interface IResendCostEstimate {
260
366
  credit_balance: number;
261
367
  has_sufficient_credits: boolean;
262
368
  }
369
+ /** Cost estimate returned by `assignments.estimateResendCost`. */
370
+ type IResendCostEstimate = ICostEstimate | ILegacyResendCostEstimate;
263
371
  /** Webhook payload envelope. */
264
372
  interface IWebhookPayload {
373
+ /** Internal activity id; use it as an idempotency/deduplication key. */
265
374
  id?: number;
266
- event?: string;
375
+ event?: WebhookEventType | AnyString;
267
376
  type?: string;
268
377
  message?: string | null;
269
378
  payload?: Record<string, unknown> | null;
270
379
  origin?: Record<string, unknown> | null;
380
+ /** Unix timestamp in seconds. */
381
+ created_at?: number;
271
382
  subject?: Record<string, unknown>;
272
383
  object?: Record<string, unknown>;
273
384
  account_id?: string;
385
+ /** Legacy envelope accepted by the verifier for backwards compatibility. */
274
386
  data?: {
275
387
  document_uuid?: string;
276
388
  document_id?: string;
@@ -360,6 +472,8 @@ interface IDocumentUploadResponse {
360
472
  bundle?: string;
361
473
  thumbnail?: string;
362
474
  };
475
+ /** Public signing-portal URL for the document (always returned by the upload endpoint). */
476
+ signing_url?: string;
363
477
  /** Empty (`[]`) on fresh upload (status `uploaded`); populated once `metadata_ready`. */
364
478
  pages: Array<{
365
479
  id: string;
@@ -374,7 +488,8 @@ interface IDocumentUploadResponse {
374
488
  updated_at: string;
375
489
  is_closed: boolean;
376
490
  decline_reason: string | null;
377
- declined_by: string | null;
491
+ /** The signer who declined, once one has (matches the sibling document response types); `null` otherwise. */
492
+ declined_by: ISigner | null;
378
493
  }
379
494
  /** Detailed document response. */
380
495
  interface IDocumentDetailsResponse {
@@ -410,8 +525,8 @@ interface IDocumentActivity {
410
525
  id: number;
411
526
  event: string;
412
527
  message: string;
413
- /** Event-specific payload snapshot. Object for most events, occasionally `[]`. */
414
- payload?: Record<string, unknown> | unknown[];
528
+ /** Event-specific payload snapshot. Object for most events, occasionally `[]` or `null`. */
529
+ payload?: Record<string, unknown> | unknown[] | null;
415
530
  /** Request origin (`ip` / `user-agent`) when available; `null` for system events. */
416
531
  origin: {
417
532
  ip?: string;
@@ -435,37 +550,93 @@ interface IListParams {
435
550
  sort?: string;
436
551
  [key: string]: string | number | boolean | undefined;
437
552
  }
438
- /** Workspace creation payload. */
553
+ /**
554
+ * Workspace creation payload.
555
+ *
556
+ * Colours are persisted and echoed back on the workspace object. Unlike tags —
557
+ * which accept a leading `#` and strip it — the account endpoints require an
558
+ * **exactly 6-character hex string with NO leading `#`** (`'ff0066'`, not
559
+ * `'#ff0066'`); a 7-character `#`-prefixed value is rejected with `400`
560
+ * ("Primary Color" deve conter 6 caracteres). Verified live against the API.
561
+ */
439
562
  interface ICreateWorkspacePayload {
440
563
  name: string;
564
+ /** Who signers see as the notification sender (`User` is the API default). */
565
+ notification_sender_type?: NotificationSenderType;
566
+ /** 6-char hex, no leading `#` (e.g. `'ff0066'`). */
441
567
  primary_color?: string;
568
+ /** 6-char hex, no leading `#` (e.g. `'0066ff'`). */
442
569
  secondary_color?: string;
443
570
  }
571
+ /** Workspace update payload. Colours follow the same 6-char-no-`#` rule as {@link ICreateWorkspacePayload}. */
444
572
  interface IUpdateWorkspacePayload {
445
573
  name?: string;
574
+ /** Who signers see as the notification sender. */
575
+ notification_sender_type?: NotificationSenderType;
576
+ /** 6-char hex, no leading `#`. */
446
577
  primary_color?: string | null;
578
+ /** 6-char hex, no leading `#`. */
447
579
  secondary_color?: string | null;
448
580
  }
449
581
  interface IWorkspaceResponse {
582
+ resource?: string;
450
583
  id: string;
451
584
  name: string;
452
585
  primary_color?: string | null;
453
586
  secondary_color?: string | null;
587
+ notification_sender_type?: NotificationSenderType;
588
+ roles?: string[];
589
+ is_delete_allowed?: boolean;
454
590
  created_at: string;
455
591
  }
456
- interface IWorkspaceListItem {
457
- id: string;
458
- name: string;
592
+ /** Notification sender identity accepted by account create/update operations. */
593
+ type NotificationSenderType = 'User' | 'Account';
594
+ interface IWorkspaceListItem extends IWorkspaceResponse {
459
595
  is_delete_allowed: boolean;
460
596
  roles: string[];
461
- created_at: string;
462
597
  }
463
598
  type IWorkspaceListResponse = PaginatedResult<IWorkspaceListItem>;
599
+ /** Branding returned by `GET /accounts/{accountId}/theme`. */
600
+ interface IAccountTheme {
601
+ account_name: string;
602
+ /** Six-character hex colour without a leading `#`. */
603
+ primary_color: string;
604
+ secondary_color: string | null;
605
+ /** Absolute URL of the account logo. */
606
+ logo: string;
607
+ }
608
+ /** Granularity accepted by account/user document-statistics endpoints. */
609
+ type DocumentStatsGranularity = 'monthly' | 'daily';
610
+ /** Query for account/user document-statistics endpoints. */
611
+ interface IDocumentStatsParams {
612
+ /** Defaults to `monthly`. */
613
+ granularity?: DocumentStatsGranularity;
614
+ /** Target `YYYY-MM`; required when `granularity` is `daily`. */
615
+ month?: string;
616
+ }
617
+ /** One zero-filled document-funnel KPI period. */
618
+ interface IDocumentStatsRow {
619
+ /** `YYYY-MM` for monthly results or `YYYY-MM-DD` for daily results. */
620
+ period: string;
621
+ documents_uploaded: number;
622
+ documents_sent: number;
623
+ signature_requests: number;
624
+ signature_requests_email: number;
625
+ signature_requests_whatsapp: number;
626
+ signature_requests_viewed: number;
627
+ signature_requests_completed: number;
628
+ documents_certified: number;
629
+ }
464
630
  /** Webhook subscription payload. */
465
631
  interface IWebhookRegisterPayload {
466
632
  url: string;
467
633
  email: string;
468
- events?: WebhookEventType[] | string[];
634
+ /**
635
+ * Events to subscribe to. Known {@link WebhookEventType} literals are
636
+ * suggested in editors while any server-controlled string is still accepted
637
+ * (via {@link AnyString}), matching the open-enum convention used elsewhere.
638
+ */
639
+ events?: (WebhookEventType | AnyString)[];
469
640
  is_active?: boolean;
470
641
  }
471
642
  /**
@@ -474,17 +645,18 @@ interface IWebhookRegisterPayload {
474
645
  * `{ events, is_active, url, email, updated_at }` (no `id` / `created_at`).
475
646
  */
476
647
  interface IWebhookSubscription {
477
- url: string;
478
- email: string;
648
+ url: string | null;
649
+ email: string | null;
479
650
  events: string[];
480
651
  is_active: boolean;
481
- updated_at?: string;
652
+ updated_at?: string | null;
482
653
  }
483
654
  interface IWebhookEventTypeInfo {
484
655
  id: WebhookEventType | AnyString;
485
656
  description: string;
486
657
  }
487
658
  interface IWebhookDispatch {
659
+ resource?: string;
488
660
  id: string;
489
661
  event: WebhookEventType | AnyString;
490
662
  activity_id: number;
@@ -507,7 +679,14 @@ interface IWebhookDispatchListParams extends IListParams {
507
679
  }
508
680
  /** Shape of the high-level `uploadAndRequestSignatures` helper result. */
509
681
  interface IUploadAndRequestSignaturesResult {
510
- document: IDocumentUploadResponse;
682
+ /**
683
+ * The document. When `waitForReady` is enabled (the default) this is the
684
+ * fully-processed {@link IDocumentDetailsResponse} re-fetched after the
685
+ * assignment is created — so `status`, `pages` and the embedded `assignment`
686
+ * are current. When `waitForReady` is `false` it is the raw
687
+ * {@link IDocumentUploadResponse} upload snapshot (`status: 'uploaded'`).
688
+ */
689
+ document: IDocumentUploadResponse | IDocumentDetailsResponse;
511
690
  assignment: IAssignment;
512
691
  signer_ids: string[];
513
692
  }
@@ -547,10 +726,9 @@ interface ITemplateListItem {
547
726
  status: string;
548
727
  /**
549
728
  * Rendered pages, each with a `download_url`. Empty until the template
550
- * finishes processing (`status: 'Ready'`).
551
- *
552
- * The list endpoint does return `pages` — contrary to what
553
- * `templates.get`'s documentation implies.
729
+ * finishes processing (`status: 'Ready'`). Both the list and get endpoints
730
+ * return `pages`, so there is no need to fetch a template again just to read
731
+ * them.
554
732
  */
555
733
  pages?: IPage[];
556
734
  roles?: ITemplateRole[];
@@ -591,7 +769,18 @@ interface IPage {
591
769
  /** Absolute URL of the page's JPEG rendering. */
592
770
  download_url?: string;
593
771
  /** Fields positioned on this page. Present on templates; absent on documents. */
594
- fields?: unknown[];
772
+ fields?: ITemplateFieldPlacement[];
773
+ }
774
+ /** A field placement returned on a rendered template page. */
775
+ interface ITemplateFieldPlacement {
776
+ id?: string;
777
+ field_id?: string;
778
+ role_id?: string;
779
+ label?: string;
780
+ /** Opaque rendering metadata; the current schema intentionally leaves it untyped. */
781
+ display_settings?: unknown;
782
+ created_at?: string;
783
+ updated_at?: string;
595
784
  }
596
785
  interface ITemplateDetailsResponse {
597
786
  resource?: string;
@@ -620,12 +809,24 @@ interface ITemplateSigner {
620
809
  /** Positive integer controlling signing order (see {@link SignerReference}). */
621
810
  step?: number;
622
811
  }
812
+ /**
813
+ * Role/channel descriptor used only for template cost estimation. The official
814
+ * schema intentionally omits signer `id` and sequential-signing `step`.
815
+ */
816
+ interface ITemplateCostSigner {
817
+ role_id: string;
818
+ verification_method?: string;
819
+ notification_methods?: string[];
820
+ }
623
821
  /** Options for creating a document from a template. */
624
822
  interface ICreateDocumentFromTemplateOptions {
625
823
  name?: string;
626
824
  message?: string;
627
825
  expires_at?: string;
628
- editor_fields?: unknown[];
826
+ editor_fields?: Array<{
827
+ field_id: string;
828
+ value: string;
829
+ }>;
629
830
  /**
630
831
  * Tag names to attach to the new document. Names that don't exist yet are
631
832
  * auto-created; the template's default-document-tags are always merged in.
@@ -644,30 +845,49 @@ interface IDocumentStatusInfo {
644
845
  description?: string;
645
846
  }
646
847
  /** Item returned by `GET /public/documents/{id}`. */
647
- interface IPublicDocumentInfo {
848
+ interface IPublicDocumentInfo extends Partial<Omit<IDocumentDetailsResponse, 'id' | 'name'>> {
648
849
  resource?: string;
649
850
  id: string;
650
851
  name: string;
852
+ /** Observed legacy/public response field; not present in the current schema. */
651
853
  page_count?: string | number;
854
+ /** Observed legacy/public response field; not present in the current schema. */
652
855
  created_by?: string;
653
856
  [key: string]: unknown;
654
857
  }
858
+ /** Result returned by public document signature-hash verification. */
859
+ interface IDocumentVerification {
860
+ hash: string;
861
+ id: string | null;
862
+ status: DocumentStatus | AnyString | null;
863
+ page_count: string | null;
864
+ signer_count: string | null;
865
+ completed_count: number | null;
866
+ completed_at: string | null;
867
+ verified_at: string;
868
+ is_valid: boolean;
869
+ message: string;
870
+ }
655
871
  /** Channel accepted by the `send-token` endpoint. */
656
872
  type SendTokenChannel = 'email' | 'whatsapp' | AnyString;
657
873
  /** Authentication: login response (also returned by social login). */
874
+ /** Authenticated user profile returned by login and `users.getCurrent()`. */
875
+ interface IAuthenticatedUser {
876
+ id: string;
877
+ name: string;
878
+ email: string;
879
+ telephone: string | null;
880
+ government_id: string | null;
881
+ is_email_verified: boolean;
882
+ has_accepted_terms: boolean;
883
+ /** Live compatibility field; absent from the current OpenAPI `AuthUser` schema. */
884
+ is_password_set?: boolean;
885
+ created_at: string;
886
+ to_be_deleted_at: string | null;
887
+ }
658
888
  interface ILoginResponse {
659
889
  access_token: string;
660
- user: {
661
- id: string;
662
- name: string;
663
- email: string;
664
- telephone?: string;
665
- government_id?: string;
666
- is_email_verified?: boolean;
667
- has_accepted_terms?: boolean;
668
- created_at?: string;
669
- to_be_deleted_at?: string | null;
670
- };
890
+ user: IAuthenticatedUser;
671
891
  accounts: Array<{
672
892
  id: string;
673
893
  name: string;
@@ -678,11 +898,11 @@ interface ILoginResponse {
678
898
  }
679
899
  /** Authentication: API key payload returned by `POST /users/api-keys`. */
680
900
  interface IApiKeyResponse {
681
- api_key: string;
901
+ api_key: string | null;
682
902
  }
683
- /** Authentication: masked API key returned by `GET /users/api-keys` (or null when never generated). */
903
+ /** Authentication: masked API key returned by `GET /users/api-keys`. */
684
904
  type IMaskedApiKeyResponse = {
685
- api_key: string;
905
+ api_key: string | null;
686
906
  } | null;
687
907
  /** Field definition object. */
688
908
  interface IFieldDefinition {
@@ -702,15 +922,18 @@ interface IFieldDefinition {
702
922
  interface ICreateFieldPayload {
703
923
  type: string;
704
924
  name: string;
705
- regex?: string;
925
+ regex?: string | null;
706
926
  is_required?: boolean;
927
+ /** Live compatibility extension; absent from the current create schema. */
707
928
  is_active?: boolean;
708
929
  }
709
930
  /** Payload for updating a field definition. */
710
931
  interface IUpdateFieldPayload {
932
+ /** Live compatibility extension; absent from the current update schema. */
711
933
  type?: string;
712
934
  name?: string;
713
935
  regex?: string | null;
936
+ /** Live compatibility extension; absent from the current update schema. */
714
937
  is_required?: boolean;
715
938
  is_active?: boolean;
716
939
  }
@@ -783,14 +1006,16 @@ interface IUpdateTagPayload {
783
1006
 
784
1007
  /** Maximum upload size accepted by the API (hard limit, 25 MB). */
785
1008
  declare const MAX_UPLOAD_BYTES: number;
786
- /** Input for an upload: either an on-disk file or an in-memory buffer. */
787
- type DocumentUploadSource = {
1009
+ /** Input for a file upload: either an on-disk file or an in-memory buffer. */
1010
+ type FileUploadSource = {
788
1011
  filePath: string;
789
1012
  fileName?: string;
790
1013
  } | {
791
1014
  buffer: Buffer;
792
1015
  fileName: string;
793
1016
  };
1017
+ /** Input accepted by PDF document/template uploads. */
1018
+ type DocumentUploadSource = FileUploadSource;
794
1019
 
795
1020
  /**
796
1021
  * Shared plumbing for every Assinafy resource:
@@ -813,6 +1038,8 @@ declare abstract class BaseResource {
813
1038
  protected accountId(explicit?: string): string;
814
1039
  /** Guard required path arguments (documentId, signerId, …). */
815
1040
  protected requireId<T extends string>(value: T | undefined | null, name: string): T;
1041
+ /** Validate and encode a value that will occupy one URL path segment. */
1042
+ protected pathSegment(value: string | undefined | null, name: string): string;
816
1043
  /** Execute an HTTP call and return the unwrapped envelope body. */
817
1044
  protected call<T>(label: string, request: RequestFn): Promise<T>;
818
1045
  /** Like {@link call} but returns `null` when the API responds with 404. */
@@ -864,26 +1091,39 @@ interface IDocumentUploadOptions {
864
1091
  accountId?: string;
865
1092
  }
866
1093
  declare class DocumentResource extends BaseResource {
1094
+ private readonly publicHttp;
1095
+ constructor(http: AxiosInstance, defaultAccountId?: string, logger?: Logger, publicHttp?: AxiosInstance);
867
1096
  /**
868
1097
  * Upload a PDF to the workspace (`POST /accounts/{accountId}/documents`).
869
1098
  *
870
- * The document is created in `metadata_processing` status and becomes
871
- * usable once it reaches `metadata_ready`; use
1099
+ * The document is created in `uploaded` status and progresses through the
1100
+ * lifecycle `uploading` `uploaded` `metadata_processing`
1101
+ * `metadata_ready`, becoming usable once it reaches `metadata_ready`; use
872
1102
  * {@link DocumentResource.waitUntilReady} to await that transition. Note
873
1103
  * that {@link DocumentResource.rename} and {@link DocumentResource.delete}
874
1104
  * return `400` while the document is still processing.
875
1105
  *
876
1106
  * @param source - The PDF to upload, as a file path or an in-memory buffer.
877
1107
  * @param options - Display name, metadata, and account override.
878
- * @returns The created document. Response shape:
1108
+ * @returns The created document, freshly uploaded (`status: 'uploaded'`,
1109
+ * empty `pages` until `metadata_ready`). Response shape:
879
1110
  * ```jsonc
880
1111
  * {
881
1112
  * "resource": "document",
882
- * "id": "c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
1113
+ * "id": "103ad216846e6b90710cb9acef59",
1114
+ * "account_id": "acc_example",
1115
+ * "template_id": null,
883
1116
  * "name": "Service agreement.pdf",
884
- * "status": "metadata_processing",
885
- * "created_at": "2026-07-15T16:15:33Z",
886
- * "updated_at": "2026-07-15T16:15:33Z"
1117
+ * "status": "uploaded", // NOT metadata_processing yet
1118
+ * "artifacts": { "original": "https://…/documents/103ad216…/download/original" },
1119
+ * "is_closed": false,
1120
+ * "signing_url": "https://app-sandbox.assinafy.com.br/sign/103ad216…",
1121
+ * "decline_reason": null,
1122
+ * "declined_by": null,
1123
+ * "tags": [],
1124
+ * "pages": [], // populated once metadata_ready
1125
+ * "created_at": "2026-07-19T17:24:43Z",
1126
+ * "updated_at": "2026-07-19T17:24:44Z"
887
1127
  * }
888
1128
  * ```
889
1129
  * @throws {ValidationError} If the file is empty, not a `.pdf`, exceeds
@@ -902,8 +1142,60 @@ declare class DocumentResource extends BaseResource {
902
1142
  */
903
1143
  upload(source: DocumentUploadSource, options?: IDocumentUploadOptions): Promise<IDocumentUploadResponse>;
904
1144
  /**
905
- * List workspace documents. Pagination info (if any) is attached in `meta`.
906
- * Supports `status`, `method`, `tags`, `search`, `sort`, `page`, `per-page`.
1145
+ * List workspace documents
1146
+ * (`GET /accounts/{accountId}/documents`).
1147
+ *
1148
+ * The full listing: unlike {@link DocumentResource.search}, each item also
1149
+ * carries the expanded `assignment` (or `null`) and the rendered `pages`,
1150
+ * so prefer it when you need signing state or page geometry. Pagination
1151
+ * info (if any) is attached in `meta`.
1152
+ *
1153
+ * @param params - Filters and pagination: `status`, `method`, `tags`
1154
+ * (comma-separated tag IDs), `search`, `sort`, `page`, `per-page`.
1155
+ * @param accountId - Override the client's default account ID.
1156
+ * @returns Matching documents, with pagination in `meta`. Each item:
1157
+ * ```jsonc
1158
+ * {
1159
+ * "id": "103acccd24234c07858ffddf6d84",
1160
+ * "account_id": "acc_example",
1161
+ * "template_id": null,
1162
+ * "name": "sdk-smoke-rename-7b006e52.pdf",
1163
+ * "status": "metadata_ready",
1164
+ * "artifacts": {
1165
+ * "original": "https://…/documents/103acccd…/download/original",
1166
+ * "thumbnail": "https://…/documents/103acccd…/thumbnail"
1167
+ * },
1168
+ * "is_closed": false,
1169
+ * "signing_url": "https://app-sandbox.assinafy.com.br/sign/103acccd…",
1170
+ * "decline_reason": null,
1171
+ * "declined_by": null,
1172
+ * "tags": [],
1173
+ * "assignment": null, // an IAssignment once signatures are requested
1174
+ * "pages": [
1175
+ * {
1176
+ * "id": "103acccd5c73af8009c3644af591",
1177
+ * "number": 1,
1178
+ * "height": 1651,
1179
+ * "width": 1275,
1180
+ * "download_url": "https://…/documents/103acccd…/pages/103acccd…/download"
1181
+ * }
1182
+ * ],
1183
+ * "created_at": "2026-07-19T14:56:54Z",
1184
+ * "updated_at": "2026-07-19T14:56:56Z"
1185
+ * }
1186
+ * ```
1187
+ * @throws {ValidationError} If no account ID is available.
1188
+ * @throws {ApiError} If the API rejects the request.
1189
+ *
1190
+ * @example
1191
+ * ```ts
1192
+ * const { data, meta } = await client.documents.list({
1193
+ * status: 'pending_signature',
1194
+ * method: 'virtual',
1195
+ * 'per-page': 50,
1196
+ * });
1197
+ * console.log(data[0]?.pages.length, meta?.total);
1198
+ * ```
907
1199
  */
908
1200
  list(params?: IDocumentListParams, accountId?: string): Promise<IDocumentListResponse>;
909
1201
  /**
@@ -978,551 +1270,3385 @@ declare class DocumentResource extends BaseResource {
978
1270
  * ```
979
1271
  */
980
1272
  rename(documentId: string, name: string): Promise<IRenameDocumentResponse>;
981
- /** Get document details. */
1273
+ /**
1274
+ * Get document details (`GET /documents/{documentId}`).
1275
+ *
1276
+ * The full single-document view, including the embedded `assignment` (or
1277
+ * `null`), rendered `pages`, and `artifacts`.
1278
+ *
1279
+ * @param documentId - The document to fetch.
1280
+ * @returns The document. Response shape (once `metadata_ready`):
1281
+ * ```jsonc
1282
+ * {
1283
+ * "resource": "document",
1284
+ * "id": "103ad216846e6b90710cb9acef59",
1285
+ * "account_id": "acc_example",
1286
+ * "template_id": null,
1287
+ * "name": "audit-test.pdf",
1288
+ * "status": "metadata_ready",
1289
+ * "artifacts": {
1290
+ * "original": "https://…/documents/103ad216…/download/original",
1291
+ * "thumbnail": "https://…/documents/103ad216…/thumbnail"
1292
+ * },
1293
+ * "is_closed": false,
1294
+ * "signing_url": "https://app-sandbox.assinafy.com.br/sign/103ad216…",
1295
+ * "decline_reason": null,
1296
+ * "declined_by": null,
1297
+ * "tags": [],
1298
+ * "assignment": null,
1299
+ * "pages": [
1300
+ * {
1301
+ * "id": "103ad216be62159d3087452d7cf8",
1302
+ * "number": 1,
1303
+ * "height": 1651,
1304
+ * "width": 1275,
1305
+ * "download_url": "https://…/documents/103ad216…/pages/103ad216…/download"
1306
+ * }
1307
+ * ],
1308
+ * "created_at": "2026-07-19T17:24:43Z",
1309
+ * "updated_at": "2026-07-19T17:24:46Z"
1310
+ * }
1311
+ * ```
1312
+ * @throws {ValidationError} If `documentId` is missing.
1313
+ * @throws {ApiError} `404` if the document does not exist.
1314
+ *
1315
+ * @example
1316
+ * ```ts
1317
+ * const doc = await client.documents.details('103ad216846e6b90710cb9acef59');
1318
+ * console.log(doc.status, doc.pages.length);
1319
+ * ```
1320
+ */
982
1321
  details(documentId: string): Promise<IDocumentDetailsResponse>;
983
- /** Alias for {@link details}. */
1322
+ /**
1323
+ * Alias for {@link DocumentResource.details}
1324
+ * (`GET /documents/{documentId}`).
1325
+ *
1326
+ * @param documentId - The document to fetch.
1327
+ * @returns The document details (see {@link DocumentResource.details} for
1328
+ * the response shape).
1329
+ * @throws {ValidationError} If `documentId` is missing.
1330
+ * @throws {ApiError} `404` if the document does not exist.
1331
+ *
1332
+ * @example
1333
+ * ```ts
1334
+ * const doc = await client.documents.get('103ad216846e6b90710cb9acef59');
1335
+ * ```
1336
+ */
984
1337
  get(documentId: string): Promise<IDocumentDetailsResponse>;
985
- /** Poll document status until ready (or a terminal status / timeout). */
1338
+ /**
1339
+ * Poll {@link DocumentResource.details} until the document reaches a ready
1340
+ * status (`metadata_ready`, `pending_signature`, or `certificated`),
1341
+ * throwing on a terminal failure status or timeout.
1342
+ *
1343
+ * Transient errors are tolerated — a `5xx` or `429` is retried on the next
1344
+ * poll — but a non-retryable `4xx` (bad key, wrong account, deleted
1345
+ * document) is surfaced immediately rather than masked as a timeout.
1346
+ *
1347
+ * @param documentId - The document to wait on.
1348
+ * @param options - `maxWaitMs` (default `30_000`) and `pollIntervalMs`
1349
+ * (default `2_000`).
1350
+ * @returns The document details once it reaches a ready status (see
1351
+ * {@link DocumentResource.details} for the shape).
1352
+ * @throws {ValidationError} If `documentId` is missing, the document enters
1353
+ * a terminal failure status (`failed`, `rejected_by_signer`,
1354
+ * `rejected_by_user`, `expired` — message
1355
+ * `Document processing failed with status: <status>`), or the wait times
1356
+ * out (`Timeout waiting for document to be ready`).
1357
+ * @throws {ApiError} On a non-retryable `4xx` other than `429`.
1358
+ *
1359
+ * @example
1360
+ * ```ts
1361
+ * const doc = await client.documents.upload({ filePath: './c.pdf' });
1362
+ * const ready = await client.documents.waitUntilReady(doc.id, {
1363
+ * maxWaitMs: 60_000,
1364
+ * pollIntervalMs: 3_000,
1365
+ * });
1366
+ * console.log(ready.status); // 'metadata_ready'
1367
+ * ```
1368
+ */
986
1369
  waitUntilReady(documentId: string, options?: {
987
1370
  maxWaitMs?: number;
988
1371
  pollIntervalMs?: number;
989
1372
  }): Promise<IDocumentDetailsResponse>;
990
- /** Download a document artifact. Defaults to the certificated (signed) PDF. */
991
- download(documentId: string, artifactName?: DocumentArtifactName): Promise<Buffer>;
992
- /** Download the document thumbnail. */
993
- thumbnail(documentId: string): Promise<Buffer>;
994
- /** Download a single page as a JPEG. */
995
- downloadPage(documentId: string, pageId: string): Promise<Buffer>;
996
- /** Fetch the document activity log. */
997
- activities(documentId: string): Promise<IDocumentActivity[]>;
998
- /** Delete a document. */
999
- delete(documentId: string): Promise<void>;
1000
- /** List the tags attached to a document. */
1001
- listTags(documentId: string, accountId?: string): Promise<ITag[]>;
1002
1373
  /**
1003
- * Replace the document's tag set with `tags` (an array of tag names).
1004
- * Unknown names are auto-created; an empty array detaches all tags.
1374
+ * Download a document artifact as raw bytes
1375
+ * (`GET /documents/{documentId}/download/{artifactName}`).
1376
+ *
1377
+ * @param documentId - The document to download from.
1378
+ * @param artifactName - Which artifact to fetch: `original`,
1379
+ * `certificated` (the default — the signed PDF), `certificate-page`, or
1380
+ * `bundle`.
1381
+ * @returns A {@link Buffer} of the artifact's bytes (PDF).
1382
+ * @throws {ValidationError} If `documentId` is missing.
1383
+ * @throws {ApiError} `404` if the document or artifact does not exist (e.g.
1384
+ * requesting `certificated` before signing completes).
1385
+ *
1386
+ * @example
1387
+ * ```ts
1388
+ * const pdf = await client.documents.download('doc-1'); // signed PDF
1389
+ * const original = await client.documents.download('doc-1', 'original');
1390
+ * await fs.promises.writeFile('signed.pdf', pdf);
1391
+ * ```
1005
1392
  */
1006
- replaceTags(documentId: string, tags: string[], accountId?: string): Promise<ITag[]>;
1007
- /** Attach additional tags (by name) without removing existing ones. Idempotent. */
1008
- addTags(documentId: string, tags: string[], accountId?: string): Promise<ITag[]>;
1009
- /** Detach a single tag from a document (the tag itself is not deleted). */
1010
- detachTag(documentId: string, tagId: string, accountId?: string): Promise<void>;
1393
+ download(documentId: string, artifactName?: DocumentArtifactName): Promise<Buffer>;
1011
1394
  /**
1012
- * Create a document from a template.
1395
+ * Download the document thumbnail image
1396
+ * (`GET /documents/{documentId}/thumbnail`).
1397
+ *
1398
+ * @param documentId - The document whose thumbnail to fetch.
1399
+ * @returns A {@link Buffer} of the thumbnail image bytes.
1400
+ * @throws {ValidationError} If `documentId` is missing.
1401
+ * @throws {ApiError} `404` if the document or its thumbnail does not exist.
1013
1402
  *
1014
1403
  * @example
1015
1404
  * ```ts
1016
- * await client.documents.createFromTemplate('tmpl_id', [
1017
- * { role_id: 'role_id', id: 'signer_id', verification_method: 'Email', notification_methods: ['Email'] },
1018
- * ], { name: 'My Contract' });
1405
+ * const thumb = await client.documents.thumbnail('doc-1');
1406
+ * await fs.promises.writeFile('thumb.jpg', thumb);
1019
1407
  * ```
1020
1408
  */
1021
- createFromTemplate(templateId: string, signers: ITemplateSigner[], options?: ICreateDocumentFromTemplateOptions, accountId?: string): Promise<IDocumentDetailsResponse>;
1409
+ thumbnail(documentId: string): Promise<Buffer>;
1022
1410
  /**
1023
- * Estimate the credit cost of creating a document from a template.
1411
+ * Download a single rendered page as a JPEG
1412
+ * (`GET /documents/{documentId}/pages/{pageId}/download`).
1413
+ *
1414
+ * The `pageId` comes from a page's `id` in {@link DocumentResource.details}
1415
+ * or {@link DocumentResource.list} (`pages[].id`).
1416
+ *
1417
+ * @param documentId - The document the page belongs to.
1418
+ * @param pageId - The page to download.
1419
+ * @returns A {@link Buffer} of the page's JPEG bytes.
1420
+ * @throws {ValidationError} If `documentId` or `pageId` is missing.
1421
+ * @throws {ApiError} `404` if the document or page does not exist.
1024
1422
  *
1025
- * @returns an {@link ICostEstimate}: `total_credits`, balances, and a
1026
- * per-line `breakdown` of what the operation would consume.
1423
+ * @example
1424
+ * ```ts
1425
+ * const doc = await client.documents.details('doc-1');
1426
+ * const page = await client.documents.downloadPage('doc-1', doc.pages[0].id);
1427
+ * await fs.promises.writeFile('page-1.jpg', page);
1428
+ * ```
1027
1429
  */
1028
- estimateCostFromTemplate(templateId: string, signers: ITemplateSigner[], accountId?: string): Promise<ICostEstimate>;
1029
- /** Verify a document by its signature hash. */
1030
- verify(hash: string): Promise<Record<string, unknown>>;
1430
+ downloadPage(documentId: string, pageId: string): Promise<Buffer>;
1031
1431
  /**
1032
- * `GET /documents/statuses` — list every possible document status with
1033
- * its description and whether documents in that status can be deleted.
1432
+ * Fetch the document activity log
1433
+ * (`GET /documents/{documentId}/activities`).
1434
+ *
1435
+ * Returns a chronological audit trail of lifecycle events. Normalises an
1436
+ * absent body to `[]`.
1437
+ *
1438
+ * @param documentId - The document whose activity log to fetch.
1439
+ * @returns The activity entries (newest first), or `[]`:
1440
+ * ```jsonc
1441
+ * [
1442
+ * {
1443
+ * "id": 15272,
1444
+ * "event": "document_metadata_ready",
1445
+ * "message": "Documento processado.",
1446
+ * "payload": [],
1447
+ * "origin": null, // system event
1448
+ * "created_at": "2026-07-19T14:56:56Z"
1449
+ * },
1450
+ * {
1451
+ * "id": 15271,
1452
+ * "event": "document_uploaded",
1453
+ * "message": "Documento criado.",
1454
+ * "payload": [],
1455
+ * "origin": { "ip": "99.75.13.162", "user-agent": "assinafy-webforms-java-client-sdk" },
1456
+ * "created_at": "2026-07-19T14:56:55Z"
1457
+ * }
1458
+ * ]
1459
+ * ```
1460
+ * @throws {ValidationError} If `documentId` is missing.
1461
+ * @throws {ApiError} If the API rejects the request.
1462
+ *
1463
+ * @example
1464
+ * ```ts
1465
+ * const events = await client.documents.activities('doc-1');
1466
+ * console.log(events.map((e) => e.event));
1467
+ * ```
1034
1468
  */
1035
- statuses(): Promise<IDocumentStatusInfo[]>;
1469
+ activities(documentId: string): Promise<IDocumentActivity[]>;
1036
1470
  /**
1037
- * `GET /public/documents/{document_id}` — public, unauthenticated lookup of
1038
- * basic document info (used by the signing portal before the signer
1039
- * authenticates via the access code).
1471
+ * Delete a document (`DELETE /documents/{documentId}`).
1472
+ *
1473
+ * Only documents in a deletable status can be removed — the API returns
1474
+ * `400` while the document is still `uploading` / `metadata_processing`
1475
+ * (await {@link DocumentResource.waitUntilReady} first) or once it has been
1476
+ * certificated.
1477
+ *
1478
+ * @param documentId - The document to delete.
1479
+ * @returns Nothing on success.
1480
+ * @throws {ValidationError} If `documentId` is missing.
1481
+ * @throws {ApiError} `400` if the document is not in a deletable status;
1482
+ * `404` if it does not exist.
1483
+ *
1484
+ * @example
1485
+ * ```ts
1486
+ * await client.documents.delete('doc-1');
1487
+ * ```
1040
1488
  */
1041
- getPublic(documentId: string): Promise<IPublicDocumentInfo>;
1489
+ delete(documentId: string): Promise<void>;
1042
1490
  /**
1043
- * `PUT /public/documents/{document_id}/send-token` send the 6-digit
1044
- * verification token to the signer's email / WhatsApp.
1491
+ * List the tags attached to a document
1492
+ * (`GET /accounts/{accountId}/documents/{documentId}/tags`).
1493
+ *
1494
+ * @param documentId - The document whose tags to list.
1495
+ * @param accountId - Override the client's default account ID.
1496
+ * @returns The attached tags:
1497
+ * ```jsonc
1498
+ * [
1499
+ * {
1500
+ * "resource": "tag",
1501
+ * "id": "103aa252123d3bf1843a317ee0e6",
1502
+ * "name": "urgent",
1503
+ * "color": "ff8800",
1504
+ * "created_at": "2026-07-18T19:09:03Z",
1505
+ * "updated_at": "2026-07-18T19:09:03Z"
1506
+ * }
1507
+ * ]
1508
+ * ```
1509
+ * @throws {ValidationError} If `documentId` is missing or no account ID is
1510
+ * available.
1511
+ * @throws {ApiError} If the API rejects the request.
1512
+ *
1513
+ * @example
1514
+ * ```ts
1515
+ * const tags = await client.documents.listTags('doc-1');
1516
+ * ```
1045
1517
  */
1046
- sendToken(documentId: string, recipient: string, channel?: SendTokenChannel): Promise<unknown>;
1047
- /** Quick check: has every signer completed their assignment? */
1048
- isFullySigned(documentId: string): Promise<boolean>;
1049
- /** Summarise signing progress for UI display. */
1050
- getSigningProgress(documentId: string): Promise<ISigningProgress>;
1051
- }
1052
-
1053
- declare class SignerResource extends BaseResource {
1518
+ listTags(documentId: string, accountId?: string): Promise<ITag[]>;
1054
1519
  /**
1055
- * Create a signer in the workspace.
1520
+ * Replace the document's tag set
1521
+ * (`PUT /accounts/{accountId}/documents/{documentId}/tags`).
1522
+ *
1523
+ * The official contract defines `tags` as an array of tag **IDs**. An empty
1524
+ * array detaches all tags. Some environments have also accepted names and
1525
+ * auto-created missing tags, but that is an undocumented extension and
1526
+ * should not be relied on. This overwrites the existing set — use
1527
+ * {@link DocumentResource.addTags} to append.
1528
+ *
1529
+ * @param documentId - The document to retag.
1530
+ * @param tags - The complete desired set of tag IDs (`[]` clears all).
1531
+ * @param accountId - Override the client's default account ID.
1532
+ * @returns The document's tags after the replace:
1533
+ * ```jsonc
1534
+ * [
1535
+ * { "resource": "tag", "id": "103aa252…", "name": "signed", "color": null,
1536
+ * "created_at": "2026-07-18T19:09:03Z", "updated_at": "2026-07-18T19:09:03Z" }
1537
+ * ]
1538
+ * ```
1539
+ * @throws {ValidationError} If `tags` is not an array, `documentId` is
1540
+ * missing, or no account ID is available.
1541
+ * @throws {ApiError} If the API rejects the request.
1056
1542
  *
1057
- * `email` is optional — the API also accepts whatsapp-only signers — but at
1058
- * least one of `email` / `whatsapp_phone_number` (or the `phone` alias) is
1059
- * required. When an `email` is supplied the call is idempotent by email:
1060
- * an existing signer with that address is reused instead of duplicated.
1543
+ * @example
1544
+ * ```ts
1545
+ * await client.documents.replaceTags('doc-1', ['tag-signed', 'tag-archived']);
1546
+ * await client.documents.replaceTags('doc-1', []); // detach all
1547
+ * ```
1061
1548
  */
1062
- create(payload: ICreateSignerPayload, accountId?: string): Promise<ICreateSignerResponse>;
1063
- /** Get a signer by ID. */
1064
- get(signerId: string, accountId?: string): Promise<ISigner>;
1065
- /** List signers for the workspace (supports `page`, `per-page`, `search`, `sort`). */
1066
- list(params?: IListParams, accountId?: string): Promise<ISignerListResponse>;
1067
- /** Update a signer. Fails if the signer has active assignments. */
1068
- update(signerId: string, payload: IUpdateSignerPayload, accountId?: string): Promise<ICreateSignerResponse>;
1069
- /** Delete a signer. */
1070
- delete(signerId: string, accountId?: string): Promise<void>;
1549
+ replaceTags(documentId: string, tags: string[], accountId?: string): Promise<ITag[]>;
1071
1550
  /**
1072
- * Find a signer by exact email, using the API's `search` filter to narrow
1073
- * the page first. Returns `null` if none match.
1074
- *
1075
- * `search` is a substring match across signer fields, so the result is
1076
- * re-filtered here for an exact, case-insensitive email match.
1551
+ * Attach additional tags without removing existing ones
1552
+ * (`POST /accounts/{accountId}/documents/{documentId}/tags`).
1077
1553
  *
1078
- * Page size is pinned to the API's maximum of 50: larger values are
1079
- * silently clamped to 50 by the server, so asking for more is misleading.
1080
- * An exact address realistically matches one signer, but a search term that
1081
- * matched more than 50 could in principle miss one — the API exposes no
1082
- * exact-email filter to rule that out.
1554
+ * `tags` is a non-empty array of tag **IDs**. Attaching an ID already
1555
+ * present is a no-op. To replace the whole set instead, use
1556
+ * {@link DocumentResource.replaceTags}.
1083
1557
  *
1084
- * @param email - Exact email address to look for.
1558
+ * @param documentId - The document to tag.
1559
+ * @param tags - Tag IDs to attach (must be non-empty).
1085
1560
  * @param accountId - Override the client's default account ID.
1086
- * @returns The matching {@link ISigner}, or `null`.
1087
- * @throws {ValidationError} If `email` is not a valid address.
1561
+ * @returns The document's tags after the attach:
1562
+ * ```jsonc
1563
+ * [
1564
+ * { "resource": "tag", "id": "103aa252…", "name": "urgent", "color": null,
1565
+ * "created_at": "2026-07-18T19:09:03Z", "updated_at": "2026-07-18T19:09:03Z" }
1566
+ * ]
1567
+ * ```
1568
+ * @throws {ValidationError} If `tags` is empty or not an array,
1569
+ * `documentId` is missing, or no account ID is available.
1570
+ * @throws {ApiError} If the API rejects the request.
1571
+ *
1572
+ * @example
1573
+ * ```ts
1574
+ * await client.documents.addTags('doc-1', ['tag-urgent']);
1575
+ * ```
1088
1576
  */
1089
- findByEmail(email: string, accountId?: string): Promise<ISigner | null>;
1090
- private assertEmail;
1091
- }
1092
-
1093
- declare class WorkspaceResource extends BaseResource {
1094
- /** Create a new workspace. */
1095
- create(payload: ICreateWorkspacePayload): Promise<IWorkspaceResponse>;
1096
- /** List workspaces the authenticated user can access. */
1097
- list(): Promise<IWorkspaceListResponse>;
1098
- /** Fetch a single workspace. */
1099
- get(accountId: string): Promise<IWorkspaceResponse>;
1100
- /** Update a workspace. */
1101
- update(accountId: string, payload: IUpdateWorkspacePayload): Promise<IWorkspaceResponse>;
1102
- /** Delete a workspace. */
1103
- delete(accountId: string): Promise<void>;
1104
- }
1105
-
1106
- /**
1107
- * Normalise an assignment payload into the shape the API expects:
1108
- * `signers: [{ id }]` plus optional docs-level fields.
1109
- */
1110
- declare function buildAssignmentPayload(payload: ICreateAssignmentPayload, options?: {
1111
- allowSignersWithoutId?: boolean;
1112
- }): Record<string, unknown>;
1113
- declare class AssignmentResource extends BaseResource {
1577
+ addTags(documentId: string, tags: string[], accountId?: string): Promise<ITag[]>;
1114
1578
  /**
1115
- * List assignments across the workspace (`GET /assignments`).
1579
+ * Detach a single tag from a document
1580
+ * (`DELETE /accounts/{accountId}/documents/{documentId}/tags/{tagId}`).
1116
1581
  *
1117
- * The account is passed as an `accountId` **query parameter** the API
1118
- * responds `400` ("Um contexto de conta é necessário e não foi fornecido")
1119
- * without it. Note the camelCase spelling: `account_id` and an
1120
- * `X-Account-Id` header are both rejected.
1582
+ * Removes the association only the workspace tag itself is not deleted.
1583
+ * Like {@link DocumentResource.addTags} /
1584
+ * {@link DocumentResource.replaceTags}, this takes the tag's **ID**.
1121
1585
  *
1122
- * @param params - `page`, `per-page`.
1586
+ * @param documentId - The document to detach from.
1587
+ * @param tagId - The ID of the tag to detach.
1588
+ * @param accountId - Override the client's default account ID.
1589
+ * @returns Nothing on success.
1590
+ * @throws {ValidationError} If `documentId` or `tagId` is missing, or no
1591
+ * account ID is available.
1592
+ * @throws {ApiError} If the API rejects the request.
1593
+ *
1594
+ * @example
1595
+ * ```ts
1596
+ * await client.documents.detachTag('doc-1', 'tag-1');
1597
+ * ```
1598
+ */
1599
+ detachTag(documentId: string, tagId: string, accountId?: string): Promise<void>;
1600
+ /**
1601
+ * Create a document from a template
1602
+ * (`POST /accounts/{accountId}/templates/{templateId}/documents`).
1603
+ *
1604
+ * Instantiates the template, binding each role to a signer, and returns the
1605
+ * new document. The request body is `{ signers, ...options }` — `signers`
1606
+ * maps template `role_id` → signer `id`, and `options` may add `name`,
1607
+ * `message`, `expires_at`, `editor_fields`, and `tags`.
1608
+ *
1609
+ * @param templateId - The template to instantiate.
1610
+ * @param signers - Role-to-signer bindings (each with `role_id` and `id`,
1611
+ * plus optional `verification_method`, `notification_methods`, `step`).
1612
+ * @param options - Optional `name`, `message`, `expires_at`,
1613
+ * `editor_fields`, `tags`.
1123
1614
  * @param accountId - Override the client's default account ID.
1124
- * @returns Assignments, with pagination in `meta`. Each item:
1615
+ * @returns The created document (an {@link IDocumentDetailsResponse} with
1616
+ * `template_id` set and its `assignment` populated):
1125
1617
  * ```jsonc
1126
1618
  * {
1127
- * "id": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4",
1128
- * "sender_email": "sender@example.com",
1129
- * "method": "virtual",
1130
- * "expires_at": null,
1131
- * "message": "Please sign this contract",
1132
- * "signers": [
1133
- * {
1134
- * "id": "b2c3d4e5f6a7b8c9d0e1f2a3b4c5",
1135
- * "full_name": "Ana Souza",
1136
- * "email": "signer@example.com",
1137
- * "whatsapp_phone_number": null,
1138
- * "has_accepted_terms": false,
1139
- * "completed": false,
1140
- * "notification_history": [],
1141
- * "verification_method": "Email",
1142
- * "notification_methods": ["Email"],
1143
- * "step": 1,
1144
- * "notified": true
1145
- * }
1146
- * ]
1619
+ * "resource": "document",
1620
+ * "id": "19f675b761b392a48b8642503bb",
1621
+ * "account_id": "acc_example",
1622
+ * "template_id": "103a0991a5cde83518e5672aa9aa",
1623
+ * "name": "Audit From Template",
1624
+ * "status": "pending_signature",
1625
+ * "artifacts": { "original": "https://…/download/original", "thumbnail": "https://…/thumbnail" },
1626
+ * "is_closed": false,
1627
+ * "signing_url": "https://app-sandbox.assinafy.com.br/sign/19f675b7…",
1628
+ * "tags": [{ "id": "103a0992…", "name": "audit-tmp-fromtmpl", "color": null }],
1629
+ * "assignment": { "id": "103a09a1…", "method": "virtual", "summary": { "signer_count": 1, "completed_count": 0 } },
1630
+ * "pages": [{ "id": "103a0992…", "number": 1, "height": 1651, "width": 1275, "download_url": "https://…/download" }],
1631
+ * "created_at": "2026-07-15T19:57:55Z",
1632
+ * "updated_at": "2026-07-15T19:59:33Z"
1147
1633
  * }
1148
1634
  * ```
1149
- * @throws {ValidationError} If no account ID is available.
1635
+ * @throws {ValidationError} If `templateId` is missing or no account ID is
1636
+ * available.
1637
+ * @throws {ApiError} `400` if the signers/roles are invalid or the template
1638
+ * is not ready.
1639
+ *
1640
+ * @example
1641
+ * ```ts
1642
+ * await client.documents.createFromTemplate('tmpl_id', [
1643
+ * { role_id: 'role_id', id: 'signer_id', verification_method: 'Email', notification_methods: ['Email'] },
1644
+ * ], { name: 'My Contract' });
1645
+ * ```
1646
+ */
1647
+ createFromTemplate(templateId: string, signers: ITemplateSigner[], options?: ICreateDocumentFromTemplateOptions, accountId?: string): Promise<IDocumentDetailsResponse>;
1648
+ /**
1649
+ * Estimate the credit cost of creating a document from a template
1650
+ * (`POST /accounts/{accountId}/templates/{templateId}/documents/estimate-cost`).
1651
+ *
1652
+ * A dry run: sends only `{ signers }` and consumes nothing. Use it to check
1653
+ * balances before calling {@link DocumentResource.createFromTemplate}.
1654
+ *
1655
+ * @param templateId - The template that would be instantiated.
1656
+ * @param signers - One channel descriptor per template role. Cost requests
1657
+ * use only `role_id`, `verification_method`, and `notification_methods`;
1658
+ * they do not send a signer ID or signing-order step.
1659
+ * @param accountId - Override the client's default account ID.
1660
+ * @returns An {@link ICostEstimate}: `total_credits`, balances, and a
1661
+ * per-line `breakdown` of what the operation would consume:
1662
+ * ```jsonc
1663
+ * {
1664
+ * "documents": 1,
1665
+ * "credits": 1,
1666
+ * "needs_extra_document": false,
1667
+ * "extra_document_cost": 0,
1668
+ * "total_credits": 1,
1669
+ * "breakdown": [
1670
+ * { "code": "signature", "name": "Assinatura", "cost": 1, "quantity": 1, "unit_cost": 1 }
1671
+ * ],
1672
+ * "document_balance": 10,
1673
+ * "credit_balance": 250,
1674
+ * "has_sufficient_resources": true,
1675
+ * "blocking_reason": null,
1676
+ * "message": null
1677
+ * }
1678
+ * ```
1679
+ * @throws {ValidationError} If `templateId` is missing or no account ID is
1680
+ * available.
1150
1681
  * @throws {ApiError} If the API rejects the request.
1151
1682
  *
1152
1683
  * @example
1153
1684
  * ```ts
1154
- * const { data, meta } = await client.assignments.list({ 'per-page': 20 });
1685
+ * const estimate = await client.documents.estimateCostFromTemplate('tmpl_id', [
1686
+ * { role_id: 'role_id', verification_method: 'Email' },
1687
+ * ]);
1688
+ * if (!estimate.has_sufficient_resources) throw new Error(estimate.blocking_reason ?? 'insufficient');
1155
1689
  * ```
1156
1690
  */
1157
- list(params?: IAssignmentListParams, accountId?: string): Promise<IAssignmentListResponse>;
1158
- /** Create a signing assignment for a document. */
1159
- create(documentId: string, payload: ICreateAssignmentPayload): Promise<ICreateAssignmentResponse>;
1691
+ estimateCostFromTemplate(templateId: string, signers: ITemplateCostSigner[], accountId?: string): Promise<ICostEstimate>;
1160
1692
  /**
1161
- * Estimate the cost (in credits/documents) of creating the assignment.
1693
+ * Verify a signed document by its signature hash
1694
+ * (`GET /documents/{documentSignatureHash}/verify`).
1162
1695
  *
1163
- * Signer entries may omit `id` and supply only `verification_method` /
1164
- * `notification_methods` when only the channel mix matters for the estimate.
1696
+ * Public authenticity check: given the hash embedded in a certificated
1697
+ * document, returns the API's typed verification record for it. Unknown
1698
+ * hashes still return HTTP 200 with `is_valid: false`.
1165
1699
  *
1166
- * @returns an {@link ICostEstimate} with `total_credits`, balances, and a
1167
- * line-item `breakdown`.
1700
+ * @param hash - The document's signature hash (the
1701
+ * `documentSignatureHash` path segment).
1702
+ * @returns `{ hash, id, status, page_count, signer_count, completed_count,
1703
+ * completed_at, verified_at, is_valid, message }`.
1704
+ * @throws {ValidationError} If `hash` is missing.
1705
+ * @throws {ApiError} If the API rejects the request.
1706
+ *
1707
+ * @example
1708
+ * ```ts
1709
+ * const result = await client.documents.verify('a7b8c9d0e1f2…');
1710
+ * ```
1168
1711
  */
1169
- estimateCost(documentId: string, payload: ICreateAssignmentPayload): Promise<ICostEstimate>;
1712
+ verify(hash: string): Promise<IDocumentVerification>;
1170
1713
  /**
1171
- * Update the expiration date of an existing assignment.
1172
- * Pass `null` to remove the expiration entirely.
1714
+ * List every possible document status (`GET /documents/statuses`).
1715
+ *
1716
+ * A static catalog (11 entries) of each status `code` and whether documents
1717
+ * in that status can be deleted (`deletable`). This catalog requires the
1718
+ * same API-key or Bearer authentication as other workspace operations.
1719
+ *
1720
+ * @returns The status catalog:
1721
+ * ```jsonc
1722
+ * [
1723
+ * { "code": "uploading", "deletable": false },
1724
+ * { "code": "uploaded", "deletable": false },
1725
+ * { "code": "metadata_processing", "deletable": false },
1726
+ * { "code": "metadata_ready", "deletable": true },
1727
+ * { "code": "pending_signature", "deletable": true },
1728
+ * { "code": "certificated", "deletable": false }
1729
+ * // …11 total: also expired, certificating, rejected_by_signer,
1730
+ * // rejected_by_user, failed
1731
+ * ]
1732
+ * ```
1733
+ * @throws {ApiError} If the API rejects the request.
1734
+ *
1735
+ * @example
1736
+ * ```ts
1737
+ * const statuses = await client.documents.statuses();
1738
+ * const deletable = statuses.filter((s) => s.deletable).map((s) => s.code);
1739
+ * ```
1173
1740
  */
1174
- resetExpiration(documentId: string, assignmentId: string, expiresAt: string | null): Promise<IAssignment>;
1175
- /** Resend the signing notification to a single signer. */
1176
- resendNotification(documentId: string, assignmentId: string, signerId: string): Promise<IResendEmailResponse>;
1741
+ statuses(): Promise<IDocumentStatusInfo[]>;
1177
1742
  /**
1178
- * Estimate the cost of resending a signer notification.
1743
+ * Public, unauthenticated lookup of basic document info
1744
+ * (`GET /public/documents/{documentId}`).
1745
+ *
1746
+ * Used by the signing portal before the signer authenticates via the access
1747
+ * code, so it returns only non-sensitive fields.
1748
+ *
1749
+ * @param documentId - The document to look up.
1750
+ * @returns Basic public info for the document:
1751
+ * ```jsonc
1752
+ * {
1753
+ * "resource": "document",
1754
+ * "id": "103ad216846e6b90710cb9acef59",
1755
+ * "name": "Service agreement.pdf",
1756
+ * "page_count": 1,
1757
+ * "created_by": "Multica Test"
1758
+ * }
1759
+ * ```
1760
+ * @throws {ValidationError} If `documentId` is missing.
1761
+ * @throws {ApiError} `404` if the document does not exist.
1179
1762
  *
1180
- * @returns an {@link IResendCostEstimate} (`total`, `breakdown`, balances).
1763
+ * @example
1764
+ * ```ts
1765
+ * const info = await client.documents.getPublic('103ad216846e6b90710cb9acef59');
1766
+ * ```
1181
1767
  */
1182
- estimateResendCost(documentId: string, assignmentId: string, signerId: string): Promise<IResendCostEstimate>;
1768
+ getPublic(documentId: string): Promise<IPublicDocumentInfo>;
1183
1769
  /**
1184
- * `GET /documents/{documentId}/assignments/{assignmentId}/whatsapp-notifications`
1185
- * list every WhatsApp notification rendered + sent for an assignment.
1770
+ * Send the signer's access token to their email / WhatsApp
1771
+ * (`PUT /public/documents/{documentId}/send-token`).
1772
+ *
1773
+ * Part of the public signing flow: dispatches the 6-digit verification
1774
+ * token the signer enters to view the document. The documented request body
1775
+ * is `{ email }`. For compatibility with Assinafy environments that still
1776
+ * require the older contract, passing an explicit `channel` sends
1777
+ * `{ recipient, channel }`; the two-argument documented call also retries
1778
+ * that legacy shape only when the server explicitly reports that
1779
+ * `channel`/`recipient` is required.
1780
+ *
1781
+ * @param documentId - The document to send the token for.
1782
+ * @param recipient - The signer's email address (or WhatsApp number when an
1783
+ * explicit channel is supplied).
1784
+ * @param channel - Optional legacy delivery channel.
1785
+ * @returns Nothing after the API's empty acknowledgement.
1786
+ * @throws {ValidationError} If `documentId` or `recipient` is missing.
1787
+ * @throws {ApiError} If the API rejects the request.
1788
+ *
1789
+ * @example
1790
+ * ```ts
1791
+ * await client.documents.sendToken('doc-1', 'signer@example.com');
1792
+ * await client.documents.sendToken('doc-1', '+5511999998888', 'whatsapp');
1793
+ * ```
1186
1794
  */
1187
- listWhatsAppNotifications(documentId: string, assignmentId: string): Promise<IWhatsAppNotification[]>;
1188
- }
1189
-
1190
- /**
1191
- * Default webhook events applied by {@link WebhookResource.register} when the
1192
- * caller omits `events` (or passes an empty array).
1193
- */
1194
- declare const DEFAULT_WEBHOOK_EVENTS: WebhookEventType[];
1195
- declare class WebhookResource extends BaseResource {
1795
+ sendToken(documentId: string, email: string): Promise<void>;
1796
+ sendToken(documentId: string, recipient: string, channel: SendTokenChannel): Promise<void>;
1196
1797
  /**
1197
- * Register (or replace) the workspace's single webhook subscription
1198
- * (`PUT /accounts/{id}/webhooks/subscriptions`). There is exactly one
1199
- * subscription per workspace, keyed by URL.
1798
+ * Quick boolean check: has every signer completed their assignment?
1200
1799
  *
1201
- * When `events` is omitted or empty, {@link DEFAULT_WEBHOOK_EVENTS} is used
1202
- * (`document_ready`, `document_prepared`, `signer_signed_document`,
1203
- * `signer_rejected_document`, `document_processing_failed`).
1800
+ * A computed convenience over {@link DocumentResource.details} (one `GET
1801
+ * /documents/{documentId}`). Returns `true` when the document status is
1802
+ * `certificated`, or when the assignment summary reports at least one signer
1803
+ * and `signer_count === completed_count`. Returns `false` when there is no
1804
+ * assignment summary (nothing to sign yet) or counts disagree.
1805
+ *
1806
+ * @param documentId - The document to check.
1807
+ * @returns `true` if fully signed, otherwise `false`.
1808
+ * @throws {ValidationError} If `documentId` is missing.
1809
+ * @throws {ApiError} `404` if the document does not exist.
1204
1810
  *
1205
1811
  * @example
1206
1812
  * ```ts
1207
- * await client.webhooks.register({ url: 'https://example.com/hook', email: 'ops@example.com' });
1208
- * // { url, email, events: [...], is_active: true, updated_at: '2026-…' }
1813
+ * if (await client.documents.isFullySigned('doc-1')) {
1814
+ * const pdf = await client.documents.download('doc-1');
1815
+ * }
1209
1816
  * ```
1210
1817
  */
1211
- register(payload: IWebhookRegisterPayload, accountId?: string): Promise<IWebhookSubscription>;
1212
- /** Fetch the current webhook subscription. Returns `null` if none exists. */
1213
- get(accountId?: string): Promise<IWebhookSubscription | null>;
1818
+ isFullySigned(documentId: string): Promise<boolean>;
1214
1819
  /**
1215
- * Inactivate the current webhook subscription.
1820
+ * Summarise signing progress for UI display.
1216
1821
  *
1217
- * This is the only supported way to stop deliveries — the API has no
1218
- * subscription-delete route. The subscription is retained (with its `url`
1219
- * and `events`) and simply stops firing; re-enable it by calling
1220
- * {@link WebhookResource.register} again with `is_active: true`.
1822
+ * A computed convenience over {@link DocumentResource.details} (one `GET
1823
+ * /documents/{documentId}`). `total` and `signed` come from the assignment
1824
+ * summary's `signer_count` / `completed_count`; when the summary is absent
1825
+ * `total` falls back to `assignment.signers.length` (and `signed` to `0`).
1826
+ * `percentage` is `signed / total` rounded to two decimals (`0` when
1827
+ * `total` is `0`).
1828
+ *
1829
+ * @param documentId - The document to summarise.
1830
+ * @returns An {@link ISigningProgress}, e.g. one of three signed:
1831
+ * ```jsonc
1832
+ * { "signed": 1, "total": 3, "pending": 2, "percentage": 33.33 }
1833
+ * ```
1834
+ * @throws {ValidationError} If `documentId` is missing.
1835
+ * @throws {ApiError} `404` if the document does not exist.
1836
+ *
1837
+ * @example
1838
+ * ```ts
1839
+ * const { signed, total, percentage } = await client.documents.getSigningProgress('doc-1');
1840
+ * console.log(`${signed}/${total} (${percentage}%)`);
1841
+ * ```
1221
1842
  */
1222
- inactivate(accountId?: string): Promise<IWebhookSubscription>;
1223
- /** List currently supported webhook event types. */
1224
- listEventTypes(): Promise<IWebhookEventTypeInfo[]>;
1225
- /** List webhook delivery history for the workspace. */
1226
- listDispatches(params?: IWebhookDispatchListParams, accountId?: string): Promise<PaginatedResult<IWebhookDispatch>>;
1227
- /** Retry delivery of a specific webhook dispatch. */
1228
- retryDispatch(dispatchId: string, accountId?: string): Promise<IWebhookDispatch>;
1843
+ getSigningProgress(documentId: string): Promise<ISigningProgress>;
1229
1844
  }
1230
1845
 
1231
- declare class TemplateResource extends BaseResource {
1846
+ declare class SignerResource extends BaseResource {
1232
1847
  /**
1233
- * Create a template by uploading a PDF (`POST /accounts/{id}/templates`).
1848
+ * Create a signer in the workspace (`POST /accounts/{accountId}/signers`).
1234
1849
  *
1235
- * The template is created in `Uploaded` status and transitions to `Ready`
1236
- * once the platform finishes processing its pages. Configure roles/fields
1237
- * afterwards in the Assinafy editor.
1850
+ * `email` and `whatsapp_phone_number` are both optional in the official
1851
+ * schema; a name-only signer is valid. When an `email` is supplied the call
1852
+ * is idempotent by email:
1853
+ * an existing signer with that address is reused instead of duplicated (a
1854
+ * duplicate POST is answered by the API with `400 "Um signatário com este
1855
+ * e-mail já existe."`, which this method recovers from transparently).
1856
+ *
1857
+ * @param payload - The signer to create. Only `full_name` is required.
1858
+ * Optional `email`, `whatsapp_phone_number`/`phone`, and `cpf` are normalized
1859
+ * before sending.
1860
+ * @param accountId - Override the client's default account ID.
1861
+ * @returns The created (or reused) signer. Note the response **never echoes
1862
+ * `cpf` back**, even when one was sent:
1863
+ * ```jsonc
1864
+ * {
1865
+ * "resource": "signer",
1866
+ * "id": "19e6b92e7895332ed9708535d8c",
1867
+ * "full_name": "Ana Souza",
1868
+ * "email": "ana@example.com",
1869
+ * "whatsapp_phone_number": null,
1870
+ * "has_accepted_terms": false
1871
+ * }
1872
+ * ```
1873
+ * @throws {ValidationError} If the name/contact values are malformed or no
1874
+ * account ID is available.
1875
+ * @throws {ApiError} If the API rejects the request for a reason other than a
1876
+ * recoverable duplicate email.
1238
1877
  *
1239
1878
  * @example
1240
1879
  * ```ts
1241
- * const tmpl = await client.templates.create(
1242
- * { filePath: './nda.pdf' },
1243
- * { name: 'NDA template' },
1244
- * );
1245
- * // → { resource: 'template', id, name, status: 'Uploaded',
1246
- * // roles: [{ id, name: 'TemplateEditor', assignment_type: 'Editor' }],
1247
- * // pages: [], tags: [], created_at, updated_at }
1880
+ * const signer = await client.signers.create({
1881
+ * full_name: 'Ana Souza',
1882
+ * email: 'ana@example.com',
1883
+ * cpf: '390.533.447-05', // sent as '39053344705', never echoed back
1884
+ * });
1885
+ *
1886
+ * // A whatsapp-only signer (no email):
1887
+ * await client.signers.create({
1888
+ * full_name: 'Bruno Lima',
1889
+ * whatsapp_phone_number: '+5548999990000',
1890
+ * });
1891
+ *
1892
+ * // Name-only is also valid (but cannot receive a notification yet):
1893
+ * await client.signers.create({ full_name: 'Carla Sem Contato' });
1248
1894
  * ```
1249
1895
  */
1250
- create(source: DocumentUploadSource, options?: {
1251
- name?: string;
1252
- accountId?: string;
1253
- }): Promise<ITemplateDetailsResponse>;
1254
- /** List templates for the workspace. */
1255
- list(params?: IListParams, accountId?: string): Promise<ITemplateListResponse>;
1896
+ create(payload: ICreateSignerPayload, accountId?: string): Promise<ICreateSignerResponse>;
1256
1897
  /**
1257
- * Get a template by ID (`GET /accounts/{id}/templates/{template_id}`).
1898
+ * Get a signer by ID (`GET /accounts/{accountId}/signers/{signerId}`).
1258
1899
  *
1259
- * Returns the same shape as {@link TemplateResource.list} plus
1260
- * `default_document_tags` (the tags auto-applied to every document created
1261
- * from this template) and `resource`. Both endpoints return `pages` with
1262
- * per-page `download_url`, so fetching a template again purely to read its
1263
- * pages is unnecessary.
1900
+ * @param signerId - The signer to fetch.
1901
+ * @param accountId - Override the client's default account ID.
1902
+ * @returns The signer:
1903
+ * ```jsonc
1904
+ * {
1905
+ * "resource": "signer",
1906
+ * "id": "19e6b92e7895332ed9708535d8c",
1907
+ * "full_name": "Example Signer",
1908
+ * "email": "signer@example.com",
1909
+ * "whatsapp_phone_number": null,
1910
+ * "has_accepted_terms": false
1911
+ * }
1912
+ * ```
1913
+ * @throws {ValidationError} If `signerId` is missing or no account ID is available.
1914
+ * @throws {ApiError} `404` if the signer does not exist.
1915
+ *
1916
+ * @example
1917
+ * ```ts
1918
+ * const signer = await client.signers.get('19e6b92e7895332ed9708535d8c');
1919
+ * ```
1264
1920
  */
1265
- get(templateId: string, accountId?: string): Promise<ITemplateDetailsResponse>;
1921
+ get(signerId: string, accountId?: string): Promise<ISigner>;
1266
1922
  /**
1267
- * Update a template's `name` and/or default `message`
1268
- * (`PUT /accounts/{id}/templates/{template_id}`). Returns the updated template.
1923
+ * List signers for the workspace (`GET /accounts/{accountId}/signers`).
1924
+ * Pagination info (if any) is attached in `meta`.
1925
+ *
1926
+ * @param params - `page`, `per-page`, `search`, `sort`. `per-page` is
1927
+ * clamped to the API maximum of 50.
1928
+ * @param accountId - Override the client's default account ID.
1929
+ * @returns The matching signers, with pagination in `meta`. Each item:
1930
+ * ```jsonc
1931
+ * {
1932
+ * "id": "19e6b92e7895332ed9708535d8c",
1933
+ * "full_name": "Example Signer",
1934
+ * "email": "signer@example.com",
1935
+ * "whatsapp_phone_number": null,
1936
+ * "has_accepted_terms": false
1937
+ * }
1938
+ * ```
1939
+ * @throws {ValidationError} If no account ID is available.
1940
+ * @throws {ApiError} If the API rejects the request.
1269
1941
  *
1270
1942
  * @example
1271
1943
  * ```ts
1272
- * await client.templates.update(templateId, { name: 'NDA v2', message: 'Please sign' });
1944
+ * const { data, meta } = await client.signers.list({
1945
+ * search: 'ana',
1946
+ * 'per-page': 20,
1947
+ * });
1273
1948
  * ```
1274
1949
  */
1275
- update(templateId: string, payload: IUpdateTemplatePayload, accountId?: string): Promise<ITemplateDetailsResponse>;
1276
- /** Delete a template (`DELETE /accounts/{id}/templates/{template_id}`). */
1277
- delete(templateId: string, accountId?: string): Promise<void>;
1950
+ list(params?: IListParams, accountId?: string): Promise<ISignerListResponse>;
1278
1951
  /**
1279
- * Download a template page as a JPEG
1280
- * (`GET /accounts/{id}/templates/{template_id}/pages/{page_id}/download`).
1952
+ * Update a signer (`PUT /accounts/{accountId}/signers/{signerId}`). Fails
1953
+ * if the signer has active assignments.
1281
1954
  *
1282
- * Used by template editors to render page thumbnails on the client. The
1283
- * matching `download_url` is also returned on each `template.pages[]` entry.
1955
+ * @param signerId - The signer to update.
1956
+ * @param payload - Fields to change. Any `cpf` is stripped to digits before
1957
+ * sending.
1958
+ * @param accountId - Override the client's default account ID.
1959
+ * @returns The updated signer (as with create, `cpf` is never echoed back):
1960
+ * ```jsonc
1961
+ * {
1962
+ * "resource": "signer",
1963
+ * "id": "19e6b92e7895332ed9708535d8c",
1964
+ * "full_name": "Ana Souza Lima",
1965
+ * "email": "ana@example.com",
1966
+ * "whatsapp_phone_number": null,
1967
+ * "has_accepted_terms": false
1968
+ * }
1969
+ * ```
1970
+ * @throws {ValidationError} If `signerId` is missing or no account ID is available.
1971
+ * @throws {ApiError} `400` if the signer has active assignments; `404` if it
1972
+ * does not exist.
1973
+ *
1974
+ * @example
1975
+ * ```ts
1976
+ * await client.signers.update('19e6b92e7895332ed9708535d8c', {
1977
+ * full_name: 'Ana Souza Lima',
1978
+ * });
1979
+ * ```
1284
1980
  */
1285
- downloadPage(templateId: string, pageId: string, accountId?: string): Promise<Buffer>;
1981
+ update(signerId: string, payload: IUpdateSignerPayload, accountId?: string): Promise<ICreateSignerResponse>;
1982
+ /**
1983
+ * Delete a signer (`DELETE /accounts/{accountId}/signers/{signerId}`).
1984
+ *
1985
+ * @param signerId - The signer to delete.
1986
+ * @param accountId - Override the client's default account ID.
1987
+ * @returns Nothing on success (resolves to `void`).
1988
+ * @throws {ValidationError} If `signerId` is missing or no account ID is available.
1989
+ * @throws {ApiError} `404` if the signer does not exist; `400`/`409` if it
1990
+ * still has active assignments.
1991
+ *
1992
+ * @example
1993
+ * ```ts
1994
+ * await client.signers.delete('19e6b92e7895332ed9708535d8c');
1995
+ * ```
1996
+ */
1997
+ delete(signerId: string, accountId?: string): Promise<void>;
1998
+ /**
1999
+ * Find a signer by exact email
2000
+ * (`GET /accounts/{accountId}/signers?search={email}`), using the API's
2001
+ * `search` filter to narrow the page first. Returns `null` if none match.
2002
+ *
2003
+ * `search` is a substring match across signer fields, so the result is
2004
+ * re-filtered here for an exact, case-insensitive email match.
2005
+ *
2006
+ * Page size is pinned to the API's maximum of 50: larger values are
2007
+ * silently clamped to 50 by the server, so asking for more is misleading.
2008
+ * An exact address realistically matches one signer, but a search term that
2009
+ * matched more than 50 could in principle miss one — the API exposes no
2010
+ * exact-email filter to rule that out.
2011
+ *
2012
+ * A `404` from the underlying list is treated as "no match" and mapped to
2013
+ * `null`; any other {@link ApiError} propagates.
2014
+ *
2015
+ * @param email - Exact email address to look for.
2016
+ * @param accountId - Override the client's default account ID.
2017
+ * @returns The matching {@link ISigner}, or `null` if none match. A hit
2018
+ * looks like:
2019
+ * ```jsonc
2020
+ * {
2021
+ * "id": "19e6b92e7895332ed9708535d8c",
2022
+ * "full_name": "Ana Souza",
2023
+ * "email": "ana@example.com",
2024
+ * "whatsapp_phone_number": null,
2025
+ * "has_accepted_terms": false
2026
+ * }
2027
+ * ```
2028
+ * @throws {ValidationError} If `email` is not a valid address.
2029
+ * @throws {ApiError} If the list request fails with a status other than 404.
2030
+ *
2031
+ * @example
2032
+ * ```ts
2033
+ * const signer = await client.signers.findByEmail('ana@example.com');
2034
+ * if (signer) console.log(signer.id);
2035
+ * ```
2036
+ */
2037
+ findByEmail(email: string, accountId?: string): Promise<ISigner | null>;
2038
+ private assertEmail;
1286
2039
  }
1287
2040
 
2041
+ /** File accepted by the account-logo upload endpoint. */
2042
+ type AccountLogoUploadSource = {
2043
+ filePath: string;
2044
+ fileName?: string;
2045
+ contentType?: string;
2046
+ } | {
2047
+ buffer: Buffer;
2048
+ fileName: string;
2049
+ contentType?: string;
2050
+ };
1288
2051
  /**
1289
- * Workspace-scoped tags used to label documents and templates.
2052
+ * Manage workspaces the Assinafy _account_ objects that own every document,
2053
+ * signer, template, tag, field, and webhook. Each endpoint lives under
2054
+ * `/accounts`, and the `accountId` used elsewhere in the SDK is a workspace id.
1290
2055
  *
1291
- * Covers the full Tag section of the API docs:
1292
- * - `GET /accounts/{id}/tags` → {@link list}
1293
- * - `POST /accounts/{id}/tags` {@link create}
1294
- * - `PUT /accounts/{id}/tags/{tag_id}` → {@link update}
1295
- * - `DELETE /accounts/{id}/tags/{tag_id}` → {@link delete}
2056
+ * Colours (`primary_color` / `secondary_color`) are stored on the workspace and
2057
+ * echoed back on the response. They must be an **exactly 6-character hex string
2058
+ * with NO leading `#`** (`'ff0066'`, not `'#ff0066'`); a `#`-prefixed value is
2059
+ * rejected with `400`. Verified live against the API.
1296
2060
  *
1297
- * Document-level attach/detach lives on {@link DocumentResource} (`listTags`,
1298
- * `replaceTags`, `addTags`, `detachTag`).
2061
+ * @example
2062
+ * ```ts
2063
+ * const ws = await client.workspaces.create({ name: 'Acme Legal' });
2064
+ * const { data } = await client.workspaces.list();
2065
+ * ```
1299
2066
  */
1300
- declare class TagResource extends BaseResource {
1301
- /** List the workspace's tags, ordered alphabetically. Optional case-insensitive `search`. */
1302
- list(params?: {
1303
- search?: string;
1304
- }, accountId?: string): Promise<ITag[]>;
1305
- /** Create a tag. Throws `ApiError` (409) if the name already exists (case-insensitive). */
1306
- create(payload: ICreateTagPayload, accountId?: string): Promise<ITag>;
2067
+ declare class WorkspaceResource extends BaseResource {
2068
+ /**
2069
+ * Create a new workspace (`POST /accounts`).
2070
+ *
2071
+ * @param payload - The workspace `name` (required) plus optional brand
2072
+ * colours. Colours are 6-char hex **without** a leading `#`.
2073
+ * @returns The created workspace. Response shape:
2074
+ * ```jsonc
2075
+ * {
2076
+ * "id": "acc_example",
2077
+ * "name": "Acme Legal",
2078
+ * "primary_color": "ff0066",
2079
+ * "secondary_color": "0066ff",
2080
+ * "created_at": "2026-05-12T18:05:11Z"
2081
+ * }
2082
+ * ```
2083
+ * @throws {ApiError} If the API rejects the request — e.g. `400` when a
2084
+ * colour is not exactly 6 hex characters (or carries a leading `#`).
2085
+ *
2086
+ * @example
2087
+ * ```ts
2088
+ * const ws = await client.workspaces.create({
2089
+ * name: 'Acme Legal',
2090
+ * primary_color: 'ff0066',
2091
+ * secondary_color: '0066ff',
2092
+ * });
2093
+ * ```
2094
+ */
2095
+ create(payload: ICreateWorkspacePayload): Promise<IWorkspaceResponse>;
2096
+ /**
2097
+ * List workspaces the authenticated user can access (`GET /accounts`).
2098
+ *
2099
+ * @returns The workspaces, with any pagination in `meta`. Each item exposes
2100
+ * the caller's `roles` and whether it may be deleted:
2101
+ * ```jsonc
2102
+ * {
2103
+ * "data": [
2104
+ * {
2105
+ * "id": "acc_example",
2106
+ * "name": "MT",
2107
+ * "roles": ["owner"],
2108
+ * "is_delete_allowed": true,
2109
+ * "created_at": "2026-05-12T18:05:11Z"
2110
+ * }
2111
+ * ]
2112
+ * }
2113
+ * ```
2114
+ * @throws {ApiError} If the API rejects the request.
2115
+ *
2116
+ * @example
2117
+ * ```ts
2118
+ * const { data } = await client.workspaces.list();
2119
+ * const owned = data.filter((w) => w.roles.includes('owner'));
2120
+ * ```
2121
+ */
2122
+ list(): Promise<IWorkspaceListResponse>;
2123
+ /**
2124
+ * Fetch a single workspace (`GET /accounts/{accountId}`).
2125
+ *
2126
+ * @param accountId - The workspace to fetch.
2127
+ * @returns The workspace. `primary_color` / `secondary_color` are `null`
2128
+ * until brand colours are set (6-char hex, no `#`, when present):
2129
+ * ```jsonc
2130
+ * {
2131
+ * "id": "acc_example",
2132
+ * "name": "MT",
2133
+ * "primary_color": null,
2134
+ * "secondary_color": null,
2135
+ * "created_at": "2026-05-12T18:05:11Z"
2136
+ * }
2137
+ * ```
2138
+ * @throws {ValidationError} If `accountId` is missing.
2139
+ * @throws {ApiError} `404` if the workspace does not exist.
2140
+ *
2141
+ * @example
2142
+ * ```ts
2143
+ * const ws = await client.workspaces.get('acc_example');
2144
+ * ```
2145
+ */
2146
+ get(accountId: string): Promise<IWorkspaceResponse>;
2147
+ /**
2148
+ * Fetch account branding (`GET /accounts/{accountId}/theme`).
2149
+ *
2150
+ * Request body/query: none.
2151
+ *
2152
+ * @param accountId - Account whose public branding should be returned.
2153
+ * @returns The unwrapped theme:
2154
+ * ```jsonc
2155
+ * {
2156
+ * "account_name": "Acme Inc.",
2157
+ * "primary_color": "aabbcc",
2158
+ * "secondary_color": "112233",
2159
+ * "logo": "https://api.assinafy.com.br/v1/accounts/account-id/logo"
2160
+ * }
2161
+ * ```
2162
+ * @throws {ValidationError} If `accountId` is empty.
2163
+ * @throws {ApiError} `401` for invalid credentials or `500` on failure.
2164
+ *
2165
+ * @example
2166
+ * ```ts
2167
+ * const theme = await client.workspaces.getTheme('acc_example');
2168
+ * ```
2169
+ */
2170
+ getTheme(accountId: string): Promise<IAccountTheme>;
2171
+ /**
2172
+ * Download the account logo (`GET /accounts/{accountId}/logo`).
2173
+ *
2174
+ * @param accountId - Account whose current logo should be downloaded.
2175
+ * @returns Raw image bytes as a Node {@link Buffer}. The endpoint's response
2176
+ * content type is `image/*` and depends on the uploaded file.
2177
+ * @throws {ValidationError} If `accountId` is empty.
2178
+ * @throws {ApiError} `404` when no logo exists.
2179
+ *
2180
+ * @example
2181
+ * ```ts
2182
+ * const logo = await client.workspaces.downloadLogo('acc_example');
2183
+ * ```
2184
+ */
2185
+ downloadLogo(accountId: string): Promise<Buffer>;
2186
+ /**
2187
+ * Upload or replace the account logo (`POST /accounts/{accountId}/logo`).
2188
+ *
2189
+ * The request is `multipart/form-data` with exactly one `file` part. No
2190
+ * response data is defined; the method resolves once the API acknowledges
2191
+ * the update.
2192
+ *
2193
+ * @param accountId - Account whose logo will be replaced.
2194
+ * @param source - File path or `{ buffer, fileName }`; optionally set an
2195
+ * explicit MIME `contentType` for an in-memory image.
2196
+ * @returns Resolves when the API acknowledges the multipart upload.
2197
+ * @throws {ValidationError} If an id/file name is missing or the file is empty.
2198
+ * Unlike PDF uploads, the official logo operation defines no 25 MB cap, so
2199
+ * the SDK does not impose the document limit here.
2200
+ * @throws {ApiError} `400`/`415` if the API rejects the image.
2201
+ *
2202
+ * @example
2203
+ * ```ts
2204
+ * await client.workspaces.uploadLogo('acc_example', {
2205
+ * buffer: logoPng,
2206
+ * fileName: 'logo.png',
2207
+ * contentType: 'image/png',
2208
+ * });
2209
+ * ```
2210
+ */
2211
+ uploadLogo(accountId: string, source: AccountLogoUploadSource): Promise<void>;
2212
+ /**
2213
+ * Delete the current account logo (`DELETE /accounts/{accountId}/logo`).
2214
+ *
2215
+ * Request/response data: none beyond the standard status/message envelope.
2216
+ *
2217
+ * @param accountId - Account whose logo should be removed.
2218
+ * @returns Resolves when the API acknowledges deletion.
2219
+ * @example
2220
+ * ```ts
2221
+ * await client.workspaces.deleteLogo('acc_example');
2222
+ * ```
2223
+ */
2224
+ deleteLogo(accountId: string): Promise<void>;
2225
+ /**
2226
+ * Return this account's document-funnel KPIs
2227
+ * (`GET /accounts/{accountId}/stats`).
2228
+ *
2229
+ * @param accountId - Account to aggregate.
2230
+ * @param params - Omit for 12 monthly rows, or request daily rows with
2231
+ * `{ granularity: 'daily', month: '2026-06' }`.
2232
+ * @returns Zero-filled KPI rows:
2233
+ * ```jsonc
2234
+ * [{
2235
+ * "period": "2026-06",
2236
+ * "documents_uploaded": 42,
2237
+ * "documents_sent": 37,
2238
+ * "signature_requests": 61,
2239
+ * "signature_requests_email": 55,
2240
+ * "signature_requests_whatsapp": 18,
2241
+ * "signature_requests_viewed": 44,
2242
+ * "signature_requests_completed": 52,
2243
+ * "documents_certified": 30
2244
+ * }]
2245
+ * ```
2246
+ * @throws {ValidationError} For an empty account id, missing daily month,
2247
+ * or a month not formatted as `YYYY-MM`.
2248
+ * @throws {ApiError} `401` for invalid credentials or `404` when the route
2249
+ * is not deployed in a lagging environment.
2250
+ *
2251
+ * @example
2252
+ * ```ts
2253
+ * const monthly = await client.workspaces.getStats('acc_example');
2254
+ * const daily = await client.workspaces.getStats('acc_example', {
2255
+ * granularity: 'daily',
2256
+ * month: '2026-06',
2257
+ * });
2258
+ * ```
2259
+ */
2260
+ getStats(accountId: string, params?: IDocumentStatsParams): Promise<IDocumentStatsRow[]>;
2261
+ /**
2262
+ * Update a workspace (`PUT /accounts/{accountId}`).
2263
+ *
2264
+ * @param accountId - The workspace to update.
2265
+ * @param payload - The fields to change (`name` and/or brand colours).
2266
+ * Colours are 6-char hex **without** a leading `#`; pass `null` to clear one.
2267
+ * @returns The updated workspace. Response shape:
2268
+ * ```jsonc
2269
+ * {
2270
+ * "id": "acc_example",
2271
+ * "name": "Acme Legal (Renamed)",
2272
+ * "primary_color": "ff0066",
2273
+ * "secondary_color": "0066ff",
2274
+ * "created_at": "2026-05-12T18:05:11Z"
2275
+ * }
2276
+ * ```
2277
+ * @throws {ValidationError} If `accountId` is missing.
2278
+ * @throws {ApiError} `400` for an invalid colour; `404` if the workspace
2279
+ * does not exist.
2280
+ *
2281
+ * @example
2282
+ * ```ts
2283
+ * await client.workspaces.update('acc_example', {
2284
+ * name: 'Acme Legal (Renamed)',
2285
+ * primary_color: 'ff0066',
2286
+ * });
2287
+ * ```
2288
+ */
2289
+ update(accountId: string, payload: IUpdateWorkspacePayload): Promise<IWorkspaceResponse>;
2290
+ /**
2291
+ * Delete a workspace (`DELETE /accounts/{accountId}`).
2292
+ *
2293
+ * A workspace with restrictions (e.g. remaining documents) is rejected with
2294
+ * `400` and a `restrictions` list; pass `{ force: true }` to override and
2295
+ * delete it anyway. The flag is sent in the request body, per the API.
2296
+ *
2297
+ * @param accountId - The workspace to delete.
2298
+ * @param options - Set `force: true` to delete despite restrictions.
2299
+ * @returns Nothing on success (`200` with no meaningful body).
2300
+ * @throws {ValidationError} If `accountId` is missing.
2301
+ * @throws {ApiError} `400` (with a `restrictions` list) when the workspace
2302
+ * has restrictions and `force` was not set; `404` if it does not exist.
2303
+ *
2304
+ * @example
2305
+ * ```ts
2306
+ * await client.workspaces.delete('acc_example');
2307
+ * // override restrictions:
2308
+ * await client.workspaces.delete('acc_example', { force: true });
2309
+ * ```
2310
+ */
2311
+ delete(accountId: string, options?: {
2312
+ force?: boolean;
2313
+ }): Promise<void>;
2314
+ }
2315
+
2316
+ /**
2317
+ * Normalize a public assignment input into the exact create-request body.
2318
+ * String IDs and legacy `signer_id` aliases become signer objects, omitted
2319
+ * values are removed, and collect assignments must include placement entries.
2320
+ *
2321
+ * @param payload - Assignment method, signer references, and optional message,
2322
+ * expiration, copy receivers, or collect-field placements.
2323
+ * @returns A JSON-ready body shaped as
2324
+ * `{ method, signers: [{ id, verification_method?, notification_methods?, step? }], message?, expires_at?, copy_receivers?, entries? }`.
2325
+ * @throws {ValidationError} If no signer is present, a signer reference is
2326
+ * malformed, or a collect assignment has no field-placement entries.
2327
+ *
2328
+ * @example
2329
+ * ```ts
2330
+ * const body = buildAssignmentPayload({
2331
+ * method: 'virtual',
2332
+ * signers: ['signer-1', { signer_id: 'signer-2', step: 2 }],
2333
+ * message: 'Please sign',
2334
+ * });
2335
+ * // body.signers → [{ id: 'signer-1' }, { id: 'signer-2', step: 2 }]
2336
+ * ```
2337
+ */
2338
+ declare function buildAssignmentPayload(payload: ICreateAssignmentPayload): Record<string, unknown>;
2339
+ declare class AssignmentResource extends BaseResource {
2340
+ /**
2341
+ * List assignments across the workspace (`GET /assignments`).
2342
+ *
2343
+ * The account is passed as an `accountId` **query parameter** — the API
2344
+ * responds `400` ("Um contexto de conta é necessário e não foi fornecido")
2345
+ * without it. Note the camelCase spelling: `account_id` and an
2346
+ * `X-Account-Id` header are both rejected.
2347
+ *
2348
+ * @param params - `page`, `per-page`.
2349
+ * @param accountId - Override the client's default account ID.
2350
+ * @returns Assignments, with pagination in `meta`. Each item is a full
2351
+ * {@link IAssignment} (same shape as {@link AssignmentResource.create}
2352
+ * returns):
2353
+ * ```jsonc
2354
+ * {
2355
+ * "id": "103033c9d2cec233bf65eea04999",
2356
+ * "sender_email": "sender@example.com",
2357
+ * "method": "virtual",
2358
+ * "expires_at": null,
2359
+ * "message": "Please sign this contract",
2360
+ * "copy_receivers": [],
2361
+ * "signers": [
2362
+ * {
2363
+ * "id": "19e6b92e7895332ed9708535d8c",
2364
+ * "full_name": "Ana Souza",
2365
+ * "email": "signer@example.com",
2366
+ * "whatsapp_phone_number": null,
2367
+ * "has_accepted_terms": false,
2368
+ * "completed": false,
2369
+ * "notification_history": [],
2370
+ * "verification_method": "Email",
2371
+ * "notification_methods": ["Email"],
2372
+ * "step": 1,
2373
+ * "notified": true
2374
+ * }
2375
+ * ],
2376
+ * "items": [
2377
+ * {
2378
+ * "id": "103033c9d33326458deb74fc3052",
2379
+ * "page": null,
2380
+ * "signer": {
2381
+ * "id": "19e6b92e7895332ed9708535d8c",
2382
+ * "full_name": "Ana Souza",
2383
+ * "email": "signer@example.com",
2384
+ * "whatsapp_phone_number": null,
2385
+ * "has_accepted_terms": false
2386
+ * },
2387
+ * "field": {
2388
+ * "id": "signer-example",
2389
+ * "name": "Virtual",
2390
+ * "type": "virtual",
2391
+ * "is_active": true
2392
+ * },
2393
+ * "value": null,
2394
+ * "completed": false
2395
+ * }
2396
+ * ],
2397
+ * "summary": {
2398
+ * "signer_count": 1,
2399
+ * "completed_count": 0,
2400
+ * "signers": [
2401
+ * {
2402
+ * "id": "19e6b92e7895332ed9708535d8c",
2403
+ * "full_name": "Ana Souza",
2404
+ * "email": "signer@example.com",
2405
+ * "whatsapp_phone_number": null,
2406
+ * "has_accepted_terms": false,
2407
+ * "completed": false
2408
+ * }
2409
+ * ]
2410
+ * },
2411
+ * "signing_urls": [
2412
+ * {
2413
+ * "signer_id": "19e6b92e7895332ed9708535d8c",
2414
+ * "url": "https://app-sandbox.assinafy.com.br/sign/103033c950d865a248a11c5cf96c?email=signer%40example.com"
2415
+ * }
2416
+ * ]
2417
+ * }
2418
+ * ```
2419
+ * @throws {ValidationError} If no account ID is available.
2420
+ * @throws {ApiError} If the API rejects the request.
2421
+ *
2422
+ * @example
2423
+ * ```ts
2424
+ * const { data, meta } = await client.assignments.list({ 'per-page': 20 });
2425
+ * ```
2426
+ */
2427
+ list(params?: IAssignmentListParams, accountId?: string): Promise<IAssignmentListResponse>;
2428
+ /**
2429
+ * Create a signing assignment for a document
2430
+ * (`POST /documents/{documentId}/assignments`).
2431
+ *
2432
+ * Signers may be passed as bare id strings or as objects
2433
+ * (`{ id, verification_method, notification_methods, step }`); the SDK
2434
+ * normalises them to the docs-sanctioned `signers: [{ ... }]` shape via
2435
+ * {@link buildAssignmentPayload}. The document must have reached
2436
+ * `metadata_ready` before an assignment can be created.
2437
+ *
2438
+ * @param documentId - The document to request signatures on.
2439
+ * @param payload - Signers plus optional `method` (defaults to `virtual`),
2440
+ * `message`, `expires_at`, `copy_receivers`, and `collect`-mode `entries`.
2441
+ * @returns The created {@link IAssignment}: `signers` (rich, with `step` /
2442
+ * `notified` / `verification_method`), `items` (one row per signer × field),
2443
+ * a `summary` count block, and per-signer `signing_urls`. Response shape:
2444
+ * ```jsonc
2445
+ * {
2446
+ * "id": "103033c9d2cec233bf65eea04999",
2447
+ * "sender_email": "sender@example.com",
2448
+ * "method": "virtual",
2449
+ * "expires_at": null,
2450
+ * "message": "Please sign this contract",
2451
+ * "copy_receivers": [],
2452
+ * "signers": [
2453
+ * {
2454
+ * "id": "19e6b92e7895332ed9708535d8c",
2455
+ * "full_name": "Ana Souza",
2456
+ * "email": "signer@example.com",
2457
+ * "whatsapp_phone_number": null,
2458
+ * "has_accepted_terms": false,
2459
+ * "completed": false,
2460
+ * "notification_history": [],
2461
+ * "verification_method": "Email",
2462
+ * "notification_methods": ["Email"],
2463
+ * "step": 1,
2464
+ * "notified": true
2465
+ * }
2466
+ * ],
2467
+ * "items": [
2468
+ * {
2469
+ * "id": "103033c9d33326458deb74fc3052",
2470
+ * "page": null,
2471
+ * "signer": {
2472
+ * "id": "19e6b92e7895332ed9708535d8c",
2473
+ * "full_name": "Ana Souza",
2474
+ * "email": "signer@example.com"
2475
+ * },
2476
+ * "field": {
2477
+ * "id": "signer-example",
2478
+ * "name": "Virtual",
2479
+ * "type": "virtual",
2480
+ * "is_active": true
2481
+ * },
2482
+ * "value": null,
2483
+ * "completed": false
2484
+ * }
2485
+ * ],
2486
+ * "summary": {
2487
+ * "signer_count": 1,
2488
+ * "completed_count": 0,
2489
+ * "signers": [
2490
+ * {
2491
+ * "id": "19e6b92e7895332ed9708535d8c",
2492
+ * "full_name": "Ana Souza",
2493
+ * "email": "signer@example.com",
2494
+ * "whatsapp_phone_number": null,
2495
+ * "has_accepted_terms": false,
2496
+ * "completed": false
2497
+ * }
2498
+ * ]
2499
+ * },
2500
+ * "signing_urls": [
2501
+ * {
2502
+ * "signer_id": "19e6b92e7895332ed9708535d8c",
2503
+ * "url": "https://app-sandbox.assinafy.com.br/sign/103033c950d865a248a11c5cf96c?email=signer%40example.com"
2504
+ * }
2505
+ * ]
2506
+ * }
2507
+ * ```
2508
+ * @throws {ValidationError} If `documentId` is missing, no signer is
2509
+ * supplied, or a signer reference is invalid.
2510
+ * @throws {ApiError} If the API rejects the request — e.g. `400`
2511
+ * ("Um signatário com este e-mail já existe.") when a signer email already
2512
+ * exists on the account.
2513
+ *
2514
+ * @example
2515
+ * ```ts
2516
+ * const assignment = await client.assignments.create('doc-1', {
2517
+ * signers: ['19e6b92e7895332ed9708535d8c'],
2518
+ * message: 'Please sign this contract',
2519
+ * });
2520
+ * // → wire body: { method: 'virtual', signers: [{ id: '19e6…' }], message: 'Please sign this contract' }
2521
+ * assignment.signing_urls?.forEach((s) => console.log(s.signer_id, s.url));
2522
+ * ```
2523
+ */
2524
+ create(documentId: string, payload: ICreateAssignmentPayload): Promise<ICreateAssignmentResponse>;
2525
+ /**
2526
+ * Estimate the cost (in credits/documents) of creating the assignment
2527
+ * (`POST /documents/{documentId}/assignments/estimate-cost`).
2528
+ *
2529
+ * Unlike {@link AssignmentResource.create}, estimate signer entries contain
2530
+ * only `verification_method` / `notification_methods` (or `{}` for the
2531
+ * default Email channel). {@link buildAssignmentEstimatePayload} projects
2532
+ * exactly the fields permitted by the estimate schema.
2533
+ *
2534
+ * @param documentId - The document the assignment would be created on.
2535
+ * @param payload - `method` plus channel-only signer descriptors and/or
2536
+ * `collect`-mode `entries`. Create-only fields and signer IDs are not part
2537
+ * of this request schema.
2538
+ * @returns an {@link ICostEstimate} with `total_credits`, balances, a
2539
+ * line-item `breakdown`, and a `has_sufficient_resources` gate. Response
2540
+ * shape:
2541
+ * ```jsonc
2542
+ * {
2543
+ * "documents": 1,
2544
+ * "credits": 0,
2545
+ * "needs_extra_document": false,
2546
+ * "extra_document_cost": 0,
2547
+ * "total_credits": 0,
2548
+ * "breakdown": [],
2549
+ * "document_balance": 67,
2550
+ * "credit_balance": 0,
2551
+ * "has_sufficient_resources": true,
2552
+ * "blocking_reason": null,
2553
+ * "message": null
2554
+ * }
2555
+ * ```
2556
+ * @throws {ValidationError} If `documentId` is missing, a `virtual` request
2557
+ * has no signer entry, or a `collect` request has no field-placement entry.
2558
+ * @throws {ApiError} If the API rejects the request.
2559
+ *
2560
+ * @example
2561
+ * ```ts
2562
+ * const cost = await client.assignments.estimateCost('doc-1', {
2563
+ * signers: [{ verification_method: 'Whatsapp' }],
2564
+ * });
2565
+ * // → wire body: { method: 'virtual', signers: [{ verification_method: 'Whatsapp' }] }
2566
+ * if (!cost.has_sufficient_resources) console.warn(cost.blocking_reason);
2567
+ * ```
2568
+ */
2569
+ estimateCost(documentId: string, payload: IEstimateAssignmentCostPayload): Promise<ICostEstimate>;
1307
2570
  /**
1308
- * Update a tag's name and/or color. Omit a field to leave it unchanged;
1309
- * pass `color: null` to clear the color. Throws `ApiError` (409) if another
1310
- * tag already uses the new name.
2571
+ * Update the expiration date of an existing assignment
2572
+ * (`PUT /documents/{documentId}/assignments/{assignmentId}/reset-expiration`).
2573
+ *
2574
+ * Sends `{ expires_at }` verbatim. The official contract accepts an ISO-8601
2575
+ * date/time string. `null` is retained as a live-unverified compatibility
2576
+ * value used by older integrations and, unlike ordinary nullable inputs, is
2577
+ * intentionally not stripped from the body.
2578
+ *
2579
+ * @param documentId - The document the assignment belongs to.
2580
+ * @param assignmentId - The assignment to update.
2581
+ * @param expiresAt - New expiry as an ISO-8601 date/time string. `null` is
2582
+ * an unverified compatibility value intended to clear it.
2583
+ * @returns The updated {@link IAssignment} — the same full shape
2584
+ * {@link AssignmentResource.create} returns (`signers`, `items`, `summary`,
2585
+ * `signing_urls`), with `expires_at` reflecting the new value:
2586
+ * ```jsonc
2587
+ * {
2588
+ * "id": "103033c9d2cec233bf65eea04999",
2589
+ * "sender_email": "sender@example.com",
2590
+ * "method": "virtual",
2591
+ * "expires_at": "2026-12-31T23:59:59Z",
2592
+ * "message": "Please sign this contract",
2593
+ * "copy_receivers": [],
2594
+ * "signers": [
2595
+ * {
2596
+ * "id": "19e6b92e7895332ed9708535d8c",
2597
+ * "full_name": "Ana Souza",
2598
+ * "email": "signer@example.com",
2599
+ * "completed": false,
2600
+ * "verification_method": "Email",
2601
+ * "notification_methods": ["Email"],
2602
+ * "step": 1,
2603
+ * "notified": true
2604
+ * }
2605
+ * ],
2606
+ * "summary": { "signer_count": 1, "completed_count": 0 },
2607
+ * "signing_urls": [
2608
+ * { "signer_id": "19e6b92e7895332ed9708535d8c", "url": "https://app-sandbox.assinafy.com.br/sign/103033c950d865a248a11c5cf96c" }
2609
+ * ]
2610
+ * }
2611
+ * ```
2612
+ * @throws {ValidationError} If `documentId` or `assignmentId` is missing.
2613
+ * @throws {ApiError} `400`/`404` if the assignment cannot be updated.
2614
+ *
2615
+ * @example
2616
+ * ```ts
2617
+ * // Extend the deadline …
2618
+ * await client.assignments.resetExpiration('doc-1', 'asg-1', '2026-12-31T23:59:59Z');
2619
+ * // … or remove it entirely (sends { expires_at: null }).
2620
+ * await client.assignments.resetExpiration('doc-1', 'asg-1', null);
2621
+ * ```
2622
+ */
2623
+ resetExpiration(documentId: string, assignmentId: string, expiresAt: string | null): Promise<IAssignment>;
2624
+ /**
2625
+ * Resend the signing notification to a single signer
2626
+ * (`PUT /documents/{documentId}/assignments/{assignmentId}/signers/{signerId}/resend`).
2627
+ *
2628
+ * Sends no request body — the target is fully identified by the path. Use
2629
+ * {@link AssignmentResource.estimateResendCost} first if you need to know
2630
+ * whether the resend will consume credits.
2631
+ *
2632
+ * @param documentId - The document the assignment belongs to.
2633
+ * @param assignmentId - The assignment containing the signer.
2634
+ * @param signerId - The signer to re-notify.
2635
+ * @returns An {@link IResendEmailResponse} confirming dispatch:
2636
+ * ```jsonc
2637
+ * {
2638
+ * "is_sent": true,
2639
+ * "document_id": "103acccd24234c07858ffddf6d84",
2640
+ * "signer_id": "19e6b92e7895332ed9708535d8c"
2641
+ * }
2642
+ * ```
2643
+ * @throws {ValidationError} If any of the three IDs is missing.
2644
+ * @throws {ApiError} If the API rejects the request.
2645
+ *
2646
+ * @example
2647
+ * ```ts
2648
+ * await client.assignments.resendNotification('doc-1', 'asg-1', 'signer-1');
2649
+ * ```
2650
+ */
2651
+ resendNotification(documentId: string, assignmentId: string, signerId: string): Promise<IResendEmailResponse>;
2652
+ /**
2653
+ * Estimate the cost of resending a signer notification
2654
+ * (`POST /documents/{documentId}/assignments/{assignmentId}/signers/{signerId}/estimate-resend-cost`).
2655
+ *
2656
+ * Sends no request body. Pair it with
2657
+ * {@link AssignmentResource.resendNotification} to gate a resend on
2658
+ * available credit.
2659
+ *
2660
+ * @param documentId - The document the assignment belongs to.
2661
+ * @param assignmentId - The assignment containing the signer.
2662
+ * @param signerId - The signer whose notification would be resent.
2663
+ * @returns An {@link IResendCostEstimate}. The published contract returns
2664
+ * the full {@link ICostEstimate}; older deployments may return the compact
2665
+ * `total` / `has_sufficient_credits` shape shown below:
2666
+ * ```jsonc
2667
+ * {
2668
+ * "total": 0,
2669
+ * "breakdown": [
2670
+ * { "code": "NotificationEmailResend", "name": "Email Notification Resend", "cost": 0 }
2671
+ * ],
2672
+ * "credit_balance": 0,
2673
+ * "has_sufficient_credits": true
2674
+ * }
2675
+ * ```
2676
+ * @throws {ValidationError} If any of the three IDs is missing.
2677
+ * @throws {ApiError} If the API rejects the request.
2678
+ *
2679
+ * @example
2680
+ * ```ts
2681
+ * const cost = await client.assignments.estimateResendCost('doc-1', 'asg-1', 'signer-1');
2682
+ * const affordable = 'total_credits' in cost
2683
+ * ? cost.has_sufficient_resources
2684
+ * : cost.has_sufficient_credits;
2685
+ * if (affordable) {
2686
+ * await client.assignments.resendNotification('doc-1', 'asg-1', 'signer-1');
2687
+ * }
2688
+ * ```
2689
+ */
2690
+ estimateResendCost(documentId: string, assignmentId: string, signerId: string): Promise<IResendCostEstimate>;
2691
+ /**
2692
+ * List every WhatsApp notification rendered + sent for an assignment
2693
+ * (`GET /documents/{documentId}/assignments/{assignmentId}/whatsapp-notifications`).
2694
+ *
2695
+ * Returns the raw array (this endpoint is not paginated), so there is no
2696
+ * `meta` — each entry is the rendered message the signer received.
2697
+ *
2698
+ * @param documentId - The document the assignment belongs to.
2699
+ * @param assignmentId - The assignment whose WhatsApp notifications to list.
2700
+ * @returns An array of {@link IWhatsAppNotification} (empty when the
2701
+ * assignment used the email channel). Response shape:
2702
+ * ```jsonc
2703
+ * [
2704
+ * {
2705
+ * "sent_at": 1784145573,
2706
+ * "header": "Assinafy",
2707
+ * "body": "Você tem um documento para assinar.",
2708
+ * "buttons": [
2709
+ * { "text": "Assinar documento", "url": "https://app-sandbox.assinafy.com.br/sign/103033c950d865a248a11c5cf96c" }
2710
+ * ],
2711
+ * "phone_number": "+5511999998888",
2712
+ * "signer_id": "19e6b92e7895332ed9708535d8c"
2713
+ * }
2714
+ * ]
2715
+ * ```
2716
+ * @throws {ValidationError} If `documentId` or `assignmentId` is missing.
2717
+ * @throws {ApiError} If the API rejects the request.
2718
+ *
2719
+ * @example
2720
+ * ```ts
2721
+ * const notifications = await client.assignments.listWhatsAppNotifications('doc-1', 'asg-1');
2722
+ * notifications.forEach((n) => console.log(n.phone_number, n.body));
2723
+ * ```
2724
+ */
2725
+ listWhatsAppNotifications(documentId: string, assignmentId: string): Promise<IWhatsAppNotification[]>;
2726
+ }
2727
+
2728
+ /**
2729
+ * Default webhook events applied by {@link WebhookResource.register} when the
2730
+ * caller omits `events` (or passes an empty array).
2731
+ */
2732
+ declare const DEFAULT_WEBHOOK_EVENTS: readonly WebhookEventType[];
2733
+ declare class WebhookResource extends BaseResource {
2734
+ /**
2735
+ * Register (or replace) the workspace's single webhook subscription
2736
+ * (`PUT /accounts/{accountId}/webhooks/subscriptions`). There is exactly one
2737
+ * subscription per workspace, keyed by URL.
2738
+ *
2739
+ * When `events` is omitted or empty, {@link DEFAULT_WEBHOOK_EVENTS} is used
2740
+ * (`document_ready`, `document_prepared`, `signer_signed_document`,
2741
+ * `signer_rejected_document`, `document_processing_failed`).
2742
+ *
2743
+ * @param payload - Subscription details. `url` and `email` are required;
2744
+ * `events` defaults to {@link DEFAULT_WEBHOOK_EVENTS} and `is_active`
2745
+ * defaults to `true`.
2746
+ * @param accountId - Override the client's default account ID.
2747
+ * @returns The saved subscription. Response shape:
2748
+ * ```jsonc
2749
+ * {
2750
+ * "url": "https://example.com/hook",
2751
+ * "email": "ops@example.com",
2752
+ * "events": [
2753
+ * "document_ready",
2754
+ * "document_prepared",
2755
+ * "signer_signed_document",
2756
+ * "signer_rejected_document",
2757
+ * "document_processing_failed"
2758
+ * ],
2759
+ * "is_active": true,
2760
+ * "updated_at": "2026-07-18T02:36:02Z" // no `id` / `created_at` are returned
2761
+ * }
2762
+ * ```
2763
+ * @throws {ValidationError} If `url` or `email` is missing.
2764
+ * @throws {ApiError} If the API rejects the subscription.
2765
+ *
2766
+ * @example
2767
+ * ```ts
2768
+ * // Subscribe to a specific set of events:
2769
+ * await client.webhooks.register({
2770
+ * url: 'https://example.com/hook',
2771
+ * email: 'ops@example.com',
2772
+ * events: ['signer_signed_document', 'document_ready'],
2773
+ * });
2774
+ *
2775
+ * // Omit `events` to fall back to DEFAULT_WEBHOOK_EVENTS:
2776
+ * await client.webhooks.register({ url: 'https://example.com/hook', email: 'ops@example.com' });
2777
+ * ```
2778
+ */
2779
+ register(payload: IWebhookRegisterPayload, accountId?: string): Promise<IWebhookSubscription>;
2780
+ /**
2781
+ * Fetch the current webhook subscription
2782
+ * (`GET /accounts/{accountId}/webhooks/subscriptions`).
2783
+ *
2784
+ * @param accountId - Override the client's default account ID.
2785
+ * @returns The subscription, or `null` when the workspace has none (the API
2786
+ * responds `404`, which is normalized to `null`). Response shape when
2787
+ * present:
2788
+ * ```jsonc
2789
+ * {
2790
+ * "url": "https://hooks.zapier.com/hooks/standard/27880178/bbe9b90c.../",
2791
+ * "email": "ops@example.com",
2792
+ * "events": [
2793
+ * "document_ready",
2794
+ * "document_prepared"
2795
+ * // …5 more (7 total)
2796
+ * ],
2797
+ * "is_active": false,
2798
+ * "updated_at": "2026-07-18T02:36:02Z"
2799
+ * }
2800
+ * ```
2801
+ * @throws {ApiError} If the API fails for a reason other than `404`.
2802
+ *
2803
+ * @example
2804
+ * ```ts
2805
+ * const sub = await client.webhooks.get();
2806
+ * if (sub === null) {
2807
+ * // no subscription configured yet
2808
+ * } else if (!sub.is_active) {
2809
+ * // exists but deliveries are paused
2810
+ * }
2811
+ * ```
2812
+ */
2813
+ get(accountId?: string): Promise<IWebhookSubscription | null>;
2814
+ /**
2815
+ * Inactivate the current webhook subscription
2816
+ * (`PUT /accounts/{accountId}/webhooks/inactivate`).
2817
+ *
2818
+ * This is the only supported way to stop deliveries — the API has no
2819
+ * subscription-delete route. The subscription is retained (with its `url`
2820
+ * and `events`) and simply stops firing; re-enable it by calling
2821
+ * {@link WebhookResource.register} again with `is_active: true`.
2822
+ *
2823
+ * @param accountId - Override the client's default account ID.
2824
+ * @returns The subscription with `is_active` flipped to `false`. Response
2825
+ * shape:
2826
+ * ```jsonc
2827
+ * {
2828
+ * "url": "https://example.com/hook",
2829
+ * "email": "ops@example.com",
2830
+ * "events": [
2831
+ * "document_ready",
2832
+ * "document_prepared",
2833
+ * "signer_signed_document",
2834
+ * "signer_rejected_document",
2835
+ * "document_processing_failed"
2836
+ * ],
2837
+ * "is_active": false,
2838
+ * "updated_at": "2026-07-18T02:36:02Z"
2839
+ * }
2840
+ * ```
2841
+ * @throws {ApiError} If the API rejects the request.
2842
+ *
2843
+ * @example
2844
+ * ```ts
2845
+ * const sub = await client.webhooks.inactivate();
2846
+ * console.log(sub.is_active); // false
2847
+ * ```
2848
+ */
2849
+ inactivate(accountId?: string): Promise<IWebhookSubscription>;
2850
+ /**
2851
+ * List currently supported webhook event types
2852
+ * (`GET /webhooks/event-types`). This is a global, account-independent
2853
+ * catalog.
2854
+ *
2855
+ * @returns The full list of event types with human-readable descriptions.
2856
+ * Live, the API returns exactly 15 entries (in this order):
2857
+ * `document_uploaded`, `document_metadata_ready`, `document_prepared`,
2858
+ * `assignment_created`, `signature_requested`, `document_ready`,
2859
+ * `signer_created`, `signer_email_verified`, `signer_whatsapp_verified`,
2860
+ * `signer_data_confirmed`, `signer_signed_document`, `signer_viewed_document`,
2861
+ * `signer_rejected_document`, `user_rejected_document`,
2862
+ * `document_processing_failed`. Response shape:
2863
+ * ```jsonc
2864
+ * [
2865
+ * {
2866
+ * "id": "document_uploaded",
2867
+ * "description": "Triggered when the User has uploaded a Document"
2868
+ * },
2869
+ * {
2870
+ * "id": "document_metadata_ready",
2871
+ * "description": "Triggered when the document is ready to be prepared. The document has been normalized to PDF and its pages are available."
2872
+ * }
2873
+ * // …13 more (15 total)
2874
+ * ]
2875
+ * ```
2876
+ * @throws {ApiError} If the API rejects the request.
2877
+ *
2878
+ * @example
2879
+ * ```ts
2880
+ * const types = await client.webhooks.listEventTypes();
2881
+ * const ids = types.map((t) => t.id);
2882
+ * ```
2883
+ */
2884
+ listEventTypes(): Promise<IWebhookEventTypeInfo[]>;
2885
+ /**
2886
+ * List webhook delivery history for the workspace
2887
+ * (`GET /accounts/{accountId}/webhooks`). Pagination info (if any) is
2888
+ * attached in `meta`.
2889
+ *
2890
+ * @param params - Optional filters and pagination:
2891
+ * - `event` — restrict to a single {@link WebhookEventType}
2892
+ * (e.g. `'signer_signed_document'`).
2893
+ * - `delivered` — `true`/`false` to filter by delivery success.
2894
+ * - `from` / `to` — Unix epoch seconds bounding `created_at`.
2895
+ * - `page` — 1-based page number.
2896
+ * - `per-page` — page size (`per_page` is normalized to `per-page`).
2897
+ * @param accountId - Override the client's default account ID.
2898
+ * @returns Delivery records, with pagination in `meta`. Each item:
2899
+ * ```jsonc
2900
+ * {
2901
+ * "id": "103a09cfce51319dd3b3f72ffcdf",
2902
+ * "event": "signature_requested",
2903
+ * "activity_id": 8629,
2904
+ * "endpoint": "https://example.com/hook",
2905
+ * "payload": {
2906
+ * // the full event body that was POSTed to `endpoint`:
2907
+ * // { id, event, object: <document + assignment>, origin, message,
2908
+ * // payload: { signer_email, signer_full_name, notification_method, ... },
2909
+ * // subject: <User>, account_id, created_at }
2910
+ * },
2911
+ * "delivered": true,
2912
+ * "http_status": 200,
2913
+ * "response_body": "{ ... }", // body returned by the receiving endpoint
2914
+ * "error": null,
2915
+ * "created_at": "2026-07-15T20:04:36Z",
2916
+ * "updated_at": "2026-07-15T20:04:36Z"
2917
+ * }
2918
+ * ```
2919
+ * @throws {ApiError} If the API rejects the request.
2920
+ *
2921
+ * @example
2922
+ * ```ts
2923
+ * // Only failed deliveries, newest page first:
2924
+ * const { data, meta } = await client.webhooks.listDispatches({
2925
+ * delivered: false,
2926
+ * 'per-page': 20,
2927
+ * });
2928
+ * for (const dispatch of data) {
2929
+ * if (!dispatch.delivered) await client.webhooks.retryDispatch(dispatch.id);
2930
+ * }
2931
+ * ```
2932
+ */
2933
+ listDispatches(params?: IWebhookDispatchListParams, accountId?: string): Promise<PaginatedResult<IWebhookDispatch>>;
2934
+ /**
2935
+ * Retry delivery of a specific webhook dispatch
2936
+ * (`POST /accounts/{accountId}/webhooks/{historyId}/retry`). Re-sends the
2937
+ * original payload to the subscription's endpoint.
2938
+ *
2939
+ * @param dispatchId - The dispatch (delivery history) ID to re-send, as
2940
+ * returned by {@link WebhookResource.listDispatches}.
2941
+ * @param accountId - Override the client's default account ID.
2942
+ * @returns A newly created delivery-history record for the retry attempt;
2943
+ * its ID is distinct from the original dispatch. Response
2944
+ * shape:
2945
+ * ```jsonc
2946
+ * {
2947
+ * "id": "103a09cfce51319dd3b3f72ffcdf",
2948
+ * "event": "signature_requested",
2949
+ * "activity_id": 8629,
2950
+ * "endpoint": "https://example.com/hook",
2951
+ * "payload": { }, // the original event body that was re-POSTed
2952
+ * "delivered": true,
2953
+ * "http_status": 200,
2954
+ * "response_body": "{ ... }",
2955
+ * "error": null,
2956
+ * "created_at": "2026-07-15T20:04:36Z",
2957
+ * "updated_at": "2026-07-15T20:05:10Z"
2958
+ * }
2959
+ * ```
2960
+ * @throws {ValidationError} If `dispatchId` is empty.
2961
+ * @throws {ApiError} If the dispatch is not found (`404`) or the retry fails.
2962
+ *
2963
+ * @example
2964
+ * ```ts
2965
+ * const dispatch = await client.webhooks.retryDispatch('103a09cfce51319dd3b3f72ffcdf');
2966
+ * console.log(dispatch.delivered);
2967
+ * ```
2968
+ */
2969
+ retryDispatch(dispatchId: string, accountId?: string): Promise<IWebhookDispatch>;
2970
+ }
2971
+
2972
+ /**
2973
+ * Live-API compatibility endpoints for managing reusable templates.
2974
+ *
2975
+ * These CRUD routes are operational in the Assinafy sandbox but are not
2976
+ * described by the current published OpenAPI document. They are retained for
2977
+ * compatibility and should be integration-tested against the target Assinafy
2978
+ * environment before a production rollout.
2979
+ */
2980
+ declare class TemplateResource extends BaseResource {
2981
+ /**
2982
+ * Create a template by uploading a PDF (`POST /accounts/{id}/templates`).
2983
+ *
2984
+ * The template is created in `Uploaded` status and transitions to `Ready`
2985
+ * once the platform finishes processing its pages (`pages` stays empty until
2986
+ * then). Configure roles/fields afterwards in the Assinafy editor. As with
2987
+ * document uploads, the API derives the display name from the file part's
2988
+ * filename, so `options.name` is applied as the (`.pdf`-suffixed) filename
2989
+ * rather than a separate form field.
2990
+ *
2991
+ * @param source - The PDF to upload, as a file path or an in-memory buffer.
2992
+ * @param options - `name` (display name) and an optional `accountId` override.
2993
+ * @returns The created template (envelope unwrapped). Response shape:
2994
+ * ```jsonc
2995
+ * {
2996
+ * "resource": "template",
2997
+ * "id": "103ad2171db7979468c3e97eb067",
2998
+ * "name": "NDA template.pdf",
2999
+ * "document_name": "NDA template.pdf",
3000
+ * "message": null,
3001
+ * "status": "Uploaded",
3002
+ * "pages": [],
3003
+ * "roles": [
3004
+ * {
3005
+ * "id": "19f7b68b811f8d1e1aeaf11178e",
3006
+ * "name": "TemplateEditor",
3007
+ * "assignment_type": "Editor",
3008
+ * "created_at": "2026-07-19T17:24:48Z",
3009
+ * "updated_at": "2026-07-19T17:24:48Z"
3010
+ * }
3011
+ * ],
3012
+ * "tags": [],
3013
+ * "created_at": "2026-07-19T17:24:47Z",
3014
+ * "updated_at": "2026-07-19T17:24:48Z"
3015
+ * }
3016
+ * ```
3017
+ * @throws {ValidationError} If the file is empty, not a `.pdf`, exceeds
3018
+ * 25 MB, no account ID is available, or the API returns no template ID.
3019
+ * @throws {ApiError} If the API rejects the upload.
3020
+ *
3021
+ * @example
3022
+ * ```ts
3023
+ * const tmpl = await client.templates.create(
3024
+ * { filePath: './nda.pdf' },
3025
+ * { name: 'NDA template' },
3026
+ * );
3027
+ * // → status: 'Uploaded'; name stored as 'NDA template.pdf'
3028
+ * ```
3029
+ */
3030
+ create(source: DocumentUploadSource, options?: {
3031
+ name?: string;
3032
+ accountId?: string;
3033
+ }): Promise<ITemplateDetailsResponse>;
3034
+ /**
3035
+ * List templates for the workspace (`GET /accounts/{id}/templates`).
3036
+ *
3037
+ * Pagination lives in the response **headers** and is surfaced on `meta`.
3038
+ * Each item is an {@link ITemplateListItem} carrying `pages[]` (each with a
3039
+ * `download_url`), so there is no need to `get()` a template again just to
3040
+ * read its rendered pages.
3041
+ *
3042
+ * @param params - `search`, `page`, and `per-page` (the SDK normalizes
3043
+ * `per_page` → `per-page`, the only spelling the API honors).
3044
+ * @param accountId - Override the client's default account ID.
3045
+ * @returns Matching templates, with pagination in `meta`. Each item:
3046
+ * ```jsonc
3047
+ * {
3048
+ * "id": "103ad2171db7979468c3e97eb067",
3049
+ * "name": "NDA template.pdf",
3050
+ * "document_name": "nda.pdf",
3051
+ * "message": null,
3052
+ * "status": "Ready",
3053
+ * "pages": [
3054
+ * {
3055
+ * "id": "103ad217673e1f978cb86179e8f8",
3056
+ * "number": 1,
3057
+ * "height": 1651,
3058
+ * "width": 1275,
3059
+ * "download_url": "https://api.assinafy.com.br/v1/accounts/…/templates/…/pages/…/download",
3060
+ * "fields": []
3061
+ * }
3062
+ * ],
3063
+ * "roles": [
3064
+ * { "id": "19f7b68b811f8d1e1aeaf11178e", "name": "TemplateEditor", "assignment_type": "Editor" }
3065
+ * ],
3066
+ * "tags": [],
3067
+ * "created_at": "2026-07-19T17:24:47Z",
3068
+ * "updated_at": "2026-07-19T17:24:51Z"
3069
+ * }
3070
+ * ```
3071
+ * @throws {ValidationError} If no account ID is available.
3072
+ * @throws {ApiError} If the API rejects the request.
3073
+ *
3074
+ * @example
3075
+ * ```ts
3076
+ * const { data, meta } = await client.templates.list({ search: 'nda', 'per-page': 20 });
3077
+ * ```
3078
+ */
3079
+ list(params?: IListParams, accountId?: string): Promise<ITemplateListResponse>;
3080
+ /**
3081
+ * Get a template by ID (`GET /accounts/{id}/templates/{template_id}`).
3082
+ *
3083
+ * Returns the same shape as {@link TemplateResource.list} plus
3084
+ * `default_document_tags` (the tags auto-applied to every document created
3085
+ * from this template) and `resource`. Both endpoints return `pages` with
3086
+ * per-page `download_url`, so fetching a template again purely to read its
3087
+ * pages is unnecessary.
3088
+ *
3089
+ * @param templateId - The template to fetch.
3090
+ * @param accountId - Override the client's default account ID.
3091
+ * @returns The full template. Response shape (`status: 'Ready'`):
3092
+ * ```jsonc
3093
+ * {
3094
+ * "resource": "template",
3095
+ * "id": "103ad2171db7979468c3e97eb067",
3096
+ * "name": "NDA template.pdf",
3097
+ * "document_name": "nda.pdf",
3098
+ * "message": null,
3099
+ * "status": "Ready",
3100
+ * "pages": [
3101
+ * {
3102
+ * "id": "103ad217673e1f978cb86179e8f8",
3103
+ * "number": 1,
3104
+ * "height": 1651,
3105
+ * "width": 1275,
3106
+ * "download_url": "https://api.assinafy.com.br/v1/accounts/…/templates/…/pages/…/download",
3107
+ * "fields": []
3108
+ * }
3109
+ * ],
3110
+ * "roles": [
3111
+ * {
3112
+ * "id": "19f7b68b811f8d1e1aeaf11178e",
3113
+ * "name": "TemplateEditor",
3114
+ * "assignment_type": "Editor",
3115
+ * "created_at": "2026-07-19T17:24:48Z",
3116
+ * "updated_at": "2026-07-19T17:24:48Z"
3117
+ * }
3118
+ * ],
3119
+ * "tags": [],
3120
+ * "created_at": "2026-07-19T17:24:47Z",
3121
+ * "updated_at": "2026-07-19T17:24:51Z",
3122
+ * "default_document_tags": []
3123
+ * }
3124
+ * ```
3125
+ * @throws {ValidationError} If `templateId` is missing or no account ID is available.
3126
+ * @throws {ApiError} `404` if the template does not exist.
3127
+ *
3128
+ * @example
3129
+ * ```ts
3130
+ * const tmpl = await client.templates.get('103ad2171db7979468c3e97eb067');
3131
+ * if (tmpl.status === 'Ready') console.log(tmpl.pages.length);
3132
+ * ```
3133
+ */
3134
+ get(templateId: string, accountId?: string): Promise<ITemplateDetailsResponse>;
3135
+ /**
3136
+ * Update a template's `name` and/or default `message`
3137
+ * (`PUT /accounts/{id}/templates/{template_id}`).
3138
+ *
3139
+ * `message` is the default invitation message applied to documents created
3140
+ * from this template. Omit a field to leave it unchanged — the SDK strips
3141
+ * `undefined` keys before sending. Unlike uploads, `name` here is a plain
3142
+ * display name and is **not** forced to end in `.pdf`.
3143
+ *
3144
+ * @param templateId - The template to update.
3145
+ * @param payload - `name` and/or `message`; both optional.
3146
+ * @param accountId - Override the client's default account ID.
3147
+ * @returns The updated template (full details, same shape as
3148
+ * {@link TemplateResource.get}). Response shape:
3149
+ * ```jsonc
3150
+ * {
3151
+ * "resource": "template",
3152
+ * "id": "103ad2171db7979468c3e97eb067",
3153
+ * "name": "NDA v2",
3154
+ * "document_name": "nda.pdf",
3155
+ * "message": "Please sign",
3156
+ * "status": "Ready",
3157
+ * "pages": [
3158
+ * { "id": "103ad217673e1f978cb86179e8f8", "number": 1, "height": 1651, "width": 1275, "download_url": "https://api.assinafy.com.br/v1/…/download", "fields": [] }
3159
+ * ],
3160
+ * "roles": [
3161
+ * { "id": "19f7b68b811f8d1e1aeaf11178e", "name": "TemplateEditor", "assignment_type": "Editor" }
3162
+ * ],
3163
+ * "tags": [],
3164
+ * "created_at": "2026-07-19T17:24:47Z",
3165
+ * "updated_at": "2026-07-19T17:24:52Z"
3166
+ * }
3167
+ * ```
3168
+ * @throws {ValidationError} If `templateId` is missing or no account ID is available.
3169
+ * @throws {ApiError} `404` if the template does not exist; `400` on an invalid payload.
3170
+ *
3171
+ * @example
3172
+ * ```ts
3173
+ * await client.templates.update(templateId, { name: 'NDA v2', message: 'Please sign' });
3174
+ * ```
3175
+ */
3176
+ update(templateId: string, payload: IUpdateTemplatePayload, accountId?: string): Promise<ITemplateDetailsResponse>;
3177
+ /**
3178
+ * Delete a template (`DELETE /accounts/{id}/templates/{template_id}`).
3179
+ *
3180
+ * The API responds with an empty `data` payload; this method resolves to
3181
+ * `void`.
3182
+ *
3183
+ * @param templateId - The template to delete.
3184
+ * @param accountId - Override the client's default account ID.
3185
+ * @returns Nothing (`Promise<void>`) on success.
3186
+ * @throws {ValidationError} If `templateId` is missing or no account ID is available.
3187
+ * @throws {ApiError} `404` if the template does not exist.
3188
+ *
3189
+ * @example
3190
+ * ```ts
3191
+ * await client.templates.delete('103ad2171db7979468c3e97eb067');
3192
+ * ```
3193
+ */
3194
+ delete(templateId: string, accountId?: string): Promise<void>;
3195
+ /**
3196
+ * Download a template page as a JPEG
3197
+ * (`GET /accounts/{id}/templates/{template_id}/pages/{page_id}/download`).
3198
+ *
3199
+ * Used by template editors to render page thumbnails on the client. The
3200
+ * matching `download_url` is also returned on each `template.pages[]` entry,
3201
+ * so if you already hold the template you can fetch that URL directly.
3202
+ *
3203
+ * @param templateId - The template that owns the page.
3204
+ * @param pageId - The page to download (`pages[].id` from `get()`/`list()`).
3205
+ * @param accountId - Override the client's default account ID.
3206
+ * @returns The page rendering as a {@link Buffer} of JPEG bytes.
3207
+ * @throws {ValidationError} If `templateId` or `pageId` is missing, or no
3208
+ * account ID is available.
3209
+ * @throws {ApiError} `404` if the template or page does not exist.
3210
+ *
3211
+ * @example
3212
+ * ```ts
3213
+ * const tmpl = await client.templates.get('103ad2171db7979468c3e97eb067');
3214
+ * const jpeg = await client.templates.downloadPage(tmpl.id, tmpl.pages[0].id);
3215
+ * await fs.writeFile('page-1.jpg', jpeg);
3216
+ * ```
3217
+ */
3218
+ downloadPage(templateId: string, pageId: string, accountId?: string): Promise<Buffer>;
3219
+ }
3220
+
3221
+ /**
3222
+ * Workspace-scoped tags used to label documents and templates.
3223
+ *
3224
+ * Covers the full Tag section of the API docs:
3225
+ * - `GET /accounts/{id}/tags` → {@link list}
3226
+ * - `POST /accounts/{id}/tags` → {@link create}
3227
+ * - `PUT /accounts/{id}/tags/{tag_id}` → {@link update}
3228
+ * - `DELETE /accounts/{id}/tags/{tag_id}` → {@link delete}
3229
+ *
3230
+ * Document-level attach/detach lives on {@link DocumentResource} (`listTags`,
3231
+ * `replaceTags`, `addTags`, `detachTag`).
3232
+ */
3233
+ declare class TagResource extends BaseResource {
3234
+ /**
3235
+ * List the workspace's tags (`GET /accounts/{accountId}/tags`).
3236
+ *
3237
+ * Tags come back ordered alphabetically by name. Pass an optional
3238
+ * case-insensitive `search` substring to filter by name.
3239
+ *
3240
+ * @param params - Optional filters. `search` matches tag names
3241
+ * case-insensitively (substring).
3242
+ * @param accountId - Override the client's default account ID.
3243
+ * @returns The matching tags (list items carry no `resource` field):
3244
+ * ```jsonc
3245
+ * [
3246
+ * {
3247
+ * "id": "103aa221874346e6b3de41688526",
3248
+ * "name": "Contracts",
3249
+ * "color": "ff8800", // 6-char hex, no leading '#'
3250
+ * "created_at": "2026-07-18T19:03:45Z",
3251
+ * "updated_at": "2026-07-18T19:03:45Z"
3252
+ * },
3253
+ * {
3254
+ * "id": "103aa252123d3bf1843a317ee0e6",
3255
+ * "name": "Invoices",
3256
+ * "color": null, // no color set
3257
+ * "created_at": "2026-07-18T19:09:03Z",
3258
+ * "updated_at": "2026-07-18T19:09:03Z"
3259
+ * }
3260
+ * ]
3261
+ * ```
3262
+ * @throws {ValidationError} If no account ID is available.
3263
+ * @throws {ApiError} If the API rejects the request.
3264
+ *
3265
+ * @example
3266
+ * ```ts
3267
+ * const all = await client.tags.list();
3268
+ * const contracts = await client.tags.list({ search: 'contract' });
3269
+ * ```
3270
+ */
3271
+ list(params?: {
3272
+ search?: string;
3273
+ }, accountId?: string): Promise<ITag[]>;
3274
+ /**
3275
+ * Create a tag (`POST /accounts/{accountId}/tags`).
3276
+ *
3277
+ * `color` is an optional 6-char hex string; the API accepts it **with or
3278
+ * without** a leading `#` and always stores it **without** — `'#ff8800'`
3279
+ * and `'ff8800'` both persist as `'ff8800'` (verified live). Omit `color`
3280
+ * (or pass `null`) for no color.
3281
+ *
3282
+ * @param payload - `name` (required) and optional `color`.
3283
+ * @param accountId - Override the client's default account ID.
3284
+ * @returns The created tag:
3285
+ * ```jsonc
3286
+ * {
3287
+ * "resource": "tag",
3288
+ * "id": "103ad216fdc641c8f0465678c813",
3289
+ * "name": "Contracts",
3290
+ * "color": "ff8800",
3291
+ * "created_at": "2026-07-19T17:24:46Z",
3292
+ * "updated_at": "2026-07-19T17:24:46Z"
3293
+ * }
3294
+ * ```
3295
+ * @throws {ValidationError} If `name` is empty, or no account ID is available.
3296
+ * @throws {ApiError} `409` if a tag with the same name already exists
3297
+ * (case-insensitive).
3298
+ *
3299
+ * @example
3300
+ * ```ts
3301
+ * const tag = await client.tags.create({ name: 'Contracts', color: '#ff8800' });
3302
+ * // → tag.color === 'ff8800' (the leading '#' is stripped by the API)
3303
+ * ```
3304
+ */
3305
+ create(payload: ICreateTagPayload, accountId?: string): Promise<ITag>;
3306
+ /**
3307
+ * Update a tag's name and/or color (`PUT /accounts/{accountId}/tags/{tagId}`).
3308
+ *
3309
+ * Omit a field to leave it unchanged. Pass `color: null` to clear the color
3310
+ * — that `null` is sent in the request body as the documented "clear color"
3311
+ * signal (an omitted `color` is not sent at all). As with {@link create}, a
3312
+ * leading `#` on `color` is accepted and stripped by the API
3313
+ * (`'#112233'` → `'112233'`).
3314
+ *
3315
+ * @param tagId - The tag to update.
3316
+ * @param payload - `name` and/or `color`. `color: null` clears the color;
3317
+ * omit a field to leave it unchanged.
3318
+ * @param accountId - Override the client's default account ID.
3319
+ * @returns The updated tag:
3320
+ * ```jsonc
3321
+ * {
3322
+ * "resource": "tag",
3323
+ * "id": "103ad216fdc641c8f0465678c813",
3324
+ * "name": "Contracts",
3325
+ * "color": "112233",
3326
+ * "created_at": "2026-07-19T17:24:46Z",
3327
+ * "updated_at": "2026-07-19T17:24:47Z"
3328
+ * }
3329
+ * ```
3330
+ * @throws {ValidationError} If `tagId` is missing, or no account ID is available.
3331
+ * @throws {ApiError} `404` if the tag does not exist; `409` if another tag
3332
+ * already uses the new name.
3333
+ *
3334
+ * @example
3335
+ * ```ts
3336
+ * // rename + recolor
3337
+ * await client.tags.update('103ad216fdc641c8f0465678c813', {
3338
+ * name: 'Signed contracts',
3339
+ * color: '112233',
3340
+ * });
3341
+ * // clear the color, keep the name
3342
+ * await client.tags.update('103ad216fdc641c8f0465678c813', { color: null });
3343
+ * ```
3344
+ */
3345
+ update(tagId: string, payload: IUpdateTagPayload, accountId?: string): Promise<ITag>;
3346
+ /**
3347
+ * Delete a tag (`DELETE /accounts/{accountId}/tags/{tagId}`).
3348
+ *
3349
+ * By default the API returns `409` if the tag is still attached to any
3350
+ * document or template. Pass `{ force: true }` to detach it everywhere
3351
+ * first — that adds a `?force=true` query param. Resolves to `void` on
3352
+ * success (the endpoint's `{ "deleted": true }` body is discarded).
3353
+ *
3354
+ * @param tagId - The tag to delete.
3355
+ * @param options - `force` to detach-and-delete when the tag is still in
3356
+ * use, and `accountId` to override the client's default account ID.
3357
+ * @returns Nothing; resolves once the tag is deleted.
3358
+ * @throws {ValidationError} If `tagId` is missing, or no account ID is available.
3359
+ * @throws {ApiError} `404` if the tag does not exist; `409` if the tag is
3360
+ * still in use and `force` was not set.
3361
+ *
3362
+ * @example
3363
+ * ```ts
3364
+ * await client.tags.delete('103ad216fdc641c8f0465678c813');
3365
+ * // detach from every document/template, then delete
3366
+ * await client.tags.delete('103ad216fdc641c8f0465678c813', { force: true });
3367
+ * ```
3368
+ */
3369
+ delete(tagId: string, options?: {
3370
+ force?: boolean;
3371
+ accountId?: string;
3372
+ }): Promise<void>;
3373
+ }
3374
+
3375
+ /**
3376
+ * Authentication endpoints (login, social login, password management) and
3377
+ * personal API key management (`/users/api-keys`).
3378
+ *
3379
+ * Most of these endpoints are intended to bootstrap an authenticated session
3380
+ * for a human user. Production server-to-server integrations should use
3381
+ * `X-Api-Key` and skip this resource entirely.
3382
+ */
3383
+ declare class AuthenticationResource extends BaseResource {
3384
+ private readonly publicHttp;
3385
+ constructor(http: AxiosInstance, defaultAccountId?: string, logger?: Logger, publicHttp?: AxiosInstance);
3386
+ /**
3387
+ * Build the browser-facing OAuth start URL
3388
+ * (`GET /auth/authenticate?authclient=…`).
3389
+ *
3390
+ * This endpoint responds with `302` to the provider consent screen, so the
3391
+ * SDK returns the URL for your web framework to redirect to instead of
3392
+ * following the redirect inside the Node process.
3393
+ *
3394
+ * @param authClient - Provider key; currently `google`.
3395
+ * @returns An absolute URL, for example
3396
+ * `https://api.assinafy.com.br/v1/auth/authenticate?authclient=google`.
3397
+ * @throws {ValidationError} If `authClient` is empty.
3398
+ *
3399
+ * @example
3400
+ * ```ts
3401
+ * response.redirect(client.auth.getSocialLoginUrl('google'));
3402
+ * ```
3403
+ */
3404
+ getSocialLoginUrl(authClient?: 'google' | AnyString): string;
3405
+ /**
3406
+ * Return the Assinafy browser callback URL (`GET /login-callback`).
3407
+ *
3408
+ * The callback response payload is intentionally unspecified by the API;
3409
+ * OAuth providers call it in a browser. Use this URL when a provider setup
3410
+ * asks for Assinafy's callback/redirect URI.
3411
+ *
3412
+ * @returns The absolute Assinafy callback URL for the configured API host.
3413
+ *
3414
+ * @example
3415
+ * ```ts
3416
+ * console.log(client.auth.getSocialLoginCallbackUrl());
3417
+ * ```
3418
+ */
3419
+ getSocialLoginCallbackUrl(): string;
3420
+ /**
3421
+ * Log in with email + password (`POST /login`).
3422
+ *
3423
+ * Exchanges credentials for a JWT `access_token` plus the authenticated
3424
+ * user and the accounts they can act on. The token authenticates
3425
+ * subsequent requests; long-lived integrations should prefer an
3426
+ * `X-Api-Key` (see {@link AuthenticationResource.createApiKey}) instead of
3427
+ * storing a password.
3428
+ *
3429
+ * @param email - The user's email address, e.g. `'user@example.com'`.
3430
+ * @param password - The user's password.
3431
+ * @returns An {@link ILoginResponse} with the access token, user, and
3432
+ * accounts. Response shape:
3433
+ * ```jsonc
3434
+ * {
3435
+ * "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…",
3436
+ * "user": {
3437
+ * "id": "md3j6p9w8b7y6qvqaoy5er42",
3438
+ * "name": "Multica Test",
3439
+ * "email": "user@example.com",
3440
+ * "telephone": null,
3441
+ * "government_id": "",
3442
+ * "is_email_verified": true,
3443
+ * "has_accepted_terms": true,
3444
+ * "created_at": "2026-05-12T13:45:11Z",
3445
+ * "to_be_deleted_at": null
3446
+ * },
3447
+ * "accounts": [
3448
+ * {
3449
+ * "id": "acc_example",
3450
+ * "name": "Multica Test",
3451
+ * "roles": ["Owner"],
3452
+ * "is_delete_allowed": true,
3453
+ * "created_at": "2026-05-12T13:45:11Z"
3454
+ * }
3455
+ * ]
3456
+ * }
3457
+ * ```
3458
+ * @throws {ValidationError} If `email` or `password` is missing.
3459
+ * @throws {ApiError} `400` if the credentials are rejected.
3460
+ *
3461
+ * @example
3462
+ * ```ts
3463
+ * const { access_token, accounts } = await client.auth.login(
3464
+ * 'user@example.com',
3465
+ * 's3cret',
3466
+ * );
3467
+ * ```
3468
+ */
3469
+ login(email: string, password: string): Promise<ILoginResponse>;
3470
+ /**
3471
+ * Log in with a social provider (`POST /authentication/social-login`).
3472
+ *
3473
+ * Exchanges a provider-issued OAuth token (currently Google) for an
3474
+ * Assinafy JWT. Returns the same {@link ILoginResponse} shape as
3475
+ * {@link AuthenticationResource.login}.
3476
+ *
3477
+ * @param payload - The social-login body.
3478
+ * @param payload.provider - OAuth provider. The API currently accepts
3479
+ * `'google'`; the type is left open for forward-compatibility.
3480
+ * @param payload.token - The provider-issued OAuth/ID token.
3481
+ * @param payload.has_accepted_terms - Whether the user has accepted the
3482
+ * terms of service.
3483
+ * @returns An {@link ILoginResponse} with the access token, user, and
3484
+ * accounts. Response shape:
3485
+ * ```jsonc
3486
+ * {
3487
+ * "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…",
3488
+ * "user": {
3489
+ * "id": "md3j6p9w8b7y6qvqaoy5er42",
3490
+ * "name": "Multica Test",
3491
+ * "email": "user@example.com",
3492
+ * "is_email_verified": true,
3493
+ * "has_accepted_terms": true
3494
+ * },
3495
+ * "accounts": [
3496
+ * {
3497
+ * "id": "acc_example",
3498
+ * "name": "Multica Test",
3499
+ * "roles": ["Owner"],
3500
+ * "is_delete_allowed": true,
3501
+ * "created_at": "2026-05-12T13:45:11Z"
3502
+ * }
3503
+ * ]
3504
+ * }
3505
+ * ```
3506
+ * @throws {ValidationError} If `provider` or `token` is missing.
3507
+ * @throws {ApiError} `400` if the provider token is rejected.
3508
+ *
3509
+ * @example
3510
+ * ```ts
3511
+ * const session = await client.auth.socialLogin({
3512
+ * provider: 'google',
3513
+ * token: googleIdToken,
3514
+ * has_accepted_terms: true,
3515
+ * });
3516
+ * ```
3517
+ */
3518
+ socialLogin(payload: {
3519
+ /** OAuth provider. The API currently accepts `google`; typed open for forward-compat. */
3520
+ provider: 'google' | AnyString;
3521
+ token: string;
3522
+ has_accepted_terms: boolean;
3523
+ }): Promise<ILoginResponse>;
3524
+ /**
3525
+ * Link a Google identity to the authenticated user
3526
+ * (`POST /auth/link-social-login`).
3527
+ *
3528
+ * Request body:
3529
+ * ```jsonc
3530
+ * { "provider": "google", "token": "provider-issued-token" }
3531
+ * ```
3532
+ * The response is the standard status/message acknowledgement with no data,
3533
+ * so this method resolves to `void`.
3534
+ *
3535
+ * @param payload - Social provider and provider-issued access/ID token.
3536
+ * @returns Resolves when the API acknowledges that the identity was linked.
3537
+ * @throws {ValidationError} If either field is empty.
3538
+ * @throws {ApiError} `400` for an invalid provider token or `401` for
3539
+ * missing/invalid Assinafy credentials.
3540
+ *
3541
+ * @example
3542
+ * ```ts
3543
+ * await client.auth.linkSocialLogin({
3544
+ * provider: 'google',
3545
+ * token: googleIdToken,
3546
+ * });
3547
+ * ```
3548
+ */
3549
+ linkSocialLogin(payload: {
3550
+ provider: 'google' | AnyString;
3551
+ token: string;
3552
+ }): Promise<void>;
3553
+ /**
3554
+ * Create (or rotate) the current user's API key (`POST /users/api-keys`).
3555
+ *
3556
+ * Returns the **full, unmasked** key exactly once — store it securely, as
3557
+ * subsequent reads via {@link AuthenticationResource.getApiKey} only return
3558
+ * a masked value. Calling this again rotates the key, invalidating the
3559
+ * previous one.
3560
+ *
3561
+ * @param password - The current user's password, required to authorize
3562
+ * key generation.
3563
+ * @returns An {@link IApiKeyResponse} containing the new key. Response
3564
+ * shape:
3565
+ * ```jsonc
3566
+ * {
3567
+ * "api_key": "Hf8s2Jd9KpQ1mZ4xVn7bLcR3tWy6aEu0oCiSgBvNEWq"
3568
+ * }
3569
+ * ```
3570
+ * @throws {ValidationError} If `password` is missing.
3571
+ * @throws {ApiError} If the API rejects the request (e.g. wrong password).
3572
+ *
3573
+ * @example
3574
+ * ```ts
3575
+ * const { api_key } = await client.auth.createApiKey('s3cret');
3576
+ * if (!api_key) throw new Error('API returned no generated key');
3577
+ * // Persist api_key now — it is not retrievable unmasked later.
3578
+ * ```
3579
+ */
3580
+ createApiKey(password: string): Promise<IApiKeyResponse>;
3581
+ /**
3582
+ * Fetch a masked view of the current API key (`GET /users/api-keys`).
3583
+ *
3584
+ * Only the last few characters are revealed; the leading characters are
3585
+ * masked with asterisks. The documented no-key form is
3586
+ * `{ api_key: null }`; older deployments may return `null` for the entire
3587
+ * data value.
3588
+ * The unmasked key is only ever returned by
3589
+ * {@link AuthenticationResource.createApiKey}.
3590
+ *
3591
+ * @returns An {@link IMaskedApiKeyResponse}: `{ api_key }` with a masked
3592
+ * string or `null`, or the legacy top-level `null`. Response shape:
3593
+ * ```jsonc
3594
+ * {
3595
+ * "api_key": "************************************************************NEWq"
3596
+ * }
3597
+ * ```
3598
+ * @throws {ApiError} If the API rejects the request.
3599
+ *
3600
+ * @example
3601
+ * ```ts
3602
+ * const masked = await client.auth.getApiKey();
3603
+ * if (masked?.api_key) console.log('Key ends with', masked.api_key.slice(-4));
3604
+ * else console.log('No API key generated yet');
3605
+ * ```
3606
+ */
3607
+ getApiKey(): Promise<IMaskedApiKeyResponse>;
3608
+ /**
3609
+ * Revoke the current API key (`DELETE /users/api-keys`).
3610
+ *
3611
+ * After this call any existing `X-Api-Key` using the deleted key stops
3612
+ * working; generate a new one with
3613
+ * {@link AuthenticationResource.createApiKey}.
3614
+ *
3615
+ * @returns Nothing; resolves once the key is revoked.
3616
+ * @throws {ApiError} If the API rejects the request.
3617
+ *
3618
+ * @example
3619
+ * ```ts
3620
+ * await client.auth.deleteApiKey();
3621
+ * ```
3622
+ */
3623
+ deleteApiKey(): Promise<void>;
3624
+ /**
3625
+ * Change the authenticated user's password
3626
+ * (`PUT /authentication/change-password`).
3627
+ *
3628
+ * Requires the current password as a confirmation. On success the API
3629
+ * echoes back the affected `email`.
3630
+ *
3631
+ * @param payload - The change-password body.
3632
+ * @param payload.email - The user's email address.
3633
+ * @param payload.password - The current password.
3634
+ * @param payload.new_password - The new password to set.
3635
+ * @returns `{ email }` — the address whose password was changed. Response
3636
+ * shape:
3637
+ * ```jsonc
3638
+ * {
3639
+ * "email": "user@example.com"
3640
+ * }
3641
+ * ```
3642
+ * @throws {ValidationError} If `email`, `password`, or `new_password` is
3643
+ * missing.
3644
+ * @throws {ApiError} `400`/`401` if the current password is wrong or the
3645
+ * new password is rejected.
3646
+ *
3647
+ * @example
3648
+ * ```ts
3649
+ * await client.auth.changePassword({
3650
+ * email: 'user@example.com',
3651
+ * password: 'old-s3cret',
3652
+ * new_password: 'new-s3cret',
3653
+ * });
3654
+ * ```
3655
+ */
3656
+ changePassword(payload: {
3657
+ email: string;
3658
+ password: string;
3659
+ new_password: string;
3660
+ }): Promise<{
3661
+ email: string;
3662
+ }>;
3663
+ /**
3664
+ * Request a password-reset email
3665
+ * (`PUT /authentication/request-password-reset`).
3666
+ *
3667
+ * Triggers Assinafy to email a reset link/token to the given address.
3668
+ * Complete the flow with {@link AuthenticationResource.resetPassword}.
3669
+ *
3670
+ * @param email - The email address to send the reset link to.
3671
+ * @returns `{ email }` — the address the reset link was sent to. Response
3672
+ * shape:
3673
+ * ```jsonc
3674
+ * {
3675
+ * "email": "user@example.com"
3676
+ * }
3677
+ * ```
3678
+ * @throws {ValidationError} If `email` is missing.
3679
+ * @throws {ApiError} If the API rejects the request.
3680
+ *
3681
+ * @example
3682
+ * ```ts
3683
+ * await client.auth.requestPasswordReset('user@example.com');
3684
+ * ```
3685
+ */
3686
+ requestPasswordReset(email: string): Promise<{
3687
+ email: string;
3688
+ }>;
3689
+ /**
3690
+ * Complete a password reset using the emailed token
3691
+ * (`PUT /authentication/reset-password`).
3692
+ *
3693
+ * Consumes the token delivered by
3694
+ * {@link AuthenticationResource.requestPasswordReset} and sets the new
3695
+ * password. On success the API echoes back the affected `email`.
3696
+ *
3697
+ * @param payload - The reset-password body.
3698
+ * @param payload.email - The user's email address.
3699
+ * @param payload.token - The reset token from the emailed link.
3700
+ * @param payload.new_password - The new password to set.
3701
+ * @returns `{ email }` — the address whose password was reset. Response
3702
+ * shape:
3703
+ * ```jsonc
3704
+ * {
3705
+ * "email": "user@example.com"
3706
+ * }
3707
+ * ```
3708
+ * @throws {ValidationError} If `email` or `new_password` is missing.
3709
+ * @throws {ApiError} `400` if the token is invalid or expired.
3710
+ *
3711
+ * @example
3712
+ * ```ts
3713
+ * await client.auth.resetPassword({
3714
+ * email: 'user@example.com',
3715
+ * token: 'reset-token-from-email',
3716
+ * new_password: 'new-s3cret',
3717
+ * });
3718
+ * ```
3719
+ */
3720
+ resetPassword(payload: {
3721
+ email: string;
3722
+ token?: string;
3723
+ new_password: string;
3724
+ }): Promise<{
3725
+ email: string;
3726
+ }>;
3727
+ private absoluteUrl;
3728
+ }
3729
+
3730
+ /**
3731
+ * Custom field definitions used by `collect` assignments.
3732
+ *
3733
+ * Covers the full Field Definition section of the API docs:
3734
+ * - `POST /accounts/{id}/fields`
3735
+ * - `GET /accounts/{id}/fields`
3736
+ * - `GET /accounts/{id}/fields/{id}`
3737
+ * - `PUT /accounts/{id}/fields/{id}`
3738
+ * - `DELETE /accounts/{id}/fields/{id}`
3739
+ * - `POST /accounts/{id}/fields/{id}/validate?signer-access-code=…`
3740
+ * - `POST /accounts/{id}/fields/validate-multiple?signer-access-code=…`
3741
+ * - `GET /field-types`
3742
+ */
3743
+ declare class FieldsResource extends BaseResource {
3744
+ /**
3745
+ * Create a field definition (`POST /accounts/{accountId}/fields`).
3746
+ *
3747
+ * @param payload - The field to create. `type` and `name` are required;
3748
+ * `type` must be one of the platform field types (see
3749
+ * {@link FieldsResource.listTypes}); `regex` may be a string or `null`,
3750
+ * and `is_required` is optional. `is_active` is a tested live extension.
3751
+ * @param accountId - Override the client's default account ID.
3752
+ * @returns The created field definition. Response shape:
3753
+ * ```jsonc
3754
+ * {
3755
+ * "resource": "field_definition",
3756
+ * "id": "103ad21709d15eca8c48085b5b8f",
3757
+ * "name": "Employee CPF",
3758
+ * "type": "cpf",
3759
+ * "regex": null,
3760
+ * "is_pre_defined": false,
3761
+ * "is_active": true,
3762
+ * "is_required": true,
3763
+ * "is_standard": false,
3764
+ * "is_read_only": false,
3765
+ * "is_visible": true
3766
+ * }
3767
+ * ```
3768
+ * @throws {ValidationError} If `type` or `name` is missing, or no account
3769
+ * ID is available.
3770
+ * @throws {ApiError} If the API rejects the request (e.g. `400` invalid type).
3771
+ *
3772
+ * @example
3773
+ * ```ts
3774
+ * const field = await client.fields.create({
3775
+ * name: 'Employee CPF',
3776
+ * type: 'cpf',
3777
+ * is_required: true,
3778
+ * });
3779
+ * ```
3780
+ */
3781
+ create(payload: ICreateFieldPayload, accountId?: string): Promise<IFieldDefinition>;
3782
+ /**
3783
+ * List field definitions for the workspace
3784
+ * (`GET /accounts/{accountId}/fields`).
3785
+ *
3786
+ * @param params - Filters.
3787
+ * @param params.include_inactive - Return inactive fields too.
3788
+ * @param params.include_standard - Also return the built-in standard fields
3789
+ * (`signature`, `initial`, `signatureDate`).
3790
+ * @param accountId - Override the client's default account ID.
3791
+ * @returns The field definitions (a plain array — this endpoint is not
3792
+ * paginated). Each item:
3793
+ * ```jsonc
3794
+ * {
3795
+ * "id": "field-example",
3796
+ * "name": "CPF",
3797
+ * "type": "cpf",
3798
+ * "regex": null,
3799
+ * "is_pre_defined": true,
3800
+ * "is_active": true,
3801
+ * "is_required": false,
3802
+ * "is_standard": false,
3803
+ * "is_read_only": false,
3804
+ * "is_visible": true
3805
+ * }
3806
+ * ```
3807
+ * @throws {ValidationError} If no account ID is available.
3808
+ * @throws {ApiError} If the API rejects the request.
3809
+ *
3810
+ * @example
3811
+ * ```ts
3812
+ * const fields = await client.fields.list({ include_standard: true });
3813
+ * ```
3814
+ */
3815
+ list(params?: {
3816
+ include_inactive?: boolean;
3817
+ include_standard?: boolean;
3818
+ }, accountId?: string): Promise<IFieldDefinition[]>;
3819
+ /**
3820
+ * Get a single field definition by ID
3821
+ * (`GET /accounts/{accountId}/fields/{fieldId}`).
3822
+ *
3823
+ * @param fieldId - The field definition to fetch.
3824
+ * @param accountId - Override the client's default account ID.
3825
+ * @returns The field definition. Response shape:
3826
+ * ```jsonc
3827
+ * {
3828
+ * "resource": "field_definition",
3829
+ * "id": "103ad21709d15eca8c48085b5b8f",
3830
+ * "name": "Employee CPF",
3831
+ * "type": "cpf",
3832
+ * "regex": null,
3833
+ * "is_pre_defined": false,
3834
+ * "is_active": true,
3835
+ * "is_required": true,
3836
+ * "is_standard": false,
3837
+ * "is_read_only": false,
3838
+ * "is_visible": true
3839
+ * }
3840
+ * ```
3841
+ * @throws {ValidationError} If `fieldId` or the account ID is missing.
3842
+ * @throws {ApiError} `404` if the field does not exist.
3843
+ *
3844
+ * @example
3845
+ * ```ts
3846
+ * const field = await client.fields.get('103ad21709d15eca8c48085b5b8f');
3847
+ * ```
3848
+ */
3849
+ get(fieldId: string, accountId?: string): Promise<IFieldDefinition>;
3850
+ /**
3851
+ * Update a field definition
3852
+ * (`PUT /accounts/{accountId}/fields/{fieldId}`).
3853
+ *
3854
+ * @param fieldId - The field definition to update.
3855
+ * @param payload - Official fields are `name`, nullable `regex`, and
3856
+ * `is_active`. The sandbox also accepts `type` and `is_required` as live
3857
+ * compatibility extensions.
3858
+ * @param accountId - Override the client's default account ID.
3859
+ * @returns The updated field definition. Response shape:
3860
+ * ```jsonc
3861
+ * {
3862
+ * "resource": "field_definition",
3863
+ * "id": "103ad21709d15eca8c48085b5b8f",
3864
+ * "name": "Employee CPF (renamed)",
3865
+ * "type": "cpf",
3866
+ * "regex": null,
3867
+ * "is_pre_defined": false,
3868
+ * "is_active": true,
3869
+ * "is_required": true,
3870
+ * "is_standard": false,
3871
+ * "is_read_only": false,
3872
+ * "is_visible": true
3873
+ * }
3874
+ * ```
3875
+ * @throws {ValidationError} If `fieldId` or the account ID is missing.
3876
+ * @throws {ApiError} `404` if the field does not exist.
3877
+ *
3878
+ * @example
3879
+ * ```ts
3880
+ * await client.fields.update('103ad21709d15eca8c48085b5b8f', {
3881
+ * name: 'Employee CPF (renamed)',
3882
+ * is_active: false,
3883
+ * });
3884
+ * ```
3885
+ */
3886
+ update(fieldId: string, payload: IUpdateFieldPayload, accountId?: string): Promise<IFieldDefinition>;
3887
+ /**
3888
+ * Delete a field definition
3889
+ * (`DELETE /accounts/{accountId}/fields/{fieldId}`).
3890
+ *
3891
+ * Fails if the field has already been used by an assignment; deactivate it
3892
+ * via {@link FieldsResource.update} (`is_active: false`) instead.
3893
+ *
3894
+ * @param fieldId - The field definition to delete.
3895
+ * @param accountId - Override the client's default account ID.
3896
+ * @returns Nothing on success.
3897
+ * @throws {ValidationError} If `fieldId` or the account ID is missing.
3898
+ * @throws {ApiError} If the field is in use or does not exist.
3899
+ *
3900
+ * @example
3901
+ * ```ts
3902
+ * await client.fields.delete('103ad21709d15eca8c48085b5b8f');
3903
+ * ```
3904
+ */
3905
+ delete(fieldId: string, accountId?: string): Promise<void>;
3906
+ /**
3907
+ * Validate a single value against a field definition
3908
+ * (`POST /accounts/{accountId}/fields/{fieldId}/validate`).
3909
+ *
3910
+ * The official operation uses the client's API-key/Bearer authentication.
3911
+ * `signerAccessCode` is retained as a deployment-specific, live-unverified
3912
+ * compatibility query and is sent as `signer-access-code` when supplied.
3913
+ *
3914
+ * @param fieldId - The field definition to validate against.
3915
+ * @param value - The value to check (validated against the field's
3916
+ * type/regex). Sent as `{ value }` in the request body.
3917
+ * @param options - Account override and optional legacy `signerAccessCode`.
3918
+ * @returns The validation result. Response shape:
3919
+ * ```jsonc
3920
+ * {
3921
+ * "type": "text",
3922
+ * "success": true,
3923
+ * "error_message": ""
3924
+ * }
3925
+ * ```
3926
+ * @throws {ValidationError} If `fieldId` or the account ID is missing.
3927
+ * @throws {ApiError} If the API rejects the request.
3928
+ *
3929
+ * @example
3930
+ * ```ts
3931
+ * const result = await client.fields.validate(
3932
+ * '103ad21709d15eca8c48085b5b8f',
3933
+ * '123.456.789-09',
3934
+ * );
3935
+ * if (!result.success) console.warn(result.error_message);
3936
+ * ```
3937
+ */
3938
+ validate(fieldId: string, value: unknown, options?: {
3939
+ signerAccessCode?: string;
3940
+ accountId?: string;
3941
+ }): Promise<IFieldValidationResult>;
3942
+ /**
3943
+ * Validate multiple values at once
3944
+ * (`POST /accounts/{accountId}/fields/validate-multiple`).
3945
+ *
3946
+ * The request body is the array of `{ field_id, value }` entries itself
3947
+ * (not wrapped in an object). The optional `signerAccessCode` query is the
3948
+ * same live-unverified compatibility extension described on
3949
+ * {@link FieldsResource.validate}.
3950
+ *
3951
+ * @param entries - Non-empty array of `{ field_id, value }` pairs.
3952
+ * @param options - Account override and optional legacy `signerAccessCode`.
3953
+ * @returns One validation result per entry. Response shape:
3954
+ * ```jsonc
3955
+ * [
3956
+ * { "type": "cpf", "success": true, "error_message": "" },
3957
+ * { "type": "text", "success": true, "error_message": "" }
3958
+ * ]
3959
+ * ```
3960
+ * @throws {ValidationError} If `entries` is empty or the account ID is missing.
3961
+ * @throws {ApiError} If the API rejects the request.
3962
+ *
3963
+ * @example
3964
+ * ```ts
3965
+ * const results = await client.fields.validateMultiple(
3966
+ * [
3967
+ * { field_id: 'field-cpf', value: '123.456.789-09' },
3968
+ * { field_id: 'field-name', value: 'Example Signer' },
3969
+ * ],
3970
+ * );
3971
+ * ```
3972
+ */
3973
+ validateMultiple(entries: IFieldValidateMultipleEntry[], options?: {
3974
+ signerAccessCode?: string;
3975
+ accountId?: string;
3976
+ }): Promise<IFieldValidationResult[]>;
3977
+ /**
3978
+ * List the platform's supported field types (`GET /field-types`).
3979
+ *
3980
+ * @returns The catalogue of field types (11 live entries). Response shape:
3981
+ * ```jsonc
3982
+ * [
3983
+ * { "type": "personName", "name": "Nome" },
3984
+ * { "type": "cpf", "name": "CPF" },
3985
+ * { "type": "email", "name": "E-mail" },
3986
+ * { "type": "text", "name": "Texto" }
3987
+ * ]
3988
+ * ```
3989
+ * @throws {ApiError} If the API rejects the request.
3990
+ *
3991
+ * @example
3992
+ * ```ts
3993
+ * const types = await client.fields.listTypes();
3994
+ * const cpf = types.find((t) => t.type === 'cpf');
3995
+ * ```
3996
+ */
3997
+ listTypes(): Promise<IFieldType[]>;
3998
+ }
3999
+
4000
+ /**
4001
+ * Signer-side endpoints for custom signing UIs. Most calls authenticate with
4002
+ * `signer-access-code` (the one-time link emailed/whatsapped to the signer),
4003
+ * never the workspace API key. The artifact-download route is the documented
4004
+ * public exception and can be called without an access code.
4005
+ */
4006
+ declare class SignerDocumentsResource extends BaseResource {
4007
+ /**
4008
+ * Fetch the document currently awaiting a given signer
4009
+ * (`GET /signers/{signer_id}/document?signer-access-code=…`).
4010
+ *
4011
+ * The signer-side counterpart of {@link DocumentResource.details}, authorised
4012
+ * by the signer's access code rather than the workspace API key.
4013
+ *
4014
+ * @param signerId - The signer whose current document is fetched.
4015
+ * @param signerAccessCode - The signer's access code, from their signing link.
4016
+ * @returns The document in the full {@link IDocumentDetailsResponse} shape:
4017
+ * ```jsonc
4018
+ * {
4019
+ * "resource": "document",
4020
+ * "id": "103acccd24234c07858ffddf6d84",
4021
+ * "account_id": "acc_example",
4022
+ * "template_id": null,
4023
+ * "name": "Service agreement.pdf",
4024
+ * "status": "pending_signature",
4025
+ * "artifacts": {
4026
+ * "original": "https://sandbox.assinafy.com.br/v1/documents/103acccd.../download/original",
4027
+ * "thumbnail": "https://sandbox.assinafy.com.br/v1/documents/103acccd.../thumbnail"
4028
+ * },
4029
+ * "is_closed": false,
4030
+ * "signing_url": "https://app-sandbox.assinafy.com.br/sign/103acccd...",
4031
+ * "decline_reason": null,
4032
+ * "declined_by": null,
4033
+ * "tags": [],
4034
+ * "assignment": null, // an IAssignment once signing has started
4035
+ * "pages": [
4036
+ * { "id": "103acccd5c73...", "number": 1, "height": 1651, "width": 1275,
4037
+ * "download_url": "https://sandbox.assinafy.com.br/v1/documents/103acccd.../pages/103acccd5c73.../download" }
4038
+ * ],
4039
+ * "created_at": "2026-07-19T14:56:54Z",
4040
+ * "updated_at": "2026-07-19T14:56:56Z"
4041
+ * }
4042
+ * ```
4043
+ * @throws {ValidationError} If `signerId` or `signerAccessCode` is missing.
4044
+ * @throws {ApiError} If the access code is invalid or expired.
4045
+ *
4046
+ * @example
4047
+ * ```ts
4048
+ * const doc = await client.signerDocuments.getCurrent(signerId, accessCode);
4049
+ * console.log(doc.status, doc.pages.length);
4050
+ * ```
4051
+ */
4052
+ getCurrent(signerId: string, signerAccessCode: string): Promise<IDocumentDetailsResponse>;
4053
+ /**
4054
+ * List every document awaiting a given signer
4055
+ * (`GET /signers/{signer_id}/documents?signer-access-code=…`).
4056
+ *
4057
+ * The signer-side counterpart of {@link DocumentResource.list}, scoped to one
4058
+ * signer and authorised by their access code. Pagination is read from the
4059
+ * `X-Pagination-*` response headers and attached in `meta`; the API honours
4060
+ * `page` and `per-page` (the SDK normalises `per_page` → `per-page`).
4061
+ *
4062
+ * @param signerId - The signer whose documents are listed.
4063
+ * @param signerAccessCode - The signer's access code, from their signing link.
4064
+ * @param params - Pagination: `page`, `per-page` (also accepts `per_page`).
4065
+ * @returns Matching documents in the compact {@link IDocumentListItem} shape,
4066
+ * with pagination in `meta`:
4067
+ * ```jsonc
4068
+ * {
4069
+ * "data": [
4070
+ * {
4071
+ * "id": "103acccd24234c07858ffddf6d84",
4072
+ * "account_id": "acc_example",
4073
+ * "template_id": null,
4074
+ * "name": "Service agreement.pdf",
4075
+ * "status": "pending_signature",
4076
+ * "artifacts": { "original": "https://...", "thumbnail": "https://..." },
4077
+ * "is_closed": false,
4078
+ * "signing_url": "https://app-sandbox.assinafy.com.br/sign/103acccd...",
4079
+ * "decline_reason": null,
4080
+ * "declined_by": null,
4081
+ * "tags": [],
4082
+ * "created_at": "2026-07-19T14:56:54Z",
4083
+ * "updated_at": "2026-07-19T14:56:56Z"
4084
+ * }
4085
+ * ],
4086
+ * "meta": { "current_page": 1, "per_page": 20, "total": 1, "last_page": 1 }
4087
+ * }
4088
+ * ```
4089
+ * @throws {ValidationError} If `signerId` or `signerAccessCode` is missing.
4090
+ * @throws {ApiError} If the access code is invalid or expired.
4091
+ *
4092
+ * @example
4093
+ * ```ts
4094
+ * const { data, meta } = await client.signerDocuments.list(signerId, accessCode, {
4095
+ * 'per-page': 20,
4096
+ * });
4097
+ * ```
4098
+ */
4099
+ list(signerId: string, signerAccessCode: string, params?: IListParams): Promise<IDocumentListResponse>;
4100
+ /**
4101
+ * Search the documents awaiting a given signer
4102
+ * (`GET /signers/{signer_id}/documents/search?signer-access-code=…`).
4103
+ *
4104
+ * The signer-side counterpart of {@link DocumentResource.search}, scoped to
4105
+ * one signer and authorised by their access code rather than the API key.
4106
+ * Like {@link SignerDocumentsResource.list}, it requires
4107
+ * `signer-access-code`; the published spec omits that parameter, but the
4108
+ * endpoint is not usable without it.
4109
+ *
4110
+ * @param signerId - The signer whose documents are searched.
4111
+ * @param signerAccessCode - The signer's access code, from their signing link.
4112
+ * @param search - Free-text term matched against the document name.
4113
+ * @returns Matching documents for that signer, in the compact
4114
+ * {@link IDocumentListItem} shape, with pagination in `meta`.
4115
+ * @throws {ValidationError} If `signerId` or `signerAccessCode` is missing.
4116
+ * @throws {ApiError} If the access code is invalid or expired.
4117
+ *
4118
+ * @example
4119
+ * ```ts
4120
+ * const { data } = await client.signerDocuments.search(
4121
+ * signerId,
4122
+ * accessCode,
4123
+ * 'agreement',
4124
+ * );
4125
+ * ```
4126
+ */
4127
+ search(signerId: string, signerAccessCode: string, search?: string): Promise<IDocumentListResponse>;
4128
+ /**
4129
+ * Download one of a signer's document artifacts as raw bytes
4130
+ * (`GET /signers/{signer_id}/documents/{document_id}/download/{artifact}`).
4131
+ *
4132
+ * The signer-side counterpart of {@link DocumentResource.download}: same
4133
+ * artifact names, exposed by the API as a public signer-link endpoint. The
4134
+ * optional access-code argument is retained for compatibility with deployed
4135
+ * environments that still accept or require the legacy query parameter. The
4136
+ * `certificated` and `bundle` artifacts only exist once the document is fully
4137
+ * signed.
4138
+ *
4139
+ * @param signerId - The signer requesting the download.
4140
+ * @param documentId - The document to download.
4141
+ * @param artifactName - Which artifact to fetch (`original`, `certificated`,
4142
+ * `certificate-page`, or `bundle`).
4143
+ * @param signerAccessCode - Optional legacy signer access code. Omit it for
4144
+ * the official public request shape.
4145
+ * @returns The artifact bytes as a Node `Buffer` (PDF for `original` /
4146
+ * `certificated` / `bundle`).
4147
+ * @throws {ValidationError} If `signerId` or `documentId` is missing, or if
4148
+ * an explicitly supplied legacy `signerAccessCode` is blank.
4149
+ * @throws {ApiError} `404` if the artifact does not exist yet.
4150
+ *
4151
+ * @example
4152
+ * ```ts
4153
+ * const pdf = await client.signerDocuments.download(
4154
+ * signerId,
4155
+ * documentId,
4156
+ * 'original',
4157
+ * );
4158
+ * await fs.writeFile('to-sign.pdf', pdf);
4159
+ * ```
4160
+ */
4161
+ download(signerId: string, documentId: string, artifactName: DocumentArtifactName, signerAccessCode?: string): Promise<Buffer>;
4162
+ /**
4163
+ * Sign several documents in one call
4164
+ * (`PUT /signers/documents/sign-multiple?signer-access-code=…`).
4165
+ *
4166
+ * Batch shortcut for a signer who has multiple pending documents under the
4167
+ * same access code — it signs each with their stored signature/initials
4168
+ * rather than field-by-field (contrast {@link SignerDocumentsResource.sign}).
4169
+ * The `document_ids` array goes in the request body; the access code
4170
+ * authenticates via the `signer-access-code` query param.
4171
+ *
4172
+ * @param documentIds - Non-empty array of document IDs to sign.
4173
+ * @param signerAccessCode - The signer's access code, from their signing link.
4174
+ * @returns Resolves when the API acknowledges the operation. The documented
4175
+ * empty-array response data is intentionally discarded.
4176
+ * @throws {ValidationError} If `documentIds` is empty/not an array, or
4177
+ * `signerAccessCode` is missing.
4178
+ * @throws {ApiError} If the access code is invalid/expired or a document is
4179
+ * not in a signable state.
4180
+ *
4181
+ * @example
4182
+ * ```ts
4183
+ * // body → { document_ids: ['103acccd...', '103aa251...'] }
4184
+ * await client.signerDocuments.signMultiple(
4185
+ * ['103acccd24234c07858ffddf6d84', '103aa251ccb4ee136e3fd5cc140b'],
4186
+ * accessCode,
4187
+ * );
4188
+ * ```
4189
+ */
4190
+ signMultiple(documentIds: string[], signerAccessCode: string): Promise<void>;
4191
+ /**
4192
+ * Decline several documents in one call
4193
+ * (`PUT /signers/documents/decline-multiple?signer-access-code=…`).
4194
+ *
4195
+ * The batch counterpart of {@link SignerDocumentsResource.signMultiple}: the
4196
+ * same `decline_reason` is recorded against every document in `documentIds`.
4197
+ * Both `document_ids` and `decline_reason` go in the request body; the access
4198
+ * code authenticates via the `signer-access-code` query param.
4199
+ *
4200
+ * @param documentIds - Non-empty array of document IDs to decline.
4201
+ * @param declineReason - Free-text reason shown to the sender (required).
4202
+ * @param signerAccessCode - The signer's access code, from their signing link.
4203
+ * @returns Resolves when the API acknowledges the operation. The documented
4204
+ * empty-array response data is intentionally discarded.
4205
+ * @throws {ValidationError} If `documentIds` is empty/not an array,
4206
+ * `declineReason` is empty, or `signerAccessCode` is missing.
4207
+ * @throws {ApiError} If the access code is invalid or expired.
4208
+ *
4209
+ * @example
4210
+ * ```ts
4211
+ * // body → { document_ids: ['103acccd...'], decline_reason: 'Wrong counterparty' }
4212
+ * await client.signerDocuments.declineMultiple(
4213
+ * ['103acccd24234c07858ffddf6d84'],
4214
+ * 'Wrong counterparty',
4215
+ * accessCode,
4216
+ * );
4217
+ * ```
4218
+ */
4219
+ declineMultiple(documentIds: string[], declineReason: string, signerAccessCode: string): Promise<void>;
4220
+ /**
4221
+ * Fetch the authenticated signer's own profile
4222
+ * (`GET /signers/self?signer-access-code=…`).
4223
+ *
4224
+ * Resolves the signer identity behind an access code, plus whether they have
4225
+ * already stored a signature/initial image — useful for deciding whether to
4226
+ * prompt for {@link SignerDocumentsResource.uploadSignature} before signing.
4227
+ *
4228
+ * @param signerAccessCode - The signer's access code, from their signing link.
4229
+ * @returns The signer profile. Unlike the workspace-side signer object, this
4230
+ * also reports `has_signature` / `has_initial`:
4231
+ * ```jsonc
4232
+ * {
4233
+ * "resource": "signer",
4234
+ * "id": "19e6b92e7895332ed9708535d8c",
4235
+ * "full_name": "Example Signer",
4236
+ * "email": "signer@example.com",
4237
+ * "whatsapp_phone_number": null,
4238
+ * "has_accepted_terms": false,
4239
+ * "has_signature": false,
4240
+ * "has_initial": false,
4241
+ * "is_signature_reusable": false
4242
+ * }
4243
+ * ```
4244
+ * @throws {ValidationError} If `signerAccessCode` is missing.
4245
+ * @throws {ApiError} If the access code is invalid or expired.
4246
+ *
4247
+ * @example
4248
+ * ```ts
4249
+ * const me = await client.signerDocuments.self(accessCode);
4250
+ * if (!me.has_signature) {
4251
+ * // prompt the signer to draw/upload a signature first
4252
+ * }
4253
+ * ```
4254
+ */
4255
+ self(signerAccessCode: string): Promise<ISignerSelf>;
4256
+ /**
4257
+ * Accept the platform terms of use as the signer
4258
+ * (`PUT /signers/accept-terms?signer-access-code=…`).
4259
+ *
4260
+ * A signer must accept terms before they can sign. The access code
4261
+ * authenticates via the `signer-access-code` **query param** — this endpoint
4262
+ * takes **no request body** (sending the code in the body leaves the request
4263
+ * unauthenticated → `401`). Pass the resulting acceptance to
4264
+ * {@link SignerDocumentsResource.getAssignment} via its `hasAcceptedTerms`
4265
+ * flag.
4266
+ *
4267
+ * @param signerAccessCode - The signer's access code, from their signing link.
4268
+ * @returns Resolves when the API acknowledges the operation. The response
4269
+ * envelope has no `data` field and is intentionally discarded.
4270
+ * @throws {ValidationError} If `signerAccessCode` is missing.
4271
+ * @throws {ApiError} If the access code is invalid or expired.
4272
+ *
4273
+ * @example
4274
+ * ```ts
4275
+ * await client.signerDocuments.acceptTerms(accessCode);
4276
+ * const assignment = await client.signerDocuments.getAssignment(accessCode, true);
4277
+ * ```
4278
+ */
4279
+ acceptTerms(signerAccessCode: string): Promise<void>;
4280
+ /**
4281
+ * Verify the signer's email one-time password
4282
+ * (`POST /verify?signer-access-code=…`).
4283
+ *
4284
+ * Confirms the 6-digit OTP the platform emailed the signer. The access code
4285
+ * authenticates via the `signer-access-code` **query param**; the request
4286
+ * **body carries only `verification-code`** (putting the access code in the
4287
+ * body leaves the request unauthenticated → `401`).
4288
+ *
4289
+ * @param payload - `signerAccessCode` (the signing-link code) and
4290
+ * `verificationCode` (the OTP the signer received).
4291
+ * @returns Resolves when the API acknowledges the operation. The response
4292
+ * envelope has no `data` field and is intentionally discarded.
4293
+ * @throws {ValidationError} If `signerAccessCode` or `verificationCode` is
4294
+ * missing.
4295
+ * @throws {ApiError} `400`/`401` if the OTP is wrong or the access code is
4296
+ * invalid or expired.
4297
+ *
4298
+ * @example
4299
+ * ```ts
4300
+ * // query → ?signer-access-code=<code> body → { 'verification-code': '123456' }
4301
+ * await client.signerDocuments.verifyEmail({
4302
+ * signerAccessCode: accessCode,
4303
+ * verificationCode: '123456',
4304
+ * });
4305
+ * ```
4306
+ */
4307
+ verifyEmail(payload: {
4308
+ signerAccessCode: string;
4309
+ verificationCode: string;
4310
+ }): Promise<void>;
4311
+ /**
4312
+ * Confirm (and optionally correct) the signer's identity data before signing
4313
+ * (`PUT /documents/{documentId}/signers/confirm-data?signer-access-code=…`).
4314
+ *
4315
+ * Lets the signer confirm the name/e-mail/government ID that will appear on
4316
+ * the signed document. Only the provided fields are sent — `undefined`/`null`
4317
+ * entries are stripped by {@link cleanParams} before the request — so you can
4318
+ * pass just the fields the signer changed. The access code authenticates via
4319
+ * the `signer-access-code` query param. Legal terms are accepted separately
4320
+ * with {@link SignerDocumentsResource.acceptTerms}; they are never asserted
4321
+ * by this identity-data request.
4322
+ *
4323
+ * @param documentId - The document the signer is confirming data for.
4324
+ * @param signerAccessCode - The signer's access code, from their signing link.
4325
+ * @param payload - Any of the official `full_name`, `email`, or
4326
+ * `government_id` fields. Fields left out are not sent.
4327
+ * @returns The confirmed signer in the full {@link ISigner} response shape.
4328
+ * @throws {ValidationError} If `documentId` or `signerAccessCode` is missing.
4329
+ * @throws {ApiError} If the access code is invalid/expired or a value fails
4330
+ * validation.
4331
+ *
4332
+ * @example
4333
+ * ```ts
4334
+ * // body → { full_name: 'Example Signer', government_id: '123.456.789-00' }
4335
+ * await client.signerDocuments.confirmData(documentId, accessCode, {
4336
+ * full_name: 'Example Signer',
4337
+ * government_id: '123.456.789-00',
4338
+ * });
4339
+ * await client.signerDocuments.acceptTerms(accessCode);
4340
+ * ```
4341
+ */
4342
+ confirmData(documentId: string, signerAccessCode: string, payload: IConfirmSignerDataPayload): Promise<ISigner>;
4343
+ /**
4344
+ * @deprecated Compatibility overload preserving the previous wire shape.
4345
+ * `whatsapp_phone_number` and `has_accepted_terms` are unverified legacy
4346
+ * pass-through fields. Call `acceptTerms()` explicitly for legal consent.
4347
+ */
4348
+ confirmData(documentId: string, signerAccessCode: string, payload: ILegacyConfirmSignerDataPayload): Promise<ISigner>;
4349
+ /**
4350
+ * Upload the signer's signature or initial image
4351
+ * (`POST /signature?signer-access-code=…&type=…`).
4352
+ *
4353
+ * The image bytes are sent as the raw request body (default
4354
+ * `Content-Type: image/png`); `type` (`signature` or `initial`) and the
4355
+ * optional `reuse` flag are query params, alongside the authenticating
4356
+ * `signer-access-code`. Set `reuse: true` to persist the image so it is
4357
+ * applied automatically to the signer's future documents.
4358
+ *
4359
+ * @param signerAccessCode - The signer's access code, from their signing link.
4360
+ * @param image - The image bytes as a non-empty `Buffer`.
4361
+ * @param options - `imageType` (`'signature'` default, or `'initial'`) and
4362
+ * `reuse` (persist for reuse). The official request content type is PNG.
4363
+ * @returns Resolves when the API acknowledges the upload. The response
4364
+ * envelope has no `data` field and is intentionally discarded.
4365
+ * @throws {ValidationError} If `signerAccessCode` is missing or `image` is not
4366
+ * a non-empty buffer.
4367
+ * @throws {ApiError} If the access code is invalid or expired.
4368
+ *
4369
+ * @example
4370
+ * ```ts
4371
+ * const png = await fs.readFile('./signature.png');
4372
+ * // query → ?signer-access-code=<code>&type=signature&reuse=true
4373
+ * await client.signerDocuments.uploadSignature(accessCode, png, {
4374
+ * imageType: 'signature',
4375
+ * reuse: true,
4376
+ * });
4377
+ * ```
1311
4378
  */
1312
- update(tagId: string, payload: IUpdateTagPayload, accountId?: string): Promise<ITag>;
4379
+ uploadSignature(signerAccessCode: string, image: Buffer, options?: IUploadSignatureOptions): Promise<void>;
1313
4380
  /**
1314
- * Delete a tag. By default fails with `ApiError` (409) if the tag is still
1315
- * attached to anything; pass `{ force: true }` to detach everywhere first.
4381
+ * @deprecated Compatibility overload for non-PNG media types. The current
4382
+ * OpenAPI contract specifies only `image/png`; other values are not certified.
1316
4383
  */
1317
- delete(tagId: string, options?: {
1318
- force?: boolean;
1319
- accountId?: string;
1320
- }): Promise<void>;
1321
- }
1322
-
1323
- /**
1324
- * Authentication endpoints (login, social login, password management) and
1325
- * personal API key management (`/users/api-keys`).
1326
- *
1327
- * Most of these endpoints are intended to bootstrap an authenticated session
1328
- * for a human user. Production server-to-server integrations should use
1329
- * `X-Api-Key` and skip this resource entirely.
1330
- */
1331
- declare class AuthenticationResource extends BaseResource {
1332
- /** `POST /login` — exchange email + password for a JWT access token. */
1333
- login(email: string, password: string): Promise<ILoginResponse>;
1334
- /** `POST /authentication/social-login` — exchange a provider token for an Assinafy JWT. */
1335
- socialLogin(payload: {
1336
- provider: string;
1337
- token: string;
1338
- has_accepted_terms: boolean;
1339
- }): Promise<ILoginResponse>;
1340
- /** `POST /users/api-keys` — generate (and rotate) the current user's API key. */
1341
- createApiKey(password: string): Promise<IApiKeyResponse>;
4384
+ uploadSignature(signerAccessCode: string, image: Buffer, options: ILegacyUploadSignatureOptions): Promise<void>;
1342
4385
  /**
1343
- * `GET /users/api-keys` fetch a masked version of the current API key, or
1344
- * `null` if no key has been generated yet.
4386
+ * Download the signer's stored signature or initial image
4387
+ * (`GET /signature/{type}?signer-access-code=…`).
4388
+ *
4389
+ * The read-side counterpart of {@link SignerDocumentsResource.uploadSignature}
4390
+ * — returns the image the signer previously uploaded (e.g. to preview it in a
4391
+ * custom signing UI). Returns bytes, not JSON.
4392
+ *
4393
+ * @param signerAccessCode - The signer's access code, from their signing link.
4394
+ * @param imageType - Which image to fetch: `'signature'` (default) or
4395
+ * `'initial'`.
4396
+ * @returns The image bytes as a Node `Buffer` (PNG by default).
4397
+ * @throws {ValidationError} If `signerAccessCode` is missing.
4398
+ * @throws {ApiError} `404` if the signer has no such image stored; `401`/`403`
4399
+ * if the access code is invalid or expired.
4400
+ *
4401
+ * @example
4402
+ * ```ts
4403
+ * const png = await client.signerDocuments.downloadSignature(accessCode, 'signature');
4404
+ * await fs.writeFile('signature.png', png);
4405
+ * ```
1345
4406
  */
1346
- getApiKey(): Promise<IMaskedApiKeyResponse>;
1347
- /** `DELETE /users/api-keys` — revoke the current API key. */
1348
- deleteApiKey(): Promise<void>;
1349
- /** `PUT /authentication/change-password` — change the authenticated user's password. */
1350
- changePassword(payload: {
1351
- email: string;
1352
- password: string;
1353
- new_password: string;
1354
- }): Promise<{
1355
- email: string;
1356
- }>;
1357
- /** `PUT /authentication/request-password-reset` — email a reset link to the user. */
1358
- requestPasswordReset(email: string): Promise<{
1359
- email: string;
1360
- }>;
1361
- /** `PUT /authentication/reset-password` — complete a password reset using the emailed token. */
1362
- resetPassword(payload: {
1363
- email: string;
1364
- token?: string;
1365
- new_password: string;
1366
- }): Promise<{
1367
- email: string;
1368
- }>;
1369
- }
1370
-
1371
- /**
1372
- * Custom field definitions used by `collect` assignments.
1373
- *
1374
- * Covers the full Field Definition section of the API docs:
1375
- * - `POST /accounts/{id}/fields`
1376
- * - `GET /accounts/{id}/fields`
1377
- * - `GET /accounts/{id}/fields/{id}`
1378
- * - `PUT /accounts/{id}/fields/{id}`
1379
- * - `DELETE /accounts/{id}/fields/{id}`
1380
- * - `POST /accounts/{id}/fields/{id}/validate?signer-access-code=…`
1381
- * - `POST /accounts/{id}/fields/validate-multiple?signer-access-code=…`
1382
- * - `GET /field-types`
1383
- */
1384
- declare class FieldsResource extends BaseResource {
1385
- /** Create a field definition. */
1386
- create(payload: ICreateFieldPayload, accountId?: string): Promise<IFieldDefinition>;
4407
+ downloadSignature(signerAccessCode: string, imageType?: 'signature' | 'initial'): Promise<Buffer>;
1387
4408
  /**
1388
- * List field definitions for the workspace.
4409
+ * Fetch the assignment (document + fields) as the signer sees it
4410
+ * (`GET /sign?signer-access-code=…`).
4411
+ *
4412
+ * The entry point for a custom signing UI: resolves the access code to the
4413
+ * document, its pages, and the {@link ISignFieldEntry}-addressable items the
4414
+ * signer must fill. Before terms are accepted the server may answer `409`, so
4415
+ * call {@link SignerDocumentsResource.acceptTerms} first (or pass
4416
+ * `hasAcceptedTerms: true` once accepted).
4417
+ *
4418
+ * @param signerAccessCode - The signer's access code, from their signing link.
4419
+ * @param hasAcceptedTerms - Maps to the `has_accepted_terms` query param
4420
+ * (server default `false`); pass `true` once the signer has accepted terms.
4421
+ * `false`/`undefined` is omitted only when `undefined` (an explicit `false`
4422
+ * is still sent).
4423
+ * @returns The document to sign, including its `assignment` (the
4424
+ * {@link IAssignment} shape: `signers`, `items`, `summary`, `signing_urls`)
4425
+ * from which the `itemId` / `fieldId` / `pageId` values for
4426
+ * {@link SignerDocumentsResource.sign} are read.
4427
+ * @throws {ValidationError} If `signerAccessCode` is missing.
4428
+ * @throws {ApiError} `401`/`403` if the access code is invalid or expired;
4429
+ * `409` if terms have not yet been accepted.
1389
4430
  *
1390
- * @param params.include_inactive return inactive fields too
1391
- * @param params.include_standard also return `signature`, `initial`, `signatureDate`
4431
+ * @example
4432
+ * ```ts
4433
+ * // query → ?signer-access-code=<code>&has_accepted_terms=true
4434
+ * const assignment = await client.signerDocuments.getAssignment(accessCode, true);
4435
+ * ```
1392
4436
  */
1393
- list(params?: {
1394
- include_inactive?: boolean;
1395
- include_standard?: boolean;
1396
- }, accountId?: string): Promise<IFieldDefinition[]>;
1397
- /** Get a single field definition by ID. */
1398
- get(fieldId: string, accountId?: string): Promise<IFieldDefinition>;
1399
- /** Update a field definition. */
1400
- update(fieldId: string, payload: IUpdateFieldPayload, accountId?: string): Promise<IFieldDefinition>;
1401
- /** Delete a field definition. Fails if the field has been used. */
1402
- delete(fieldId: string, accountId?: string): Promise<void>;
4437
+ getAssignment(signerAccessCode: string, hasAcceptedTerms?: boolean): Promise<IDocumentDetailsResponse>;
1403
4438
  /**
1404
- * Validate a single value against a field definition.
4439
+ * Submit the signer's field values to sign an assignment
4440
+ * (`POST /documents/{documentId}/assignments/{assignmentId}?signer-access-code=…`).
1405
4441
  *
1406
- * Pass `signerAccessCode` for signer-side validation (the typical use case);
1407
- * omit it when the caller is authenticated via API key.
4442
+ * The precise, field-by-field counterpart of
4443
+ * {@link SignerDocumentsResource.signMultiple}: the `entries` array is sent as
4444
+ * the request body, each entry addressing one item resolved from
4445
+ * {@link SignerDocumentsResource.getAssignment}. The access code
4446
+ * authenticates via the `signer-access-code` query param.
4447
+ *
4448
+ * @param documentId - The document being signed.
4449
+ * @param assignmentId - The assignment within that document.
4450
+ * @param signerAccessCode - The signer's access code, from their signing link.
4451
+ * @param entries - Non-empty array of {@link ISignFieldEntry}
4452
+ * (`itemId`, `fieldId`, `pageId`, `value`) — the body sent to the API.
4453
+ * @returns The API's signing result object. Its keys are operation-specific,
4454
+ * so the SDK preserves them as a {@link Record} without inventing fields.
4455
+ * @throws {ValidationError} If any of `documentId`, `assignmentId`, or
4456
+ * `signerAccessCode` is missing, or `entries` is empty.
4457
+ * @throws {ApiError} `400`/`409` if a value fails validation or the assignment
4458
+ * is no longer signable; `401`/`403` if the access code is invalid/expired.
4459
+ *
4460
+ * @example
4461
+ * ```ts
4462
+ * // body → [{ itemId, fieldId, pageId, value: 'Example Signer' }]
4463
+ * await client.signerDocuments.sign(documentId, assignmentId, accessCode, [
4464
+ * { itemId: 'item-1', fieldId: 'field-1', pageId: 'page-1', value: 'Example Signer' },
4465
+ * ]);
4466
+ * ```
1408
4467
  */
1409
- validate(fieldId: string, value: unknown, options?: {
1410
- signerAccessCode?: string;
1411
- accountId?: string;
1412
- }): Promise<IFieldValidationResult>;
1413
- /** Validate multiple values at once. */
1414
- validateMultiple(entries: IFieldValidateMultipleEntry[], options?: {
1415
- signerAccessCode?: string;
1416
- accountId?: string;
1417
- }): Promise<IFieldValidationResult[]>;
1418
- /** List the platform's supported field types. */
1419
- listTypes(): Promise<IFieldType[]>;
1420
- }
1421
-
1422
- /**
1423
- * Signer-side endpoints. Every call here is authenticated by `signer-access-code`
1424
- * (the one-time link emailed/whatsapped to the signer), not by the workspace
1425
- * API key. Use this resource when building a custom signer UI.
1426
- */
1427
- declare class SignerDocumentsResource extends BaseResource {
1428
- /** `GET /signers/{signer_id}/document?signer-access-code=…` */
1429
- getCurrent(signerId: string, signerAccessCode: string): Promise<IDocumentDetailsResponse>;
1430
- /** `GET /signers/{signer_id}/documents?signer-access-code=…` */
1431
- list(signerId: string, signerAccessCode: string, params?: IListParams): Promise<IDocumentListResponse>;
4468
+ sign(documentId: string, assignmentId: string, signerAccessCode: string, entries: ISignFieldEntry[]): Promise<Record<string, unknown>>;
1432
4469
  /**
1433
- * Search the documents awaiting a given signer
1434
- * (`GET /signers/{signer_id}/documents/search?signer-access-code=…`).
4470
+ * Decline (reject) a single assignment as the signer
4471
+ * (`PUT /documents/{documentId}/assignments/{assignmentId}/reject?signer-access-code=…`).
1435
4472
  *
1436
- * The signer-side counterpart of {@link DocumentResource.search}, scoped to
1437
- * one signer and authorised by their access code rather than the API key.
1438
- * Like {@link SignerDocumentsResource.list}, it requires
1439
- * `signer-access-code`; the published spec omits that parameter, but the
1440
- * endpoint is not usable without it.
4473
+ * The single-document counterpart of
4474
+ * {@link SignerDocumentsResource.declineMultiple}. The `decline_reason` is
4475
+ * sent in the request body; the access code authenticates via the
4476
+ * `signer-access-code` query param. (The workspace-side equivalent is to
4477
+ * delete the document via `documents.delete`; there is no workspace "cancel"
4478
+ * endpoint.)
1441
4479
  *
1442
- * @param signerId - The signer whose documents are searched.
4480
+ * @param documentId - The document being declined.
4481
+ * @param assignmentId - The assignment within that document.
1443
4482
  * @param signerAccessCode - The signer's access code, from their signing link.
1444
- * @param search - Free-text term matched against the document name.
1445
- * @returns Matching documents for that signer, in the compact
1446
- * {@link IDocumentListItem} shape, with pagination in `meta`.
1447
- * @throws {ValidationError} If `signerId` or `signerAccessCode` is missing.
4483
+ * @param declineReason - Free-text reason shown to the sender (required).
4484
+ * @returns Resolves when the API acknowledges the operation. The documented
4485
+ * empty-array response data is intentionally discarded.
4486
+ * @throws {ValidationError} If any of `documentId`, `assignmentId`, or
4487
+ * `signerAccessCode` is missing, or `declineReason` is empty.
1448
4488
  * @throws {ApiError} If the access code is invalid or expired.
1449
4489
  *
1450
4490
  * @example
1451
4491
  * ```ts
1452
- * const { data } = await client.signerDocuments.search(
1453
- * signerId,
4492
+ * // body → { decline_reason: 'Terms are unacceptable' }
4493
+ * await client.signerDocuments.decline(
4494
+ * documentId,
4495
+ * assignmentId,
1454
4496
  * accessCode,
1455
- * 'agreement',
4497
+ * 'Terms are unacceptable',
1456
4498
  * );
1457
4499
  * ```
1458
4500
  */
1459
- search(signerId: string, signerAccessCode: string, search?: string): Promise<IDocumentListResponse>;
1460
- /** `GET /signers/{signer_id}/documents/{document_id}/download/{artifact}?signer-access-code=…` */
1461
- download(signerId: string, documentId: string, artifactName: DocumentArtifactName, signerAccessCode: string): Promise<Buffer>;
1462
- /** `PUT /signers/documents/sign-multiple?signer-access-code=…` */
1463
- signMultiple(documentIds: string[], signerAccessCode: string): Promise<unknown>;
1464
- /** `PUT /signers/documents/decline-multiple?signer-access-code=…` */
1465
- declineMultiple(documentIds: string[], declineReason: string, signerAccessCode: string): Promise<unknown>;
1466
- /** `GET /signers/self?signer-access-code=…` — fetch the signer's own profile. */
1467
- self(signerAccessCode: string): Promise<unknown>;
1468
- /** `PUT /signers/accept-terms` — accept the platform terms as the signer. */
1469
- acceptTerms(signerAccessCode: string): Promise<unknown>;
1470
- /** `POST /verify` — verify the email OTP for a signer. */
1471
- verifyEmail(payload: {
1472
- signerAccessCode: string;
1473
- verificationCode: string;
1474
- }): Promise<unknown>;
1475
- /** `PUT /documents/{documentId}/signers/confirm-data?signer-access-code=…` */
1476
- confirmData(documentId: string, signerAccessCode: string, payload: {
1477
- email?: string;
1478
- whatsapp_phone_number?: string;
1479
- has_accepted_terms?: boolean;
1480
- }): Promise<unknown>;
1481
- /**
1482
- * `POST /signature?signer-access-code=…&type=…` — upload the signer's
1483
- * signature or initial image. `imageType` defaults to `signature`.
1484
- */
1485
- uploadSignature(signerAccessCode: string, image: Buffer, options?: {
1486
- imageType?: 'signature' | 'initial';
1487
- contentType?: string;
1488
- }): Promise<unknown>;
1489
- /** `GET /signature/{type}?signer-access-code=…` — download the signer's signature/initial. */
1490
- downloadSignature(signerAccessCode: string, imageType?: 'signature' | 'initial'): Promise<Buffer>;
4501
+ decline(documentId: string, assignmentId: string, signerAccessCode: string, declineReason: string): Promise<void>;
4502
+ }
4503
+
4504
+ /** Operations for the authenticated Assinafy user. */
4505
+ declare class UserResource extends BaseResource {
1491
4506
  /**
1492
- * `GET /sign?signer-access-code=…` — fetch the assignment as the signer sees it.
4507
+ * Return the authenticated user's profile (`GET /users/self`).
1493
4508
  *
1494
- * @param hasAcceptedTerms maps to the `has_accepted_terms` query param
1495
- * (server default `false`); pass `true` once the signer has accepted terms.
4509
+ * Request body: none. Authentication: `X-Api-Key` or Bearer token.
4510
+ *
4511
+ * @returns The unwrapped user payload:
4512
+ * ```jsonc
4513
+ * {
4514
+ * "id": "bgjazeo5r9v2lq7l36dx48np",
4515
+ * "name": "John Smith",
4516
+ * "email": "john@example.com",
4517
+ * "telephone": null,
4518
+ * "government_id": null,
4519
+ * "is_email_verified": true,
4520
+ * "has_accepted_terms": true,
4521
+ * "created_at": "2026-06-03T03:54:16Z",
4522
+ * "to_be_deleted_at": null
4523
+ * }
4524
+ * ```
4525
+ * @throws {ApiError} `401` when credentials are missing/invalid, or `500`
4526
+ * when the API cannot load the user.
4527
+ *
4528
+ * @example
4529
+ * ```ts
4530
+ * const user = await client.users.getCurrent();
4531
+ * console.log(user.email);
4532
+ * ```
1496
4533
  */
1497
- getAssignment(signerAccessCode: string, hasAcceptedTerms?: boolean): Promise<unknown>;
1498
- /** `POST /documents/{documentId}/assignments/{assignmentId}?signer-access-code=…` — sign. */
1499
- sign(documentId: string, assignmentId: string, signerAccessCode: string, entries: ISignFieldEntry[]): Promise<unknown>;
4534
+ getCurrent(): Promise<IAuthenticatedUser>;
1500
4535
  /**
1501
- * `PUT /documents/{documentId}/assignments/{assignmentId}/reject?signer-access-code=…`
1502
- * signer-side decline. (The workspace-side equivalent is to delete the
1503
- * document via `documents.delete`; there is no workspace "cancel" endpoint.)
4536
+ * Return document-funnel KPIs summed across all accounts the user currently
4537
+ * belongs to (`GET /users/self/stats`).
4538
+ *
4539
+ * @param params - Omit for the latest 12 monthly rows. For daily rows pass
4540
+ * `{ granularity: 'daily', month: '2026-06' }`.
4541
+ * @returns A zero-filled series, most recent period first:
4542
+ * ```jsonc
4543
+ * [{
4544
+ * "period": "2026-06",
4545
+ * "documents_uploaded": 42,
4546
+ * "documents_sent": 37,
4547
+ * "signature_requests": 61,
4548
+ * "signature_requests_email": 55,
4549
+ * "signature_requests_whatsapp": 18,
4550
+ * "signature_requests_viewed": 44,
4551
+ * "signature_requests_completed": 52,
4552
+ * "documents_certified": 30
4553
+ * }]
4554
+ * ```
4555
+ * @throws {ValidationError} If daily granularity has no month or `month`
4556
+ * does not use `YYYY-MM`.
4557
+ * @throws {ApiError} `400` for an invalid query or `401` for invalid auth.
4558
+ *
4559
+ * @example
4560
+ * ```ts
4561
+ * const monthly = await client.users.getStats();
4562
+ * const daily = await client.users.getStats({
4563
+ * granularity: 'daily',
4564
+ * month: '2026-06',
4565
+ * });
4566
+ * ```
1504
4567
  */
1505
- decline(documentId: string, assignmentId: string, signerAccessCode: string, declineReason: string): Promise<unknown>;
4568
+ getStats(params?: IDocumentStatsParams): Promise<IDocumentStatsRow[]>;
1506
4569
  }
1507
4570
 
1508
4571
  /**
1509
- * Verifier for Assinafy webhook payloads.
4572
+ * Opt-in verifier for deployments that wrap Assinafy webhook bodies in an
4573
+ * HMAC-SHA256 convention of their own.
1510
4574
  *
1511
- * The Assinafy platform signs webhook bodies with HMAC-SHA256 using the
1512
- * workspace webhook secret and sends the hex digest in an `X-Assinafy-Signature`
1513
- * header. Use {@link WebhookVerifier.verify} to confirm the signature before
1514
- * trusting the payload.
4575
+ * The current public Assinafy API contract does not specify a webhook-signature
4576
+ * header or shared-secret exchange. This helper therefore makes no claim about
4577
+ * a platform-provided header: callers must explicitly supply the raw lowercase
4578
+ * or uppercase hexadecimal HMAC digest produced by their own trusted gateway.
1515
4579
  */
1516
4580
  declare class WebhookVerifier {
1517
- private readonly webhookSecret?;
1518
- constructor(webhookSecret?: string | undefined);
1519
- /** Returns `true` if `signature` is a valid HMAC-SHA256 of `payload`. */
4581
+ private readonly webhookSecret;
4582
+ /**
4583
+ * Create an opt-in verifier for a gateway-defined HMAC convention.
4584
+ *
4585
+ * @param webhookSecret - Shared secret configured in both the trusted
4586
+ * gateway and this process. Omit it to keep verification disabled.
4587
+ *
4588
+ * @example
4589
+ * ```ts
4590
+ * const verifier = new WebhookVerifier(process.env.WEBHOOK_SHARED_SECRET);
4591
+ * ```
4592
+ */
4593
+ constructor(webhookSecret?: string);
4594
+ /**
4595
+ * Compare a hexadecimal HMAC-SHA256 digest with the raw request body.
4596
+ *
4597
+ * @param payload - Exact, unparsed request bytes (or their UTF-8 string).
4598
+ * @param signature - 64-character hexadecimal SHA-256 digest supplied by
4599
+ * the caller's trusted gateway.
4600
+ * @returns `true` only for a well-formed, timing-safe match; `false` when
4601
+ * verification is disabled or either input is invalid.
4602
+ *
4603
+ * @example
4604
+ * ```ts
4605
+ * const valid = verifier.verify(rawRequestBody, gatewaySignature);
4606
+ * if (!valid) throw new Error('Invalid webhook signature');
4607
+ * ```
4608
+ */
1520
4609
  verify(payload: string | Buffer, signature: string): boolean;
1521
- /** Parse the raw webhook body into a JSON event envelope. */
4610
+ /**
4611
+ * Parse the raw webhook body into a JSON object. Inbound webhook bodies are
4612
+ * not described by the current OpenAPI, so this remains deliberately
4613
+ * tolerant of both the observed rich envelope and legacy `{ type, data }`.
4614
+ *
4615
+ * @param payload - Raw UTF-8 JSON request body.
4616
+ * @returns The object envelope, or `null` for malformed JSON, primitives,
4617
+ * arrays, and `null`.
4618
+ *
4619
+ * @example
4620
+ * ```ts
4621
+ * const event = verifier.extractEvent(rawRequestBody);
4622
+ * if (!event) return response.status(400).end();
4623
+ * ```
4624
+ */
1522
4625
  extractEvent(payload: string | Buffer): IWebhookPayload | null;
1523
- /** Extract the event name (`event` or `type`) from an event envelope. */
4626
+ /**
4627
+ * Extract an event name from the current `event` or legacy `type` field.
4628
+ *
4629
+ * @param event - Parsed webhook envelope, or a nullable parse result.
4630
+ * @returns The event name, or `null` when neither field is a string.
4631
+ *
4632
+ * @example
4633
+ * ```ts
4634
+ * const type = verifier.getEventType(event);
4635
+ * if (type === 'document_ready') await handleReady(event);
4636
+ * ```
4637
+ */
1524
4638
  getEventType(event: IWebhookPayload | null | undefined): string | null;
1525
- /** Extract the event data (`data` or `object`) from an event envelope. */
4639
+ /**
4640
+ * Extract the event-specific object, falling back to legacy `data`.
4641
+ *
4642
+ * @param event - Parsed webhook envelope, or a nullable parse result.
4643
+ * @returns `event.object`, then `event.data`, or an empty object when no
4644
+ * object payload exists.
4645
+ *
4646
+ * @example
4647
+ * ```ts
4648
+ * const data = verifier.getEventData(event);
4649
+ * console.log(data.document_id);
4650
+ * ```
4651
+ */
1526
4652
  getEventData(event: IWebhookPayload | null | undefined): Record<string, unknown>;
1527
4653
  }
1528
4654
 
@@ -1541,6 +4667,7 @@ interface ClientConfigInput {
1541
4667
  webhookSecret?: string;
1542
4668
  timeout?: number;
1543
4669
  maxRetries?: number;
4670
+ max_retries?: number;
1544
4671
  logger?: Logger;
1545
4672
  }
1546
4673
  /**
@@ -1559,6 +4686,7 @@ interface ClientConfigInput {
1559
4686
  */
1560
4687
  declare class AssinafyClient {
1561
4688
  private readonly axiosInstance;
4689
+ private readonly publicAxiosInstance;
1562
4690
  private readonly defaultAccountId;
1563
4691
  private readonly logger;
1564
4692
  private readonly webhookSecret;
@@ -1572,15 +4700,164 @@ declare class AssinafyClient {
1572
4700
  readonly auth: AuthenticationResource;
1573
4701
  readonly fields: FieldsResource;
1574
4702
  readonly signerDocuments: SignerDocumentsResource;
4703
+ readonly users: UserResource;
1575
4704
  readonly webhookVerifier: WebhookVerifier;
1576
- constructor(options: AssinafyClientOptions);
1577
- /** Convenience factory for the common apiKey + accountId setup. */
4705
+ /**
4706
+ * Create a client. Supply `apiKey` (preferred, sent as `X-Api-Key`) or a
4707
+ * Bearer `token` for protected operations. Credentials are optional so the
4708
+ * same client can drive public login, verification, OAuth-URL and
4709
+ * signer-access-code flows; a protected request without credentials receives
4710
+ * the API's normal `401` {@link ApiError}.
4711
+ *
4712
+ * @param options - Credentials and configuration. `apiKey` or `token`
4713
+ * authenticates protected operations; `accountId` sets the default
4714
+ * workspace used by every account-scoped resource; `baseUrl` (default the
4715
+ * production API), `timeout`
4716
+ * (default 30 s), `maxRetries` (default 2, for HTTP 429 on idempotent
4717
+ * requests), `webhookSecret` (enables
4718
+ * {@link AssinafyClient.webhookVerifier}) and `logger` are optional.
4719
+ * Non-idempotent requests are retried only when they explicitly carry an
4720
+ * `Idempotency-Key` header.
4721
+ *
4722
+ * @example
4723
+ * ```ts
4724
+ * const client = new AssinafyClient({
4725
+ * apiKey: process.env.ASSINAFY_API_KEY!,
4726
+ * accountId: process.env.ASSINAFY_ACCOUNT_ID!,
4727
+ * });
4728
+ * ```
4729
+ */
4730
+ constructor(options?: AssinafyClientOptions);
4731
+ /**
4732
+ * Convenience factory for the common apiKey + accountId setup.
4733
+ *
4734
+ * @param apiKey - Workspace API key (sent as the `X-Api-Key` header).
4735
+ * @param accountId - Default account ID used by account-scoped calls.
4736
+ * @param options - Extra client options (`baseUrl`, `timeout`, `maxRetries`,
4737
+ * `webhookSecret`, `logger`), minus `apiKey`/`accountId`.
4738
+ * @returns A configured {@link AssinafyClient}.
4739
+ *
4740
+ * @example
4741
+ * ```ts
4742
+ * const client = AssinafyClient.create(
4743
+ * process.env.ASSINAFY_API_KEY!,
4744
+ * process.env.ASSINAFY_ACCOUNT_ID!,
4745
+ * { webhookSecret: process.env.ASSINAFY_WEBHOOK_SECRET },
4746
+ * );
4747
+ * ```
4748
+ */
1578
4749
  static create(apiKey: string, accountId: string, options?: Omit<AssinafyClientOptions, 'apiKey' | 'accountId'>): AssinafyClient;
1579
- /** Build a client from a plain object (supports snake_case and camelCase keys). */
4750
+ /**
4751
+ * Build a client from a plain object, accepting both snake_case and
4752
+ * camelCase keys (e.g. `api_key`/`apiKey`, `account_id`/`accountId`,
4753
+ * `webhook_secret`/`webhookSecret`). Handy for loading config straight from
4754
+ * environment variables or a JSON file.
4755
+ *
4756
+ * @param config - Loosely-typed configuration ({@link ClientConfigInput}).
4757
+ * @returns A configured {@link AssinafyClient}.
4758
+ *
4759
+ * @example
4760
+ * ```ts
4761
+ * const client = AssinafyClient.fromConfig({
4762
+ * api_key: process.env.ASSINAFY_API_KEY,
4763
+ * account_id: process.env.ASSINAFY_ACCOUNT_ID,
4764
+ * });
4765
+ * ```
4766
+ */
1580
4767
  static fromConfig(config: ClientConfigInput): AssinafyClient;
1581
4768
  /**
1582
- * High-level helper that uploads a PDF, ensures it's processed, creates any
1583
- * missing signers, and kicks off a virtual signature assignment.
4769
+ * Flagship helper: upload a PDF, wait for it to process, ensure each signer
4770
+ * exists, and open a **virtual** signature assignment — the whole "send this
4771
+ * document for signature" flow in a single call.
4772
+ *
4773
+ * Sequence of API calls:
4774
+ * 1. `POST /accounts/{accountId}/documents` — upload the PDF
4775
+ * ({@link DocumentResource.upload}).
4776
+ * 2. Poll `GET /documents/{id}` until the document reaches a ready status
4777
+ * ({@link DocumentResource.waitUntilReady}).
4778
+ * 3. For each signer, reuse an existing signer by email or
4779
+ * `POST /accounts/{accountId}/signers` to create one
4780
+ * ({@link SignerResource.create} — idempotent by email).
4781
+ * 4. `POST /documents/{id}/assignments` with `method: 'virtual'` and the
4782
+ * collected signer IDs ({@link AssignmentResource.create}).
4783
+ * 5. When `waitForReady` is not `false`, re-fetch `GET /documents/{id}` so
4784
+ * the returned document reflects the just-created assignment; otherwise
4785
+ * the upload snapshot is returned, avoiding only this final round-trip.
4786
+ *
4787
+ * @param options - Workflow options.
4788
+ * @param options.source - The PDF to upload, as a file path or in-memory
4789
+ * buffer (see {@link DocumentUploadSource}).
4790
+ * @param options.signers - Signers to request signatures from — at least one
4791
+ * is required. Each is `{ name, email?, whatsapp_phone_number? | phone?,
4792
+ * cpf?, metadata? }`; a signer needs an email or a WhatsApp number to be
4793
+ * notified.
4794
+ * @param options.message - Optional invitation message attached to the
4795
+ * assignment.
4796
+ * @param options.metadata - Optional metadata attached to the uploaded
4797
+ * document.
4798
+ * @param options.waitForReady - Controls the final document re-fetch and
4799
+ * return shape. Defaults to `true`. The workflow always waits for
4800
+ * `metadata_ready` before creating an assignment because the API rejects
4801
+ * assignments for documents that are still being processed.
4802
+ * @param options.expiresAt - Optional ISO-8601 assignment expiry, e.g.
4803
+ * `'2026-08-01T00:00:00Z'`.
4804
+ * @param options.copyReceivers - Optional CC recipients (see the caveat on
4805
+ * {@link ICreateAssignmentPayload.copy_receivers} — silently dropped on some
4806
+ * plans).
4807
+ * @param options.accountId - Override the client's default account ID.
4808
+ * @returns `{ document, assignment, signer_ids }`. `document` is the
4809
+ * re-fetched {@link IDocumentDetailsResponse} when `waitForReady` (the
4810
+ * default), otherwise the {@link IDocumentUploadResponse} upload snapshot;
4811
+ * `signer_ids` are the created/reused signer IDs in signer order:
4812
+ * ```jsonc
4813
+ * {
4814
+ * "document": {
4815
+ * "resource": "document",
4816
+ * "id": "103ad216846e6b90710cb9acef59",
4817
+ * "name": "contract.pdf",
4818
+ * "status": "pending_signature", // re-fetched after assignment when waitForReady is true
4819
+ * "artifacts": { "original": "https://…", "thumbnail": "https://…" },
4820
+ * "assignment": { "id": "1032c55c58bb00a8dc35db916751" }, // the just-created assignment (same as the top-level `assignment` below)
4821
+ * "pages": [
4822
+ * { "id": "103ad216be62159d3087452d7cf8", "number": 1, "height": 1651, "width": 1275, "download_url": "https://…" }
4823
+ * ]
4824
+ * },
4825
+ * "assignment": {
4826
+ * "id": "1032c55c58bb00a8dc35db916751",
4827
+ * "method": "virtual",
4828
+ * "sender_email": "sender@example.com",
4829
+ * "message": "Please sign the attached agreement.",
4830
+ * "expires_at": null,
4831
+ * "signers": [
4832
+ * { "id": "1032becb82a279550bc3e5df9bbb", "step": 1, "email": "ana@example.com", "full_name": "Ana Souza", "notified": true, "completed": false }
4833
+ * ],
4834
+ * "signing_urls": [
4835
+ * { "signer_id": "1032becb82a279550bc3e5df9bbb", "url": "https://app-sandbox.assinafy.com.br/sign/103ad216846e6b90710cb9acef59?email=ana%40example.com" }
4836
+ * ]
4837
+ * },
4838
+ * "signer_ids": ["1032becb82a279550bc3e5df9bbb"]
4839
+ * }
4840
+ * ```
4841
+ * @throws {ValidationError} If `signers` is empty, the upload fails
4842
+ * validation (empty / non-PDF / larger than 25 MB), or the document never
4843
+ * reaches a ready status before the
4844
+ * {@link DocumentResource.waitUntilReady} timeout.
4845
+ * @throws {ApiError} If any underlying API call is rejected.
4846
+ *
4847
+ * @example
4848
+ * ```ts
4849
+ * const { document, assignment, signer_ids } = await client.uploadAndRequestSignatures({
4850
+ * source: { filePath: './contract.pdf' },
4851
+ * signers: [
4852
+ * { name: 'Ana Souza', email: 'ana@example.com' },
4853
+ * { name: 'Bruno Lima', whatsapp_phone_number: '+5511999999999' },
4854
+ * ],
4855
+ * message: 'Please sign the attached agreement.',
4856
+ * });
4857
+ * console.log(document.status); // 'metadata_ready'
4858
+ * console.log(signer_ids.length); // 2
4859
+ * console.log(assignment.signing_urls); // per-signer signing links
4860
+ * ```
1584
4861
  */
1585
4862
  uploadAndRequestSignatures(options: {
1586
4863
  source: DocumentUploadSource;
@@ -1592,30 +4869,103 @@ declare class AssinafyClient {
1592
4869
  copyReceivers?: string[];
1593
4870
  accountId?: string;
1594
4871
  }): Promise<IUploadAndRequestSignaturesResult>;
1595
- /** Expose the underlying axios instance for advanced use cases (interceptors, custom endpoints). */
4872
+ /**
4873
+ * Expose the underlying axios instance for advanced use cases: adding
4874
+ * interceptors, inspecting defaults, or calling endpoints not yet wrapped by
4875
+ * a resource.
4876
+ *
4877
+ * @returns The configured `AxiosInstance` — auth headers, base URL, timeout,
4878
+ * and the HTTP 429 retry interceptor are already applied. Automatic retries
4879
+ * are limited to `GET`, `HEAD`, `OPTIONS`, `PUT`, and `DELETE`; add a unique
4880
+ * `Idempotency-Key` header to explicitly permit replay of another method.
4881
+ *
4882
+ * @example
4883
+ * ```ts
4884
+ * client.getAxiosInstance().interceptors.request.use((cfg) => {
4885
+ * cfg.headers['X-Trace-Id'] = crypto.randomUUID();
4886
+ * return cfg;
4887
+ * });
4888
+ * ```
4889
+ */
1596
4890
  getAxiosInstance(): AxiosInstance;
1597
4891
  }
1598
4892
 
1599
4893
  /** Base class for all Assinafy SDK errors. */
1600
4894
  declare class AssinafyError extends Error {
1601
4895
  readonly context: Record<string, unknown>;
4896
+ /**
4897
+ * Create a base SDK error with structured diagnostic context.
4898
+ *
4899
+ * @param message - Human-readable error summary.
4900
+ * @param context - Structured details safe for the caller to inspect.
4901
+ * @param options - Standard JavaScript error options, including `cause`.
4902
+ *
4903
+ * @example
4904
+ * ```ts
4905
+ * throw new AssinafyError('Operation failed', { operation: 'upload' });
4906
+ * ```
4907
+ */
1602
4908
  constructor(message: string, context?: Record<string, unknown>, options?: ErrorOptions);
1603
4909
  }
1604
4910
  /** Thrown when the API returns a non-success HTTP status. */
1605
4911
  declare class ApiError extends AssinafyError {
1606
4912
  readonly statusCode: number;
1607
4913
  readonly responseData: unknown;
4914
+ /**
4915
+ * Create an error representing a non-success API response.
4916
+ *
4917
+ * @param message - API-provided or fallback error summary.
4918
+ * @param statusCode - HTTP response status.
4919
+ * @param responseData - Parsed response body, when available.
4920
+ * @param options - Standard JavaScript error options, including `cause`.
4921
+ */
1608
4922
  constructor(message: string, statusCode: number, responseData?: unknown, options?: ErrorOptions);
4923
+ /**
4924
+ * Convert a status/body pair into an {@link ApiError}.
4925
+ *
4926
+ * @param statusCode - Non-success HTTP response status.
4927
+ * @param responseData - Parsed API body. String `message` takes priority,
4928
+ * followed by string `error`, then the stable fallback message.
4929
+ * @returns An `ApiError` retaining the original response body.
4930
+ *
4931
+ * @example
4932
+ * ```ts
4933
+ * const error = ApiError.fromResponse(422, { message: 'Invalid signer' });
4934
+ * console.log(error.statusCode, error.message);
4935
+ * ```
4936
+ */
1609
4937
  static fromResponse(statusCode: number, responseData: unknown): ApiError;
1610
4938
  }
1611
4939
  /** Thrown when client-side validation fails before the request is sent. */
1612
4940
  declare class ValidationError extends AssinafyError {
1613
4941
  readonly errors: Record<string, unknown>;
4942
+ /**
4943
+ * Create a client-side validation failure raised before network I/O.
4944
+ *
4945
+ * @param message - Human-readable validation summary.
4946
+ * @param errors - Field/value diagnostics for programmatic handling.
4947
+ *
4948
+ * @example
4949
+ * ```ts
4950
+ * throw new ValidationError('Signer ID is required', { signerId: '' });
4951
+ * ```
4952
+ */
1614
4953
  constructor(message?: string, errors?: Record<string, unknown>);
1615
4954
  }
1616
4955
  /** Thrown when the HTTP transport itself fails (DNS, timeout, etc.). */
1617
4956
  declare class NetworkError extends AssinafyError {
4957
+ /**
4958
+ * Create a transport-layer failure such as DNS, connection, or timeout.
4959
+ *
4960
+ * @param message - Sanitized transport error summary.
4961
+ * @param options - Standard JavaScript error options carrying a safe cause.
4962
+ *
4963
+ * @example
4964
+ * ```ts
4965
+ * throw new NetworkError('Request timed out', { cause });
4966
+ * ```
4967
+ */
1618
4968
  constructor(message: string, options?: ErrorOptions);
1619
4969
  }
1620
4970
 
1621
- export { type AnyString, ApiError, type AssignmentMethod, type AssignmentNotificationMethod, AssignmentResource, type AssignmentVerificationMethod, AssinafyClient, type AssinafyClientOptions, AssinafyError, AuthenticationResource, type ClientConfigInput, DEFAULT_WEBHOOK_EVENTS, type DocumentArtifactName, DocumentResource, type DocumentStatus, type DocumentUploadSource, FieldsResource, type IApiKeyResponse, type IAssignment, type IAssignmentItem, type IAssignmentListParams, type IAssignmentListResponse, type IAssignmentSigner, type ICostEstimate, type ICreateAssignmentPayload, type ICreateAssignmentResponse, type ICreateDocumentFromTemplateOptions, type ICreateFieldPayload, type ICreateSignerPayload, type ICreateSignerResponse, type ICreateTagPayload, type ICreateWorkspacePayload, type IDocumentActivity, type IDocumentDetailsResponse, type IDocumentListItem, type IDocumentListParams, type IDocumentListResponse, type IDocumentSearchParams, type IDocumentStatusInfo, type IDocumentUploadOptions, type IDocumentUploadResponse, type IFieldDefinition, type IFieldType, type IFieldValidateMultipleEntry, type IFieldValidationResult, type IInlineTag, type IListParams, type ILoginResponse, type IMaskedApiKeyResponse, type IPage, type IPaginatedResponse, type IPublicDocumentInfo, type IRenameDocumentResponse, type IResendCostEstimate, type IResendEmailResponse, type ISignFieldEntry, type ISigner, type ISignerListResponse, type ISigningProgress, type ITag, type ITemplateDetailsResponse, type ITemplateListItem, type ITemplateListResponse, type ITemplateRole, type ITemplateSigner, type IUpdateFieldPayload, type IUpdateSignerPayload, type IUpdateTagPayload, type IUpdateTemplatePayload, type IUpdateWorkspacePayload, type IUploadAndRequestSignaturesResult, type IUploadAndRequestSignaturesSigner, type IWebhookDispatch, type IWebhookDispatchListParams, type IWebhookEventTypeInfo, type IWebhookPayload, type IWebhookRegisterPayload, type IWebhookSubscription, type IWhatsAppNotification, type IWorkspaceListItem, type IWorkspaceListResponse, type IWorkspaceResponse, type Logger, MAX_UPLOAD_BYTES, NetworkError, type PaginatedResult, type PaginationMeta, type SendTokenChannel, SignerDocumentsResource, type SignerReference, SignerResource, TagResource, TemplateResource, ValidationError, type WebhookEventType, WebhookResource, WebhookVerifier, WorkspaceResource, buildAssignmentPayload };
4971
+ export { type AccountLogoUploadSource, type AnyString, ApiError, type AssignmentMethod, type AssignmentNotificationMethod, AssignmentResource, type AssignmentVerificationMethod, AssinafyClient, type AssinafyClientOptions, AssinafyError, AuthenticationResource, type ClientConfigInput, DEFAULT_WEBHOOK_EVENTS, type DocumentArtifactName, DocumentResource, type DocumentStatsGranularity, type DocumentStatus, type DocumentUploadSource, FieldsResource, type IAccountTheme, type IApiKeyResponse, type IAssignment, type IAssignmentCostSigner, type IAssignmentEntry, type IAssignmentItem, type IAssignmentListParams, type IAssignmentListResponse, type IAssignmentSigner, type IAuthenticatedUser, type IConfirmSignerDataPayload, type ICostEstimate, type ICreateAssignmentPayload, type ICreateAssignmentResponse, type ICreateDocumentFromTemplateOptions, type ICreateFieldPayload, type ICreateSignerPayload, type ICreateSignerResponse, type ICreateTagPayload, type ICreateWorkspacePayload, type IDocumentActivity, type IDocumentDetailsResponse, type IDocumentListItem, type IDocumentListParams, type IDocumentListResponse, type IDocumentSearchParams, type IDocumentStatsParams, type IDocumentStatsRow, type IDocumentStatusInfo, type IDocumentUploadOptions, type IDocumentUploadResponse, type IDocumentVerification, type IEstimateAssignmentCostPayload, type IFieldDefinition, type IFieldType, type IFieldValidateMultipleEntry, type IFieldValidationResult, type IInlineTag, type ILegacyConfirmSignerDataPayload, type ILegacyResendCostEstimate, type ILegacyUploadSignatureOptions, type IListParams, type ILoginResponse, type IMaskedApiKeyResponse, type INotificationHistoryEntry, type IPage, type IPaginatedResponse, type IPublicDocumentInfo, type IRenameDocumentResponse, type IResendCostEstimate, type IResendEmailResponse, type ISignFieldEntry, type ISigner, type ISignerListResponse, type ISignerSelf, type ISigningProgress, type ITag, type ITemplateCostSigner, type ITemplateDetailsResponse, type ITemplateFieldPlacement, type ITemplateListItem, type ITemplateListResponse, type ITemplateRole, type ITemplateSigner, type IUpdateFieldPayload, type IUpdateSignerPayload, type IUpdateTagPayload, type IUpdateTemplatePayload, type IUpdateWorkspacePayload, type IUploadAndRequestSignaturesResult, type IUploadAndRequestSignaturesSigner, type IUploadSignatureOptions, type IWebhookDispatch, type IWebhookDispatchListParams, type IWebhookEventTypeInfo, type IWebhookPayload, type IWebhookRegisterPayload, type IWebhookSubscription, type IWhatsAppNotification, type IWorkspaceListItem, type IWorkspaceListResponse, type IWorkspaceResponse, type Logger, MAX_UPLOAD_BYTES, NetworkError, type NotificationSenderType, type PaginatedResult, type PaginationMeta, type SendTokenChannel, SignerDocumentsResource, type SignerReference, SignerResource, TagResource, TemplateResource, UserResource, ValidationError, type WebhookEventType, WebhookResource, WebhookVerifier, WorkspaceResource, buildAssignmentPayload };