signyu 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,275 @@
1
+ /**
2
+ * Types mirroring the SignYu REST API (src/app/api/v1/** in the SignYu repo).
3
+ * Timestamps are ISO 8601 strings as returned in JSON.
4
+ */
5
+ /** Document lifecycle state. `PENDING` until sent, `SENT` while out for signature, `COMPLETED` when every signer has signed. */
6
+ type DocumentStatus = "PENDING" | "SENT" | "COMPLETED" | "FAILED" | "CANCELLED" | (string & {});
7
+ /** One stamp rectangle in PDF points, origin at the bottom-left of the page. */
8
+ interface SignaturePosition {
9
+ /** 1-based page index. */
10
+ page: number;
11
+ /** Left edge in PDF points. */
12
+ x: number;
13
+ /** Bottom edge in PDF points (origin is bottom-left). */
14
+ y: number;
15
+ /** Box width in PDF points (minimum 140). */
16
+ width: number;
17
+ /** Box height in PDF points (minimum 110). */
18
+ height: number;
19
+ }
20
+ interface SignaturePlacement {
21
+ /** One rectangle per page, 1 to 20 entries, pages must be distinct. */
22
+ positions: SignaturePosition[];
23
+ }
24
+ interface SignerAdvanced {
25
+ signaturePlacement?: SignaturePlacement;
26
+ }
27
+ interface SignerInput {
28
+ /** Signer's full name. */
29
+ name: string;
30
+ /** Digits only, at least 10 characters. */
31
+ phone: string;
32
+ /** Valid email address. The signing link is emailed here. */
33
+ email: string;
34
+ /** Optional custom stamp placement. Omit to use the default fixed slot. */
35
+ advanced?: SignerAdvanced;
36
+ }
37
+ /** Response of `POST /api/v1/documents`. */
38
+ interface CreatedDocument {
39
+ documentId: string;
40
+ name: string;
41
+ status: DocumentStatus;
42
+ }
43
+ interface SignerCounts {
44
+ total: number;
45
+ signed: number;
46
+ }
47
+ interface DocumentSummary {
48
+ documentId: string;
49
+ name: string;
50
+ status: DocumentStatus;
51
+ createdAt: string;
52
+ signers: SignerCounts;
53
+ }
54
+ /** Response of `GET /api/v1/documents`. */
55
+ interface DocumentList {
56
+ documents: DocumentSummary[];
57
+ limit: number;
58
+ offset: number;
59
+ }
60
+ interface DocumentSigner {
61
+ signerId: string;
62
+ name: string;
63
+ email: string | null;
64
+ phone: string;
65
+ signingOrder: number;
66
+ openedAt: string | null;
67
+ signedAt: string | null;
68
+ hasSigned: boolean;
69
+ /** `null` until the document has been sent. */
70
+ signUrl: string | null;
71
+ advanced?: {
72
+ signaturePlacement: SignaturePlacement;
73
+ };
74
+ }
75
+ /** Response of `GET /api/v1/documents/{documentId}`. */
76
+ interface Document {
77
+ documentId: string;
78
+ name: string;
79
+ status: DocumentStatus;
80
+ createdAt: string;
81
+ updatedAt: string;
82
+ completedAt: string | null;
83
+ /** Temporary presigned link to the signed PDF, set once `COMPLETED`. */
84
+ downloadUrl: string | null;
85
+ /** Bearer-authenticated certificate endpoint, set once `COMPLETED`. */
86
+ certificateUrl: string | null;
87
+ signers: DocumentSigner[];
88
+ }
89
+ interface AddedSigner {
90
+ signerId: string;
91
+ name: string;
92
+ email: string | null;
93
+ signingOrder: number;
94
+ advanced?: {
95
+ signaturePlacement: SignaturePlacement;
96
+ };
97
+ }
98
+ /** Response of `POST /api/v1/documents/{documentId}/signers`. */
99
+ interface AddSignersResponse {
100
+ signers: AddedSigner[];
101
+ }
102
+ interface SentSigner {
103
+ signerId: string;
104
+ name: string;
105
+ email: string | null;
106
+ signingOrder: number;
107
+ signUrl: string;
108
+ }
109
+ /** Response of `POST /api/v1/documents/{documentId}/send`. */
110
+ interface SendDocumentResponse {
111
+ documentId: string;
112
+ status: "SENT";
113
+ creditsRemaining: number;
114
+ signers: SentSigner[];
115
+ }
116
+ /** Error body returned by every failing API call. */
117
+ interface ApiErrorBody {
118
+ error: string;
119
+ message: string;
120
+ }
121
+ type WebhookEventType = "signer.signed" | "document.completed";
122
+ interface WebhookSigner {
123
+ signerId: string;
124
+ name: string;
125
+ email: string | null;
126
+ signingOrder: number;
127
+ signedAt: string | null;
128
+ hasSigned: boolean;
129
+ }
130
+ interface SignerSignedEvent {
131
+ event: "signer.signed";
132
+ documentId: string;
133
+ status: DocumentStatus;
134
+ occurredAt: string;
135
+ /** The signer who just signed. */
136
+ signer: WebhookSigner | null;
137
+ signers: WebhookSigner[];
138
+ }
139
+ interface DocumentCompletedEvent {
140
+ event: "document.completed";
141
+ documentId: string;
142
+ status: DocumentStatus;
143
+ occurredAt: string;
144
+ completedAt: string | null;
145
+ certificateUrl: string;
146
+ signers: WebhookSigner[];
147
+ }
148
+ type WebhookEvent = SignerSignedEvent | DocumentCompletedEvent;
149
+
150
+ /** Header carrying the signature, `sha256=<hex>`. */
151
+ declare const SIGNATURE_HEADER = "X-SignSetu-Signature";
152
+ /** Header carrying the event type, for example `signer.signed`. */
153
+ declare const EVENT_HEADER = "X-SignSetu-Event";
154
+ type WebhookPayload = string | Uint8Array | ArrayBuffer;
155
+ /** Computes the `sha256=<hex>` header value SignYu sends for a raw body. */
156
+ declare function computeSignature(payload: WebhookPayload, secret: string): string;
157
+ /**
158
+ * Returns true when `signatureHeader` (the `X-SignSetu-Signature` value) is a
159
+ * valid HMAC-SHA256 of the raw request body under `secret`. Pass the raw body
160
+ * bytes exactly as received; a re-serialized object will not match.
161
+ * Comparison is constant time.
162
+ */
163
+ declare function verifySignature(payload: WebhookPayload, signatureHeader: string | null | undefined, secret: string): boolean;
164
+ /**
165
+ * Verifies the signature and returns the parsed event. Throws
166
+ * `WebhookSignatureError` if the signature is missing or invalid.
167
+ */
168
+ declare function constructEvent(payload: WebhookPayload, signatureHeader: string | null | undefined, secret: string): WebhookEvent;
169
+ declare const webhooks: {
170
+ SIGNATURE_HEADER: string;
171
+ EVENT_HEADER: string;
172
+ computeSignature: typeof computeSignature;
173
+ verifySignature: typeof verifySignature;
174
+ constructEvent: typeof constructEvent;
175
+ };
176
+ type Webhooks = typeof webhooks;
177
+
178
+ declare const DEFAULT_BASE_URL = "https://signyu.com";
179
+ interface SignYuOptions {
180
+ /** Your secret API key, `sk_live_...`. Keep it server side. */
181
+ apiKey: string;
182
+ /** Defaults to `https://signyu.com`. */
183
+ baseUrl?: string;
184
+ /** Per-request timeout in milliseconds. Defaults to 60000. */
185
+ timeoutMs?: number;
186
+ /** Custom fetch implementation (defaults to the global `fetch`). */
187
+ fetch?: typeof fetch;
188
+ }
189
+ type FileInput = Blob | Uint8Array | ArrayBuffer;
190
+ interface CreateDocumentParams {
191
+ /** The PDF to sign, at most 10MB. A Node.js `Buffer` works here. */
192
+ file: FileInput;
193
+ /** File name sent with the upload. Defaults to `document.pdf`. */
194
+ fileName?: string;
195
+ /** Label for the document. Defaults to the file name. */
196
+ name?: string;
197
+ }
198
+ interface ListDocumentsParams {
199
+ /** 1 to 100, default 20. */
200
+ limit?: number;
201
+ /** Default 0. */
202
+ offset?: number;
203
+ }
204
+ interface RequestOptions {
205
+ method: "GET" | "POST";
206
+ path: string;
207
+ query?: Record<string, string | number | undefined>;
208
+ body?: BodyInit;
209
+ json?: unknown;
210
+ expect?: "json" | "binary";
211
+ }
212
+ declare class Documents {
213
+ private readonly client;
214
+ constructor(client: SignYu);
215
+ /** `POST /api/v1/documents`: upload a PDF and create a `PENDING` document. */
216
+ create(params: CreateDocumentParams): Promise<CreatedDocument>;
217
+ /** `GET /api/v1/documents`: your documents, most recent first. */
218
+ list(params?: ListDocumentsParams): Promise<DocumentList>;
219
+ /** `GET /api/v1/documents/{documentId}`: status and per-signer progress. */
220
+ get(documentId: string): Promise<Document>;
221
+ /** `POST /api/v1/documents/{documentId}/signers`: add signers while `PENDING` (max 6 per document). */
222
+ addSigners(documentId: string, signers: SignerInput[]): Promise<AddSignersResponse>;
223
+ /**
224
+ * `POST /api/v1/documents/{documentId}/send`: deducts one credit per signer,
225
+ * emails signing links and returns them. Not idempotent: call it once.
226
+ */
227
+ send(documentId: string): Promise<SendDocumentResponse>;
228
+ /**
229
+ * `GET /api/v1/documents/{documentId}/certificate`: the completion
230
+ * certificate and audit trail PDF as raw bytes. Only available once the
231
+ * document is `COMPLETED` (otherwise `409 invalid_state`).
232
+ */
233
+ getCertificate(documentId: string): Promise<Uint8Array>;
234
+ }
235
+ declare class SignYu {
236
+ readonly documents: Documents;
237
+ readonly webhooks: Webhooks;
238
+ readonly baseUrl: string;
239
+ private readonly apiKey;
240
+ private readonly timeoutMs;
241
+ private readonly fetchImpl;
242
+ constructor(options: SignYuOptions);
243
+ /** @internal */
244
+ _request<T>(opts: RequestOptions): Promise<T>;
245
+ }
246
+
247
+ /**
248
+ * Thrown for any non-2xx API response, network failure or timeout.
249
+ *
250
+ * `code` is the API's machine readable `error` field (for example
251
+ * `insufficient_credits`). For responses without a JSON error body it is
252
+ * `rate_limited` (429) or `http_error`; for network failures it is
253
+ * `connection_error` and for timeouts `timeout`, both with `status` 0.
254
+ */
255
+ declare class SignYuError extends Error {
256
+ readonly status: number;
257
+ readonly code: string;
258
+ /** Parsed response body, when there was one. */
259
+ readonly body: unknown;
260
+ constructor(opts: {
261
+ status: number;
262
+ code: string;
263
+ message: string;
264
+ body?: unknown;
265
+ cause?: unknown;
266
+ });
267
+ }
268
+ /** Thrown by `webhooks.constructEvent` when the signature does not match. */
269
+ declare class WebhookSignatureError extends Error {
270
+ constructor(message?: string);
271
+ }
272
+
273
+ declare const VERSION = "0.1.0";
274
+
275
+ export { type AddSignersResponse, type AddedSigner, type ApiErrorBody, type CreateDocumentParams, type CreatedDocument, DEFAULT_BASE_URL, type Document, type DocumentCompletedEvent, type DocumentList, type DocumentSigner, type DocumentStatus, type DocumentSummary, Documents, EVENT_HEADER, type FileInput, type ListDocumentsParams, SIGNATURE_HEADER, type SendDocumentResponse, type SentSigner, SignYu, SignYuError, type SignYuOptions, type SignaturePlacement, type SignaturePosition, type SignerAdvanced, type SignerCounts, type SignerInput, type SignerSignedEvent, VERSION, type WebhookEvent, type WebhookEventType, type WebhookPayload, WebhookSignatureError, type WebhookSigner, type Webhooks, computeSignature, constructEvent, verifySignature, webhooks };
@@ -0,0 +1,275 @@
1
+ /**
2
+ * Types mirroring the SignYu REST API (src/app/api/v1/** in the SignYu repo).
3
+ * Timestamps are ISO 8601 strings as returned in JSON.
4
+ */
5
+ /** Document lifecycle state. `PENDING` until sent, `SENT` while out for signature, `COMPLETED` when every signer has signed. */
6
+ type DocumentStatus = "PENDING" | "SENT" | "COMPLETED" | "FAILED" | "CANCELLED" | (string & {});
7
+ /** One stamp rectangle in PDF points, origin at the bottom-left of the page. */
8
+ interface SignaturePosition {
9
+ /** 1-based page index. */
10
+ page: number;
11
+ /** Left edge in PDF points. */
12
+ x: number;
13
+ /** Bottom edge in PDF points (origin is bottom-left). */
14
+ y: number;
15
+ /** Box width in PDF points (minimum 140). */
16
+ width: number;
17
+ /** Box height in PDF points (minimum 110). */
18
+ height: number;
19
+ }
20
+ interface SignaturePlacement {
21
+ /** One rectangle per page, 1 to 20 entries, pages must be distinct. */
22
+ positions: SignaturePosition[];
23
+ }
24
+ interface SignerAdvanced {
25
+ signaturePlacement?: SignaturePlacement;
26
+ }
27
+ interface SignerInput {
28
+ /** Signer's full name. */
29
+ name: string;
30
+ /** Digits only, at least 10 characters. */
31
+ phone: string;
32
+ /** Valid email address. The signing link is emailed here. */
33
+ email: string;
34
+ /** Optional custom stamp placement. Omit to use the default fixed slot. */
35
+ advanced?: SignerAdvanced;
36
+ }
37
+ /** Response of `POST /api/v1/documents`. */
38
+ interface CreatedDocument {
39
+ documentId: string;
40
+ name: string;
41
+ status: DocumentStatus;
42
+ }
43
+ interface SignerCounts {
44
+ total: number;
45
+ signed: number;
46
+ }
47
+ interface DocumentSummary {
48
+ documentId: string;
49
+ name: string;
50
+ status: DocumentStatus;
51
+ createdAt: string;
52
+ signers: SignerCounts;
53
+ }
54
+ /** Response of `GET /api/v1/documents`. */
55
+ interface DocumentList {
56
+ documents: DocumentSummary[];
57
+ limit: number;
58
+ offset: number;
59
+ }
60
+ interface DocumentSigner {
61
+ signerId: string;
62
+ name: string;
63
+ email: string | null;
64
+ phone: string;
65
+ signingOrder: number;
66
+ openedAt: string | null;
67
+ signedAt: string | null;
68
+ hasSigned: boolean;
69
+ /** `null` until the document has been sent. */
70
+ signUrl: string | null;
71
+ advanced?: {
72
+ signaturePlacement: SignaturePlacement;
73
+ };
74
+ }
75
+ /** Response of `GET /api/v1/documents/{documentId}`. */
76
+ interface Document {
77
+ documentId: string;
78
+ name: string;
79
+ status: DocumentStatus;
80
+ createdAt: string;
81
+ updatedAt: string;
82
+ completedAt: string | null;
83
+ /** Temporary presigned link to the signed PDF, set once `COMPLETED`. */
84
+ downloadUrl: string | null;
85
+ /** Bearer-authenticated certificate endpoint, set once `COMPLETED`. */
86
+ certificateUrl: string | null;
87
+ signers: DocumentSigner[];
88
+ }
89
+ interface AddedSigner {
90
+ signerId: string;
91
+ name: string;
92
+ email: string | null;
93
+ signingOrder: number;
94
+ advanced?: {
95
+ signaturePlacement: SignaturePlacement;
96
+ };
97
+ }
98
+ /** Response of `POST /api/v1/documents/{documentId}/signers`. */
99
+ interface AddSignersResponse {
100
+ signers: AddedSigner[];
101
+ }
102
+ interface SentSigner {
103
+ signerId: string;
104
+ name: string;
105
+ email: string | null;
106
+ signingOrder: number;
107
+ signUrl: string;
108
+ }
109
+ /** Response of `POST /api/v1/documents/{documentId}/send`. */
110
+ interface SendDocumentResponse {
111
+ documentId: string;
112
+ status: "SENT";
113
+ creditsRemaining: number;
114
+ signers: SentSigner[];
115
+ }
116
+ /** Error body returned by every failing API call. */
117
+ interface ApiErrorBody {
118
+ error: string;
119
+ message: string;
120
+ }
121
+ type WebhookEventType = "signer.signed" | "document.completed";
122
+ interface WebhookSigner {
123
+ signerId: string;
124
+ name: string;
125
+ email: string | null;
126
+ signingOrder: number;
127
+ signedAt: string | null;
128
+ hasSigned: boolean;
129
+ }
130
+ interface SignerSignedEvent {
131
+ event: "signer.signed";
132
+ documentId: string;
133
+ status: DocumentStatus;
134
+ occurredAt: string;
135
+ /** The signer who just signed. */
136
+ signer: WebhookSigner | null;
137
+ signers: WebhookSigner[];
138
+ }
139
+ interface DocumentCompletedEvent {
140
+ event: "document.completed";
141
+ documentId: string;
142
+ status: DocumentStatus;
143
+ occurredAt: string;
144
+ completedAt: string | null;
145
+ certificateUrl: string;
146
+ signers: WebhookSigner[];
147
+ }
148
+ type WebhookEvent = SignerSignedEvent | DocumentCompletedEvent;
149
+
150
+ /** Header carrying the signature, `sha256=<hex>`. */
151
+ declare const SIGNATURE_HEADER = "X-SignSetu-Signature";
152
+ /** Header carrying the event type, for example `signer.signed`. */
153
+ declare const EVENT_HEADER = "X-SignSetu-Event";
154
+ type WebhookPayload = string | Uint8Array | ArrayBuffer;
155
+ /** Computes the `sha256=<hex>` header value SignYu sends for a raw body. */
156
+ declare function computeSignature(payload: WebhookPayload, secret: string): string;
157
+ /**
158
+ * Returns true when `signatureHeader` (the `X-SignSetu-Signature` value) is a
159
+ * valid HMAC-SHA256 of the raw request body under `secret`. Pass the raw body
160
+ * bytes exactly as received; a re-serialized object will not match.
161
+ * Comparison is constant time.
162
+ */
163
+ declare function verifySignature(payload: WebhookPayload, signatureHeader: string | null | undefined, secret: string): boolean;
164
+ /**
165
+ * Verifies the signature and returns the parsed event. Throws
166
+ * `WebhookSignatureError` if the signature is missing or invalid.
167
+ */
168
+ declare function constructEvent(payload: WebhookPayload, signatureHeader: string | null | undefined, secret: string): WebhookEvent;
169
+ declare const webhooks: {
170
+ SIGNATURE_HEADER: string;
171
+ EVENT_HEADER: string;
172
+ computeSignature: typeof computeSignature;
173
+ verifySignature: typeof verifySignature;
174
+ constructEvent: typeof constructEvent;
175
+ };
176
+ type Webhooks = typeof webhooks;
177
+
178
+ declare const DEFAULT_BASE_URL = "https://signyu.com";
179
+ interface SignYuOptions {
180
+ /** Your secret API key, `sk_live_...`. Keep it server side. */
181
+ apiKey: string;
182
+ /** Defaults to `https://signyu.com`. */
183
+ baseUrl?: string;
184
+ /** Per-request timeout in milliseconds. Defaults to 60000. */
185
+ timeoutMs?: number;
186
+ /** Custom fetch implementation (defaults to the global `fetch`). */
187
+ fetch?: typeof fetch;
188
+ }
189
+ type FileInput = Blob | Uint8Array | ArrayBuffer;
190
+ interface CreateDocumentParams {
191
+ /** The PDF to sign, at most 10MB. A Node.js `Buffer` works here. */
192
+ file: FileInput;
193
+ /** File name sent with the upload. Defaults to `document.pdf`. */
194
+ fileName?: string;
195
+ /** Label for the document. Defaults to the file name. */
196
+ name?: string;
197
+ }
198
+ interface ListDocumentsParams {
199
+ /** 1 to 100, default 20. */
200
+ limit?: number;
201
+ /** Default 0. */
202
+ offset?: number;
203
+ }
204
+ interface RequestOptions {
205
+ method: "GET" | "POST";
206
+ path: string;
207
+ query?: Record<string, string | number | undefined>;
208
+ body?: BodyInit;
209
+ json?: unknown;
210
+ expect?: "json" | "binary";
211
+ }
212
+ declare class Documents {
213
+ private readonly client;
214
+ constructor(client: SignYu);
215
+ /** `POST /api/v1/documents`: upload a PDF and create a `PENDING` document. */
216
+ create(params: CreateDocumentParams): Promise<CreatedDocument>;
217
+ /** `GET /api/v1/documents`: your documents, most recent first. */
218
+ list(params?: ListDocumentsParams): Promise<DocumentList>;
219
+ /** `GET /api/v1/documents/{documentId}`: status and per-signer progress. */
220
+ get(documentId: string): Promise<Document>;
221
+ /** `POST /api/v1/documents/{documentId}/signers`: add signers while `PENDING` (max 6 per document). */
222
+ addSigners(documentId: string, signers: SignerInput[]): Promise<AddSignersResponse>;
223
+ /**
224
+ * `POST /api/v1/documents/{documentId}/send`: deducts one credit per signer,
225
+ * emails signing links and returns them. Not idempotent: call it once.
226
+ */
227
+ send(documentId: string): Promise<SendDocumentResponse>;
228
+ /**
229
+ * `GET /api/v1/documents/{documentId}/certificate`: the completion
230
+ * certificate and audit trail PDF as raw bytes. Only available once the
231
+ * document is `COMPLETED` (otherwise `409 invalid_state`).
232
+ */
233
+ getCertificate(documentId: string): Promise<Uint8Array>;
234
+ }
235
+ declare class SignYu {
236
+ readonly documents: Documents;
237
+ readonly webhooks: Webhooks;
238
+ readonly baseUrl: string;
239
+ private readonly apiKey;
240
+ private readonly timeoutMs;
241
+ private readonly fetchImpl;
242
+ constructor(options: SignYuOptions);
243
+ /** @internal */
244
+ _request<T>(opts: RequestOptions): Promise<T>;
245
+ }
246
+
247
+ /**
248
+ * Thrown for any non-2xx API response, network failure or timeout.
249
+ *
250
+ * `code` is the API's machine readable `error` field (for example
251
+ * `insufficient_credits`). For responses without a JSON error body it is
252
+ * `rate_limited` (429) or `http_error`; for network failures it is
253
+ * `connection_error` and for timeouts `timeout`, both with `status` 0.
254
+ */
255
+ declare class SignYuError extends Error {
256
+ readonly status: number;
257
+ readonly code: string;
258
+ /** Parsed response body, when there was one. */
259
+ readonly body: unknown;
260
+ constructor(opts: {
261
+ status: number;
262
+ code: string;
263
+ message: string;
264
+ body?: unknown;
265
+ cause?: unknown;
266
+ });
267
+ }
268
+ /** Thrown by `webhooks.constructEvent` when the signature does not match. */
269
+ declare class WebhookSignatureError extends Error {
270
+ constructor(message?: string);
271
+ }
272
+
273
+ declare const VERSION = "0.1.0";
274
+
275
+ export { type AddSignersResponse, type AddedSigner, type ApiErrorBody, type CreateDocumentParams, type CreatedDocument, DEFAULT_BASE_URL, type Document, type DocumentCompletedEvent, type DocumentList, type DocumentSigner, type DocumentStatus, type DocumentSummary, Documents, EVENT_HEADER, type FileInput, type ListDocumentsParams, SIGNATURE_HEADER, type SendDocumentResponse, type SentSigner, SignYu, SignYuError, type SignYuOptions, type SignaturePlacement, type SignaturePosition, type SignerAdvanced, type SignerCounts, type SignerInput, type SignerSignedEvent, VERSION, type WebhookEvent, type WebhookEventType, type WebhookPayload, WebhookSignatureError, type WebhookSigner, type Webhooks, computeSignature, constructEvent, verifySignature, webhooks };