@sendly/node 3.27.1 → 3.29.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/dist/index.d.mts CHANGED
@@ -877,7 +877,12 @@ declare const ALL_SUPPORTED_COUNTRIES: string[];
877
877
  /**
878
878
  * Webhook event types
879
879
  */
880
- type WebhookEventType = "message.sent" | "message.delivered" | "message.failed" | "message.bounced" | "message.retrying" | "message.queued" | "message.received" | "message.opt_out" | "message.opt_in" | "verification.created" | "verification.delivered" | "verification.verified" | "verification.expired" | "verification.failed" | "verification.resent" | "verification.delivery_failed";
880
+ type WebhookEventType = "message.sent" | "message.delivered" | "message.failed" | "message.bounced" | "message.retrying" | "message.queued" | "message.received" | "message.opt_out" | "message.opt_in" | "verification.created" | "verification.delivered" | "verification.verified" | "verification.expired" | "verification.failed" | "verification.resent" | "verification.delivery_failed" | "contact.auto_flagged" | "contact.marked_valid" | "contacts.lookup_completed" | "contacts.bulk_marked_valid";
881
+ /**
882
+ * Source of a list-health event. Frozen enum — new values will be
883
+ * added in minor SDK versions, never removed.
884
+ */
885
+ type ListHealthEventSource = "send_failure" | "carrier_lookup" | "user_action" | "bulk_mark_valid";
881
886
  /**
882
887
  * Webhook mode - filters which events are delivered
883
888
  * - "all": Receives all events (sandbox + production)
@@ -1527,6 +1532,39 @@ interface Contact {
1527
1532
  * Whether the contact has opted out
1528
1533
  */
1529
1534
  optedOut?: boolean;
1535
+ /**
1536
+ * Carrier-reported line type for this number. One of: `mobile`, `voip`,
1537
+ * `toll free`, `fixed line`, `fixed line or mobile`, `pager`, `voicemail`,
1538
+ * `shared cost`, `premium rate`, `uan`, `personal number`, `unknown`.
1539
+ * Populated after a carrier lookup (either automatic or via checkNumbers).
1540
+ */
1541
+ lineType?: string | null;
1542
+ /**
1543
+ * Carrier name reported by the lookup (e.g., "AT&T", "Verizon").
1544
+ */
1545
+ carrierName?: string | null;
1546
+ /**
1547
+ * When the carrier lookup last ran for this contact.
1548
+ */
1549
+ lineTypeCheckedAt?: string | null;
1550
+ /**
1551
+ * Reason this contact is excluded from future campaigns. One of:
1552
+ * `landline`, `invalid_number`, `non_sms_capable`. Set automatically
1553
+ * after terminal send failures or by a carrier lookup. Clear it with
1554
+ * `contacts.markValid(id)`.
1555
+ */
1556
+ invalidReason?: string | null;
1557
+ /**
1558
+ * When the invalid flag was set.
1559
+ */
1560
+ invalidatedAt?: string | null;
1561
+ /**
1562
+ * When a user manually cleared an auto-flag on this contact. Carrier
1563
+ * re-checks that would re-flag the contact as invalid respect this
1564
+ * timestamp and leave the contact clean, so your manual decisions
1565
+ * survive future lookups.
1566
+ */
1567
+ userMarkedValidAt?: string | null;
1530
1568
  /**
1531
1569
  * When the contact was created
1532
1570
  */
@@ -1543,6 +1581,38 @@ interface Contact {
1543
1581
  name: string;
1544
1582
  }>;
1545
1583
  }
1584
+ /**
1585
+ * Response from triggering a bulk carrier lookup via `contacts.checkNumbers()`.
1586
+ */
1587
+ interface CheckNumbersResponse {
1588
+ success: boolean;
1589
+ /**
1590
+ * True if a carrier lookup for this scope was already running when you
1591
+ * called this. The dashboard renders an "already in progress" toast when
1592
+ * it sees this flag; server-side integrators can treat it as a soft
1593
+ * no-op and wait for `contacts.lookup_completed` webhook.
1594
+ */
1595
+ alreadyRunning?: boolean;
1596
+ message?: string;
1597
+ }
1598
+ /**
1599
+ * Scope for `contacts.bulkMarkValid()`. Pass either an explicit id array
1600
+ * (up to 10,000 per call) OR a `listId` — not both. Foreign ids silently
1601
+ * no-op via the per-org filter.
1602
+ */
1603
+ interface BulkMarkValidOptions {
1604
+ /** Explicit contact ids to clear (max 10,000). */
1605
+ ids?: string[];
1606
+ /** Clear every flagged member of this list. */
1607
+ listId?: string;
1608
+ }
1609
+ /**
1610
+ * Response from `contacts.bulkMarkValid()`.
1611
+ */
1612
+ interface BulkMarkValidResponse {
1613
+ /** Number of contacts whose invalid flag was actually cleared. */
1614
+ cleared: number;
1615
+ }
1546
1616
  /**
1547
1617
  * Request to create a contact
1548
1618
  */
