@dealcrawl/sdk 2.11.1 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,6 +6,46 @@ Official TypeScript SDK for the DealCrawl web scraping and crawling API.
6
6
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
7
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
8
 
9
+ ## What's New in v2.12.0 (January 2026) ✨
10
+
11
+ ### New Methods - 100% API Coverage
12
+
13
+ All missing API endpoints now have SDK methods (completes the 87% → 100% alignment):
14
+
15
+ **Status Resource (`client.status.*`)**
16
+
17
+ - `getJobErrors(jobId, options?)` - Get job errors without loading full results (useful for debugging large crawls)
18
+
19
+ **Data Resource (`client.data.*`)**
20
+
21
+ - `getJob(jobId)` - Get full job details with result
22
+ - `getJobResult(jobId)` - Get only the result of a completed job
23
+ - `exportJob(jobId, format)` - Export job in multiple formats (json, markdown, llm, csv)
24
+
25
+ **Webhooks Resource (`client.webhooks.*`)**
26
+
27
+ - `rotateSecret(webhookId, options)` - Rotate webhook secret with grace period support
28
+ - `getSecretStatus(webhookId)` - Check secret version and grace period status
29
+ - `verifySignature(options)` - Verify webhook signature and replay protection
30
+
31
+ ### Examples
32
+
33
+ ```typescript
34
+ // Get job errors for debugging
35
+ const errors = await client.status.getJobErrors("job_abc123", { limit: 50 });
36
+
37
+ // Export crawl results as Markdown
38
+ const markdown = await client.data.exportJob("crawl_123", "markdown");
39
+
40
+ // Rotate webhook secret with 24h grace period
41
+ await client.webhooks.rotateSecret("webhook_abc", {
42
+ newSecret: "new-secure-key",
43
+ gracePeriodHours: 24
44
+ });
45
+ ```
46
+
47
+ ---
48
+
9
49
  ## What's New in v2.11.1 (January 2026) 🐛
10
50
 
11
51
  ### Bug Fixes
package/dist/index.d.mts CHANGED
@@ -19,7 +19,20 @@ interface ResponseMeta {
19
19
  timestamp: string;
20
20
  duration?: number;
21
21
  }
