@sendly/node 3.8.1 → 3.9.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.mjs CHANGED
@@ -1462,6 +1462,397 @@ var AccountResource = class {
1462
1462
  }
1463
1463
  };
1464
1464
 
1465
+ // src/resources/verify.ts
1466
+ var VerifyResource = class {
1467
+ http;
1468
+ constructor(http) {
1469
+ this.http = http;
1470
+ }
1471
+ /**
1472
+ * Send an OTP verification code
1473
+ *
1474
+ * @param request - Verification request details
1475
+ * @returns The created verification with ID and expiry
1476
+ *
1477
+ * @example
1478
+ * ```typescript
1479
+ * // Basic usage
1480
+ * const verification = await sendly.verify.send({
1481
+ * to: '+15551234567'
1482
+ * });
1483
+ *
1484
+ * // With custom options
1485
+ * const verification = await sendly.verify.send({
1486
+ * to: '+15551234567',
1487
+ * appName: 'MyApp',
1488
+ * codeLength: 8,
1489
+ * timeoutSecs: 600
1490
+ * });
1491
+ *
1492
+ * // In sandbox mode, the code is returned for testing
1493
+ * if (verification.sandboxCode) {
1494
+ * console.log('Test code:', verification.sandboxCode);
1495
+ * }
1496
+ * ```
1497
+ */
1498
+ async send(request) {
1499
+ validatePhoneNumber(request.to);
1500
+ const response = await this.http.request({
1501
+ method: "POST",
1502
+ path: "/verify",
1503
+ body: {
1504
+ to: request.to,
1505
+ ...request.templateId && { template_id: request.templateId },
1506
+ ...request.profileId && { profile_id: request.profileId },
1507
+ ...request.appName && { app_name: request.appName },
1508
+ ...request.timeoutSecs && { timeout_secs: request.timeoutSecs },
1509
+ ...request.codeLength && { code_length: request.codeLength }
1510
+ }
1511
+ });
1512
+ return {
1513
+ id: response.id,
1514
+ status: response.status,
1515
+ phone: response.phone,
1516
+ expiresAt: response.expires_at,
1517
+ sandbox: response.sandbox,
1518
+ sandboxCode: response.sandbox_code,
1519
+ message: response.message
1520
+ };
1521
+ }
1522
+ /**
1523
+ * Check/verify an OTP code
1524
+ *
1525
+ * @param id - Verification ID
1526
+ * @param request - The code to verify
1527
+ * @returns Verification result
1528
+ *
1529
+ * @example
1530
+ * ```typescript
1531
+ * const result = await sendly.verify.check('ver_xxx', {
1532
+ * code: '123456'
1533
+ * });
1534
+ *
1535
+ * if (result.status === 'verified') {
1536
+ * // User is verified
1537
+ * } else if (result.remainingAttempts !== undefined) {
1538
+ * console.log(`Wrong code. ${result.remainingAttempts} attempts remaining`);
1539
+ * }
1540
+ * ```
1541
+ */
1542
+ async check(id, request) {
1543
+ const response = await this.http.request({
1544
+ method: "POST",
1545
+ path: `/verify/${id}/check`,
1546
+ body: { code: request.code }
1547
+ });
1548
+ return {
1549
+ id: response.id,
1550
+ status: response.status,
1551
+ phone: response.phone,
1552
+ verifiedAt: response.verified_at,
1553
+ remainingAttempts: response.remaining_attempts
1554
+ };
1555
+ }
1556
+ /**
1557
+ * Get a verification by ID
1558
+ *
1559
+ * @param id - Verification ID
1560
+ * @returns The verification record
1561
+ *
1562
+ * @example
1563
+ * ```typescript
1564
+ * const verification = await sendly.verify.get('ver_xxx');
1565
+ * console.log(verification.status); // 'pending', 'verified', 'expired', etc.
1566
+ * ```
1567
+ */
1568
+ async get(id) {
1569
+ const response = await this.http.request({
1570
+ method: "GET",
1571
+ path: `/verify/${id}`
1572
+ });
1573
+ return {
1574
+ id: response.id,
1575
+ status: response.status,
1576
+ phone: response.phone,
1577
+ deliveryStatus: response.delivery_status,
1578
+ attempts: response.attempts,
1579
+ maxAttempts: response.max_attempts,
1580
+ expiresAt: response.expires_at,
1581
+ verifiedAt: response.verified_at,
1582
+ createdAt: response.created_at,
1583
+ sandbox: response.sandbox,
1584
+ appName: response.app_name,
1585
+ templateId: response.template_id,
1586
+ profileId: response.profile_id
1587
+ };
1588
+ }
1589
+ /**
1590
+ * List recent verifications
1591
+ *
1592
+ * @param options - Filter and pagination options
1593
+ * @returns List of verifications
1594
+ *
1595
+ * @example
1596
+ * ```typescript
1597
+ * // List recent verifications
1598
+ * const { verifications } = await sendly.verify.list({ limit: 10 });
1599
+ *
1600
+ * // Filter by status
1601
+ * const { verifications } = await sendly.verify.list({
1602
+ * status: 'verified'
1603
+ * });
1604
+ * ```
1605
+ */
1606
+ async list(options = {}) {
1607
+ const response = await this.http.request({
1608
+ method: "GET",
1609
+ path: "/verify",
1610
+ query: {
1611
+ ...options.limit && { limit: options.limit },
1612
+ ...options.status && { status: options.status }
1613
+ }
1614
+ });
1615
+ return {
1616
+ verifications: response.verifications.map((v) => ({
1617
+ id: v.id,
1618
+ status: v.status,
1619
+ phone: v.phone,
1620
+ deliveryStatus: v.delivery_status,
1621
+ attempts: v.attempts,
1622
+ maxAttempts: v.max_attempts,
1623
+ expiresAt: v.expires_at,
1624
+ verifiedAt: v.verified_at,
1625
+ createdAt: v.created_at,
1626
+ sandbox: v.sandbox,
1627
+ appName: v.app_name,
1628
+ templateId: v.template_id,
1629
+ profileId: v.profile_id
1630
+ })),
1631
+ pagination: {
1632
+ limit: response.pagination.limit,
1633
+ hasMore: response.pagination.has_more
1634
+ }
1635
+ };
1636
+ }
1637
+ };
1638
+
1639
+ // src/resources/templates.ts
1640
+ var TemplatesResource = class {
1641
+ http;
1642
+ constructor(http) {
1643
+ this.http = http;
1644
+ }
1645
+ /**
1646
+ * List all templates (presets + custom)
1647
+ *
1648
+ * @returns List of templates
1649
+ *
1650
+ * @example
1651
+ * ```typescript
1652
+ * const { templates } = await sendly.templates.list();
1653
+ * templates.forEach(t => {
1654
+ * console.log(`${t.name}: ${t.isPreset ? 'preset' : t.status}`);
1655
+ * });
1656
+ * ```
1657
+ */
1658
+ async list() {
1659
+ const response = await this.http.request({
1660
+ method: "GET",
1661
+ path: "/templates"
1662
+ });
1663
+ return {
1664
+ templates: response.templates.map((t) => this.transformTemplate(t))
1665
+ };
1666
+ }
1667
+ /**
1668
+ * List preset templates only (no auth required)
1669
+ *
1670
+ * @returns List of preset templates
1671
+ *
1672
+ * @example
1673
+ * ```typescript
1674
+ * const { templates } = await sendly.templates.presets();
1675
+ * // Returns: otp, 2fa, login, signup, reset, generic
1676
+ * ```
1677
+ */
1678
+ async presets() {
1679
+ const response = await this.http.request({
1680
+ method: "GET",
1681
+ path: "/templates/presets"
1682
+ });
1683
+ return {
1684
+ templates: response.templates.map((t) => this.transformTemplate(t))
1685
+ };
1686
+ }
1687
+ /**
1688
+ * Get a template by ID
1689
+ *
1690
+ * @param id - Template ID
1691
+ * @returns The template
1692
+ *
1693
+ * @example
1694
+ * ```typescript
1695
+ * const template = await sendly.templates.get('tpl_preset_otp');
1696
+ * console.log(template.text); // "Your {{app_name}} code is {{code}}"
1697
+ * ```
1698
+ */
1699
+ async get(id) {
1700
+ const response = await this.http.request({
1701
+ method: "GET",
1702
+ path: `/templates/${id}`
1703
+ });
1704
+ return this.transformTemplate(response);
1705
+ }
1706
+ /**
1707
+ * Create a new template
1708
+ *
1709
+ * @param request - Template details
1710
+ * @returns The created template (as draft)
1711
+ *
1712
+ * @example
1713
+ * ```typescript
1714
+ * const template = await sendly.templates.create({
1715
+ * name: 'Password Reset',
1716
+ * text: '{{app_name}}: Your password reset code is {{code}}. Valid for 10 minutes.'
1717
+ * });
1718
+ *
1719
+ * // Template is created as draft, publish when ready
1720
+ * await sendly.templates.publish(template.id);
1721
+ * ```
1722
+ */
1723
+ async create(request) {
1724
+ const response = await this.http.request({
1725
+ method: "POST",
1726
+ path: "/templates",
1727
+ body: {
1728
+ name: request.name,
1729
+ text: request.text
1730
+ }
1731
+ });
1732
+ return this.transformTemplate(response);
1733
+ }
1734
+ /**
1735
+ * Update a template
1736
+ *
1737
+ * Note: Updating a published template creates a new draft version.
1738
+ *
1739
+ * @param id - Template ID
1740
+ * @param request - Fields to update
1741
+ * @returns The updated template
1742
+ *
1743
+ * @example
1744
+ * ```typescript
1745
+ * const template = await sendly.templates.update('tpl_xxx', {
1746
+ * text: 'New message text with {{code}}'
1747
+ * });
1748
+ * ```
1749
+ */
1750
+ async update(id, request) {
1751
+ const response = await this.http.request({
1752
+ method: "PATCH",
1753
+ path: `/templates/${id}`,
1754
+ body: {
1755
+ ...request.name && { name: request.name },
1756
+ ...request.text && { text: request.text }
1757
+ }
1758
+ });
1759
+ return this.transformTemplate(response);
1760
+ }
1761
+ /**
1762
+ * Publish a draft template
1763
+ *
1764
+ * Published templates are locked and can be used with the Verify API.
1765
+ *
1766
+ * @param id - Template ID
1767
+ * @returns The published template
1768
+ *
1769
+ * @example
1770
+ * ```typescript
1771
+ * const template = await sendly.templates.publish('tpl_xxx');
1772
+ * console.log(template.status); // 'published'
1773
+ * ```
1774
+ */
1775
+ async publish(id) {
1776
+ const response = await this.http.request({
1777
+ method: "POST",
1778
+ path: `/templates/${id}/publish`
1779
+ });
1780
+ return this.transformTemplate(response);
1781
+ }
1782
+ /**
1783
+ * Preview a template with sample values
1784
+ *
1785
+ * @param id - Template ID
1786
+ * @param variables - Optional custom variable values
1787
+ * @returns Template with interpolated preview text
1788
+ *
1789
+ * @example
1790
+ * ```typescript
1791
+ * const preview = await sendly.templates.preview('tpl_preset_otp', {
1792
+ * app_name: 'MyApp',
1793
+ * code: '123456'
1794
+ * });
1795
+ * console.log(preview.previewText);
1796
+ * // "Your MyApp code is 123456"
1797
+ * ```
1798
+ */
1799
+ async preview(id, variables) {
1800
+ const response = await this.http.request({
1801
+ method: "POST",
1802
+ path: `/templates/${id}/preview`,
1803
+ body: variables ? { variables } : {}
1804
+ });
1805
+ return {
1806
+ id: response.id,
1807
+ name: response.name,
1808
+ originalText: response.original_text,
1809
+ previewText: response.preview_text,
1810
+ variables: response.variables.map((v) => ({
1811
+ key: v.key,
1812
+ type: v.type,
1813
+ fallback: v.fallback
1814
+ }))
1815
+ };
1816
+ }
1817
+ /**
1818
+ * Delete a template
1819
+ *
1820
+ * Note: Preset templates cannot be deleted.
1821
+ *
1822
+ * @param id - Template ID
1823
+ *
1824
+ * @example
1825
+ * ```typescript
1826
+ * await sendly.templates.delete('tpl_xxx');
1827
+ * ```
1828
+ */
1829
+ async delete(id) {
1830
+ await this.http.request({
1831
+ method: "DELETE",
1832
+ path: `/templates/${id}`
1833
+ });
1834
+ }
1835
+ transformTemplate(t) {
1836
+ return {
1837
+ id: t.id,
1838
+ name: t.name,
1839
+ text: t.text,
1840
+ variables: t.variables.map((v) => ({
1841
+ key: v.key,
1842
+ type: v.type,
1843
+ fallback: v.fallback
1844
+ })),
1845
+ isPreset: t.is_preset,
1846
+ presetSlug: t.preset_slug,
1847
+ status: t.status,
1848
+ version: t.version,
1849
+ publishedAt: t.published_at,
1850
+ createdAt: t.created_at,
1851
+ updatedAt: t.updated_at
1852
+ };
1853
+ }
1854
+ };
1855
+
1465
1856
  // src/client.ts