@@ -3459,6 +3529,77 @@ declare class ContactsResource {
3459
3529
  */
3460
3530
  delete(id: string): Promise<void>;
3461
3531
  import(request: ImportContactsRequest): Promise<ImportContactsResponse>;
3532
+ /**
3533
+ * Clear the invalid flag on a contact so future campaigns include it again.
3534
+ *
3535
+ * Contacts get auto-flagged as invalid when a send fails with a terminal
3536
+ * bad-number error (landline, invalid number) or when a carrier lookup
3537
+ * reports they can't receive SMS. Use this when you disagree with the
3538
+ * auto-flag — e.g. the recipient ported from a landline to mobile.
3539
+ *
3540
+ * @param id - Contact ID
3541
+ * @returns The contact with the flag cleared
3542
+ *
3543
+ * @example
3544
+ * ```typescript
3545
+ * const contact = await sendly.contacts.markValid('cnt_xxx');
3546
+ * console.log(contact.invalidReason); // null
3547
+ * ```
3548
+ */
3549
+ markValid(id: string): Promise<Contact>;
3550
+ /**
3551
+ * Clear the invalid flag on many contacts at once — the escape hatch
3552
+ * for when auto-flag misclassifies at scale. Pass either an explicit
3553
+ * id array (up to 10,000 per call) OR a `listId`, not both. Foreign
3554
+ * ids silently no-op via the per-organization filter.
3555
+ *
3556
+ * @param options - `{ ids }` or `{ listId }`
3557
+ * @returns `{ cleared }` — number of contacts whose flag was actually
3558
+ * cleared. Already-clean contacts and foreign ids don't count.
3559
+ *
3560
+ * @example
3561
+ * ```typescript
3562
+ * // Clear a specific set of ids
3563
+ * const { cleared } = await sendly.contacts.bulkMarkValid({
3564
+ * ids: ['cnt_abc', 'cnt_def', 'cnt_ghi'],
3565
+ * });
3566
+ *
3567
+ * // Clear every flagged member of a list
3568
+ * await sendly.contacts.bulkMarkValid({ listId: 'lst_xxx' });
3569
+ * ```
3570
+ */
3571
+ bulkMarkValid(options: BulkMarkValidOptions): Promise<BulkMarkValidResponse>;
3572
+ /**
3573
+ * Trigger a background carrier lookup across your contacts. Landlines and
3574
+ * other non-SMS-capable numbers are auto-excluded from future campaigns.
3575
+ *
3576
+ * The lookup runs asynchronously and takes 1–5 minutes depending on list
3577
+ * size. Results populate the `lineType`, `carrierName`, and `invalidReason`
3578
+ * fields on affected contacts — fetch the contact again after a few minutes
3579
+ * to see updated state.
3580
+ *
3581
+ * Idempotent: re-triggering while a lookup is already running for the same
3582
+ * scope is a no-op.
3583
+ *
3584
+ * @param options - Optional: scope to a single list, or force re-check
3585
+ * @returns Acknowledgement
3586
+ *
3587
+ * @example
3588
+ * ```typescript
3589
+ * // Check all un-checked contacts
3590
+ * await sendly.contacts.checkNumbers();
3591
+ *
3592
+ * // Check a specific list only
3593
+ * await sendly.contacts.checkNumbers({ listId: 'lst_xxx' });
3594
+ *
3595
+ * // Re-check contacts even if previously looked up
3596
+ * await sendly.contacts.checkNumbers({ force: true });
3597
+ * ```
3598
+ */
3599
+ checkNumbers(options?: {
3600
+ listId?: string;
3601
+ force?: boolean;
3602
+ }): Promise<CheckNumbersResponse>;
3462
3603
  private transformContact;
3463
3604
  }
3464
3605
  /**
@@ -4480,4 +4621,4 @@ declare class Webhooks {
4480
4621
  */
4481
4622
  type WebhookMessageData = WebhookMessageObject;
4482
4623
 
