@dealcrawl/sdk 2.11.0 → 2.12.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,69 @@ 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
+
49
+ ## What's New in v2.11.1 (January 2026) 🐛
50
+
51
+ ### Bug Fixes
52
+
53
+ - **DataResource**: Fixed syntax error in `getDealsByCategory()` method (unclosed docstring + duplicate line)
54
+ - **SDK-API Alignment**: Verified 87% endpoint coverage with detailed alignment report
55
+
56
+ ### Known Gaps
57
+
58
+ The following API endpoints do not have SDK methods yet (see [API-SDK Alignment Report](../../docs/API-SDK-ALIGNMENT-REPORT.md)):
59
+
60
+ - `GET /v1/status/:jobId/errors` - Get job errors
61
+ - `GET /v1/data/jobs/:jobId` - Get full job details
62
+ - `GET /v1/data/jobs/:jobId/result` - Get job result
63
+ - `GET /v1/data/jobs/:jobId/export` - Export job in multiple formats
64
+ - `POST /v1/webhooks/:id/rotate` - Rotate webhook secret
65
+ - `GET /v1/webhooks/:id/secret-status` - Get webhook secret status
66
+ - `POST /v1/webhooks/verify` - Verify webhook signature
67
+
68
+ These methods will be added in a future release.
69
+
70
+ ---
71
+
9
72
  ## What's New in v2.11.0 (January 2026) 🎉
10
73
 
11
74
  ### Breaking Changes ⚠️
package/dist/index.d.mts CHANGED
@@ -690,6 +690,22 @@ interface CancelJobResponse {
690
690
  jobId: string;
691
691
  message: string;
692
692
  }
693
+ /** Job error entry */
694
+ interface JobErrorEntry {
695
+ url?: string;
696
+ error: string;
697
+ timestamp?: string;
698
+ }
699
+ /** Job errors response */
700
+ interface JobErrorsResponse {
701
+ data: JobErrorEntry[];
702
+ pagination: PaginationInfo;
703
+ meta?: {
704
+ jobId: string;
705
+ status?: JobStatus$1;
706
+ offset?: number;
707
+ };
708
+ }
693
709
  /** Job summary in list */
694
710
  interface JobSummary {
695
711
  id: string;
@@ -769,6 +785,32 @@ interface ClientStatsResponse {
769
785
  }>;
770
786
  };
771
787
  }
788
+ /** Full job details response */
789
+ interface JobDetailsResponse {
790
+ id: string;
791
+ type: "scrape" | "crawl" | "dork" | "extract";
792
+ status: JobStatus$1;
793
+ input: Record<string, unknown>;
794
+ result?: unknown;
795
+ progress?: number;
796
+ error?: string;
797
+ dealsFound?: number;
798
+ avgDealScore?: number;
799
+ highestDealScore?: number;
800
+ checkpoint?: CheckpointInfo;
801
+ createdAt: string;
802
+ updatedAt: string;
803
+ completedAt?: string;
804
+ }
805
+ /** Job result response */
806
+ interface JobResultResponse {
807
+ jobId: string;
808
+ status: "completed";
809
+ result: unknown;
810
+ completedAt?: string;
811
+ }
812
+ /** Job export response (string for CSV/Markdown/LLM, object for JSON) */
813
+ type JobExportResponse = string | Record<string, unknown>;
772
814
  /** Webhook in list */