22
- type JobStatus$1 = "pending" | "active" | "completed" | "failed" | "delayed" | "paused";
22
+ /**
23
+ * Job status for API responses.
24
+ * Maps to BullMQ native states returned by job.getState().
25
+ *
26
+ * Status meanings:
27
+ * - `waiting`: Job in queue, waiting for a worker to pick it up
28
+ * - `active`: Job is currently being processed by a worker
29
+ * - `completed`: Job finished successfully
30
+ * - `failed`: Job failed (may have been retried)
31
+ * - `delayed`: Job scheduled for future execution
32
+ * - `paused`: Queue is paused (job will resume when queue unpauses)
33
+ * - `expired`: Job data has been cleaned up by retention policy
34
+ */
35
+ type JobStatus$1 = "waiting" | "active" | "completed" | "failed" | "delayed" | "paused" | "expired";
23
36
  interface PaginatedResponse<T> {
24
37
  data: T[];
25
38
  pagination: {
@@ -153,7 +166,7 @@ interface AIExtraction {
153
166
  raw?: Record<string, unknown>;
154
167
  }
155
168
  interface Entity {
156
- type: "person" | "organization" | "location" | "product" | "other";
169
+ type: "person" | "organization" | "location" | "product" | "brand" | "other";
157
170
  value: string;
158
171
  confidence: number;
159
172
  }
@@ -690,6 +703,22 @@ interface CancelJobResponse {
690
703
  jobId: string;
691
704
  message: string;
692
705
  }
706
+ /** Job error entry */
707
+ interface JobErrorEntry {
708
+ url?: string;
709
+ error: string;
710
+ timestamp?: string;
711
+ }
712
+ /** Job errors response */
713
+ interface JobErrorsResponse {
714
+ data: JobErrorEntry[];
715
+ pagination: PaginationInfo;
716
+ meta?: {
717
+ jobId: string;
718
+ status?: JobStatus$1;
719
+ offset?: number;
720
+ };
721
+ }
693
722
  /** Job summary in list */
694
723
  interface JobSummary {
695
724
  id: string;
@@ -769,6 +798,32 @@ interface ClientStatsResponse {
769
798
  }>;
770
799
  };
771
800
  }
801
+ /** Full job details response */
802
+ interface JobDetailsResponse {
803
+ id: string;
804
+ type: "scrape" | "crawl" | "dork" | "extract";
805
+ status: JobStatus$1;
806
+ input: Record<string, unknown>;
807
+ result?: unknown;
808
+ progress?: number;
809
+ error?: string;
810
+ dealsFound?: number;
811
+ avgDealScore?: number;
812
+ highestDealScore?: number;
813
+ checkpoint?: CheckpointInfo;
814
+ createdAt: string;
815
+ updatedAt: string;
816
+ completedAt?: string;
817
+ }
818
+ /** Job result response */
819
+ interface JobResultResponse {
820
+ jobId: string;
821
+ status: "completed";
822
+ result: unknown;
823
+ completedAt?: string;
824
+ }
825
+ /** Job export response (string for CSV/Markdown/LLM, object for JSON) */
826
+ type JobExportResponse = string | Record<string, unknown>;
772
827
  /** Webhook in list */
773
828
  interface WebhookItem {
774
829
  id: string;
@@ -824,6 +879,35 @@ interface TestWebhookResponse {
824
879
  responseTime?: number;
825
880
  error?: string;
826
881
  }
882
+ /** Rotate webhook secret response */
883
+ interface RotateSecretResponse {
884
+ success: boolean;
885
+ webhookId: string;
886
+ secretVersion: number;
887
+ previousSecretValidUntil: string;
888
+ gracePeriodHours: number;
889
+ message: string;
890
+ }
891
+ /** Webhook secret status response */
892
+ interface SecretStatusResponse {
893
+ webhookId: string;
894
+ hasSecret: boolean;
895
+ secretVersion: number;
896
+ lastRotatedAt?: string;
897
+ gracePeriod?: {
898
+ active: boolean;
899
+ previousVersion: number;
900
+ expiresAt: string;
901
+ } | null;
902
+ }
903
+ /** Verify webhook signature response */
904
+ interface VerifyWebhookResponse {
905
+ valid: boolean;
906
+ webhookId?: string;
907
+ message: string;
908
+ error?: string;
909
+ reason?: string;
910
+ }
827
911
  /** API key info (safe, without secret) */
828
912
  interface ApiKeyInfo {
829
913
  id: string;
@@ -2645,6 +2729,47 @@ declare class DataResource {
2645
2729
  * ```
2646
2730
  */
2647
2731
  getRecentJobs(limit?: number): Promise<ListJobsResponse>;
2732
+ /**
2733
+ * Get full job details with result
2734
+ *
2735
+ * @example
2736
+ * ```ts
2737
+ * const job = await client.data.getJob("job_abc123");
2738
+ * console.log(job.result);
2739
+ * console.log(job.dealsFound);
2740
+ * ```
2741
+ */
2742
+ getJob(jobId: string): Promise<JobDetailsResponse>;
2743
+ /**
2744
+ * Get only the result of a completed job
2745
+ *
2746
+ * @example
2747
+ * ```ts
2748
+ * const result = await client.data.getJobResult("job_abc123");
2749
+ * console.log(result.result);
2750
+ * ```
2751
+ */
2752
+ getJobResult(jobId: string): Promise<JobResultResponse>;
2753
+ /**
2754
+ * Export job results in various formats
2755
+ * Supports: json, markdown, llm, csv
2756
+ *
2757
+ * @example
2758
+ * ```ts
2759
+ * // Export as JSON
2760
+ * const jsonData = await client.data.exportJob("job_abc123", "json");
2761
+ *
2762
+ * // Export as Markdown
2763
+ * const markdown = await client.data.exportJob("job_abc123", "markdown");
2764
+ *
2765
+ * // Export as LLM-optimized format
2766
+ * const llmText = await client.data.exportJob("job_abc123", "llm");
2767
+ *
2768
+ * // Export as CSV
2769
+ * const csv = await client.data.exportJob("job_abc123", "csv");
2770
+ * ```
2771
+ */
2772
+ exportJob(jobId: string, format?: "json" | "markdown" | "llm" | "csv"): Promise<JobExportResponse>;
2648
2773
  /**
2649
2774
  * List all deals
2650
2775
  *
@@ -3537,6 +3662,24 @@ declare class StatusResource {
3537
3662
  * ```
3538
3663
  */
3539
3664
  getMetrics(jobId: string): Promise<JobMetricsResponse>;
3665
+ /**
3666
+ * Get errors from a job
3667
+ * Useful for debugging large crawls without loading full results
3668
+ *
3669
+ * @example
3670
+ * ```ts
3671
+ * const errors = await client.status.getJobErrors("job_abc123", {
3672
+ * limit: 50,
3673
+ * offset: 0
3674
+ * });
3675
+ * console.log(errors.data);
3676
+ * console.log(errors.pagination.total);
3677
+ * ```
3678
+ */
3679
+ getJobErrors(jobId: string, options?: {
3680
+ limit?: number;
3681
+ offset?: number;
3682
+ }): Promise<JobErrorsResponse>;
3540
3683
  /**
3541
3684
  * Cancel a pending or active job
3542
3685
  *
@@ -3701,6 +3844,65 @@ declare class WebhooksResource {
3701
3844
  * ```
3702
3845
  */
3703
3846
  getByEvent(event: CreateWebhookOptions["event"]): Promise<WebhookItem[]>;
3847
+ /**
3848
+ * Rotate webhook secret
3849
+ * Rotates the secret while keeping the old one valid during grace period
3850
+ *
3851
+ * @example
3852
+ * ```ts
3853
+ * const result = await client.webhooks.rotateSecret("webhook_abc123", {
3854
+ * newSecret: "new-secure-secret-key",
3855
+ * gracePeriodHours: 24
3856
+ * });
3857
+ * console.log(result.secretVersion);
3858
+ * console.log(result.previousSecretValidUntil);
3859
+ * ```
3860
+ */
3861
+ rotateSecret(webhookId: string, options: {
3862
+ newSecret: string;
3863
+ gracePeriodHours?: number;
3864
+ }): Promise<RotateSecretResponse>;
3865
+ /**
3866
+ * Get webhook secret rotation status
3867
+ * Check current secret version and grace period status
3868
+ *
3869
+ * @example
3870
+ * ```ts
3871
+ * const status = await client.webhooks.getSecretStatus("webhook_abc123");
3872
+ * console.log(status.secretVersion);
3873
+ * if (status.gracePeriod?.active) {
3874
+ * console.log(`Grace period expires: ${status.gracePeriod.expiresAt}`);
3875
+ * }
3876
+ * ```
3877
+ */
3878
+ getSecretStatus(webhookId: string): Promise<SecretStatusResponse>;
3879
+ /**
3880
+ * Verify webhook signature and replay protection
3881
+ * Validates signature, timestamp, and nonce from received webhook
3882
+ *
3883
+ * @example
3884
+ * ```ts
3885
+ * const isValid = await client.webhooks.verifySignature({
3886
+ * webhookId: "webhook_abc123",
3887
+ * payload: receivedPayload,
3888
+ * signature: headers["x-dealcrawl-signature"],
3889
+ * timestamp: parseInt(headers["x-dealcrawl-timestamp"]),
3890
+ * nonce: headers["x-dealcrawl-nonce"]
3891
+ * });
3892
+ * if (isValid.valid) {
3893
+ * console.log("Webhook is valid");
3894
+ * } else {
3895
+ * console.log(`Invalid: ${isValid.error}`);
3896
+ * }
3897
+ * ```
3898
+ */
3899
+ verifySignature(options: {
3900
+ webhookId: string;
3901
+ payload: Record<string, unknown>;
3902
+ signature: string;
3903
+ timestamp: number;
3904
+ nonce: string;
3905
+ }): Promise<VerifyWebhookResponse>;
3704
3906
  }
3705
3907
 
3706
3908
  /**
@@ -4425,7 +4627,7 @@ declare function getErrorMessage(code: ErrorCode): string;
4425
4627
  /**
4426
4628
  * Primary job status - represents the main lifecycle stage
4427
4629
  */
4428
- type JobStatus = "queued" | "scheduled" | "priority_queued" | "initializing" | "active" | "processing" | "extracting" | "uploading" | "finalizing" | "retrying" | "backing_off" | "paused" | "pausing" | "resuming" | "completed" | "partial" | "failed" | "timeout" | "cancelled" | "rejected" | "stale" | "zombie" | "stuck";
4630
+ type JobStatus = "queued" | "scheduled" | "priority_queued" | "initializing" | "active" | "processing" | "extracting" | "uploading" | "finalizing" | "retrying" | "backing_off" | "paused" | "pausing" | "resuming" | "completed" | "partial" | "failed" | "timeout" | "cancelled" | "rejected" | "stale" | "zombie" | "stuck" | "expiring" | "expired";
4429
4631
  /**
4430
4632
  * Sub-status provides granular detail within a primary status
4431
4633
  */
package/dist/index.d.ts CHANGED
@@ -19,7 +19,20 @@ interface ResponseMeta {
19
19
  timestamp: string;
20
20
  duration?: number;
21
21
  }
22
- type JobStatus$1 = "pending" | "active" | "completed" | "failed" | "delayed" | "paused";
22
+ /**
23
+ * Job status for API responses.
24
+ * Maps to BullMQ native states returned by job.getState().
25
+ *
26
+ * Status meanings:
27
+ * - `waiting`: Job in queue, waiting for a worker to pick it up
28
+ * - `active`: Job is currently being processed by a worker
29
+ * - `completed`: Job finished successfully
30
+ * - `failed`: Job failed (may have been retried)
31
+ * - `delayed`: Job scheduled for future execution
32
+ * - `paused`: Queue is paused (job will resume when queue unpauses)
33
+ * - `expired`: Job data has been cleaned up by retention policy
34
+ */
35
+ type JobStatus$1 = "waiting" | "active" | "completed" | "failed" | "delayed" | "paused" | "expired";
23
36
  interface PaginatedResponse<T> {
24
37
  data: T[];
25
38
  pagination: {
@@ -153,7 +166,7 @@ interface AIExtraction {
153
166
  raw?: Record<string, unknown>;
154
167
  }
155
168
  interface Entity {
156
- type: "person" | "organization" | "location" | "product" | "other";
169
+ type: "person" | "organization" | "location" | "product" | "brand" | "other";
157
170
  value: string;
158
171
  confidence: number;
159
172
  }
@@ -690,6 +703,22 @@ interface CancelJobResponse {
690
703
  jobId: string;
691
704
  message: string;
692
705
  }
706
+ /** Job error entry */
707
+ interface JobErrorEntry {
708
+ url?: string;
709
+ error: string;
710
+ timestamp?: string;
711
+ }
712
+ /** Job errors response */
713
+ interface JobErrorsResponse {
714
+ data: JobErrorEntry[];
715
+ pagination: PaginationInfo;
716
+ meta?: {
717
+ jobId: string;
718
+ status?: JobStatus$1;
719
+ offset?: number;
720
+ };
721
+ }
693
722
  /** Job summary in list */
694
723
  interface JobSummary {
695
724
  id: string;
@@ -769,6 +798,32 @@ interface ClientStatsResponse {
769
798
  }>;
770
799
  };
771
800
  }
801
+ /** Full job details response */
802
+ interface JobDetailsResponse {
803
+ id: string;
804
+ type: "scrape" | "crawl" | "dork" | "extract";
805
+ status: JobStatus$1;
806
+ input: Record<string, unknown>;
807
+ result?: unknown;
808
+ progress?: number;
809
+ error?: string;
810
+ dealsFound?: number;
811
+ avgDealScore?: number;
812
+ highestDealScore?: number;
813
+ checkpoint?: CheckpointInfo;
814
+ createdAt: string;
815
+ updatedAt: string;
816
+ completedAt?: string;
817
+ }
818
+ /** Job result response */
819
+ interface JobResultResponse {
820
+ jobId: string;
821
+ status: "completed";
822
+ result: unknown;
823
+ completedAt?: string;
824
+ }
825
+ /** Job export response (string for CSV/Markdown/LLM, object for JSON) */
826
+ type JobExportResponse = string | Record<string, unknown>;
772
827
  /** Webhook in list */
773
828
  interface WebhookItem {
774
829
  id: string;
@@ -824,6 +879,35 @@ interface TestWebhookResponse {
824
879
  responseTime?: number;
825
880
  error?: string;
826
881
  }
882
+ /** Rotate webhook secret response */
883
+ interface RotateSecretResponse {
884
+ success: boolean;
885
+ webhookId: string;
886
+ secretVersion: number;
887
+ previousSecretValidUntil: string;
888
+ gracePeriodHours: number;
889
+ message: string;
890
+ }
891
+ /** Webhook secret status response */
892
+ interface SecretStatusResponse {
893
+ webhookId: string;
894
+ hasSecret: boolean;
895
+ secretVersion: number;
896
+ lastRotatedAt?: string;
897
+ gracePeriod?: {
898
+ active: boolean;
899
+ previousVersion: number;
900
+ expiresAt: string;
901
+ } | null;
902
+ }
903
+ /** Verify webhook signature response */
904
+ interface VerifyWebhookResponse {
905
+ valid: boolean;
906
+ webhookId?: string;
907
+ message: string;
908
+ error?: string;
909
+ reason?: string;
910
+ }
827
911
  /** API key info (safe, without secret) */
828
912
  interface ApiKeyInfo {
829
913
  id: string;
@@ -2645,6 +2729,47 @@ declare class DataResource {
2645
2729
  * ```
2646
2730
  */
2647
2731
  getRecentJobs(limit?: number): Promise<ListJobsResponse>;
2732
+ /**
2733
+ * Get full job details with result
2734
+ *
2735
+ * @example
2736
+ * ```ts
2737
+ * const job = await client.data.getJob("job_abc123");
2738
+ * console.log(job.result);
2739
+ * console.log(job.dealsFound);
2740
+ * ```
2741
+ */
2742
+ getJob(jobId: string): Promise<JobDetailsResponse>;
2743
+ /**
2744
+ * Get only the result of a completed job
2745
+ *
2746
+ * @example
2747
+ * ```ts
2748
+ * const result = await client.data.getJobResult("job_abc123");
2749
+ * console.log(result.result);
2750
+ * ```
2751
+ */
2752
+ getJobResult(jobId: string): Promise<JobResultResponse>;
2753
+ /**
2754
+ * Export job results in various formats
2755
+ * Supports: json, markdown, llm, csv
2756
+ *
2757
+ * @example
2758
+ * ```ts
2759
+ * // Export as JSON
2760
+ * const jsonData = await client.data.exportJob("job_abc123", "json");
2761
+ *
2762
+ * // Export as Markdown
2763
+ * const markdown = await client.data.exportJob("job_abc123", "markdown");
2764
+ *
2765
+ * // Export as LLM-optimized format
2766
+ * const llmText = await client.data.exportJob("job_abc123", "llm");
2767
+ *
2768
+ * // Export as CSV
2769
+ * const csv = await client.data.exportJob("job_abc123", "csv");
2770
+ * ```
2771
+ */
2772
+ exportJob(jobId: string, format?: "json" | "markdown" | "llm" | "csv"): Promise<JobExportResponse>;
2648
2773
  /**
2649
2774
  * List all deals
2650
2775
  *
@@ -3537,6 +3662,24 @@ declare class StatusResource {
3537
3662
  * ```
3538
3663
  */
3539
3664
  getMetrics(jobId: string): Promise<JobMetricsResponse>;
3665
+ /**
3666
+ * Get errors from a job
3667
+ * Useful for debugging large crawls without loading full results
3668
+ *
3669
+ * @example
3670
+ * ```ts
3671
+ * const errors = await client.status.getJobErrors("job_abc123", {
3672
+ * limit: 50,
3673
+ * offset: 0
3674
+ * });
3675
+ * console.log(errors.data);
3676
+ * console.log(errors.pagination.total);
3677
+ * ```
3678
+ */
3679
+ getJobErrors(jobId: string, options?: {
3680
+ limit?: number;
3681
+ offset?: number;
3682
+ }): Promise<JobErrorsResponse>;
3540
3683
  /**
3541
3684
  * Cancel a pending or active job
3542
3685
  *
@@ -3701,6 +3844,65 @@ declare class WebhooksResource {
3701
3844
  * ```
3702
3845
  */
3703
3846
  getByEvent(event: CreateWebhookOptions["event"]): Promise<WebhookItem[]>;
3847
+ /**
3848
+ * Rotate webhook secret
3849
+ * Rotates the secret while keeping the old one valid during grace period
3850
+ *
3851
+ * @example
3852
+ * ```ts
3853
+ * const result = await client.webhooks.rotateSecret("webhook_abc123", {
3854
+ * newSecret: "new-secure-secret-key",
3855
+ * gracePeriodHours: 24
3856
+ * });
3857
+ * console.log(result.secretVersion);
3858
+ * console.log(result.previousSecretValidUntil);
3859
+ * ```
3860
+ */
3861
+ rotateSecret(webhookId: string, options: {
3862
+ newSecret: string;
3863
+ gracePeriodHours?: number;
3864
+ }): Promise<RotateSecretResponse>;
3865
+ /**
3866
+ * Get webhook secret rotation status
3867
+ * Check current secret version and grace period status
3868
+ *
3869
+ * @example
3870
+ * ```ts
3871
+ * const status = await client.webhooks.getSecretStatus("webhook_abc123");
3872
+ * console.log(status.secretVersion);
3873
+ * if (status.gracePeriod?.active) {
3874
+ * console.log(`Grace period expires: ${status.gracePeriod.expiresAt}`);
3875
+ * }
3876
+ * ```
3877
+ */
3878
+ getSecretStatus(webhookId: string): Promise<SecretStatusResponse>;
3879
+ /**
3880
+ * Verify webhook signature and replay protection
3881
+ * Validates signature, timestamp, and nonce from received webhook
3882
+ *
3883
+ * @example
3884
+ * ```ts
3885
+ * const isValid = await client.webhooks.verifySignature({
3886
+ * webhookId: "webhook_abc123",
3887
+ * payload: receivedPayload,
3888
+ * signature: headers["x-dealcrawl-signature"],
3889
+ * timestamp: parseInt(headers["x-dealcrawl-timestamp"]),
3890
+ * nonce: headers["x-dealcrawl-nonce"]
3891
+ * });
3892
+ * if (isValid.valid) {
3893
+ * console.log("Webhook is valid");
3894
+ * } else {
3895
+ * console.log(`Invalid: ${isValid.error}`);
3896
+ * }
3897
+ * ```
3898
+ */
3899
+ verifySignature(options: {
3900
+ webhookId: string;
3901
+ payload: Record<string, unknown>;
3902
+ signature: string;
3903
+ timestamp: number;
3904
+ nonce: string;
3905
+ }): Promise<VerifyWebhookResponse>;
3704
3906
  }
3705
3907
 
3706
3908
  /**
@@ -4425,7 +4627,7 @@ declare function getErrorMessage(code: ErrorCode): string;
4425
4627
  /**
4426
4628
  * Primary job status - represents the main lifecycle stage
4427
4629
  */
4428
- type JobStatus = "queued" | "scheduled" | "priority_queued" | "initializing" | "active" | "processing" | "extracting" | "uploading" | "finalizing" | "retrying" | "backing_off" | "paused" | "pausing" | "resuming" | "completed" | "partial" | "failed" | "timeout" | "cancelled" | "rejected" | "stale" | "zombie" | "stuck";
4630
+ type JobStatus = "queued" | "scheduled" | "priority_queued" | "initializing" | "active" | "processing" | "extracting" | "uploading" | "finalizing" | "retrying" | "backing_off" | "paused" | "pausing" | "resuming" | "completed" | "partial" | "failed" | "timeout" | "cancelled" | "rejected" | "stale" | "zombie" | "stuck" | "expiring" | "expired";
4429
4631
  /**
4430
4632
  * Sub-status provides granular detail within a primary status
4431
4633
  */