4483
- export { ALL_SUPPORTED_COUNTRIES, type Account, type AddLabelsRequest, type AnalyticsOverview, type AnalyticsPeriod, type ApiErrorResponse, type ApiKey, AuthenticationError, type AutoTopUpSettings, type BatchListResponse, type BatchMessageItem, type BatchMessageRequest, type BatchMessageResponse, type BatchMessageResult, type BatchStatus, type BillingBreakdown, type BillingBreakdownOptions, type BulkProvisionResult, type BulkProvisionResultItem, type BulkProvisionWorkspace, CREDITS_PER_SMS, type Campaign, type CampaignListResponse, type CampaignPreview, type CampaignStatus, type CancelledMessageResponse, type CheckVerificationRequest, type CheckVerificationResponse, type CircuitState, type Contact, type ContactList, type ContactListResponse, type ContactListsResponse, type Conversation, type ConversationListResponse, type ConversationStatus, type ConversationWithMessages, type CreateCampaignRequest, type CreateContactListRequest, type CreateContactRequest, type CreateDraftRequest, type CreateKeyOptions, type CreateLabelRequest, type CreateOptInPageOptions, type CreateOptInPageResult, type CreateTemplateRequest, type CreateVerifySessionRequest, type CreateWebhookOptions, type CreateWorkspaceOptions, type CreatedApiKey, type CreditAnalytics, type CreditAnalyticsDataPoint, type CreditTransaction, type Credits, type DeliveryAnalyticsItem, type DeliveryStatus, type DnsRecord, type DraftListResponse, type DraftStatus, type EnterpriseAccount, type EnterpriseWebhook, type EnterpriseWebhookTestResult, type EnterpriseWorkspace, type EnterpriseWorkspaceDetail, type EnterpriseWorkspaceSummary, type GenerateBusinessPageOptions, type GenerateBusinessPageResponse, type GetConversationOptions, type ImportContactItem, type ImportContactsError, type ImportContactsRequest, type ImportContactsResponse, InsufficientCreditsError, type Invitation, type Label, type LabelListResponse, type ListBatchesOptions, type ListCampaignsOptions, type ListContactsOptions, type ListConversationsOptions, type ListDraftsOptions, type ListMessagesOptions, type ListScheduledMessagesOptions, type ListVerificationsOptions, type MediaFile, type MediaUploadOptions, type Message, type MessageAnalytics, type MessageAnalyticsDataPoint, type MessageDraft, type MessageListResponse, type MessageStatus, type MessageType, NetworkError, NotFoundError, type OptInPage, type PricingTier, type ProvisionWorkspaceOptions, type ProvisionWorkspaceResult, type QuotaSettings, RateLimitError, type RateLimitInfo, type ReplyToConversationRequest, type ResumeWorkspaceResult, SANDBOX_TEST_NUMBERS, SUPPORTED_COUNTRIES, type ScheduleCampaignRequest, type ScheduleMessageRequest, type ScheduledMessage, type ScheduledMessageListResponse, type ScheduledMessageStatus, type SendInvitationOptions, type SendMessageRequest, type SendVerificationRequest, type SendVerificationResponse, type SenderType, Sendly, type SendlyConfig, SendlyError, type SendlyErrorCode, type SetCustomDomainResult, type SetWorkspaceWebhookOptions, type SetWorkspaceWebhookResult, type SuggestRepliesResponse, type SuggestedReply, type SuspendWorkspaceOptions, type SuspendWorkspaceResult, type Template, type TemplateListResponse, type TemplatePreview, type TemplateStatus, type TemplateVariable, TimeoutError, type TransferCreditsOptions, type TransferCreditsResult, type UpdateAutoTopUpOptions, type UpdateCampaignRequest, type UpdateContactListRequest, type UpdateContactRequest, type UpdateConversationRequest, type UpdateDraftRequest, type UpdateOptInPageOptions, type UpdateQuotaOptions, type UpdateTemplateRequest, type UpdateWebhookOptions, type ValidateSessionTokenRequest, type ValidateSessionTokenResponse, ValidationError, type Verification, type VerificationDeliveryStatus, type VerificationListResponse, type VerificationStatus, type VerifySession, type VerifySessionStatus, type Webhook, type WebhookCreatedResponse, type WebhookDelivery, type WebhookEvent, type WebhookEventType, type WebhookMessageData, type WebhookMessageStatus, type WebhookSecretRotation, WebhookSignatureError, type WebhookTestResult, Webhooks, type WorkspaceBillingItem, type WorkspaceCredits, type WorkspaceWebhook, calculateSegments, Sendly as default, generateWebhookSignature, getCountryFromPhone, isCountrySupported, parseWebhookEvent, validateMessageText, validatePhoneNumber, validateSenderId, verifyWebhookSignature };
4624
+ export { ALL_SUPPORTED_COUNTRIES, type Account, type AddLabelsRequest, type AnalyticsOverview, type AnalyticsPeriod, type ApiErrorResponse, type ApiKey, AuthenticationError, type AutoTopUpSettings, type BatchListResponse, type BatchMessageItem, type BatchMessageRequest, type BatchMessageResponse, type BatchMessageResult, type BatchStatus, type BillingBreakdown, type BillingBreakdownOptions, type BulkMarkValidOptions, type BulkMarkValidResponse, type BulkProvisionResult, type BulkProvisionResultItem, type BulkProvisionWorkspace, CREDITS_PER_SMS, type Campaign, type CampaignListResponse, type CampaignPreview, type CampaignStatus, type CancelledMessageResponse, type CheckNumbersResponse, type CheckVerificationRequest, type CheckVerificationResponse, type CircuitState, type Contact, type ContactList, type ContactListResponse, type ContactListsResponse, type Conversation, type ConversationListResponse, type ConversationStatus, type ConversationWithMessages, type CreateCampaignRequest, type CreateContactListRequest, type CreateContactRequest, type CreateDraftRequest, type CreateKeyOptions, type CreateLabelRequest, type CreateOptInPageOptions, type CreateOptInPageResult, type CreateTemplateRequest, type CreateVerifySessionRequest, type CreateWebhookOptions, type CreateWorkspaceOptions, type CreatedApiKey, type CreditAnalytics, type CreditAnalyticsDataPoint, type CreditTransaction, type Credits, type DeliveryAnalyticsItem, type DeliveryStatus, type DnsRecord, type DraftListResponse, type DraftStatus, type EnterpriseAccount, type EnterpriseWebhook, type EnterpriseWebhookTestResult, type EnterpriseWorkspace, type EnterpriseWorkspaceDetail, type EnterpriseWorkspaceSummary, type GenerateBusinessPageOptions, type GenerateBusinessPageResponse, type GetConversationOptions, type ImportContactItem, type ImportContactsError, type ImportContactsRequest, type ImportContactsResponse, InsufficientCreditsError, type Invitation, type Label, type LabelListResponse, type ListBatchesOptions, type ListCampaignsOptions, type ListContactsOptions, type ListConversationsOptions, type ListDraftsOptions, type ListHealthEventSource, type ListMessagesOptions, type ListScheduledMessagesOptions, type ListVerificationsOptions, type MediaFile, type MediaUploadOptions, type Message, type MessageAnalytics, type MessageAnalyticsDataPoint, type MessageDraft, type MessageListResponse, type MessageStatus, type MessageType, NetworkError, NotFoundError, type OptInPage, type PricingTier, type ProvisionWorkspaceOptions, type ProvisionWorkspaceResult, type QuotaSettings, RateLimitError, type RateLimitInfo, type ReplyToConversationRequest, type ResumeWorkspaceResult, SANDBOX_TEST_NUMBERS, SUPPORTED_COUNTRIES, type ScheduleCampaignRequest, type ScheduleMessageRequest, type ScheduledMessage, type ScheduledMessageListResponse, type ScheduledMessageStatus, type SendInvitationOptions, type SendMessageRequest, type SendVerificationRequest, type SendVerificationResponse, type SenderType, Sendly, type SendlyConfig, SendlyError, type SendlyErrorCode, type SetCustomDomainResult, type SetWorkspaceWebhookOptions, type SetWorkspaceWebhookResult, type SuggestRepliesResponse, type SuggestedReply, type SuspendWorkspaceOptions, type SuspendWorkspaceResult, type Template, type TemplateListResponse, type TemplatePreview, type TemplateStatus, type TemplateVariable, TimeoutError, type TransferCreditsOptions, type TransferCreditsResult, type UpdateAutoTopUpOptions, type UpdateCampaignRequest, type UpdateContactListRequest, type UpdateContactRequest, type UpdateConversationRequest, type UpdateDraftRequest, type UpdateOptInPageOptions, type UpdateQuotaOptions, type UpdateTemplateRequest, type UpdateWebhookOptions, type ValidateSessionTokenRequest, type ValidateSessionTokenResponse, ValidationError, type Verification, type VerificationDeliveryStatus, type VerificationListResponse, type VerificationStatus, type VerifySession, type VerifySessionStatus, type Webhook, type WebhookCreatedResponse, type WebhookDelivery, type WebhookEvent, type WebhookEventType, type WebhookMessageData, type WebhookMessageStatus, type WebhookSecretRotation, WebhookSignatureError, type WebhookTestResult, Webhooks, type WorkspaceBillingItem, type WorkspaceCredits, type WorkspaceWebhook, calculateSegments, Sendly as default, generateWebhookSignature, getCountryFromPhone, isCountrySupported, parseWebhookEvent, validateMessageText, validatePhoneNumber, validateSenderId, verifyWebhookSignature };
package/dist/index.d.ts CHANGED
@@ -877,7 +877,12 @@ declare const ALL_SUPPORTED_COUNTRIES: string[];
877
877
  /**
878
878
  * Webhook event types
879
879
  */