773
815
  interface WebhookItem {
774
816
  id: string;
@@ -792,10 +834,17 @@ interface CreateWebhookResponse {
792
834
  minDealScore: number;
793
835
  active: boolean;
794
836
  }
795
- /** List webhooks response */
837
+ /** List webhooks response (standardized list format) */
796
838
  interface ListWebhooksResponse {
797
- webhooks: WebhookItem[];
798
- count: number;
839
+ data: WebhookItem[];
840
+ pagination: {
841
+ page: number;
842
+ limit: number;
843
+ total: number;
844
+ totalPages: number;
845
+ hasMore: boolean;
846
+ };
847
+ meta?: Record<string, unknown>;
799
848
  }
800
849
  /** Update webhook response */
801
850
  interface UpdateWebhookResponse {
@@ -817,6 +866,35 @@ interface TestWebhookResponse {
817
866
  responseTime?: number;
818
867
  error?: string;
819
868
  }
869
+ /** Rotate webhook secret response */
870
+ interface RotateSecretResponse {
871
+ success: boolean;
872
+ webhookId: string;
873
+ secretVersion: number;
874
+ previousSecretValidUntil: string;
875
+ gracePeriodHours: number;
876
+ message: string;
877
+ }
878
+ /** Webhook secret status response */
879
+ interface SecretStatusResponse {
880
+ webhookId: string;
881
+ hasSecret: boolean;
882
+ secretVersion: number;
883
+ lastRotatedAt?: string;
884
+ gracePeriod?: {
885
+ active: boolean;
886
+ previousVersion: number;
887
+ expiresAt: string;
888
+ } | null;
889
+ }
890
+ /** Verify webhook signature response */
891
+ interface VerifyWebhookResponse {
892
+ valid: boolean;
893
+ webhookId?: string;
894
+ message: string;
895
+ error?: string;
896
+ reason?: string;
897
+ }
820
898
  /** API key info (safe, without secret) */
821
899
  interface ApiKeyInfo {
822
900
  id: string;
@@ -1415,7 +1493,7 @@ interface PriceRange {
1415
1493
  interface CrawlOptions {
1416
1494
  /** Starting URL for the crawl (required) */
1417
1495
  url: string;
1418
- /** Alias for url - Starting URL for the crawl */
1496
+ /** @deprecated Use 'url' instead. Kept for backward compatibility. */
1419
1497
  startUrl?: string;
1420
1498
  /** Prompt to guide the crawl (optional) */
1421
1499
  prompt?: string;
@@ -1535,8 +1613,6 @@ interface DorkOptions {
1535
1613
  inTitle?: string;
1536
1614
  /** Maximum results to return (default: 10, max: 100) */
1537
1615
  maxResults?: number;
1538
- /** Region code (2 letter ISO code) */
1539
- region?: string;
1540
1616
  }
1541
1617
  /** Options for getting job deals */
1542
1618
  interface GetDealsOptions {
@@ -1612,19 +1688,25 @@ interface ExportDealsOptions {
1612
1688
  format?: ExportFormat;
1613
1689
  /** Minimum deal score */
1614
1690
  minScore?: number;
1615
- /** Maximum price */
1616
- maxPrice?: number;
1617
1691
  /** Filter by category */
1618
1692
  category?: string;
1619
- /** Include raw signals in export */
1620
- includeRawSignals?: boolean;
1693
+ /** Filter by sync status to DealUp */
1694
+ synced?: boolean;
1695
+ /** Filter from date (ISO string) */
1696
+ fromDate?: string;
1697
+ /** Filter to date (ISO string) */
1698
+ toDate?: string;
1699
+ /** Maximum number of deals to export (default: 500, max: 1000) */
1700
+ limit?: number;
1621
1701
  }
1622
1702
  /** Webhook event types */
1623
1703
  type WebhookEvent = "deal.found" | "deal.synced" | "crawl.completed" | "crawl.failed";
1624
1704
  /** Options for creating a webhook */
1625
1705
  interface CreateWebhookOptions {
1626
- /** Event type to subscribe to */
1627
- event: WebhookEvent;
1706
+ /** Event types to subscribe to (array) */
1707
+ events?: WebhookEvent[];
1708
+ /** @deprecated Use 'events' array instead */
1709
+ event?: WebhookEvent;
1628
1710
  /** URL to receive webhook notifications */
1629
1711
  url: string;
1630
1712
  /** Secret for signature verification */
@@ -2315,9 +2397,9 @@ declare class AuthResource {
2315
2397
  * and how many are currently active.
2316
2398
  *
2317
2399
  * Tier limits:
2318
- * - Free: 2 concurrent connections
2319
- * - Pro: 10 concurrent connections
2320
- * - Enterprise: 50 concurrent connections
2400
+ * - Free: 10 concurrent connections
2401
+ * - Pro: 50 concurrent connections
2402
+ * - Enterprise: 200 concurrent connections
2321
2403
  *
2322
2404
  * @example
2323
2405
  * ```ts
@@ -2634,6 +2716,47 @@ declare class DataResource {
2634
2716
  * ```
2635
2717
  */
2636
2718
  getRecentJobs(limit?: number): Promise<ListJobsResponse>;
2719
+ /**
2720
+ * Get full job details with result
2721
+ *
2722
+ * @example
2723
+ * ```ts
2724
+ * const job = await client.data.getJob("job_abc123");
2725
+ * console.log(job.result);
2726
+ * console.log(job.dealsFound);
2727
+ * ```
2728
+ */
2729
+ getJob(jobId: string): Promise<JobDetailsResponse>;
2730
+ /**
2731
+ * Get only the result of a completed job
2732
+ *
2733
+ * @example
2734
+ * ```ts
2735
+ * const result = await client.data.getJobResult("job_abc123");
2736
+ * console.log(result.result);
2737
+ * ```
2738
+ */
2739
+ getJobResult(jobId: string): Promise<JobResultResponse>;
2740
+ /**
2741
+ * Export job results in various formats
2742
+ * Supports: json, markdown, llm, csv
2743
+ *
2744
+ * @example
2745
+ * ```ts
2746
+ * // Export as JSON
2747
+ * const jsonData = await client.data.exportJob("job_abc123", "json");
2748
+ *
2749
+ * // Export as Markdown
2750
+ * const markdown = await client.data.exportJob("job_abc123", "markdown");
2751
+ *
2752
+ * // Export as LLM-optimized format
2753
+ * const llmText = await client.data.exportJob("job_abc123", "llm");
2754
+ *
2755
+ * // Export as CSV
2756
+ * const csv = await client.data.exportJob("job_abc123", "csv");
2757
+ * ```
2758
+ */
2759
+ exportJob(jobId: string, format?: "json" | "markdown" | "llm" | "csv"): Promise<JobExportResponse>;
2637
2760
  /**
2638
2761
  * List all deals
2639
2762
  *
@@ -2676,17 +2799,9 @@ declare class DataResource {
2676
2799
  * @example
2677
2800
  * ```ts
2678
2801
  * const electronicsDeals = await client.data.getDealsByCategory("electronics");
2679
- async getDealsByCategory(
2680
- category: string,
2681
- options?: Omit<ListDealsOptions, "category">
2682
- ): Promise<ListDealsResponse> {
2683
- if (!category || !category.trim()) {
2684
- throw new Error("category is required and cannot be empty");
2685
- }
2686
- return this.listDeals({ category, ...options });
2687
- } return this.listDeals({ category, ...options });
2688
- }
2689
-
2802
+ * ```
2803
+ */
2804
+ getDealsByCategory(category: string, options?: Omit<ListDealsOptions, "category">): Promise<ListDealsResponse>;
2690
2805
  /**
2691
2806
  * Get unsynced deals (not yet sent to DealUp)
2692
2807
  *
@@ -3221,7 +3336,9 @@ declare class KeysResource {
3221
3336
  */
3222
3337
  revokeAll(): Promise<{
3223
3338
  success: boolean;
3224
- count: number;
3339
+ revokedCount: number;
3340
+ message: string;
3341
+ warning: string;
3225
3342
  }>;
3226
3343
  /**
3227
3344
  * Get active keys only
@@ -3532,6 +3649,24 @@ declare class StatusResource {
3532
3649
  * ```
3533
3650
  */
3534
3651
  getMetrics(jobId: string): Promise<JobMetricsResponse>;
3652
+ /**
3653
+ * Get errors from a job
3654
+ * Useful for debugging large crawls without loading full results
3655
+ *
3656
+ * @example
3657
+ * ```ts
3658
+ * const errors = await client.status.getJobErrors("job_abc123", {
3659
+ * limit: 50,
3660
+ * offset: 0
3661
+ * });
3662
+ * console.log(errors.data);
3663
+ * console.log(errors.pagination.total);
3664
+ * ```
3665
+ */
3666
+ getJobErrors(jobId: string, options?: {
3667
+ limit?: number;
3668
+ offset?: number;
3669
+ }): Promise<JobErrorsResponse>;
3535
3670
  /**
3536
3671
  * Cancel a pending or active job
3537
3672
  *
@@ -3696,6 +3831,65 @@ declare class WebhooksResource {
3696
3831
  * ```
3697
3832
  */
3698
3833
  getByEvent(event: CreateWebhookOptions["event"]): Promise<WebhookItem[]>;
3834
+ /**
3835
+ * Rotate webhook secret
3836
+ * Rotates the secret while keeping the old one valid during grace period
3837
+ *
3838
+ * @example
3839
+ * ```ts
3840
+ * const result = await client.webhooks.rotateSecret("webhook_abc123", {
3841
+ * newSecret: "new-secure-secret-key",
3842
+ * gracePeriodHours: 24
3843
+ * });
3844
+ * console.log(result.secretVersion);
3845
+ * console.log(result.previousSecretValidUntil);
3846
+ * ```
3847
+ */
3848
+ rotateSecret(webhookId: string, options: {
3849
+ newSecret: string;
3850
+ gracePeriodHours?: number;
3851
+ }): Promise<RotateSecretResponse>;
3852
+ /**
3853
+ * Get webhook secret rotation status
3854
+ * Check current secret version and grace period status
3855
+ *
3856
+ * @example
3857
+ * ```ts
3858
+ * const status = await client.webhooks.getSecretStatus("webhook_abc123");
3859
+ * console.log(status.secretVersion);
3860
+ * if (status.gracePeriod?.active) {
3861
+ * console.log(`Grace period expires: ${status.gracePeriod.expiresAt}`);
3862
+ * }
3863
+ * ```
3864
+ */
3865
+ getSecretStatus(webhookId: string): Promise<SecretStatusResponse>;
3866
+ /**
3867
+ * Verify webhook signature and replay protection
3868
+ * Validates signature, timestamp, and nonce from received webhook
3869
+ *
3870
+ * @example
3871
+ * ```ts
3872
+ * const isValid = await client.webhooks.verifySignature({
3873
+ * webhookId: "webhook_abc123",
3874
+ * payload: receivedPayload,
3875
+ * signature: headers["x-dealcrawl-signature"],
3876
+ * timestamp: parseInt(headers["x-dealcrawl-timestamp"]),
3877
+ * nonce: headers["x-dealcrawl-nonce"]
3878
+ * });
3879
+ * if (isValid.valid) {
3880
+ * console.log("Webhook is valid");
3881
+ * } else {
3882
+ * console.log(`Invalid: ${isValid.error}`);
3883
+ * }
3884
+ * ```
3885
+ */
3886
+ verifySignature(options: {
3887
+ webhookId: string;
3888
+ payload: Record<string, unknown>;
3889
+ signature: string;
3890
+ timestamp: number;
3891
+ nonce: string;
3892
+ }): Promise<VerifyWebhookResponse>;
3699
3893
  }
3700
3894
 
3701
3895
  /**