1466
1857
  var DEFAULT_BASE_URL2 = "https://sendly.live/api/v1";
1467
1858
  var DEFAULT_TIMEOUT2 = 3e4;
@@ -1518,6 +1909,47 @@ var Sendly = class {
1518
1909
  * ```
1519
1910
  */
1520
1911
  account;
1912
+ /**
1913
+ * Verify API resource - OTP verification
1914
+ *
1915
+ * @example
1916
+ * ```typescript
1917
+ * // Send an OTP
1918
+ * const verification = await sendly.verify.send({
1919
+ * to: '+15551234567',
1920
+ * appName: 'MyApp'
1921
+ * });
1922
+ *
1923
+ * // Check the OTP (user enters code)
1924
+ * const result = await sendly.verify.check(verification.id, {
1925
+ * code: '123456'
1926
+ * });
1927
+ *
1928
+ * if (result.status === 'verified') {
1929
+ * console.log('Phone verified!');
1930
+ * }
1931
+ * ```
1932
+ */
1933
+ verify;
1934
+ /**
1935
+ * Templates API resource - SMS template management
1936
+ *
1937
+ * @example
1938
+ * ```typescript
1939
+ * // List preset templates
1940
+ * const { templates } = await sendly.templates.presets();
1941
+ *
1942
+ * // Create a custom template
1943
+ * const template = await sendly.templates.create({
1944
+ * name: 'My OTP',
1945
+ * text: 'Your {{app_name}} code is {{code}}'
1946
+ * });
1947
+ *
1948
+ * // Publish for use
1949
+ * await sendly.templates.publish(template.id);
1950
+ * ```
1951
+ */
1952
+ templates;
1521
1953
  http;
1522
1954
  config;
1523
1955
  /**
@@ -1550,6 +1982,8 @@ var Sendly = class {
1550
1982
  this.messages = new MessagesResource(this.http);
1551
1983
  this.webhooks = new WebhooksResource(this.http);
1552
1984
  this.account = new AccountResource(this.http);
1985
+ this.verify = new VerifyResource(this.http);
1986
+ this.templates = new TemplatesResource(this.http);
1553
1987
  }
1554
1988
  /**
1555
1989
  * Check if the client is using a test API key
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sendly/node",
3
- "version": "3.8.1",
3
+ "version": "3.9.0",
4
4
  "description": "Official Sendly Node.js SDK for SMS messaging",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -36,11 +36,11 @@
36
36
  "license": "MIT",
37
37
  "repository": {
38
38
  "type": "git",
39
- "url": "https://github.com/sendly-live/sendly-node.git"
39
+ "url": "https://github.com/SendlyHQ/sendly-node.git"
40
40
  },
41
41
  "homepage": "https://sendly.live/docs",
42
42
  "bugs": {
43
- "url": "https://github.com/sendly-live/sendly-node/issues"
43
+ "url": "https://github.com/SendlyHQ/sendly-node/issues"
44
44
  },
45
45
  "engines": {
46
46
  "node": ">=18.0.0"