880
- type WebhookEventType = "message.sent" | "message.delivered" | "message.failed" | "message.bounced" | "message.retrying" | "message.queued" | "message.received" | "message.opt_out" | "message.opt_in" | "verification.created" | "verification.delivered" | "verification.verified" | "verification.expired" | "verification.failed" | "verification.resent" | "verification.delivery_failed";
880
+ type WebhookEventType = "message.sent" | "message.delivered" | "message.failed" | "message.bounced" | "message.retrying" | "message.queued" | "message.received" | "message.opt_out" | "message.opt_in" | "verification.created" | "verification.delivered" | "verification.verified" | "verification.expired" | "verification.failed" | "verification.resent" | "verification.delivery_failed" | "contact.auto_flagged" | "contact.marked_valid" | "contacts.lookup_completed" | "contacts.bulk_marked_valid";
881
+ /**
882
+ * Source of a list-health event. Frozen enum — new values will be
883
+ * added in minor SDK versions, never removed.
884
+ */
885
+ type ListHealthEventSource = "send_failure" | "carrier_lookup" | "user_action" | "bulk_mark_valid";
881
886
  /**
882
887
  * Webhook mode - filters which events are delivered
883
888
  * - "all": Receives all events (sandbox + production)
@@ -1527,6 +1532,39 @@ interface Contact {
1527
1532
  * Whether the contact has opted out
1528
1533
  */
1529
1534
  optedOut?: boolean;
1535
+ /**
1536
+ * Carrier-reported line type for this number. One of: `mobile`, `voip`,
1537
+ * `toll free`, `fixed line`, `fixed line or mobile`, `pager`, `voicemail`,
1538
+ * `shared cost`, `premium rate`, `uan`, `personal number`, `unknown`.
1539
+ * Populated after a carrier lookup (either automatic or via checkNumbers).
1540
+ */
1541
+ lineType?: string | null;
1542
+ /**
1543
+ * Carrier name reported by the lookup (e.g., "AT&T", "Verizon").
1544
+ */
1545
+ carrierName?: string | null;
1546
+ /**
1547
+ * When the carrier lookup last ran for this contact.
1548
+ */
1549
+ lineTypeCheckedAt?: string | null;
1550
+ /**
1551
+ * Reason this contact is excluded from future campaigns. One of:
1552
+ * `landline`, `invalid_number`, `non_sms_capable`. Set automatically
1553
+ * after terminal send failures or by a carrier lookup. Clear it with
1554
+ * `contacts.markValid(id)`.
1555
+ */
1556
+ invalidReason?: string | null;
1557
+ /**
1558
+ * When the invalid flag was set.
1559
+ */
1560
+ invalidatedAt?: string | null;
1561
+ /**
1562
+ * When a user manually cleared an auto-flag on this contact. Carrier
1563
+ * re-checks that would re-flag the contact as invalid respect this
1564
+ * timestamp and leave the contact clean, so your manual decisions
1565
+ * survive future lookups.
1566
+ */
1567
+ userMarkedValidAt?: string | null;
1530
1568
  /**
1531
1569
  * When the contact was created
1532
1570
  */
@@ -1543,6 +1581,38 @@ interface Contact {
1543
1581
  name: string;
1544
1582
  }>;
1545
1583
  }
1584
+ /**
1585
+ * Response from triggering a bulk carrier lookup via `contacts.checkNumbers()`.
1586
+ */
1587
+ interface CheckNumbersResponse {
1588
+ success: boolean;
1589
+ /**
1590
+ * True if a carrier lookup for this scope was already running when you
1591
+ * called this. The dashboard renders an "already in progress" toast when
1592
+ * it sees this flag; server-side integrators can treat it as a soft
1593
+ * no-op and wait for `contacts.lookup_completed` webhook.
1594
+ */
1595
+ alreadyRunning?: boolean;
1596
+ message?: string;
1597
+ }
1598
+ /**
1599
+ * Scope for `contacts.bulkMarkValid()`. Pass either an explicit id array
1600
+ * (up to 10,000 per call) OR a `listId` — not both. Foreign ids silently
1601
+ * no-op via the per-org filter.
1602
+ */
1603
+ interface BulkMarkValidOptions {
1604
+ /** Explicit contact ids to clear (max 10,000). */
1605
+ ids?: string[];
1606
+ /** Clear every flagged member of this list. */
1607
+ listId?: string;
1608
+ }
1609
+ /**
1610
+ * Response from `contacts.bulkMarkValid()`.
1611
+ */
1612
+ interface BulkMarkValidResponse {
1613
+ /** Number of contacts whose invalid flag was actually cleared. */
1614
+ cleared: number;
1615
+ }
1546
1616
  /**
1547
1617
  * Request to create a contact
1548
1618
  */
@@ -3459,6 +3529,77 @@ declare class ContactsResource {
3459
3529
  */
3460
3530
  delete(id: string): Promise<void>;
3461
3531
  import(request: ImportContactsRequest): Promise<ImportContactsResponse>;
3532
+ /**
3533
+ * Clear the invalid flag on a contact so future campaigns include it again.
3534
+ *
3535
+ * Contacts get auto-flagged as invalid when a send fails with a terminal
3536
+ * bad-number error (landline, invalid number) or when a carrier lookup
3537
+ * reports they can't receive SMS. Use this when you disagree with the
3538
+ * auto-flag — e.g. the recipient ported from a landline to mobile.
3539
+ *
3540
+ * @param id - Contact ID
3541
+ * @returns The contact with the flag cleared
3542
+ *
3543
+ * @example
3544
+ * ```typescript
3545
+ * const contact = await sendly.contacts.markValid('cnt_xxx');
3546
+ * console.log(contact.invalidReason); // null
3547
+ * ```
3548
+ */
3549
+ markValid(id: string): Promise<Contact>;
3550
+ /**
3551
+ * Clear the invalid flag on many contacts at once — the escape hatch
3552
+ * for when auto-flag misclassifies at scale. Pass either an explicit
3553
+ * id array (up to 10,000 per call) OR a `listId`, not both. Foreign
3554
+ * ids silently no-op via the per-organization filter.
3555
+ *
3556
+ * @param options - `{ ids }` or `{ listId }`
3557
+ * @returns `{ cleared }` — number of contacts whose flag was actually
3558
+ * cleared. Already-clean contacts and foreign ids don't count.
3559
+ *
3560
+ * @example
3561
+ * ```typescript
3562
+ * // Clear a specific set of ids
3563
+ * const { cleared } = await sendly.contacts.bulkMarkValid({
3564
+ * ids: ['cnt_abc', 'cnt_def', 'cnt_ghi'],
3565
+ * });
3566
+ *
3567
+ * // Clear every flagged member of a list
3568
+ * await sendly.contacts.bulkMarkValid({ listId: 'lst_xxx' });
3569
+ * ```
3570
+ */
3571
+ bulkMarkValid(options: BulkMarkValidOptions): Promise<BulkMarkValidResponse>;
3572
+ /**
3573
+ * Trigger a background carrier lookup across your contacts. Landlines and
3574
+ * other non-SMS-capable numbers are auto-excluded from future campaigns.
3575
+ *
3576
+ * The lookup runs asynchronously and takes 1–5 minutes depending on list
3577
+ * size. Results populate the `lineType`, `carrierName`, and `invalidReason`
3578
+ * fields on affected contacts — fetch the contact again after a few minutes
3579
+ * to see updated state.
3580
+ *
3581
+ * Idempotent: re-triggering while a lookup is already running for the same
3582
+ * scope is a no-op.
3583
+ *
3584
+ * @param options - Optional: scope to a single list, or force re-check
3585
+ * @returns Acknowledgement
3586
+ *
3587
+ * @example
3588
+ * ```typescript
3589
+ * // Check all un-checked contacts
3590
+ * await sendly.contacts.checkNumbers();
3591
+ *
3592
+ * // Check a specific list only
3593
+ * await sendly.contacts.checkNumbers({ listId: 'lst_xxx' });
3594
+ *
3595
+ * // Re-check contacts even if previously looked up
3596
+ * await sendly.contacts.checkNumbers({ force: true });
3597
+ * ```
3598
+ */
3599
+ checkNumbers(options?: {
3600
+ listId?: string;
3601
+ force?: boolean;
3602
+ }): Promise<CheckNumbersResponse>;
3462
3603
  private transformContact;
3463
3604
  }
3464
3605
  /**
@@ -4480,4 +4621,4 @@ declare class Webhooks {
4480
4621
  */
4481
4622
  type WebhookMessageData = WebhookMessageObject;
4482
4623
 
4483
- export { ALL_SUPPORTED_COUNTRIES, type Account, type AddLabelsRequest, type AnalyticsOverview, type AnalyticsPeriod, type ApiErrorResponse, type ApiKey, AuthenticationError, type AutoTopUpSettings, type BatchListResponse, type BatchMessageItem, type BatchMessageRequest, type BatchMessageResponse, type BatchMessageResult, type BatchStatus, type BillingBreakdown, type BillingBreakdownOptions, type BulkProvisionResult, type BulkProvisionResultItem, type BulkProvisionWorkspace, CREDITS_PER_SMS, type Campaign, type CampaignListResponse, type CampaignPreview, type CampaignStatus, type CancelledMessageResponse, type CheckVerificationRequest, type CheckVerificationResponse, type CircuitState, type Contact, type ContactList, type ContactListResponse, type ContactListsResponse, type Conversation, type ConversationListResponse, type ConversationStatus, type ConversationWithMessages, type CreateCampaignRequest, type CreateContactListRequest, type CreateContactRequest, type CreateDraftRequest, type CreateKeyOptions, type CreateLabelRequest, type CreateOptInPageOptions, type CreateOptInPageResult, type CreateTemplateRequest, type CreateVerifySessionRequest, type CreateWebhookOptions, type CreateWorkspaceOptions, type CreatedApiKey, type CreditAnalytics, type CreditAnalyticsDataPoint, type CreditTransaction, type Credits, type DeliveryAnalyticsItem, type DeliveryStatus, type DnsRecord, type DraftListResponse, type DraftStatus, type EnterpriseAccount, type EnterpriseWebhook, type EnterpriseWebhookTestResult, type EnterpriseWorkspace, type EnterpriseWorkspaceDetail, type EnterpriseWorkspaceSummary, type GenerateBusinessPageOptions, type GenerateBusinessPageResponse, type GetConversationOptions, type ImportContactItem, type ImportContactsError, type ImportContactsRequest, type ImportContactsResponse, InsufficientCreditsError, type Invitation, type Label, type LabelListResponse, type ListBatchesOptions, type ListCampaignsOptions, type ListContactsOptions, type ListConversationsOptions, type ListDraftsOptions, type ListMessagesOptions, type ListScheduledMessagesOptions, type ListVerificationsOptions, type MediaFile, type MediaUploadOptions, type Message, type MessageAnalytics, type MessageAnalyticsDataPoint, type MessageDraft, type MessageListResponse, type MessageStatus, type MessageType, NetworkError, NotFoundError, type OptInPage, type PricingTier, type ProvisionWorkspaceOptions, type ProvisionWorkspaceResult, type QuotaSettings, RateLimitError, type RateLimitInfo, type ReplyToConversationRequest, type ResumeWorkspaceResult, SANDBOX_TEST_NUMBERS, SUPPORTED_COUNTRIES, type ScheduleCampaignRequest, type ScheduleMessageRequest, type ScheduledMessage, type ScheduledMessageListResponse, type ScheduledMessageStatus, type SendInvitationOptions, type SendMessageRequest, type SendVerificationRequest, type SendVerificationResponse, type SenderType, Sendly, type SendlyConfig, SendlyError, type SendlyErrorCode, type SetCustomDomainResult, type SetWorkspaceWebhookOptions, type SetWorkspaceWebhookResult, type SuggestRepliesResponse, type SuggestedReply, type SuspendWorkspaceOptions, type SuspendWorkspaceResult, type Template, type TemplateListResponse, type TemplatePreview, type TemplateStatus, type TemplateVariable, TimeoutError, type TransferCreditsOptions, type TransferCreditsResult, type UpdateAutoTopUpOptions, type UpdateCampaignRequest, type UpdateContactListRequest, type UpdateContactRequest, type UpdateConversationRequest, type UpdateDraftRequest, type UpdateOptInPageOptions, type UpdateQuotaOptions, type UpdateTemplateRequest, type UpdateWebhookOptions, type ValidateSessionTokenRequest, type ValidateSessionTokenResponse, ValidationError, type Verification, type VerificationDeliveryStatus, type VerificationListResponse, type VerificationStatus, type VerifySession, type VerifySessionStatus, type Webhook, type WebhookCreatedResponse, type WebhookDelivery, type WebhookEvent, type WebhookEventType, type WebhookMessageData, type WebhookMessageStatus, type WebhookSecretRotation, WebhookSignatureError, type WebhookTestResult, Webhooks, type WorkspaceBillingItem, type WorkspaceCredits, type WorkspaceWebhook, calculateSegments, Sendly as default, generateWebhookSignature, getCountryFromPhone, isCountrySupported, parseWebhookEvent, validateMessageText, validatePhoneNumber, validateSenderId, verifyWebhookSignature };
4624
+ export { ALL_SUPPORTED_COUNTRIES, type Account, type AddLabelsRequest, type AnalyticsOverview, type AnalyticsPeriod, type ApiErrorResponse, type ApiKey, AuthenticationError, type AutoTopUpSettings, type BatchListResponse, type BatchMessageItem, type BatchMessageRequest, type BatchMessageResponse, type BatchMessageResult, type BatchStatus, type BillingBreakdown, type BillingBreakdownOptions, type BulkMarkValidOptions, type BulkMarkValidResponse, type BulkProvisionResult, type BulkProvisionResultItem, type BulkProvisionWorkspace, CREDITS_PER_SMS, type Campaign, type CampaignListResponse, type CampaignPreview, type CampaignStatus, type CancelledMessageResponse, type CheckNumbersResponse, type CheckVerificationRequest, type CheckVerificationResponse, type CircuitState, type Contact, type ContactList, type ContactListResponse, type ContactListsResponse, type Conversation, type ConversationListResponse, type ConversationStatus, type ConversationWithMessages, type CreateCampaignRequest, type CreateContactListRequest, type CreateContactRequest, type CreateDraftRequest, type CreateKeyOptions, type CreateLabelRequest, type CreateOptInPageOptions, type CreateOptInPageResult, type CreateTemplateRequest, type CreateVerifySessionRequest, type CreateWebhookOptions, type CreateWorkspaceOptions, type CreatedApiKey, type CreditAnalytics, type CreditAnalyticsDataPoint, type CreditTransaction, type Credits, type DeliveryAnalyticsItem, type DeliveryStatus, type DnsRecord, type DraftListResponse, type DraftStatus, type EnterpriseAccount, type EnterpriseWebhook, type EnterpriseWebhookTestResult, type EnterpriseWorkspace, type EnterpriseWorkspaceDetail, type EnterpriseWorkspaceSummary, type GenerateBusinessPageOptions, type GenerateBusinessPageResponse, type GetConversationOptions, type ImportContactItem, type ImportContactsError, type ImportContactsRequest, type ImportContactsResponse, InsufficientCreditsError, type Invitation, type Label, type LabelListResponse, type ListBatchesOptions, type ListCampaignsOptions, type ListContactsOptions, type ListConversationsOptions, type ListDraftsOptions, type ListHealthEventSource, type ListMessagesOptions, type ListScheduledMessagesOptions, type ListVerificationsOptions, type MediaFile, type MediaUploadOptions, type Message, type MessageAnalytics, type MessageAnalyticsDataPoint, type MessageDraft, type MessageListResponse, type MessageStatus, type MessageType, NetworkError, NotFoundError, type OptInPage, type PricingTier, type ProvisionWorkspaceOptions, type ProvisionWorkspaceResult, type QuotaSettings, RateLimitError, type RateLimitInfo, type ReplyToConversationRequest, type ResumeWorkspaceResult, SANDBOX_TEST_NUMBERS, SUPPORTED_COUNTRIES, type ScheduleCampaignRequest, type ScheduleMessageRequest, type ScheduledMessage, type ScheduledMessageListResponse, type ScheduledMessageStatus, type SendInvitationOptions, type SendMessageRequest, type SendVerificationRequest, type SendVerificationResponse, type SenderType, Sendly, type SendlyConfig, SendlyError, type SendlyErrorCode, type SetCustomDomainResult, type SetWorkspaceWebhookOptions, type SetWorkspaceWebhookResult, type SuggestRepliesResponse, type SuggestedReply, type SuspendWorkspaceOptions, type SuspendWorkspaceResult, type Template, type TemplateListResponse, type TemplatePreview, type TemplateStatus, type TemplateVariable, TimeoutError, type TransferCreditsOptions, type TransferCreditsResult, type UpdateAutoTopUpOptions, type UpdateCampaignRequest, type UpdateContactListRequest, type UpdateContactRequest, type UpdateConversationRequest, type UpdateDraftRequest, type UpdateOptInPageOptions, type UpdateQuotaOptions, type UpdateTemplateRequest, type UpdateWebhookOptions, type ValidateSessionTokenRequest, type ValidateSessionTokenResponse, ValidationError, type Verification, type VerificationDeliveryStatus, type VerificationListResponse, type VerificationStatus, type VerifySession, type VerifySessionStatus, type Webhook, type WebhookCreatedResponse, type WebhookDelivery, type WebhookEvent, type WebhookEventType, type WebhookMessageData, type WebhookMessageStatus, type WebhookSecretRotation, WebhookSignatureError, type WebhookTestResult, Webhooks, type WorkspaceBillingItem, type WorkspaceCredits, type WorkspaceWebhook, calculateSegments, Sendly as default, generateWebhookSignature, getCountryFromPhone, isCountrySupported, parseWebhookEvent, validateMessageText, validatePhoneNumber, validateSenderId, verifyWebhookSignature };
package/dist/index.js CHANGED
@@ -2610,16 +2610,118 @@ var ContactsResource = class {
2610
2610
  body
2611
2611
  });
2612
2612
  }
2613
+ /**
2614
+ * Clear the invalid flag on a contact so future campaigns include it again.
2615
+ *
2616
+ * Contacts get auto-flagged as invalid when a send fails with a terminal
2617
+ * bad-number error (landline, invalid number) or when a carrier lookup
2618
+ * reports they can't receive SMS. Use this when you disagree with the
2619
+ * auto-flag — e.g. the recipient ported from a landline to mobile.
2620
+ *
2621
+ * @param id - Contact ID
2622
+ * @returns The contact with the flag cleared
2623
+ *
2624
+ * @example
2625
+ * ```typescript
2626
+ * const contact = await sendly.contacts.markValid('cnt_xxx');
2627
+ * console.log(contact.invalidReason); // null
2628
+ * ```
2629
+ */
2630
+ async markValid(id) {
2631
+ const response = await this.http.request({
2632
+ method: "POST",
2633
+ path: `/contacts/${id}/mark-valid`
2634
+ });
2635
+ return this.transformContact(response);
2636
+ }
2637
+ /**
2638
+ * Clear the invalid flag on many contacts at once — the escape hatch
2639
+ * for when auto-flag misclassifies at scale. Pass either an explicit
2640
+ * id array (up to 10,000 per call) OR a `listId`, not both. Foreign
2641
+ * ids silently no-op via the per-organization filter.
2642
+ *
2643
+ * @param options - `{ ids }` or `{ listId }`
2644
+ * @returns `{ cleared }` — number of contacts whose flag was actually
2645
+ * cleared. Already-clean contacts and foreign ids don't count.
2646
+ *
2647
+ * @example
2648
+ * ```typescript
2649
+ * // Clear a specific set of ids
2650
+ * const { cleared } = await sendly.contacts.bulkMarkValid({
2651
+ * ids: ['cnt_abc', 'cnt_def', 'cnt_ghi'],
2652
+ * });
2653
+ *
2654
+ * // Clear every flagged member of a list
2655
+ * await sendly.contacts.bulkMarkValid({ listId: 'lst_xxx' });
2656
+ * ```
2657
+ */
2658
+ async bulkMarkValid(options) {
2659
+ if (!options.ids && !options.listId) {
2660
+ throw new Error("bulkMarkValid requires either 'ids' or 'listId'");
2661
+ }
2662
+ if (options.ids && options.listId) {
2663
+ throw new Error("bulkMarkValid accepts 'ids' OR 'listId', not both");
2664
+ }
2665
+ return this.http.request({
2666
+ method: "POST",
2667
+ path: "/contacts/bulk-mark-valid",
2668
+ body: options.ids ? { ids: options.ids } : { listId: options.listId }
2669
+ });
2670
+ }
2671
+ /**
2672
+ * Trigger a background carrier lookup across your contacts. Landlines and
2673
+ * other non-SMS-capable numbers are auto-excluded from future campaigns.
2674
+ *
2675
+ * The lookup runs asynchronously and takes 1–5 minutes depending on list
2676
+ * size. Results populate the `lineType`, `carrierName`, and `invalidReason`
2677
+ * fields on affected contacts — fetch the contact again after a few minutes
2678
+ * to see updated state.
2679
+ *
2680
+ * Idempotent: re-triggering while a lookup is already running for the same
2681
+ * scope is a no-op.
2682
+ *
2683
+ * @param options - Optional: scope to a single list, or force re-check
2684
+ * @returns Acknowledgement
2685
+ *
2686
+ * @example
2687
+ * ```typescript
2688
+ * // Check all un-checked contacts
2689
+ * await sendly.contacts.checkNumbers();
2690
+ *
2691
+ * // Check a specific list only
2692
+ * await sendly.contacts.checkNumbers({ listId: 'lst_xxx' });
2693
+ *
2694
+ * // Re-check contacts even if previously looked up
2695
+ * await sendly.contacts.checkNumbers({ force: true });
2696
+ * ```
2697
+ */
2698
+ async checkNumbers(options = {}) {
2699
+ return this.http.request({
2700
+ method: "POST",
2701
+ path: "/contacts/lookup",
2702
+ body: {
2703
+ listId: options.listId ?? null,
2704
+ force: options.force ?? false
2705
+ }
2706
+ });
2707
+ }
2613
2708
  transformContact(raw) {
2709
+ const r = raw;
2614
2710
  return {
2615
2711
  id: raw.id,
2616
- phoneNumber: raw.phone_number,
2712
+ phoneNumber: raw.phone_number ?? r.phoneNumber,
2617
2713
  name: raw.name,
2618
2714
  email: raw.email,
2619
2715
  metadata: raw.metadata,
2620
- optedOut: raw.opted_out,
2621
- createdAt: raw.created_at,
2622
- updatedAt: raw.updated_at,
2716
+ optedOut: raw.opted_out ?? r.optedOut,
2717
+ lineType: raw.line_type ?? r.lineType ?? null,
2718
+ carrierName: raw.carrier_name ?? r.carrierName ?? null,
2719
+ lineTypeCheckedAt: raw.line_type_checked_at ?? r.lineTypeCheckedAt ?? null,
2720
+ invalidReason: raw.invalid_reason ?? r.invalidReason ?? null,
2721
+ invalidatedAt: raw.invalidated_at ?? r.invalidatedAt ?? null,
2722
+ userMarkedValidAt: raw.user_marked_valid_at ?? r.userMarkedValidAt ?? null,
2723
+ createdAt: raw.created_at ?? r.createdAt,
2724
+ updatedAt: raw.updated_at ?? r.updatedAt,
2623
2725
  lists: raw.lists?.map((l) => ({ id: l.id, name: l.name }))
2624
2726
  };
2625
2727
  }
package/dist/index.mjs CHANGED
@@ -2550,16 +2550,118 @@ var ContactsResource = class {
2550
2550
  body
2551
2551
  });
2552
2552
  }
2553
+ /**
2554
+ * Clear the invalid flag on a contact so future campaigns include it again.
2555
+ *
2556
+ * Contacts get auto-flagged as invalid when a send fails with a terminal
2557
+ * bad-number error (landline, invalid number) or when a carrier lookup
2558
+ * reports they can't receive SMS. Use this when you disagree with the
2559
+ * auto-flag — e.g. the recipient ported from a landline to mobile.
2560
+ *
2561
+ * @param id - Contact ID
2562
+ * @returns The contact with the flag cleared
2563
+ *
2564
+ * @example
2565
+ * ```typescript
2566
+ * const contact = await sendly.contacts.markValid('cnt_xxx');
2567
+ * console.log(contact.invalidReason); // null
2568
+ * ```
2569
+ */
2570
+ async markValid(id) {
2571
+ const response = await this.http.request({
2572
+ method: "POST",
2573
+ path: `/contacts/${id}/mark-valid`
2574
+ });
2575
+ return this.transformContact(response);
2576
+ }
2577
+ /**
2578
+ * Clear the invalid flag on many contacts at once — the escape hatch
2579
+ * for when auto-flag misclassifies at scale. Pass either an explicit
2580
+ * id array (up to 10,000 per call) OR a `listId`, not both. Foreign
2581
+ * ids silently no-op via the per-organization filter.
2582
+ *
2583
+ * @param options - `{ ids }` or `{ listId }`
2584
+ * @returns `{ cleared }` — number of contacts whose flag was actually
2585
+ * cleared. Already-clean contacts and foreign ids don't count.
2586
+ *
2587
+ * @example
2588
+ * ```typescript
2589
+ * // Clear a specific set of ids
2590
+ * const { cleared } = await sendly.contacts.bulkMarkValid({
2591
+ * ids: ['cnt_abc', 'cnt_def', 'cnt_ghi'],
2592
+ * });
2593
+ *
2594
+ * // Clear every flagged member of a list
2595
+ * await sendly.contacts.bulkMarkValid({ listId: 'lst_xxx' });
2596
+ * ```
2597
+ */
2598
+ async bulkMarkValid(options) {
2599
+ if (!options.ids && !options.listId) {
2600
+ throw new Error("bulkMarkValid requires either 'ids' or 'listId'");
2601
+ }
2602
+ if (options.ids && options.listId) {
2603
+ throw new Error("bulkMarkValid accepts 'ids' OR 'listId', not both");
2604
+ }
2605
+ return this.http.request({
2606
+ method: "POST",
2607
+ path: "/contacts/bulk-mark-valid",
2608
+ body: options.ids ? { ids: options.ids } : { listId: options.listId }
2609
+ });
2610
+ }
2611
+ /**
2612
+ * Trigger a background carrier lookup across your contacts. Landlines and
2613
+ * other non-SMS-capable numbers are auto-excluded from future campaigns.
2614
+ *
2615
+ * The lookup runs asynchronously and takes 1–5 minutes depending on list
2616
+ * size. Results populate the `lineType`, `carrierName`, and `invalidReason`
2617
+ * fields on affected contacts — fetch the contact again after a few minutes
2618
+ * to see updated state.
2619
+ *
2620
+ * Idempotent: re-triggering while a lookup is already running for the same
2621
+ * scope is a no-op.
2622
+ *
2623
+ * @param options - Optional: scope to a single list, or force re-check
2624
+ * @returns Acknowledgement
2625
+ *
2626
+ * @example
2627
+ * ```typescript
2628
+ * // Check all un-checked contacts
2629
+ * await sendly.contacts.checkNumbers();
2630
+ *
2631
+ * // Check a specific list only
2632
+ * await sendly.contacts.checkNumbers({ listId: 'lst_xxx' });
2633
+ *
2634
+ * // Re-check contacts even if previously looked up
2635
+ * await sendly.contacts.checkNumbers({ force: true });
2636
+ * ```
2637
+ */
2638
+ async checkNumbers(options = {}) {
2639
+ return this.http.request({
2640
+ method: "POST",
2641
+ path: "/contacts/lookup",
2642
+ body: {
2643
+ listId: options.listId ?? null,
2644
+ force: options.force ?? false
2645
+ }
2646
+ });
2647
+ }
2553
2648
  transformContact(raw) {
2649
+ const r = raw;
2554
2650
  return {
2555
2651
  id: raw.id,
2556
- phoneNumber: raw.phone_number,
2652
+ phoneNumber: raw.phone_number ?? r.phoneNumber,
2557
2653
  name: raw.name,
2558
2654
  email: raw.email,
2559
2655
  metadata: raw.metadata,
2560
- optedOut: raw.opted_out,
2561
- createdAt: raw.created_at,
2562
- updatedAt: raw.updated_at,
2656
+ optedOut: raw.opted_out ?? r.optedOut,
2657
+ lineType: raw.line_type ?? r.lineType ?? null,
2658
+ carrierName: raw.carrier_name ?? r.carrierName ?? null,
2659
+ lineTypeCheckedAt: raw.line_type_checked_at ?? r.lineTypeCheckedAt ?? null,
2660
+ invalidReason: raw.invalid_reason ?? r.invalidReason ?? null,
2661
+ invalidatedAt: raw.invalidated_at ?? r.invalidatedAt ?? null,
2662
+ userMarkedValidAt: raw.user_marked_valid_at ?? r.userMarkedValidAt ?? null,
2663
+ createdAt: raw.created_at ?? r.createdAt,
2664
+ updatedAt: raw.updated_at ?? r.updatedAt,
2563
2665
  lists: raw.lists?.map((l) => ({ id: l.id, name: l.name }))
2564
2666
  };
2565
2667
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sendly/node",
3
- "version": "3.27.1",
3
+ "version": "3.29.0",
4
4
  "description": "Official Sendly Node.js SDK for SMS messaging",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",