@isnap/sdk 1.3.0 → 1.4.0-next.203
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/CHANGELOG.md +10 -0
- package/README.md +1 -1
- package/dist/client.d.ts +2 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +3 -0
- package/dist/client.js.map +1 -1
- package/dist/generated/openapi.d.ts +1784 -346
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/resources/apps.d.ts +11 -4
- package/dist/resources/apps.d.ts.map +1 -1
- package/dist/resources/apps.js +11 -4
- package/dist/resources/apps.js.map +1 -1
- package/dist/resources/lines.d.ts +206 -6
- package/dist/resources/lines.d.ts.map +1 -1
- package/dist/resources/lines.js +215 -6
- package/dist/resources/lines.js.map +1 -1
- package/dist/resources/macos-sessions.d.ts +48 -0
- package/dist/resources/macos-sessions.d.ts.map +1 -0
- package/dist/resources/macos-sessions.js +51 -0
- package/dist/resources/macos-sessions.js.map +1 -0
- package/dist/resources/preorders.d.ts +19 -7
- package/dist/resources/preorders.d.ts.map +1 -1
- package/dist/resources/preorders.js +19 -7
- package/dist/resources/preorders.js.map +1 -1
- package/dist/resources/webhooks.d.ts +1 -1
- package/dist/resources/webhooks.js +1 -1
- package/dist/version.d.ts +2 -2
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +13 -5
- package/dist/version.js.map +1 -1
- package/dist/webhooks/types.d.ts +46 -3
- package/dist/webhooks/types.d.ts.map +1 -1
- package/dist/webhooks/types.js +3 -0
- package/dist/webhooks/types.js.map +1 -1
- package/dist/webhooks/verify.d.ts +22 -9
- package/dist/webhooks/verify.d.ts.map +1 -1
- package/dist/webhooks/verify.js +101 -29
- package/dist/webhooks/verify.js.map +1 -1
- package/package.json +1 -1
|
@@ -387,7 +387,7 @@ export interface paths {
|
|
|
387
387
|
};
|
|
388
388
|
/**
|
|
389
389
|
* List available lines (public marketplace)
|
|
390
|
-
* @description Browse the marketplace inventory of unassigned lines. Filter by billing tier, area code, country code,
|
|
390
|
+
* @description Browse the marketplace inventory of unassigned lines. Filter by billing tier, area code, country code, state, country. Returns only `status: available` and never the iSnap-internal `shared_pool` tier — `?status=` therefore accepts `available` alone and refuses any other status with a 400, rather than answering with a list you did not ask for (WHA-2777). Unauthenticated — partners use this in prospecting / quote flows.
|
|
391
391
|
*/
|
|
392
392
|
get: {
|
|
393
393
|
parameters: {
|
|
@@ -399,6 +399,7 @@ export interface paths {
|
|
|
399
399
|
state?: string;
|
|
400
400
|
/** @description Country filter — ISO alpha-2 code or country name. */
|
|
401
401
|
country?: string;
|
|
402
|
+
/** @description Comma-separated set of statuses to filter on. Every member must be one of: available — anything else is a 400, never an empty list. Omitted or blank means no status filter. */
|
|
402
403
|
status?: string;
|
|
403
404
|
page?: number;
|
|
404
405
|
limit?: number;
|
|
@@ -551,7 +552,7 @@ export interface paths {
|
|
|
551
552
|
};
|
|
552
553
|
/**
|
|
553
554
|
* Get line details (public marketplace)
|
|
554
|
-
* @description Fetch a single line by its `line_<base62>` id. Available unauthenticated for the marketplace browsing flow
|
|
555
|
+
* @description Fetch a single line by its `line_<base62>` id. Available unauthenticated for the marketplace browsing flow, where the `phone_number` is masked so the inventory cannot be scraped. Authenticate with your API key (or dashboard JWT) and, when you own the line, the `phone_number` comes back unmasked — the same full number `GET /v1/lines/my` returns (WHA-3030). A credential that does not own the line, or none at all, still gets the masked number.
|
|
555
556
|
*/
|
|
556
557
|
get: {
|
|
557
558
|
parameters: {
|
|
@@ -623,8 +624,8 @@ export interface paths {
|
|
|
623
624
|
options?: never;
|
|
624
625
|
head?: never;
|
|
625
626
|
/**
|
|
626
|
-
* Update line
|
|
627
|
-
* @description
|
|
627
|
+
* Update a line
|
|
628
|
+
* @description Update the line's free-form `metadata` tag object, its billing anchor, or both. **`metadata`** is a MERGE-patch: pass `null` for a key to delete it, a new value to overwrite. It is echoed on every `line.*` webhook so partners can attribute events back to their own customer IDs. **`billing_anchor_at`** is the date the customer who pays for this line is billed on: a change takes effect at the NEXT occurrence and never rewrites a period already billed, and `null` clears it so the line falls back to its activation instant. Send at least one of the two — a body that sets neither is refused with `no_fields_to_patch`.
|
|
628
629
|
*/
|
|
629
630
|
patch: {
|
|
630
631
|
parameters: {
|
|
@@ -1059,7 +1060,7 @@ export interface paths {
|
|
|
1059
1060
|
put?: never;
|
|
1060
1061
|
/**
|
|
1061
1062
|
* Activate a reserved line
|
|
1062
|
-
* @description Commit a `reserved` line to `active`. Wholesale partners (no Stripe checkout surface)
|
|
1063
|
+
* @description Commit a `reserved` line to `active`. **Wholesale partners only** (no Stripe checkout surface): this is the second phase of reserve→activate — they reserve, bill their own end-user, then activate within the 15-minute window with no per-line Stripe sub (EOM-metered), and may pick the INBOUND product via `inbound_only` (a line that cannot initiate — the contact must message first, after which the exchange is unrestricted; not receive-only). Pass `billing_anchor_at` to bill this line on the date your own customer is billed on rather than on its activation instant — one full month at each occurrence, with a credit at the first one for the days the activation month had already paid for past it. Direct customers get `402 checkout_required`: their line is activated by the `checkout.session.completed` webhook once `POST /v1/billing/checkout` is paid, which is what mints the Stripe subscription that bills them (§2.5 Flow A). `inbound_only` is meaningless for them — theirs comes from the checkout price.
|
|
1063
1064
|
*/
|
|
1064
1065
|
post: {
|
|
1065
1066
|
parameters: {
|
|
@@ -1109,6 +1110,15 @@ export interface paths {
|
|
|
1109
1110
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
1110
1111
|
};
|
|
1111
1112
|
};
|
|
1113
|
+
/** @description Payment required — no billing relationship entitles this call */
|
|
1114
|
+
402: {
|
|
1115
|
+
headers: {
|
|
1116
|
+
[name: string]: unknown;
|
|
1117
|
+
};
|
|
1118
|
+
content: {
|
|
1119
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
1120
|
+
};
|
|
1121
|
+
};
|
|
1112
1122
|
/** @description Forbidden — caller authenticated but not allowed */
|
|
1113
1123
|
403: {
|
|
1114
1124
|
headers: {
|
|
@@ -1496,7 +1506,7 @@ export interface paths {
|
|
|
1496
1506
|
patch?: never;
|
|
1497
1507
|
trace?: never;
|
|
1498
1508
|
};
|
|
1499
|
-
"/v1/lines/{id}/
|
|
1509
|
+
"/v1/lines/{id}/variant": {
|
|
1500
1510
|
parameters: {
|
|
1501
1511
|
query?: never;
|
|
1502
1512
|
header?: never;
|
|
@@ -1506,8 +1516,8 @@ export interface paths {
|
|
|
1506
1516
|
get?: never;
|
|
1507
1517
|
put?: never;
|
|
1508
1518
|
/**
|
|
1509
|
-
*
|
|
1510
|
-
* @description
|
|
1519
|
+
* Switch a rental line between inbound-only and two-way
|
|
1520
|
+
* @description Move a rental line you own between the INBOUND product (`inbound_only: true` — the line may only message a handle that has messaged it first; it is NOT receive-only) and the TWO-WAY product, **keeping the same phone number, hardware and device session**. `effective` says WHEN: `now` (the default, and the only behaviour before the field existed) applies it to the very next send; `next_anchor` stores it against the line's next billing anchor, leaves `inbound_only` alone, and surfaces the change as `pending_variant` on the line — which is what a DOWNGRADE needs, so the customer keeps the product they have already paid for through the month. Idempotent on the value in both modes: asking for the variant the line already has (or re-scheduling the change already pending) returns 200 and writes nothing. **A scheduled call can therefore legitimately answer `pending_variant: null`** — scheduling the variant the line ALREADY carries writes nothing, because nothing is pending: the line will still be on that variant at the anchor. That is a truthful 200, not a failure. Tell it apart from a dropped-field failure by reading the top-level `inbound_only`: equal to what you asked for means already-at-target; different means your `effective` never reached this endpoint and the change was applied immediately. `not_before` (optional ISO instant, `next_anchor` only, default now) is the earliest instant the change may take effect; iSnap schedules it at the first anchor occurrence AT OR AFTER it, so a quarterly or annual customer keeps their product for the whole period they paid for instead of losing it at the next anchor. A `not_before` in the past is refused with `400 not_before_in_the_past` rather than clamped. Refused with 409 on a non-rental line (`not_a_rental_line`), on a line that is not `active` (`line_not_active`), on a line carrying an iSnap Stripe subscription (`variant_bound_to_stripe_price`) — there the subscription's price is the variant and changing the subscription is how it moves — and, when scheduling, on a line that already has a DIFFERENT change pending (`variant_change_already_pending`; cancel it first). Emits `line.variant_changed` on an immediate change and `line.variant_scheduled` on a scheduled one.
|
|
1511
1521
|
*/
|
|
1512
1522
|
post: {
|
|
1513
1523
|
parameters: {
|
|
@@ -1518,9 +1528,13 @@ export interface paths {
|
|
|
1518
1528
|
};
|
|
1519
1529
|
cookie?: never;
|
|
1520
1530
|
};
|
|
1521
|
-
requestBody?:
|
|
1531
|
+
requestBody?: {
|
|
1532
|
+
content: {
|
|
1533
|
+
"application/json": components["schemas"]["SetLineVariant"];
|
|
1534
|
+
};
|
|
1535
|
+
};
|
|
1522
1536
|
responses: {
|
|
1523
|
-
/** @description Line
|
|
1537
|
+
/** @description Line. With `effective: "now"` its `inbound_only` reflects the requested variant; with `effective: "next_anchor"` `inbound_only` is unchanged and `pending_variant` carries the requested variant and the date it applies. */
|
|
1524
1538
|
200: {
|
|
1525
1539
|
headers: {
|
|
1526
1540
|
[name: string]: unknown;
|
|
@@ -1571,6 +1585,15 @@ export interface paths {
|
|
|
1571
1585
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
1572
1586
|
};
|
|
1573
1587
|
};
|
|
1588
|
+
/** @description Conflict — concurrent or terminal state */
|
|
1589
|
+
409: {
|
|
1590
|
+
headers: {
|
|
1591
|
+
[name: string]: unknown;
|
|
1592
|
+
};
|
|
1593
|
+
content: {
|
|
1594
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
1595
|
+
};
|
|
1596
|
+
};
|
|
1574
1597
|
/** @description Too many requests — rate limit exceeded */
|
|
1575
1598
|
429: {
|
|
1576
1599
|
headers: {
|
|
@@ -1591,24 +1614,11 @@ export interface paths {
|
|
|
1591
1614
|
};
|
|
1592
1615
|
};
|
|
1593
1616
|
};
|
|
1594
|
-
delete?: never;
|
|
1595
|
-
options?: never;
|
|
1596
|
-
head?: never;
|
|
1597
|
-
patch?: never;
|
|
1598
|
-
trace?: never;
|
|
1599
|
-
};
|
|
1600
|
-
"/v1/lines/{id}/quota": {
|
|
1601
|
-
parameters: {
|
|
1602
|
-
query?: never;
|
|
1603
|
-
header?: never;
|
|
1604
|
-
path?: never;
|
|
1605
|
-
cookie?: never;
|
|
1606
|
-
};
|
|
1607
1617
|
/**
|
|
1608
|
-
*
|
|
1609
|
-
* @description
|
|
1618
|
+
* Cancel a scheduled variant change
|
|
1619
|
+
* @description Call off the variant change scheduled for this line's next billing anchor (`POST /v1/lines/{id}/variant` with `effective: 'next_anchor'`). The line's live `inbound_only` is never touched by this call — it was never moved by the scheduling either — so the only effect is that `pending_variant` becomes `null` and nothing happens at the anchor. Answers `404 no_pending_variant_change` when the line carries no pending change, which includes a change the anchor has already applied; a change applied while this request was in flight is `409 variant_change_already_applied`. Succeeds on a suspended or cancelled line: withdrawing an instruction must never be blocked by the state that made it moot. Emits `line.variant_unscheduled`.
|
|
1610
1620
|
*/
|
|
1611
|
-
|
|
1621
|
+
delete: {
|
|
1612
1622
|
parameters: {
|
|
1613
1623
|
query?: never;
|
|
1614
1624
|
header?: never;
|
|
@@ -1619,14 +1629,12 @@ export interface paths {
|
|
|
1619
1629
|
};
|
|
1620
1630
|
requestBody?: never;
|
|
1621
1631
|
responses: {
|
|
1622
|
-
/** @description
|
|
1623
|
-
|
|
1632
|
+
/** @description Scheduled variant change cancelled */
|
|
1633
|
+
204: {
|
|
1624
1634
|
headers: {
|
|
1625
1635
|
[name: string]: unknown;
|
|
1626
1636
|
};
|
|
1627
|
-
content
|
|
1628
|
-
"application/json": components["schemas"]["QuotaEnvelope"];
|
|
1629
|
-
};
|
|
1637
|
+
content?: never;
|
|
1630
1638
|
};
|
|
1631
1639
|
/** @description Bad request — validation failed */
|
|
1632
1640
|
400: {
|
|
@@ -1664,6 +1672,15 @@ export interface paths {
|
|
|
1664
1672
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
1665
1673
|
};
|
|
1666
1674
|
};
|
|
1675
|
+
/** @description Conflict — concurrent or terminal state */
|
|
1676
|
+
409: {
|
|
1677
|
+
headers: {
|
|
1678
|
+
[name: string]: unknown;
|
|
1679
|
+
};
|
|
1680
|
+
content: {
|
|
1681
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
1682
|
+
};
|
|
1683
|
+
};
|
|
1667
1684
|
/** @description Too many requests — rate limit exceeded */
|
|
1668
1685
|
429: {
|
|
1669
1686
|
headers: {
|
|
@@ -1684,47 +1701,52 @@ export interface paths {
|
|
|
1684
1701
|
};
|
|
1685
1702
|
};
|
|
1686
1703
|
};
|
|
1687
|
-
put?: never;
|
|
1688
|
-
post?: never;
|
|
1689
|
-
delete?: never;
|
|
1690
1704
|
options?: never;
|
|
1691
1705
|
head?: never;
|
|
1692
1706
|
patch?: never;
|
|
1693
1707
|
trace?: never;
|
|
1694
1708
|
};
|
|
1695
|
-
"/v1/lines/{id}/
|
|
1709
|
+
"/v1/lines/{id}/terminate": {
|
|
1696
1710
|
parameters: {
|
|
1697
1711
|
query?: never;
|
|
1698
1712
|
header?: never;
|
|
1699
1713
|
path?: never;
|
|
1700
1714
|
cookie?: never;
|
|
1701
1715
|
};
|
|
1716
|
+
get?: never;
|
|
1717
|
+
put?: never;
|
|
1702
1718
|
/**
|
|
1703
|
-
*
|
|
1704
|
-
* @description
|
|
1719
|
+
* Terminate a line you own
|
|
1720
|
+
* @description Permanently END an active line the caller owns — the self-serve counterpart to the admin terminate. Use this when your own customer cancels: `/release` only returns a *reserved* marketplace line to the shelf, while this ends a live `rental` line or a virtual `shared` line for good. The line flips to the terminal `cancelled` status and keeps its owner (who held it when it died is history, not a shelf return); queued messages fail with `carrier_terminated`, shared-fleet bindings are released (`binding.released`), device sessions are revoked, and `line.disconnected` fires with `reason: customer_initiated`. Billing stops in both shapes: a per-line Stripe subscription is cancelled immediately (not at period end), and a wholesale partner's end-of-month active-line count drops the line in the same breath. Dedicated hardware goes back to iSnap stock — the eSIM and Apple ID are recycled, never scrapped, because a customer ending a rental says nothing about whether the carrier plan is still good. **Idempotent**: terminating an already-terminated line returns 200 with the line unchanged and fires nothing a second time. Only an `active` or `suspended` line — the ones you are actually being billed for — is terminable: a merely `reserved` line is a 15-minute hold you give back with `/release`, and a `provisioning` pre-order line is cancelled through `/v1/pre-orders/{id}/cancel`. BYOD lines are refused (400) — that hardware is yours and is billed per device slot by `/v1/byod/*`; owned test lines are refused (403) until converted back with `/convert-from-test`.
|
|
1705
1721
|
*/
|
|
1706
|
-
|
|
1722
|
+
post: {
|
|
1707
1723
|
parameters: {
|
|
1708
|
-
query?:
|
|
1709
|
-
limit?: number;
|
|
1710
|
-
cursor?: string;
|
|
1711
|
-
status?: "queued" | "scheduled" | "delivered_to_device";
|
|
1712
|
-
};
|
|
1724
|
+
query?: never;
|
|
1713
1725
|
header?: never;
|
|
1714
1726
|
path: {
|
|
1715
1727
|
id: string;
|
|
1716
1728
|
};
|
|
1717
1729
|
cookie?: never;
|
|
1718
1730
|
};
|
|
1719
|
-
requestBody?:
|
|
1731
|
+
requestBody?: {
|
|
1732
|
+
content: {
|
|
1733
|
+
"application/json": components["schemas"]["TerminateLine"];
|
|
1734
|
+
};
|
|
1735
|
+
};
|
|
1720
1736
|
responses: {
|
|
1721
|
-
/** @description
|
|
1737
|
+
/** @description Line terminated (or already terminated — the call is idempotent). Returns the line at its terminal `cancelled` status. */
|
|
1722
1738
|
200: {
|
|
1723
1739
|
headers: {
|
|
1724
1740
|
[name: string]: unknown;
|
|
1725
1741
|
};
|
|
1726
1742
|
content: {
|
|
1727
|
-
"application/json":
|
|
1743
|
+
"application/json": {
|
|
1744
|
+
/** @enum {boolean} */
|
|
1745
|
+
success: true;
|
|
1746
|
+
data: components["schemas"]["Line"];
|
|
1747
|
+
trace_id: string;
|
|
1748
|
+
request_id: string;
|
|
1749
|
+
};
|
|
1728
1750
|
};
|
|
1729
1751
|
};
|
|
1730
1752
|
/** @description Bad request — validation failed */
|
|
@@ -1763,6 +1785,15 @@ export interface paths {
|
|
|
1763
1785
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
1764
1786
|
};
|
|
1765
1787
|
};
|
|
1788
|
+
/** @description Conflict — concurrent or terminal state */
|
|
1789
|
+
409: {
|
|
1790
|
+
headers: {
|
|
1791
|
+
[name: string]: unknown;
|
|
1792
|
+
};
|
|
1793
|
+
content: {
|
|
1794
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
1795
|
+
};
|
|
1796
|
+
};
|
|
1766
1797
|
/** @description Too many requests — rate limit exceeded */
|
|
1767
1798
|
429: {
|
|
1768
1799
|
headers: {
|
|
@@ -1783,26 +1814,26 @@ export interface paths {
|
|
|
1783
1814
|
};
|
|
1784
1815
|
};
|
|
1785
1816
|
};
|
|
1786
|
-
put?: never;
|
|
1787
|
-
post?: never;
|
|
1788
1817
|
delete?: never;
|
|
1789
1818
|
options?: never;
|
|
1790
1819
|
head?: never;
|
|
1791
1820
|
patch?: never;
|
|
1792
1821
|
trace?: never;
|
|
1793
1822
|
};
|
|
1794
|
-
"/v1/lines/{id}/
|
|
1823
|
+
"/v1/lines/{id}/cancel": {
|
|
1795
1824
|
parameters: {
|
|
1796
1825
|
query?: never;
|
|
1797
1826
|
header?: never;
|
|
1798
1827
|
path?: never;
|
|
1799
1828
|
cookie?: never;
|
|
1800
1829
|
};
|
|
1830
|
+
get?: never;
|
|
1831
|
+
put?: never;
|
|
1801
1832
|
/**
|
|
1802
|
-
*
|
|
1803
|
-
* @description
|
|
1833
|
+
* Cancel a line at its next billing anniversary
|
|
1834
|
+
* @description Schedule the END of a line you own for its next billing anniversary, and keep using it until then. This is the verb for "my own customer cancelled": the month is already paid for and iSnap never prorates, so terminating on the spot would destroy days you have bought. The line stays fully `active` — it sends, receives and bills exactly as before — and iSnap terminates it itself when `cancel_at` arrives, firing `line.terminated` with `origin: scheduled_cancellation`. The date is the next occurrence of `anniversary_at` strictly after now, clamped to the last day of a shorter month (a line taken on the 31st renews on the 28th in February and on the 31st again in March — the clamp never sticks). **Idempotent**: cancelling an already-cancelled line returns the SAME `cancel_at`, never a recomputed one, so a retry that happens to cross the anniversary cannot push your own cancellation a month into the future. Undo it with `/uncancel` any time before the date. Refused with 409 `line_has_no_anniversary` on a line that has none — state it with `/anniversary`, or end the line now with `/terminate`.
|
|
1804
1835
|
*/
|
|
1805
|
-
|
|
1836
|
+
post: {
|
|
1806
1837
|
parameters: {
|
|
1807
1838
|
query?: never;
|
|
1808
1839
|
header?: never;
|
|
@@ -1813,13 +1844,19 @@ export interface paths {
|
|
|
1813
1844
|
};
|
|
1814
1845
|
requestBody?: never;
|
|
1815
1846
|
responses: {
|
|
1816
|
-
/** @description
|
|
1847
|
+
/** @description Cancellation scheduled (or already scheduled — the call is idempotent). Returns the line, still `active`, with `cancel_at` set. */
|
|
1817
1848
|
200: {
|
|
1818
1849
|
headers: {
|
|
1819
1850
|
[name: string]: unknown;
|
|
1820
1851
|
};
|
|
1821
1852
|
content: {
|
|
1822
|
-
"application/json":
|
|
1853
|
+
"application/json": {
|
|
1854
|
+
/** @enum {boolean} */
|
|
1855
|
+
success: true;
|
|
1856
|
+
data: components["schemas"]["Line"];
|
|
1857
|
+
trace_id: string;
|
|
1858
|
+
request_id: string;
|
|
1859
|
+
};
|
|
1823
1860
|
};
|
|
1824
1861
|
};
|
|
1825
1862
|
/** @description Bad request — validation failed */
|
|
@@ -1858,6 +1895,15 @@ export interface paths {
|
|
|
1858
1895
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
1859
1896
|
};
|
|
1860
1897
|
};
|
|
1898
|
+
/** @description Conflict — concurrent or terminal state */
|
|
1899
|
+
409: {
|
|
1900
|
+
headers: {
|
|
1901
|
+
[name: string]: unknown;
|
|
1902
|
+
};
|
|
1903
|
+
content: {
|
|
1904
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
1905
|
+
};
|
|
1906
|
+
};
|
|
1861
1907
|
/** @description Too many requests — rate limit exceeded */
|
|
1862
1908
|
429: {
|
|
1863
1909
|
headers: {
|
|
@@ -1878,26 +1924,26 @@ export interface paths {
|
|
|
1878
1924
|
};
|
|
1879
1925
|
};
|
|
1880
1926
|
};
|
|
1881
|
-
put?: never;
|
|
1882
|
-
post?: never;
|
|
1883
1927
|
delete?: never;
|
|
1884
1928
|
options?: never;
|
|
1885
1929
|
head?: never;
|
|
1886
1930
|
patch?: never;
|
|
1887
1931
|
trace?: never;
|
|
1888
1932
|
};
|
|
1889
|
-
"/v1/lines/{id}/
|
|
1933
|
+
"/v1/lines/{id}/uncancel": {
|
|
1890
1934
|
parameters: {
|
|
1891
1935
|
query?: never;
|
|
1892
1936
|
header?: never;
|
|
1893
1937
|
path?: never;
|
|
1894
1938
|
cookie?: never;
|
|
1895
1939
|
};
|
|
1940
|
+
get?: never;
|
|
1941
|
+
put?: never;
|
|
1896
1942
|
/**
|
|
1897
|
-
*
|
|
1898
|
-
* @description
|
|
1943
|
+
* Undo a scheduled cancellation
|
|
1944
|
+
* @description Clear a pending cancellation: `cancel_at` goes back to `null` and the line resumes renewing at its anniversary like any other. Nothing about the line changed while it was cancelled — it never stopped working — so there is nothing to restore. **A no-op on a line that is not cancelled**: 200 with the line and `cancel_at: null`, which is the honest answer to "make sure this line is not cancelled" and lets a reconciliation loop run without treating its own success as an error. Refused with 409 `line_already_terminated` once the anniversary has passed and iSnap has ended the line — that cannot be undone; order a new line instead.
|
|
1899
1945
|
*/
|
|
1900
|
-
|
|
1946
|
+
post: {
|
|
1901
1947
|
parameters: {
|
|
1902
1948
|
query?: never;
|
|
1903
1949
|
header?: never;
|
|
@@ -1908,13 +1954,19 @@ export interface paths {
|
|
|
1908
1954
|
};
|
|
1909
1955
|
requestBody?: never;
|
|
1910
1956
|
responses: {
|
|
1911
|
-
/** @description
|
|
1957
|
+
/** @description Cancellation cleared, or the line was not cancelled. Returns the line with `cancel_at: null`. */
|
|
1912
1958
|
200: {
|
|
1913
1959
|
headers: {
|
|
1914
1960
|
[name: string]: unknown;
|
|
1915
1961
|
};
|
|
1916
1962
|
content: {
|
|
1917
|
-
"application/json":
|
|
1963
|
+
"application/json": {
|
|
1964
|
+
/** @enum {boolean} */
|
|
1965
|
+
success: true;
|
|
1966
|
+
data: components["schemas"]["Line"];
|
|
1967
|
+
trace_id: string;
|
|
1968
|
+
request_id: string;
|
|
1969
|
+
};
|
|
1918
1970
|
};
|
|
1919
1971
|
};
|
|
1920
1972
|
/** @description Bad request — validation failed */
|
|
@@ -1953,6 +2005,15 @@ export interface paths {
|
|
|
1953
2005
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
1954
2006
|
};
|
|
1955
2007
|
};
|
|
2008
|
+
/** @description Conflict — concurrent or terminal state */
|
|
2009
|
+
409: {
|
|
2010
|
+
headers: {
|
|
2011
|
+
[name: string]: unknown;
|
|
2012
|
+
};
|
|
2013
|
+
content: {
|
|
2014
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2015
|
+
};
|
|
2016
|
+
};
|
|
1956
2017
|
/** @description Too many requests — rate limit exceeded */
|
|
1957
2018
|
429: {
|
|
1958
2019
|
headers: {
|
|
@@ -1973,16 +2034,26 @@ export interface paths {
|
|
|
1973
2034
|
};
|
|
1974
2035
|
};
|
|
1975
2036
|
};
|
|
1976
|
-
put?: never;
|
|
1977
|
-
post?: never;
|
|
1978
2037
|
delete?: never;
|
|
1979
2038
|
options?: never;
|
|
1980
2039
|
head?: never;
|
|
2040
|
+
patch?: never;
|
|
2041
|
+
trace?: never;
|
|
2042
|
+
};
|
|
2043
|
+
"/v1/lines/{id}/anniversary": {
|
|
2044
|
+
parameters: {
|
|
2045
|
+
query?: never;
|
|
2046
|
+
header?: never;
|
|
2047
|
+
path?: never;
|
|
2048
|
+
cookie?: never;
|
|
2049
|
+
};
|
|
2050
|
+
get?: never;
|
|
2051
|
+
put?: never;
|
|
1981
2052
|
/**
|
|
1982
|
-
*
|
|
1983
|
-
* @description
|
|
2053
|
+
* State the day you took this line
|
|
2054
|
+
* @description Record the instant you took this line, which becomes the day of the month it renews on and the date `/cancel` waits for. **This is for lines migrated from your own system**, whose real start date iSnap cannot know: a line taken through the iSnap API is stamped automatically at activation and needs no call. A BYOD line is accepted here even though `/cancel` refuses it: it is on the same monthly meter and carries an anniversary, iSnap simply has no way to end it for you at that date yet. Overwrites an existing anniversary — a date somebody states beats a date iSnap inferred — but is refused with 409 `line_cancellation_pending` while a cancellation is scheduled, because that `cancel_at` was computed from the anniversary you are replacing and would otherwise end the line on a day nothing explains: uncancel, set the date, cancel again. Audited as `line.anniversary_set` with the previous value.
|
|
1984
2055
|
*/
|
|
1985
|
-
|
|
2056
|
+
post: {
|
|
1986
2057
|
parameters: {
|
|
1987
2058
|
query?: never;
|
|
1988
2059
|
header?: never;
|
|
@@ -1993,17 +2064,23 @@ export interface paths {
|
|
|
1993
2064
|
};
|
|
1994
2065
|
requestBody?: {
|
|
1995
2066
|
content: {
|
|
1996
|
-
"application/json": components["schemas"]["
|
|
2067
|
+
"application/json": components["schemas"]["SetLineAnniversary"];
|
|
1997
2068
|
};
|
|
1998
2069
|
};
|
|
1999
2070
|
responses: {
|
|
2000
|
-
/** @description
|
|
2071
|
+
/** @description Anniversary recorded. Returns the line with the new `anniversary_at`. */
|
|
2001
2072
|
200: {
|
|
2002
2073
|
headers: {
|
|
2003
2074
|
[name: string]: unknown;
|
|
2004
2075
|
};
|
|
2005
2076
|
content: {
|
|
2006
|
-
"application/json":
|
|
2077
|
+
"application/json": {
|
|
2078
|
+
/** @enum {boolean} */
|
|
2079
|
+
success: true;
|
|
2080
|
+
data: components["schemas"]["Line"];
|
|
2081
|
+
trace_id: string;
|
|
2082
|
+
request_id: string;
|
|
2083
|
+
};
|
|
2007
2084
|
};
|
|
2008
2085
|
};
|
|
2009
2086
|
/** @description Bad request — validation failed */
|
|
@@ -2042,6 +2119,15 @@ export interface paths {
|
|
|
2042
2119
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2043
2120
|
};
|
|
2044
2121
|
};
|
|
2122
|
+
/** @description Conflict — concurrent or terminal state */
|
|
2123
|
+
409: {
|
|
2124
|
+
headers: {
|
|
2125
|
+
[name: string]: unknown;
|
|
2126
|
+
};
|
|
2127
|
+
content: {
|
|
2128
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2129
|
+
};
|
|
2130
|
+
};
|
|
2045
2131
|
/** @description Too many requests — rate limit exceeded */
|
|
2046
2132
|
429: {
|
|
2047
2133
|
headers: {
|
|
@@ -2062,39 +2148,49 @@ export interface paths {
|
|
|
2062
2148
|
};
|
|
2063
2149
|
};
|
|
2064
2150
|
};
|
|
2151
|
+
delete?: never;
|
|
2152
|
+
options?: never;
|
|
2153
|
+
head?: never;
|
|
2154
|
+
patch?: never;
|
|
2065
2155
|
trace?: never;
|
|
2066
2156
|
};
|
|
2067
|
-
"/v1/
|
|
2157
|
+
"/v1/lines/{id}/release": {
|
|
2068
2158
|
parameters: {
|
|
2069
2159
|
query?: never;
|
|
2070
2160
|
header?: never;
|
|
2071
2161
|
path?: never;
|
|
2072
2162
|
cookie?: never;
|
|
2073
2163
|
};
|
|
2164
|
+
get?: never;
|
|
2165
|
+
put?: never;
|
|
2074
2166
|
/**
|
|
2075
|
-
*
|
|
2076
|
-
* @description
|
|
2167
|
+
* Release a line back to the marketplace
|
|
2168
|
+
* @description Cancel the line's ownership and return it to `available`. Cancels the underlying Stripe subscription at period end. The caller must own the line. See `/concepts/billing` for the proration rules.
|
|
2077
2169
|
*/
|
|
2078
|
-
|
|
2170
|
+
post: {
|
|
2079
2171
|
parameters: {
|
|
2080
|
-
query?:
|
|
2081
|
-
status?: "draft" | "pending" | "provisioning" | "ready" | "fulfilled" | "cancelled" | "refunded";
|
|
2082
|
-
cursor?: string;
|
|
2083
|
-
limit?: number;
|
|
2084
|
-
};
|
|
2172
|
+
query?: never;
|
|
2085
2173
|
header?: never;
|
|
2086
|
-
path
|
|
2174
|
+
path: {
|
|
2175
|
+
id: string;
|
|
2176
|
+
};
|
|
2087
2177
|
cookie?: never;
|
|
2088
2178
|
};
|
|
2089
2179
|
requestBody?: never;
|
|
2090
2180
|
responses: {
|
|
2091
|
-
/** @description
|
|
2181
|
+
/** @description Line released */
|
|
2092
2182
|
200: {
|
|
2093
2183
|
headers: {
|
|
2094
2184
|
[name: string]: unknown;
|
|
2095
2185
|
};
|
|
2096
2186
|
content: {
|
|
2097
|
-
"application/json":
|
|
2187
|
+
"application/json": {
|
|
2188
|
+
/** @enum {boolean} */
|
|
2189
|
+
success: true;
|
|
2190
|
+
data: components["schemas"]["Line"];
|
|
2191
|
+
trace_id: string;
|
|
2192
|
+
request_id: string;
|
|
2193
|
+
};
|
|
2098
2194
|
};
|
|
2099
2195
|
};
|
|
2100
2196
|
/** @description Bad request — validation failed */
|
|
@@ -2115,6 +2211,24 @@ export interface paths {
|
|
|
2115
2211
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2116
2212
|
};
|
|
2117
2213
|
};
|
|
2214
|
+
/** @description Forbidden — caller authenticated but not allowed */
|
|
2215
|
+
403: {
|
|
2216
|
+
headers: {
|
|
2217
|
+
[name: string]: unknown;
|
|
2218
|
+
};
|
|
2219
|
+
content: {
|
|
2220
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2221
|
+
};
|
|
2222
|
+
};
|
|
2223
|
+
/** @description Not found */
|
|
2224
|
+
404: {
|
|
2225
|
+
headers: {
|
|
2226
|
+
[name: string]: unknown;
|
|
2227
|
+
};
|
|
2228
|
+
content: {
|
|
2229
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2230
|
+
};
|
|
2231
|
+
};
|
|
2118
2232
|
/** @description Too many requests — rate limit exceeded */
|
|
2119
2233
|
429: {
|
|
2120
2234
|
headers: {
|
|
@@ -2135,12 +2249,556 @@ export interface paths {
|
|
|
2135
2249
|
};
|
|
2136
2250
|
};
|
|
2137
2251
|
};
|
|
2138
|
-
|
|
2252
|
+
delete?: never;
|
|
2253
|
+
options?: never;
|
|
2254
|
+
head?: never;
|
|
2255
|
+
patch?: never;
|
|
2256
|
+
trace?: never;
|
|
2257
|
+
};
|
|
2258
|
+
"/v1/lines/{id}/quota": {
|
|
2259
|
+
parameters: {
|
|
2260
|
+
query?: never;
|
|
2261
|
+
header?: never;
|
|
2262
|
+
path?: never;
|
|
2263
|
+
cookie?: never;
|
|
2264
|
+
};
|
|
2139
2265
|
/**
|
|
2140
|
-
*
|
|
2141
|
-
* @description
|
|
2266
|
+
* Get a line's quota snapshot
|
|
2267
|
+
* @description Five-bucket quota snapshot: new-contacts, known-contacts, total daily messages, hourly, and minute counters with their effective limits plus 80%-warning flags, alongside the reply lane's rolling budget. Each bucket also reports `*_frees_at` — the instant it drops back under its limit, or `null` when it has room now. Drives the dashboard usage panel and partner self-service throttle decisions.
|
|
2142
2268
|
*/
|
|
2143
|
-
|
|
2269
|
+
get: {
|
|
2270
|
+
parameters: {
|
|
2271
|
+
query?: never;
|
|
2272
|
+
header?: never;
|
|
2273
|
+
path: {
|
|
2274
|
+
id: string;
|
|
2275
|
+
};
|
|
2276
|
+
cookie?: never;
|
|
2277
|
+
};
|
|
2278
|
+
requestBody?: never;
|
|
2279
|
+
responses: {
|
|
2280
|
+
/** @description 5-bucket quota snapshot */
|
|
2281
|
+
200: {
|
|
2282
|
+
headers: {
|
|
2283
|
+
[name: string]: unknown;
|
|
2284
|
+
};
|
|
2285
|
+
content: {
|
|
2286
|
+
"application/json": components["schemas"]["QuotaEnvelope"];
|
|
2287
|
+
};
|
|
2288
|
+
};
|
|
2289
|
+
/** @description Bad request — validation failed */
|
|
2290
|
+
400: {
|
|
2291
|
+
headers: {
|
|
2292
|
+
[name: string]: unknown;
|
|
2293
|
+
};
|
|
2294
|
+
content: {
|
|
2295
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2296
|
+
};
|
|
2297
|
+
};
|
|
2298
|
+
/** @description Unauthenticated — missing or invalid bearer token */
|
|
2299
|
+
401: {
|
|
2300
|
+
headers: {
|
|
2301
|
+
[name: string]: unknown;
|
|
2302
|
+
};
|
|
2303
|
+
content: {
|
|
2304
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2305
|
+
};
|
|
2306
|
+
};
|
|
2307
|
+
/** @description Forbidden — caller authenticated but not allowed */
|
|
2308
|
+
403: {
|
|
2309
|
+
headers: {
|
|
2310
|
+
[name: string]: unknown;
|
|
2311
|
+
};
|
|
2312
|
+
content: {
|
|
2313
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2314
|
+
};
|
|
2315
|
+
};
|
|
2316
|
+
/** @description Not found */
|
|
2317
|
+
404: {
|
|
2318
|
+
headers: {
|
|
2319
|
+
[name: string]: unknown;
|
|
2320
|
+
};
|
|
2321
|
+
content: {
|
|
2322
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2323
|
+
};
|
|
2324
|
+
};
|
|
2325
|
+
/** @description Too many requests — rate limit exceeded */
|
|
2326
|
+
429: {
|
|
2327
|
+
headers: {
|
|
2328
|
+
[name: string]: unknown;
|
|
2329
|
+
};
|
|
2330
|
+
content: {
|
|
2331
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2332
|
+
};
|
|
2333
|
+
};
|
|
2334
|
+
/** @description Internal server error */
|
|
2335
|
+
500: {
|
|
2336
|
+
headers: {
|
|
2337
|
+
[name: string]: unknown;
|
|
2338
|
+
};
|
|
2339
|
+
content: {
|
|
2340
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2341
|
+
};
|
|
2342
|
+
};
|
|
2343
|
+
};
|
|
2344
|
+
};
|
|
2345
|
+
put?: never;
|
|
2346
|
+
post?: never;
|
|
2347
|
+
delete?: never;
|
|
2348
|
+
options?: never;
|
|
2349
|
+
head?: never;
|
|
2350
|
+
patch?: never;
|
|
2351
|
+
trace?: never;
|
|
2352
|
+
};
|
|
2353
|
+
"/v1/lines/{id}/queue": {
|
|
2354
|
+
parameters: {
|
|
2355
|
+
query?: never;
|
|
2356
|
+
header?: never;
|
|
2357
|
+
path?: never;
|
|
2358
|
+
cookie?: never;
|
|
2359
|
+
};
|
|
2360
|
+
/**
|
|
2361
|
+
* Inspect a line's queued and scheduled messages
|
|
2362
|
+
* @description Cursor-paginated queue snapshot: per-row `to` / `body` / `status` (`queued` / `scheduled` / `delivered_to_device`) + the schedule reason and the activity-curve hour. Companion to `GET /v1/lines/{id}/quota` for partners debugging delivery delays.
|
|
2363
|
+
*/
|
|
2364
|
+
get: {
|
|
2365
|
+
parameters: {
|
|
2366
|
+
query?: {
|
|
2367
|
+
limit?: number;
|
|
2368
|
+
cursor?: string;
|
|
2369
|
+
status?: "queued" | "scheduled" | "delivered_to_device";
|
|
2370
|
+
};
|
|
2371
|
+
header?: never;
|
|
2372
|
+
path: {
|
|
2373
|
+
id: string;
|
|
2374
|
+
};
|
|
2375
|
+
cookie?: never;
|
|
2376
|
+
};
|
|
2377
|
+
requestBody?: never;
|
|
2378
|
+
responses: {
|
|
2379
|
+
/** @description Queue inspection — summary + paginated items */
|
|
2380
|
+
200: {
|
|
2381
|
+
headers: {
|
|
2382
|
+
[name: string]: unknown;
|
|
2383
|
+
};
|
|
2384
|
+
content: {
|
|
2385
|
+
"application/json": components["schemas"]["QueueEnvelope"];
|
|
2386
|
+
};
|
|
2387
|
+
};
|
|
2388
|
+
/** @description Bad request — validation failed */
|
|
2389
|
+
400: {
|
|
2390
|
+
headers: {
|
|
2391
|
+
[name: string]: unknown;
|
|
2392
|
+
};
|
|
2393
|
+
content: {
|
|
2394
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2395
|
+
};
|
|
2396
|
+
};
|
|
2397
|
+
/** @description Unauthenticated — missing or invalid bearer token */
|
|
2398
|
+
401: {
|
|
2399
|
+
headers: {
|
|
2400
|
+
[name: string]: unknown;
|
|
2401
|
+
};
|
|
2402
|
+
content: {
|
|
2403
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2404
|
+
};
|
|
2405
|
+
};
|
|
2406
|
+
/** @description Forbidden — caller authenticated but not allowed */
|
|
2407
|
+
403: {
|
|
2408
|
+
headers: {
|
|
2409
|
+
[name: string]: unknown;
|
|
2410
|
+
};
|
|
2411
|
+
content: {
|
|
2412
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2413
|
+
};
|
|
2414
|
+
};
|
|
2415
|
+
/** @description Not found */
|
|
2416
|
+
404: {
|
|
2417
|
+
headers: {
|
|
2418
|
+
[name: string]: unknown;
|
|
2419
|
+
};
|
|
2420
|
+
content: {
|
|
2421
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2422
|
+
};
|
|
2423
|
+
};
|
|
2424
|
+
/** @description Too many requests — rate limit exceeded */
|
|
2425
|
+
429: {
|
|
2426
|
+
headers: {
|
|
2427
|
+
[name: string]: unknown;
|
|
2428
|
+
};
|
|
2429
|
+
content: {
|
|
2430
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2431
|
+
};
|
|
2432
|
+
};
|
|
2433
|
+
/** @description Internal server error */
|
|
2434
|
+
500: {
|
|
2435
|
+
headers: {
|
|
2436
|
+
[name: string]: unknown;
|
|
2437
|
+
};
|
|
2438
|
+
content: {
|
|
2439
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2440
|
+
};
|
|
2441
|
+
};
|
|
2442
|
+
};
|
|
2443
|
+
};
|
|
2444
|
+
put?: never;
|
|
2445
|
+
post?: never;
|
|
2446
|
+
delete?: never;
|
|
2447
|
+
options?: never;
|
|
2448
|
+
head?: never;
|
|
2449
|
+
patch?: never;
|
|
2450
|
+
trace?: never;
|
|
2451
|
+
};
|
|
2452
|
+
"/v1/lines/{id}/health": {
|
|
2453
|
+
parameters: {
|
|
2454
|
+
query?: never;
|
|
2455
|
+
header?: never;
|
|
2456
|
+
path?: never;
|
|
2457
|
+
cookie?: never;
|
|
2458
|
+
};
|
|
2459
|
+
/**
|
|
2460
|
+
* Get a BYOD line's health snapshot
|
|
2461
|
+
* @description BYOD-only health rollup. `state` (`active` / `degraded` / `offline`) is derived from the device's fundamental capabilities — min(send_text, imessage) — with offline (no heartbeat) taking precedence. Also returns `runtime_capabilities` (the per-key tri-valued descriptor the device last reported), last heartbeat timestamp, daily quota headroom, Apple-ID-flagged flag, last-error string, bridge version. Rental tiers receive 403 `rental_health_not_exposed` — they don't own the hardware and surfacing transient state creates support-ticket noise.
|
|
2462
|
+
*/
|
|
2463
|
+
get: {
|
|
2464
|
+
parameters: {
|
|
2465
|
+
query?: never;
|
|
2466
|
+
header?: never;
|
|
2467
|
+
path: {
|
|
2468
|
+
id: string;
|
|
2469
|
+
};
|
|
2470
|
+
cookie?: never;
|
|
2471
|
+
};
|
|
2472
|
+
requestBody?: never;
|
|
2473
|
+
responses: {
|
|
2474
|
+
/** @description BYOD line health snapshot */
|
|
2475
|
+
200: {
|
|
2476
|
+
headers: {
|
|
2477
|
+
[name: string]: unknown;
|
|
2478
|
+
};
|
|
2479
|
+
content: {
|
|
2480
|
+
"application/json": components["schemas"]["LineHealthEnvelope"];
|
|
2481
|
+
};
|
|
2482
|
+
};
|
|
2483
|
+
/** @description Bad request — validation failed */
|
|
2484
|
+
400: {
|
|
2485
|
+
headers: {
|
|
2486
|
+
[name: string]: unknown;
|
|
2487
|
+
};
|
|
2488
|
+
content: {
|
|
2489
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2490
|
+
};
|
|
2491
|
+
};
|
|
2492
|
+
/** @description Unauthenticated — missing or invalid bearer token */
|
|
2493
|
+
401: {
|
|
2494
|
+
headers: {
|
|
2495
|
+
[name: string]: unknown;
|
|
2496
|
+
};
|
|
2497
|
+
content: {
|
|
2498
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2499
|
+
};
|
|
2500
|
+
};
|
|
2501
|
+
/** @description Forbidden — caller authenticated but not allowed */
|
|
2502
|
+
403: {
|
|
2503
|
+
headers: {
|
|
2504
|
+
[name: string]: unknown;
|
|
2505
|
+
};
|
|
2506
|
+
content: {
|
|
2507
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2508
|
+
};
|
|
2509
|
+
};
|
|
2510
|
+
/** @description Not found */
|
|
2511
|
+
404: {
|
|
2512
|
+
headers: {
|
|
2513
|
+
[name: string]: unknown;
|
|
2514
|
+
};
|
|
2515
|
+
content: {
|
|
2516
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2517
|
+
};
|
|
2518
|
+
};
|
|
2519
|
+
/** @description Too many requests — rate limit exceeded */
|
|
2520
|
+
429: {
|
|
2521
|
+
headers: {
|
|
2522
|
+
[name: string]: unknown;
|
|
2523
|
+
};
|
|
2524
|
+
content: {
|
|
2525
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2526
|
+
};
|
|
2527
|
+
};
|
|
2528
|
+
/** @description Internal server error */
|
|
2529
|
+
500: {
|
|
2530
|
+
headers: {
|
|
2531
|
+
[name: string]: unknown;
|
|
2532
|
+
};
|
|
2533
|
+
content: {
|
|
2534
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2535
|
+
};
|
|
2536
|
+
};
|
|
2537
|
+
};
|
|
2538
|
+
};
|
|
2539
|
+
put?: never;
|
|
2540
|
+
post?: never;
|
|
2541
|
+
delete?: never;
|
|
2542
|
+
options?: never;
|
|
2543
|
+
head?: never;
|
|
2544
|
+
patch?: never;
|
|
2545
|
+
trace?: never;
|
|
2546
|
+
};
|
|
2547
|
+
"/v1/lines/{id}/config": {
|
|
2548
|
+
parameters: {
|
|
2549
|
+
query?: never;
|
|
2550
|
+
header?: never;
|
|
2551
|
+
path?: never;
|
|
2552
|
+
cookie?: never;
|
|
2553
|
+
};
|
|
2554
|
+
/**
|
|
2555
|
+
* Get a line's effective send configuration
|
|
2556
|
+
* @description Return the resolved send configuration for this line — tier defaults merged with per-line overrides. Surfaces effective quota caps, timezone, activity-curve target hour, and the `overridden_keys` list so partners can see which fields they've customised.
|
|
2557
|
+
*/
|
|
2558
|
+
get: {
|
|
2559
|
+
parameters: {
|
|
2560
|
+
query?: never;
|
|
2561
|
+
header?: never;
|
|
2562
|
+
path: {
|
|
2563
|
+
id: string;
|
|
2564
|
+
};
|
|
2565
|
+
cookie?: never;
|
|
2566
|
+
};
|
|
2567
|
+
requestBody?: never;
|
|
2568
|
+
responses: {
|
|
2569
|
+
/** @description Effective config (tier defaults + per-line overrides) */
|
|
2570
|
+
200: {
|
|
2571
|
+
headers: {
|
|
2572
|
+
[name: string]: unknown;
|
|
2573
|
+
};
|
|
2574
|
+
content: {
|
|
2575
|
+
"application/json": components["schemas"]["LineConfigEnvelope"];
|
|
2576
|
+
};
|
|
2577
|
+
};
|
|
2578
|
+
/** @description Bad request — validation failed */
|
|
2579
|
+
400: {
|
|
2580
|
+
headers: {
|
|
2581
|
+
[name: string]: unknown;
|
|
2582
|
+
};
|
|
2583
|
+
content: {
|
|
2584
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2585
|
+
};
|
|
2586
|
+
};
|
|
2587
|
+
/** @description Unauthenticated — missing or invalid bearer token */
|
|
2588
|
+
401: {
|
|
2589
|
+
headers: {
|
|
2590
|
+
[name: string]: unknown;
|
|
2591
|
+
};
|
|
2592
|
+
content: {
|
|
2593
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2594
|
+
};
|
|
2595
|
+
};
|
|
2596
|
+
/** @description Forbidden — caller authenticated but not allowed */
|
|
2597
|
+
403: {
|
|
2598
|
+
headers: {
|
|
2599
|
+
[name: string]: unknown;
|
|
2600
|
+
};
|
|
2601
|
+
content: {
|
|
2602
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2603
|
+
};
|
|
2604
|
+
};
|
|
2605
|
+
/** @description Not found */
|
|
2606
|
+
404: {
|
|
2607
|
+
headers: {
|
|
2608
|
+
[name: string]: unknown;
|
|
2609
|
+
};
|
|
2610
|
+
content: {
|
|
2611
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2612
|
+
};
|
|
2613
|
+
};
|
|
2614
|
+
/** @description Too many requests — rate limit exceeded */
|
|
2615
|
+
429: {
|
|
2616
|
+
headers: {
|
|
2617
|
+
[name: string]: unknown;
|
|
2618
|
+
};
|
|
2619
|
+
content: {
|
|
2620
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2621
|
+
};
|
|
2622
|
+
};
|
|
2623
|
+
/** @description Internal server error */
|
|
2624
|
+
500: {
|
|
2625
|
+
headers: {
|
|
2626
|
+
[name: string]: unknown;
|
|
2627
|
+
};
|
|
2628
|
+
content: {
|
|
2629
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2630
|
+
};
|
|
2631
|
+
};
|
|
2632
|
+
};
|
|
2633
|
+
};
|
|
2634
|
+
put?: never;
|
|
2635
|
+
post?: never;
|
|
2636
|
+
delete?: never;
|
|
2637
|
+
options?: never;
|
|
2638
|
+
head?: never;
|
|
2639
|
+
/**
|
|
2640
|
+
* Update a line's send configuration
|
|
2641
|
+
* @description Merge-patch the line's per-line config overrides (quota caps, timezone, activity curve). Pass `null` for a key to revert it to the tier default. Validates the activity curve sums to 1.0 and rejects an unknown timezone with 400.
|
|
2642
|
+
*/
|
|
2643
|
+
patch: {
|
|
2644
|
+
parameters: {
|
|
2645
|
+
query?: never;
|
|
2646
|
+
header?: never;
|
|
2647
|
+
path: {
|
|
2648
|
+
id: string;
|
|
2649
|
+
};
|
|
2650
|
+
cookie?: never;
|
|
2651
|
+
};
|
|
2652
|
+
requestBody?: {
|
|
2653
|
+
content: {
|
|
2654
|
+
"application/json": components["schemas"]["LineConfigPatch"];
|
|
2655
|
+
};
|
|
2656
|
+
};
|
|
2657
|
+
responses: {
|
|
2658
|
+
/** @description Updated effective config (merged) + overridden_keys */
|
|
2659
|
+
200: {
|
|
2660
|
+
headers: {
|
|
2661
|
+
[name: string]: unknown;
|
|
2662
|
+
};
|
|
2663
|
+
content: {
|
|
2664
|
+
"application/json": components["schemas"]["LineConfigEnvelope"];
|
|
2665
|
+
};
|
|
2666
|
+
};
|
|
2667
|
+
/** @description Bad request — validation failed */
|
|
2668
|
+
400: {
|
|
2669
|
+
headers: {
|
|
2670
|
+
[name: string]: unknown;
|
|
2671
|
+
};
|
|
2672
|
+
content: {
|
|
2673
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2674
|
+
};
|
|
2675
|
+
};
|
|
2676
|
+
/** @description Unauthenticated — missing or invalid bearer token */
|
|
2677
|
+
401: {
|
|
2678
|
+
headers: {
|
|
2679
|
+
[name: string]: unknown;
|
|
2680
|
+
};
|
|
2681
|
+
content: {
|
|
2682
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2683
|
+
};
|
|
2684
|
+
};
|
|
2685
|
+
/** @description Forbidden — caller authenticated but not allowed */
|
|
2686
|
+
403: {
|
|
2687
|
+
headers: {
|
|
2688
|
+
[name: string]: unknown;
|
|
2689
|
+
};
|
|
2690
|
+
content: {
|
|
2691
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2692
|
+
};
|
|
2693
|
+
};
|
|
2694
|
+
/** @description Not found */
|
|
2695
|
+
404: {
|
|
2696
|
+
headers: {
|
|
2697
|
+
[name: string]: unknown;
|
|
2698
|
+
};
|
|
2699
|
+
content: {
|
|
2700
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2701
|
+
};
|
|
2702
|
+
};
|
|
2703
|
+
/** @description Too many requests — rate limit exceeded */
|
|
2704
|
+
429: {
|
|
2705
|
+
headers: {
|
|
2706
|
+
[name: string]: unknown;
|
|
2707
|
+
};
|
|
2708
|
+
content: {
|
|
2709
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2710
|
+
};
|
|
2711
|
+
};
|
|
2712
|
+
/** @description Internal server error */
|
|
2713
|
+
500: {
|
|
2714
|
+
headers: {
|
|
2715
|
+
[name: string]: unknown;
|
|
2716
|
+
};
|
|
2717
|
+
content: {
|
|
2718
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2719
|
+
};
|
|
2720
|
+
};
|
|
2721
|
+
};
|
|
2722
|
+
};
|
|
2723
|
+
trace?: never;
|
|
2724
|
+
};
|
|
2725
|
+
"/v1/pre-orders": {
|
|
2726
|
+
parameters: {
|
|
2727
|
+
query?: never;
|
|
2728
|
+
header?: never;
|
|
2729
|
+
path?: never;
|
|
2730
|
+
cookie?: never;
|
|
2731
|
+
};
|
|
2732
|
+
/**
|
|
2733
|
+
* List pre-orders
|
|
2734
|
+
* @description Cursor-paginated list of the caller's pre-orders. Filter by status (`draft`, `provisioning`, `fulfilled`, `cancelled`) to surface only the ones the dashboard needs.
|
|
2735
|
+
*/
|
|
2736
|
+
get: {
|
|
2737
|
+
parameters: {
|
|
2738
|
+
query?: {
|
|
2739
|
+
status?: "draft" | "provisioning" | "fulfilled" | "cancelled";
|
|
2740
|
+
cursor?: string;
|
|
2741
|
+
limit?: number;
|
|
2742
|
+
};
|
|
2743
|
+
header?: never;
|
|
2744
|
+
path?: never;
|
|
2745
|
+
cookie?: never;
|
|
2746
|
+
};
|
|
2747
|
+
requestBody?: never;
|
|
2748
|
+
responses: {
|
|
2749
|
+
/** @description Pre-order list */
|
|
2750
|
+
200: {
|
|
2751
|
+
headers: {
|
|
2752
|
+
[name: string]: unknown;
|
|
2753
|
+
};
|
|
2754
|
+
content: {
|
|
2755
|
+
"application/json": components["schemas"]["PreOrderList"];
|
|
2756
|
+
};
|
|
2757
|
+
};
|
|
2758
|
+
/** @description Bad request — validation failed */
|
|
2759
|
+
400: {
|
|
2760
|
+
headers: {
|
|
2761
|
+
[name: string]: unknown;
|
|
2762
|
+
};
|
|
2763
|
+
content: {
|
|
2764
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2765
|
+
};
|
|
2766
|
+
};
|
|
2767
|
+
/** @description Unauthenticated — missing or invalid bearer token */
|
|
2768
|
+
401: {
|
|
2769
|
+
headers: {
|
|
2770
|
+
[name: string]: unknown;
|
|
2771
|
+
};
|
|
2772
|
+
content: {
|
|
2773
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2774
|
+
};
|
|
2775
|
+
};
|
|
2776
|
+
/** @description Too many requests — rate limit exceeded */
|
|
2777
|
+
429: {
|
|
2778
|
+
headers: {
|
|
2779
|
+
[name: string]: unknown;
|
|
2780
|
+
};
|
|
2781
|
+
content: {
|
|
2782
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2783
|
+
};
|
|
2784
|
+
};
|
|
2785
|
+
/** @description Internal server error */
|
|
2786
|
+
500: {
|
|
2787
|
+
headers: {
|
|
2788
|
+
[name: string]: unknown;
|
|
2789
|
+
};
|
|
2790
|
+
content: {
|
|
2791
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2792
|
+
};
|
|
2793
|
+
};
|
|
2794
|
+
};
|
|
2795
|
+
};
|
|
2796
|
+
put?: never;
|
|
2797
|
+
/**
|
|
2798
|
+
* Create a pre-order (draft)
|
|
2799
|
+
* @description Place a pre-order as a `draft` (WHA-1155). A draft has NO side effects — no provisioning line, no procurement, no Stripe charge — so the partner can hold intent / bill its own end-user first. Call `POST /v1/pre-orders/{id}/confirm` to engage the month and start procurement. A pre-order carries the area codes you would accept, in order of preference, the plan (`inbound_only`), which is remembered for confirm and read back on every response, and optionally the SKU (`billing_tier`). The tier and the plan are ORTHOGONAL — `rental_iphone` covers both the outbound and the inbound product, which is what `inbound_only` selects — so naming both is never a contradiction. `billing_tier` is optional because a pre-order that omits it is still `rental_iphone`, the only tier this flow mints; when named it is ANSWERED, never discarded: `rental_android` is `400 android_rental_not_purchasable` (no Android product exists in the Stripe catalogue, WHA-2474) and a tier no pre-order can procure — BYOD, virtual shared, pool — is `400 tier_not_pre_orderable`, naming the endpoint to call instead (WHA-2949). The body is otherwise STRICT (WHA-2644) — any other property is a `400`, including `quantity` and `metadata`, which earlier revisions of this contract documented and the server silently discarded.
|
|
2800
|
+
*/
|
|
2801
|
+
post: {
|
|
2144
2802
|
parameters: {
|
|
2145
2803
|
query?: never;
|
|
2146
2804
|
header?: never;
|
|
@@ -2150,18 +2808,107 @@ export interface paths {
|
|
|
2150
2808
|
requestBody?: {
|
|
2151
2809
|
content: {
|
|
2152
2810
|
"application/json": {
|
|
2153
|
-
/** @enum {string} */
|
|
2154
|
-
billing_tier: "rental_iphone" | "rental_android";
|
|
2155
2811
|
/** @default [] */
|
|
2156
2812
|
preferred_area_codes?: string[];
|
|
2157
2813
|
/** @default false */
|
|
2158
2814
|
inbound_only?: boolean;
|
|
2815
|
+
/** @enum {string} */
|
|
2816
|
+
billing_tier?: "rental_iphone" | "rental_android" | "byod_imessage" | "byod_android" | "shared_pool" | "shared_imessage";
|
|
2817
|
+
/**
|
|
2818
|
+
* Format: date-time
|
|
2819
|
+
* @description The billing anchor of the customer who pays for this line (ISO-8601, UTC) — the ONE date it is billed on. Its day of the month becomes the line’s billing day, clamped to the last day of a shorter month; the time of day is kept, because the anchor is an instant and not a calendar day. State the date your own customer is billed on and every line they hold moves together: at each occurrence the line is charged one full month, and at the FIRST occurrence after activation it is credited for the days the activation month had already paid for past it, at the activation rate. Omit it and the line is billed on its activation instant, which is the behaviour of every line provisioned before anchors existed. Refused (400 `billing_anchor_too_far`) more than 31 days after the activation — that would make the first period longer than a month.
|
|
2820
|
+
* @example 2026-09-11T09:15:00Z
|
|
2821
|
+
*/
|
|
2822
|
+
billing_anchor_at?: string;
|
|
2823
|
+
};
|
|
2824
|
+
};
|
|
2825
|
+
};
|
|
2826
|
+
responses: {
|
|
2827
|
+
/** @description Pre-order draft created */
|
|
2828
|
+
201: {
|
|
2829
|
+
headers: {
|
|
2830
|
+
[name: string]: unknown;
|
|
2831
|
+
};
|
|
2832
|
+
content: {
|
|
2833
|
+
"application/json": {
|
|
2834
|
+
/** @enum {boolean} */
|
|
2835
|
+
success: true;
|
|
2836
|
+
data: components["schemas"]["PreOrder"];
|
|
2837
|
+
trace_id: string;
|
|
2838
|
+
request_id: string;
|
|
2839
|
+
};
|
|
2840
|
+
};
|
|
2841
|
+
};
|
|
2842
|
+
/** @description Bad request — validation failed */
|
|
2843
|
+
400: {
|
|
2844
|
+
headers: {
|
|
2845
|
+
[name: string]: unknown;
|
|
2846
|
+
};
|
|
2847
|
+
content: {
|
|
2848
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2849
|
+
};
|
|
2850
|
+
};
|
|
2851
|
+
/** @description Unauthenticated — missing or invalid bearer token */
|
|
2852
|
+
401: {
|
|
2853
|
+
headers: {
|
|
2854
|
+
[name: string]: unknown;
|
|
2855
|
+
};
|
|
2856
|
+
content: {
|
|
2857
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2858
|
+
};
|
|
2859
|
+
};
|
|
2860
|
+
/** @description Too many requests — rate limit exceeded */
|
|
2861
|
+
429: {
|
|
2862
|
+
headers: {
|
|
2863
|
+
[name: string]: unknown;
|
|
2864
|
+
};
|
|
2865
|
+
content: {
|
|
2866
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2867
|
+
};
|
|
2868
|
+
};
|
|
2869
|
+
/** @description Internal server error */
|
|
2870
|
+
500: {
|
|
2871
|
+
headers: {
|
|
2872
|
+
[name: string]: unknown;
|
|
2159
2873
|
};
|
|
2874
|
+
content: {
|
|
2875
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2876
|
+
};
|
|
2877
|
+
};
|
|
2878
|
+
};
|
|
2879
|
+
};
|
|
2880
|
+
delete?: never;
|
|
2881
|
+
options?: never;
|
|
2882
|
+
head?: never;
|
|
2883
|
+
patch?: never;
|
|
2884
|
+
trace?: never;
|
|
2885
|
+
};
|
|
2886
|
+
"/v1/pre-orders/{id}/confirm": {
|
|
2887
|
+
parameters: {
|
|
2888
|
+
query?: never;
|
|
2889
|
+
header?: never;
|
|
2890
|
+
path?: never;
|
|
2891
|
+
cookie?: never;
|
|
2892
|
+
};
|
|
2893
|
+
get?: never;
|
|
2894
|
+
put?: never;
|
|
2895
|
+
/**
|
|
2896
|
+
* Confirm a pre-order draft
|
|
2897
|
+
* @description Confirm a `draft` pre-order (WHA-1155). The binding step: engages the one-month commitment (full month, no proration) and triggers procurement — mints the `provisioning` line + fulfillment task, notifies ops, and (for direct customers) creates the first-month Stripe payment intent, returned as `stripe_client_secret`. Only a draft can be confirmed.
|
|
2898
|
+
*/
|
|
2899
|
+
post: {
|
|
2900
|
+
parameters: {
|
|
2901
|
+
query?: never;
|
|
2902
|
+
header?: never;
|
|
2903
|
+
path: {
|
|
2904
|
+
id: string;
|
|
2160
2905
|
};
|
|
2906
|
+
cookie?: never;
|
|
2161
2907
|
};
|
|
2908
|
+
requestBody?: never;
|
|
2162
2909
|
responses: {
|
|
2163
|
-
/** @description Pre-order
|
|
2164
|
-
|
|
2910
|
+
/** @description Pre-order confirmed (now provisioning) */
|
|
2911
|
+
200: {
|
|
2165
2912
|
headers: {
|
|
2166
2913
|
[name: string]: unknown;
|
|
2167
2914
|
};
|
|
@@ -2193,6 +2940,15 @@ export interface paths {
|
|
|
2193
2940
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2194
2941
|
};
|
|
2195
2942
|
};
|
|
2943
|
+
/** @description Not found */
|
|
2944
|
+
404: {
|
|
2945
|
+
headers: {
|
|
2946
|
+
[name: string]: unknown;
|
|
2947
|
+
};
|
|
2948
|
+
content: {
|
|
2949
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2950
|
+
};
|
|
2951
|
+
};
|
|
2196
2952
|
/** @description Too many requests — rate limit exceeded */
|
|
2197
2953
|
429: {
|
|
2198
2954
|
headers: {
|
|
@@ -2219,20 +2975,18 @@ export interface paths {
|
|
|
2219
2975
|
patch?: never;
|
|
2220
2976
|
trace?: never;
|
|
2221
2977
|
};
|
|
2222
|
-
"/v1/pre-orders/{id}
|
|
2978
|
+
"/v1/pre-orders/{id}": {
|
|
2223
2979
|
parameters: {
|
|
2224
2980
|
query?: never;
|
|
2225
2981
|
header?: never;
|
|
2226
2982
|
path?: never;
|
|
2227
2983
|
cookie?: never;
|
|
2228
2984
|
};
|
|
2229
|
-
get?: never;
|
|
2230
|
-
put?: never;
|
|
2231
2985
|
/**
|
|
2232
|
-
*
|
|
2233
|
-
* @description
|
|
2986
|
+
* Get a pre-order
|
|
2987
|
+
* @description Fetch a single pre-order, including its current status, the linked Stripe payment intent, and the fulfilled-line reference if the procurement has completed.
|
|
2234
2988
|
*/
|
|
2235
|
-
|
|
2989
|
+
get: {
|
|
2236
2990
|
parameters: {
|
|
2237
2991
|
query?: never;
|
|
2238
2992
|
header?: never;
|
|
@@ -2243,7 +2997,7 @@ export interface paths {
|
|
|
2243
2997
|
};
|
|
2244
2998
|
requestBody?: never;
|
|
2245
2999
|
responses: {
|
|
2246
|
-
/** @description Pre-order
|
|
3000
|
+
/** @description Pre-order */
|
|
2247
3001
|
200: {
|
|
2248
3002
|
headers: {
|
|
2249
3003
|
[name: string]: unknown;
|
|
@@ -2305,24 +3059,28 @@ export interface paths {
|
|
|
2305
3059
|
};
|
|
2306
3060
|
};
|
|
2307
3061
|
};
|
|
3062
|
+
put?: never;
|
|
3063
|
+
post?: never;
|
|
2308
3064
|
delete?: never;
|
|
2309
3065
|
options?: never;
|
|
2310
3066
|
head?: never;
|
|
2311
3067
|
patch?: never;
|
|
2312
3068
|
trace?: never;
|
|
2313
3069
|
};
|
|
2314
|
-
"/v1/pre-orders/{id}": {
|
|
3070
|
+
"/v1/pre-orders/{id}/cancel": {
|
|
2315
3071
|
parameters: {
|
|
2316
3072
|
query?: never;
|
|
2317
3073
|
header?: never;
|
|
2318
3074
|
path?: never;
|
|
2319
3075
|
cookie?: never;
|
|
2320
3076
|
};
|
|
3077
|
+
get?: never;
|
|
3078
|
+
put?: never;
|
|
2321
3079
|
/**
|
|
2322
|
-
*
|
|
2323
|
-
* @description
|
|
3080
|
+
* Cancel a pre-order draft
|
|
3081
|
+
* @description Cancel an unconfirmed `draft` pre-order (WHA-1155) — free, nothing was provisioned or charged. A CONFIRMED pre-order cannot be cancelled here (the month is committed, full month no proration); release its provisioned line through the standard line endpoint `POST /v1/lines/{id}/release` instead.
|
|
2324
3082
|
*/
|
|
2325
|
-
|
|
3083
|
+
post: {
|
|
2326
3084
|
parameters: {
|
|
2327
3085
|
query?: never;
|
|
2328
3086
|
header?: never;
|
|
@@ -2333,7 +3091,7 @@ export interface paths {
|
|
|
2333
3091
|
};
|
|
2334
3092
|
requestBody?: never;
|
|
2335
3093
|
responses: {
|
|
2336
|
-
/** @description Pre-order */
|
|
3094
|
+
/** @description Pre-order cancelled */
|
|
2337
3095
|
200: {
|
|
2338
3096
|
headers: {
|
|
2339
3097
|
[name: string]: unknown;
|
|
@@ -2375,6 +3133,15 @@ export interface paths {
|
|
|
2375
3133
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2376
3134
|
};
|
|
2377
3135
|
};
|
|
3136
|
+
/** @description Conflict — concurrent or terminal state */
|
|
3137
|
+
409: {
|
|
3138
|
+
headers: {
|
|
3139
|
+
[name: string]: unknown;
|
|
3140
|
+
};
|
|
3141
|
+
content: {
|
|
3142
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
3143
|
+
};
|
|
3144
|
+
};
|
|
2378
3145
|
/** @description Too many requests — rate limit exceeded */
|
|
2379
3146
|
429: {
|
|
2380
3147
|
headers: {
|
|
@@ -2395,15 +3162,112 @@ export interface paths {
|
|
|
2395
3162
|
};
|
|
2396
3163
|
};
|
|
2397
3164
|
};
|
|
3165
|
+
delete?: never;
|
|
3166
|
+
options?: never;
|
|
3167
|
+
head?: never;
|
|
3168
|
+
patch?: never;
|
|
3169
|
+
trace?: never;
|
|
3170
|
+
};
|
|
3171
|
+
"/v1/billing/checkout": {
|
|
3172
|
+
parameters: {
|
|
3173
|
+
query?: never;
|
|
3174
|
+
header?: never;
|
|
3175
|
+
path?: never;
|
|
3176
|
+
cookie?: never;
|
|
3177
|
+
};
|
|
3178
|
+
get?: never;
|
|
2398
3179
|
put?: never;
|
|
2399
|
-
|
|
3180
|
+
/**
|
|
3181
|
+
* Start a Stripe Checkout for a reserved line
|
|
3182
|
+
* @description Create a Stripe Checkout Session for the line previously reserved by `POST /v1/lines/{id}/reserve`. Returns the hosted checkout URL — redirect the customer there. The webhook handler activates the line once the session completes.
|
|
3183
|
+
*/
|
|
3184
|
+
post: {
|
|
3185
|
+
parameters: {
|
|
3186
|
+
query?: never;
|
|
3187
|
+
header?: never;
|
|
3188
|
+
path?: never;
|
|
3189
|
+
cookie?: never;
|
|
3190
|
+
};
|
|
3191
|
+
requestBody?: {
|
|
3192
|
+
content: {
|
|
3193
|
+
"application/json": {
|
|
3194
|
+
/**
|
|
3195
|
+
* @description Line to check out. Send the `line_<base62>` public ID returned by `POST /v1/lines/{id}/reserve`; the internal UUID is also accepted for backward compatibility. Must be status `reserved`.
|
|
3196
|
+
* @example line_2k9Qp7RtY4mNb8VcXs3Wd6Lf1
|
|
3197
|
+
*/
|
|
3198
|
+
line_id: string;
|
|
3199
|
+
/**
|
|
3200
|
+
* @description Buy the INBOUND rental product instead of the outbound one. An inbound line cannot INITIATE a conversation — the contact must message first, after which the exchange is unrestricted; it is NOT receive-only. Rental tiers only. The chosen Stripe price is the source of truth: `lines.inbound_only` is re-derived from its lookup_key on `customer.subscription.created/updated`.
|
|
3201
|
+
* @default false
|
|
3202
|
+
*/
|
|
3203
|
+
inbound_only?: boolean;
|
|
3204
|
+
};
|
|
3205
|
+
};
|
|
3206
|
+
};
|
|
3207
|
+
responses: {
|
|
3208
|
+
/** @description Checkout session */
|
|
3209
|
+
200: {
|
|
3210
|
+
headers: {
|
|
3211
|
+
[name: string]: unknown;
|
|
3212
|
+
};
|
|
3213
|
+
content: {
|
|
3214
|
+
"application/json": components["schemas"]["Checkout"];
|
|
3215
|
+
};
|
|
3216
|
+
};
|
|
3217
|
+
/** @description Bad request — validation failed */
|
|
3218
|
+
400: {
|
|
3219
|
+
headers: {
|
|
3220
|
+
[name: string]: unknown;
|
|
3221
|
+
};
|
|
3222
|
+
content: {
|
|
3223
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
3224
|
+
};
|
|
3225
|
+
};
|
|
3226
|
+
/** @description Unauthenticated — missing or invalid bearer token */
|
|
3227
|
+
401: {
|
|
3228
|
+
headers: {
|
|
3229
|
+
[name: string]: unknown;
|
|
3230
|
+
};
|
|
3231
|
+
content: {
|
|
3232
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
3233
|
+
};
|
|
3234
|
+
};
|
|
3235
|
+
/** @description Not found */
|
|
3236
|
+
404: {
|
|
3237
|
+
headers: {
|
|
3238
|
+
[name: string]: unknown;
|
|
3239
|
+
};
|
|
3240
|
+
content: {
|
|
3241
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
3242
|
+
};
|
|
3243
|
+
};
|
|
3244
|
+
/** @description Too many requests — rate limit exceeded */
|
|
3245
|
+
429: {
|
|
3246
|
+
headers: {
|
|
3247
|
+
[name: string]: unknown;
|
|
3248
|
+
};
|
|
3249
|
+
content: {
|
|
3250
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
3251
|
+
};
|
|
3252
|
+
};
|
|
3253
|
+
/** @description Internal server error */
|
|
3254
|
+
500: {
|
|
3255
|
+
headers: {
|
|
3256
|
+
[name: string]: unknown;
|
|
3257
|
+
};
|
|
3258
|
+
content: {
|
|
3259
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
3260
|
+
};
|
|
3261
|
+
};
|
|
3262
|
+
};
|
|
3263
|
+
};
|
|
2400
3264
|
delete?: never;
|
|
2401
3265
|
options?: never;
|
|
2402
3266
|
head?: never;
|
|
2403
3267
|
patch?: never;
|
|
2404
3268
|
trace?: never;
|
|
2405
3269
|
};
|
|
2406
|
-
"/v1/
|
|
3270
|
+
"/v1/billing/byod-checkout": {
|
|
2407
3271
|
parameters: {
|
|
2408
3272
|
query?: never;
|
|
2409
3273
|
header?: never;
|
|
@@ -2413,33 +3277,108 @@ export interface paths {
|
|
|
2413
3277
|
get?: never;
|
|
2414
3278
|
put?: never;
|
|
2415
3279
|
/**
|
|
2416
|
-
*
|
|
2417
|
-
* @description
|
|
3280
|
+
* Start a Stripe Checkout for BYOD slots
|
|
3281
|
+
* @description Create a Stripe Checkout Session for the BYOD subscription product (`$15/mo`, `$40.50/quarter` or `$150/yr` per slot, `device_count` slots). All three cadences the BYOP catalogue carries are sellable — `GET /pricing` publishes the amount of each. The completed session writes a `byod_subscriptions` row that `POST /v1/byod/pair` reads to enforce slot capacity.
|
|
2418
3282
|
*/
|
|
2419
3283
|
post: {
|
|
2420
3284
|
parameters: {
|
|
2421
3285
|
query?: never;
|
|
2422
3286
|
header?: never;
|
|
2423
|
-
path
|
|
2424
|
-
|
|
3287
|
+
path?: never;
|
|
3288
|
+
cookie?: never;
|
|
3289
|
+
};
|
|
3290
|
+
requestBody?: {
|
|
3291
|
+
content: {
|
|
3292
|
+
"application/json": components["schemas"]["ByodCheckoutBody"];
|
|
3293
|
+
};
|
|
3294
|
+
};
|
|
3295
|
+
responses: {
|
|
3296
|
+
/** @description BYOD checkout session */
|
|
3297
|
+
200: {
|
|
3298
|
+
headers: {
|
|
3299
|
+
[name: string]: unknown;
|
|
3300
|
+
};
|
|
3301
|
+
content: {
|
|
3302
|
+
"application/json": components["schemas"]["ByodCheckoutEnvelope"];
|
|
3303
|
+
};
|
|
3304
|
+
};
|
|
3305
|
+
/** @description Bad request — validation failed */
|
|
3306
|
+
400: {
|
|
3307
|
+
headers: {
|
|
3308
|
+
[name: string]: unknown;
|
|
3309
|
+
};
|
|
3310
|
+
content: {
|
|
3311
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
3312
|
+
};
|
|
3313
|
+
};
|
|
3314
|
+
/** @description Unauthenticated — missing or invalid bearer token */
|
|
3315
|
+
401: {
|
|
3316
|
+
headers: {
|
|
3317
|
+
[name: string]: unknown;
|
|
3318
|
+
};
|
|
3319
|
+
content: {
|
|
3320
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
3321
|
+
};
|
|
3322
|
+
};
|
|
3323
|
+
/** @description Too many requests — rate limit exceeded */
|
|
3324
|
+
429: {
|
|
3325
|
+
headers: {
|
|
3326
|
+
[name: string]: unknown;
|
|
3327
|
+
};
|
|
3328
|
+
content: {
|
|
3329
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
3330
|
+
};
|
|
3331
|
+
};
|
|
3332
|
+
/** @description Internal server error */
|
|
3333
|
+
500: {
|
|
3334
|
+
headers: {
|
|
3335
|
+
[name: string]: unknown;
|
|
3336
|
+
};
|
|
3337
|
+
content: {
|
|
3338
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
3339
|
+
};
|
|
2425
3340
|
};
|
|
3341
|
+
};
|
|
3342
|
+
};
|
|
3343
|
+
delete?: never;
|
|
3344
|
+
options?: never;
|
|
3345
|
+
head?: never;
|
|
3346
|
+
patch?: never;
|
|
3347
|
+
trace?: never;
|
|
3348
|
+
};
|
|
3349
|
+
"/v1/billing/mac-checkout": {
|
|
3350
|
+
parameters: {
|
|
3351
|
+
query?: never;
|
|
3352
|
+
header?: never;
|
|
3353
|
+
path?: never;
|
|
3354
|
+
cookie?: never;
|
|
3355
|
+
};
|
|
3356
|
+
get?: never;
|
|
3357
|
+
put?: never;
|
|
3358
|
+
/**
|
|
3359
|
+
* Start a Stripe Checkout for hosted macOS sessions
|
|
3360
|
+
* @description Create a Stripe Checkout Session for `quantity` rented macOS sessions, priced on a graduated ladder ($35/$30/$25/$20 per session across the 1–10 / 11–30 / 31–50 / 51+ bands). Two rules are enforced here and nowhere else: the quantity must be a whole number of packs at or above the one-pack minimum (`422 mac_quantity_not_a_pack`, the divisor echoed as `issues[0].min`), and a rented session hosts the bridge for one BYOP iPhone so sessions may not exceed the account’s BYOP lines (`422 mac_sessions_exceed_byop_lines`). Stripe’s hosted UI cannot change the quantity afterwards — use `PATCH /v1/billing/subscriptions/{id}`, which applies the same two rules.
|
|
3361
|
+
*/
|
|
3362
|
+
post: {
|
|
3363
|
+
parameters: {
|
|
3364
|
+
query?: never;
|
|
3365
|
+
header?: never;
|
|
3366
|
+
path?: never;
|
|
2426
3367
|
cookie?: never;
|
|
2427
3368
|
};
|
|
2428
|
-
requestBody?:
|
|
3369
|
+
requestBody?: {
|
|
3370
|
+
content: {
|
|
3371
|
+
"application/json": components["schemas"]["MacCheckoutBody"];
|
|
3372
|
+
};
|
|
3373
|
+
};
|
|
2429
3374
|
responses: {
|
|
2430
|
-
/** @description
|
|
3375
|
+
/** @description macOS session checkout */
|
|
2431
3376
|
200: {
|
|
2432
3377
|
headers: {
|
|
2433
3378
|
[name: string]: unknown;
|
|
2434
3379
|
};
|
|
2435
3380
|
content: {
|
|
2436
|
-
"application/json":
|
|
2437
|
-
/** @enum {boolean} */
|
|
2438
|
-
success: true;
|
|
2439
|
-
data: components["schemas"]["PreOrder"];
|
|
2440
|
-
trace_id: string;
|
|
2441
|
-
request_id: string;
|
|
2442
|
-
};
|
|
3381
|
+
"application/json": components["schemas"]["MacCheckoutEnvelope"];
|
|
2443
3382
|
};
|
|
2444
3383
|
};
|
|
2445
3384
|
/** @description Bad request — validation failed */
|
|
@@ -2469,8 +3408,8 @@ export interface paths {
|
|
|
2469
3408
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2470
3409
|
};
|
|
2471
3410
|
};
|
|
2472
|
-
/** @description
|
|
2473
|
-
|
|
3411
|
+
/** @description Unprocessable — domain rule violation */
|
|
3412
|
+
422: {
|
|
2474
3413
|
headers: {
|
|
2475
3414
|
[name: string]: unknown;
|
|
2476
3415
|
};
|
|
@@ -2504,7 +3443,7 @@ export interface paths {
|
|
|
2504
3443
|
patch?: never;
|
|
2505
3444
|
trace?: never;
|
|
2506
3445
|
};
|
|
2507
|
-
"/v1/billing/
|
|
3446
|
+
"/v1/billing/subscriptions/{id}": {
|
|
2508
3447
|
parameters: {
|
|
2509
3448
|
query?: never;
|
|
2510
3449
|
header?: never;
|
|
@@ -2513,41 +3452,29 @@ export interface paths {
|
|
|
2513
3452
|
};
|
|
2514
3453
|
get?: never;
|
|
2515
3454
|
put?: never;
|
|
3455
|
+
post?: never;
|
|
2516
3456
|
/**
|
|
2517
|
-
*
|
|
2518
|
-
* @description
|
|
3457
|
+
* Cancel a subscription
|
|
3458
|
+
* @description Schedule the subscription to cancel at the end of the current billing period. The line remains active until the period rolls over; the partner sees the `cancel_at_period_end: true` flag in `GET /v1/billing/subscriptions` until then.
|
|
2519
3459
|
*/
|
|
2520
|
-
|
|
3460
|
+
delete: {
|
|
2521
3461
|
parameters: {
|
|
2522
3462
|
query?: never;
|
|
2523
3463
|
header?: never;
|
|
2524
|
-
path
|
|
2525
|
-
|
|
2526
|
-
};
|
|
2527
|
-
requestBody?: {
|
|
2528
|
-
content: {
|
|
2529
|
-
"application/json": {
|
|
2530
|
-
/**
|
|
2531
|
-
* @description Line to check out. Send the `line_<base62>` public ID returned by `POST /v1/lines/{id}/reserve`; the internal UUID is also accepted for backward compatibility. Must be status `reserved`.
|
|
2532
|
-
* @example line_2k9Qp7RtY4mNb8VcXs3Wd6Lf1
|
|
2533
|
-
*/
|
|
2534
|
-
line_id: string;
|
|
2535
|
-
/**
|
|
2536
|
-
* @description Buy the INBOUND rental product instead of the outbound one. An inbound line cannot INITIATE a conversation — the contact must message first, after which the exchange is unrestricted; it is NOT receive-only. Rental tiers only. The chosen Stripe price is the source of truth: `lines.inbound_only` is re-derived from its lookup_key on `customer.subscription.created/updated`.
|
|
2537
|
-
* @default false
|
|
2538
|
-
*/
|
|
2539
|
-
inbound_only?: boolean;
|
|
2540
|
-
};
|
|
3464
|
+
path: {
|
|
3465
|
+
id: string;
|
|
2541
3466
|
};
|
|
3467
|
+
cookie?: never;
|
|
2542
3468
|
};
|
|
3469
|
+
requestBody?: never;
|
|
2543
3470
|
responses: {
|
|
2544
|
-
/** @description
|
|
3471
|
+
/** @description Subscription cancelled */
|
|
2545
3472
|
200: {
|
|
2546
3473
|
headers: {
|
|
2547
3474
|
[name: string]: unknown;
|
|
2548
3475
|
};
|
|
2549
3476
|
content: {
|
|
2550
|
-
"application/json": components["schemas"]["
|
|
3477
|
+
"application/json": components["schemas"]["BillingMessage"];
|
|
2551
3478
|
};
|
|
2552
3479
|
};
|
|
2553
3480
|
/** @description Bad request — validation failed */
|
|
@@ -2577,6 +3504,15 @@ export interface paths {
|
|
|
2577
3504
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2578
3505
|
};
|
|
2579
3506
|
};
|
|
3507
|
+
/** @description Conflict — concurrent or terminal state */
|
|
3508
|
+
409: {
|
|
3509
|
+
headers: {
|
|
3510
|
+
[name: string]: unknown;
|
|
3511
|
+
};
|
|
3512
|
+
content: {
|
|
3513
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
3514
|
+
};
|
|
3515
|
+
};
|
|
2580
3516
|
/** @description Too many requests — rate limit exceeded */
|
|
2581
3517
|
429: {
|
|
2582
3518
|
headers: {
|
|
@@ -2597,45 +3533,34 @@ export interface paths {
|
|
|
2597
3533
|
};
|
|
2598
3534
|
};
|
|
2599
3535
|
};
|
|
2600
|
-
delete?: never;
|
|
2601
3536
|
options?: never;
|
|
2602
3537
|
head?: never;
|
|
2603
|
-
patch?: never;
|
|
2604
|
-
trace?: never;
|
|
2605
|
-
};
|
|
2606
|
-
"/v1/billing/byod-checkout": {
|
|
2607
|
-
parameters: {
|
|
2608
|
-
query?: never;
|
|
2609
|
-
header?: never;
|
|
2610
|
-
path?: never;
|
|
2611
|
-
cookie?: never;
|
|
2612
|
-
};
|
|
2613
|
-
get?: never;
|
|
2614
|
-
put?: never;
|
|
2615
3538
|
/**
|
|
2616
|
-
*
|
|
2617
|
-
* @description
|
|
3539
|
+
* Change a subscription’s quantity
|
|
3540
|
+
* @description Set the quantity on the subscription’s single quantity-adjustable item — hosted macOS sessions, or BYOP slots. Both directions of the 1:1 rule are enforced: raising sessions above the account’s BYOP lines is `422 mac_sessions_exceed_byop_lines`, and lowering BYOP below the macOS sessions already rented is `422 byop_reduction_strands_mac_sessions`. A macOS quantity must additionally be a whole pack (`422 mac_quantity_not_a_pack`). A subscription that does not carry exactly one adjustable item — a per-line rental, or a wholesale master subscription whose quantities are pushed by metering — is refused `409 subscription_not_quantity_adjustable`.
|
|
2618
3541
|
*/
|
|
2619
|
-
|
|
3542
|
+
patch: {
|
|
2620
3543
|
parameters: {
|
|
2621
3544
|
query?: never;
|
|
2622
3545
|
header?: never;
|
|
2623
|
-
path
|
|
3546
|
+
path: {
|
|
3547
|
+
id: string;
|
|
3548
|
+
};
|
|
2624
3549
|
cookie?: never;
|
|
2625
3550
|
};
|
|
2626
3551
|
requestBody?: {
|
|
2627
3552
|
content: {
|
|
2628
|
-
"application/json": components["schemas"]["
|
|
3553
|
+
"application/json": components["schemas"]["SubscriptionQuantityBody"];
|
|
2629
3554
|
};
|
|
2630
3555
|
};
|
|
2631
3556
|
responses: {
|
|
2632
|
-
/** @description
|
|
3557
|
+
/** @description Quantity updated */
|
|
2633
3558
|
200: {
|
|
2634
3559
|
headers: {
|
|
2635
3560
|
[name: string]: unknown;
|
|
2636
3561
|
};
|
|
2637
3562
|
content: {
|
|
2638
|
-
"application/json": components["schemas"]["
|
|
3563
|
+
"application/json": components["schemas"]["SubscriptionQuantityEnvelope"];
|
|
2639
3564
|
};
|
|
2640
3565
|
};
|
|
2641
3566
|
/** @description Bad request — validation failed */
|
|
@@ -2656,8 +3581,8 @@ export interface paths {
|
|
|
2656
3581
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2657
3582
|
};
|
|
2658
3583
|
};
|
|
2659
|
-
/** @description
|
|
2660
|
-
|
|
3584
|
+
/** @description Forbidden — caller authenticated but not allowed */
|
|
3585
|
+
403: {
|
|
2661
3586
|
headers: {
|
|
2662
3587
|
[name: string]: unknown;
|
|
2663
3588
|
};
|
|
@@ -2665,8 +3590,8 @@ export interface paths {
|
|
|
2665
3590
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2666
3591
|
};
|
|
2667
3592
|
};
|
|
2668
|
-
/** @description
|
|
2669
|
-
|
|
3593
|
+
/** @description Not found */
|
|
3594
|
+
404: {
|
|
2670
3595
|
headers: {
|
|
2671
3596
|
[name: string]: unknown;
|
|
2672
3597
|
};
|
|
@@ -2674,45 +3599,8 @@ export interface paths {
|
|
|
2674
3599
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2675
3600
|
};
|
|
2676
3601
|
};
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
delete?: never;
|
|
2680
|
-
options?: never;
|
|
2681
|
-
head?: never;
|
|
2682
|
-
patch?: never;
|
|
2683
|
-
trace?: never;
|
|
2684
|
-
};
|
|
2685
|
-
"/v1/billing/subscriptions": {
|
|
2686
|
-
parameters: {
|
|
2687
|
-
query?: never;
|
|
2688
|
-
header?: never;
|
|
2689
|
-
path?: never;
|
|
2690
|
-
cookie?: never;
|
|
2691
|
-
};
|
|
2692
|
-
/**
|
|
2693
|
-
* List Stripe subscriptions
|
|
2694
|
-
* @description Return every active Stripe subscription on the authenticated user's customer record — both per-line rental subs and BYOD slot subs. Period boundaries, line link, price ID, and cancellation flag are surfaced verbatim from Stripe.
|
|
2695
|
-
*/
|
|
2696
|
-
get: {
|
|
2697
|
-
parameters: {
|
|
2698
|
-
query?: never;
|
|
2699
|
-
header?: never;
|
|
2700
|
-
path?: never;
|
|
2701
|
-
cookie?: never;
|
|
2702
|
-
};
|
|
2703
|
-
requestBody?: never;
|
|
2704
|
-
responses: {
|
|
2705
|
-
/** @description Subscription list */
|
|
2706
|
-
200: {
|
|
2707
|
-
headers: {
|
|
2708
|
-
[name: string]: unknown;
|
|
2709
|
-
};
|
|
2710
|
-
content: {
|
|
2711
|
-
"application/json": components["schemas"]["SubscriptionListEnvelope"];
|
|
2712
|
-
};
|
|
2713
|
-
};
|
|
2714
|
-
/** @description Bad request — validation failed */
|
|
2715
|
-
400: {
|
|
3602
|
+
/** @description Conflict — concurrent or terminal state */
|
|
3603
|
+
409: {
|
|
2716
3604
|
headers: {
|
|
2717
3605
|
[name: string]: unknown;
|
|
2718
3606
|
};
|
|
@@ -2720,8 +3608,8 @@ export interface paths {
|
|
|
2720
3608
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2721
3609
|
};
|
|
2722
3610
|
};
|
|
2723
|
-
/** @description
|
|
2724
|
-
|
|
3611
|
+
/** @description Unprocessable — domain rule violation */
|
|
3612
|
+
422: {
|
|
2725
3613
|
headers: {
|
|
2726
3614
|
[name: string]: unknown;
|
|
2727
3615
|
};
|
|
@@ -2749,15 +3637,9 @@ export interface paths {
|
|
|
2749
3637
|
};
|
|
2750
3638
|
};
|
|
2751
3639
|
};
|
|
2752
|
-
put?: never;
|
|
2753
|
-
post?: never;
|
|
2754
|
-
delete?: never;
|
|
2755
|
-
options?: never;
|
|
2756
|
-
head?: never;
|
|
2757
|
-
patch?: never;
|
|
2758
3640
|
trace?: never;
|
|
2759
3641
|
};
|
|
2760
|
-
"/v1/billing/
|
|
3642
|
+
"/v1/billing/subscriptions": {
|
|
2761
3643
|
parameters: {
|
|
2762
3644
|
query?: never;
|
|
2763
3645
|
header?: never;
|
|
@@ -2765,8 +3647,8 @@ export interface paths {
|
|
|
2765
3647
|
cookie?: never;
|
|
2766
3648
|
};
|
|
2767
3649
|
/**
|
|
2768
|
-
* List Stripe
|
|
2769
|
-
* @description
|
|
3650
|
+
* List Stripe subscriptions
|
|
3651
|
+
* @description Return every active Stripe subscription on the authenticated user's customer record — both per-line rental subs and BYOD slot subs. Period boundaries, line link, price ID, and cancellation flag are surfaced verbatim from Stripe.
|
|
2770
3652
|
*/
|
|
2771
3653
|
get: {
|
|
2772
3654
|
parameters: {
|
|
@@ -2777,13 +3659,13 @@ export interface paths {
|
|
|
2777
3659
|
};
|
|
2778
3660
|
requestBody?: never;
|
|
2779
3661
|
responses: {
|
|
2780
|
-
/** @description
|
|
3662
|
+
/** @description Subscription list */
|
|
2781
3663
|
200: {
|
|
2782
3664
|
headers: {
|
|
2783
3665
|
[name: string]: unknown;
|
|
2784
3666
|
};
|
|
2785
3667
|
content: {
|
|
2786
|
-
"application/json": components["schemas"]["
|
|
3668
|
+
"application/json": components["schemas"]["SubscriptionListEnvelope"];
|
|
2787
3669
|
};
|
|
2788
3670
|
};
|
|
2789
3671
|
/** @description Bad request — validation failed */
|
|
@@ -2832,38 +3714,33 @@ export interface paths {
|
|
|
2832
3714
|
patch?: never;
|
|
2833
3715
|
trace?: never;
|
|
2834
3716
|
};
|
|
2835
|
-
"/v1/billing/
|
|
3717
|
+
"/v1/billing/invoices": {
|
|
2836
3718
|
parameters: {
|
|
2837
3719
|
query?: never;
|
|
2838
3720
|
header?: never;
|
|
2839
3721
|
path?: never;
|
|
2840
3722
|
cookie?: never;
|
|
2841
3723
|
};
|
|
2842
|
-
get?: never;
|
|
2843
|
-
put?: never;
|
|
2844
|
-
post?: never;
|
|
2845
3724
|
/**
|
|
2846
|
-
*
|
|
2847
|
-
* @description
|
|
3725
|
+
* List Stripe invoices
|
|
3726
|
+
* @description List the authenticated user's Stripe invoices in reverse-chronological order. Each invoice exposes the period boundaries (unix seconds), the integer-cent amounts, the hosted invoice URL, and the PDF link.
|
|
2848
3727
|
*/
|
|
2849
|
-
|
|
3728
|
+
get: {
|
|
2850
3729
|
parameters: {
|
|
2851
3730
|
query?: never;
|
|
2852
3731
|
header?: never;
|
|
2853
|
-
path
|
|
2854
|
-
id: string;
|
|
2855
|
-
};
|
|
3732
|
+
path?: never;
|
|
2856
3733
|
cookie?: never;
|
|
2857
3734
|
};
|
|
2858
3735
|
requestBody?: never;
|
|
2859
3736
|
responses: {
|
|
2860
|
-
/** @description
|
|
3737
|
+
/** @description Invoice list */
|
|
2861
3738
|
200: {
|
|
2862
3739
|
headers: {
|
|
2863
3740
|
[name: string]: unknown;
|
|
2864
3741
|
};
|
|
2865
3742
|
content: {
|
|
2866
|
-
"application/json": components["schemas"]["
|
|
3743
|
+
"application/json": components["schemas"]["InvoiceListEnvelope"];
|
|
2867
3744
|
};
|
|
2868
3745
|
};
|
|
2869
3746
|
/** @description Bad request — validation failed */
|
|
@@ -2884,24 +3761,6 @@ export interface paths {
|
|
|
2884
3761
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2885
3762
|
};
|
|
2886
3763
|
};
|
|
2887
|
-
/** @description Not found */
|
|
2888
|
-
404: {
|
|
2889
|
-
headers: {
|
|
2890
|
-
[name: string]: unknown;
|
|
2891
|
-
};
|
|
2892
|
-
content: {
|
|
2893
|
-
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2894
|
-
};
|
|
2895
|
-
};
|
|
2896
|
-
/** @description Conflict — concurrent or terminal state */
|
|
2897
|
-
409: {
|
|
2898
|
-
headers: {
|
|
2899
|
-
[name: string]: unknown;
|
|
2900
|
-
};
|
|
2901
|
-
content: {
|
|
2902
|
-
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
2903
|
-
};
|
|
2904
|
-
};
|
|
2905
3764
|
/** @description Too many requests — rate limit exceeded */
|
|
2906
3765
|
429: {
|
|
2907
3766
|
headers: {
|
|
@@ -2922,6 +3781,9 @@ export interface paths {
|
|
|
2922
3781
|
};
|
|
2923
3782
|
};
|
|
2924
3783
|
};
|
|
3784
|
+
put?: never;
|
|
3785
|
+
post?: never;
|
|
3786
|
+
delete?: never;
|
|
2925
3787
|
options?: never;
|
|
2926
3788
|
head?: never;
|
|
2927
3789
|
patch?: never;
|
|
@@ -3242,15 +4104,21 @@ export interface paths {
|
|
|
3242
4104
|
};
|
|
3243
4105
|
/**
|
|
3244
4106
|
* List messages
|
|
3245
|
-
* @description Cursor-paginated list of messages, newest first. Each item carries the full `MessageV1` shape — partners can write a uniform handler over both `GET /v1/messages` and `GET /v1/messages/{id}`. Filter by `line_id`, `status`, `direction`, or `kind` (`message` drops the separate reaction/voice rows for a clean feed; `reaction`/`voice` fetch only those; omit for all kinds); pass an opaque `cursor` from the previous page's `next_cursor` to advance.
|
|
4107
|
+
* @description Cursor-paginated list of messages, newest first by default. Each item carries the full `MessageV1` shape — partners can write a uniform handler over both `GET /v1/messages` and `GET /v1/messages/{id}`. Filter by `line_id`, `status`, `direction`, or `kind` (`message` drops the separate reaction/voice rows for a clean feed; `reaction`/`voice` fetch only those; omit for all kinds); pass an opaque `cursor` from the previous page's `next_cursor` to advance. `sort=scheduled_for` serves the queue in departure order instead (rows with no `scheduled_for` last in either direction); `order` flips the direction. A cursor belongs to the sort it was minted for — replaying it under a different `sort`/`order` restarts from the first page.
|
|
3246
4108
|
*/
|
|
3247
4109
|
get: {
|
|
3248
4110
|
parameters: {
|
|
3249
4111
|
query?: {
|
|
3250
4112
|
line_id?: string;
|
|
3251
|
-
status?: "queued" | "sent" | "delivered" | "read" | "failed";
|
|
4113
|
+
status?: "queued" | "scheduled" | "sent" | "delivered" | "read" | "failed" | "cancelled";
|
|
3252
4114
|
direction?: "outbound" | "inbound";
|
|
4115
|
+
since?: string;
|
|
4116
|
+
until?: string;
|
|
3253
4117
|
kind?: "message" | "voice" | "reaction";
|
|
4118
|
+
/** @description Ordering key. `created_at` (default) is arrival order; `scheduled_for` is departure order — the same instant the `scheduled_for` field reads back, with rows that have none last in both directions. */
|
|
4119
|
+
sort?: "created_at" | "scheduled_for";
|
|
4120
|
+
/** @description Ordering direction. Defaults to `desc` for `sort=created_at` (newest first) and `asc` for `sort=scheduled_for` (soonest first). */
|
|
4121
|
+
order?: "asc" | "desc";
|
|
3254
4122
|
cursor?: string;
|
|
3255
4123
|
limit?: number;
|
|
3256
4124
|
};
|
|
@@ -3926,7 +4794,7 @@ export interface paths {
|
|
|
3926
4794
|
};
|
|
3927
4795
|
};
|
|
3928
4796
|
};
|
|
3929
|
-
/** @description Bad request —
|
|
4797
|
+
/** @description Bad request. `validation_failed` — the body does not match the schema. `webhook_url_not_allowed` — the URL is refused by the SSRF guard; `error.issues[0].code` names why: `not_https` (only https:// is accepted), `ssrf_blocked` (the host is, or resolves to, a loopback, link-local, private, carrier-grade NAT or otherwise non-public address — every resolved address is checked), `dns_failed` (the host does not resolve) or `invalid_url`. The same guard runs again before every delivery: a subscription whose host later resolves to a non-public address gets no request, and is suspended. */
|
|
3930
4798
|
400: {
|
|
3931
4799
|
headers: {
|
|
3932
4800
|
[name: string]: unknown;
|
|
@@ -4156,7 +5024,7 @@ export interface paths {
|
|
|
4156
5024
|
"application/json": components["schemas"]["WebhookV1Envelope"];
|
|
4157
5025
|
};
|
|
4158
5026
|
};
|
|
4159
|
-
/** @description Bad request —
|
|
5027
|
+
/** @description Bad request. `validation_failed` — the body does not match the schema. `webhook_url_not_allowed` — the URL is refused by the SSRF guard; `error.issues[0].code` names why: `not_https` (only https:// is accepted), `ssrf_blocked` (the host is, or resolves to, a loopback, link-local, private, carrier-grade NAT or otherwise non-public address — every resolved address is checked), `dns_failed` (the host does not resolve) or `invalid_url`. The same guard runs again before every delivery: a subscription whose host later resolves to a non-public address gets no request, and is suspended. */
|
|
4160
5028
|
400: {
|
|
4161
5029
|
headers: {
|
|
4162
5030
|
[name: string]: unknown;
|
|
@@ -4757,22 +5625,101 @@ export interface paths {
|
|
|
4757
5625
|
};
|
|
4758
5626
|
};
|
|
4759
5627
|
responses: {
|
|
4760
|
-
/** @description Lookup result — cache hit, fast probe, or an un-probed miss */
|
|
5628
|
+
/** @description Lookup result — cache hit, fast probe, or an un-probed miss */
|
|
5629
|
+
200: {
|
|
5630
|
+
headers: {
|
|
5631
|
+
[name: string]: unknown;
|
|
5632
|
+
};
|
|
5633
|
+
content: {
|
|
5634
|
+
"application/json": components["schemas"]["LookupEnvelope"];
|
|
5635
|
+
};
|
|
5636
|
+
};
|
|
5637
|
+
/** @description Lookup pending — a device probe was dispatched but had not answered within the wait budget; re-poll the same request after `retry_after` seconds */
|
|
5638
|
+
202: {
|
|
5639
|
+
headers: {
|
|
5640
|
+
[name: string]: unknown;
|
|
5641
|
+
};
|
|
5642
|
+
content: {
|
|
5643
|
+
"application/json": components["schemas"]["LookupEnvelope"];
|
|
5644
|
+
};
|
|
5645
|
+
};
|
|
5646
|
+
/** @description Bad request — validation failed */
|
|
5647
|
+
400: {
|
|
5648
|
+
headers: {
|
|
5649
|
+
[name: string]: unknown;
|
|
5650
|
+
};
|
|
5651
|
+
content: {
|
|
5652
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
5653
|
+
};
|
|
5654
|
+
};
|
|
5655
|
+
/** @description Unauthenticated — missing or invalid bearer token */
|
|
5656
|
+
401: {
|
|
5657
|
+
headers: {
|
|
5658
|
+
[name: string]: unknown;
|
|
5659
|
+
};
|
|
5660
|
+
content: {
|
|
5661
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
5662
|
+
};
|
|
5663
|
+
};
|
|
5664
|
+
/** @description Too many requests — rate limit exceeded */
|
|
5665
|
+
429: {
|
|
5666
|
+
headers: {
|
|
5667
|
+
[name: string]: unknown;
|
|
5668
|
+
};
|
|
5669
|
+
content: {
|
|
5670
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
5671
|
+
};
|
|
5672
|
+
};
|
|
5673
|
+
/** @description Internal server error */
|
|
5674
|
+
500: {
|
|
5675
|
+
headers: {
|
|
5676
|
+
[name: string]: unknown;
|
|
5677
|
+
};
|
|
5678
|
+
content: {
|
|
5679
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
5680
|
+
};
|
|
5681
|
+
};
|
|
5682
|
+
};
|
|
5683
|
+
};
|
|
5684
|
+
delete?: never;
|
|
5685
|
+
options?: never;
|
|
5686
|
+
head?: never;
|
|
5687
|
+
patch?: never;
|
|
5688
|
+
trace?: never;
|
|
5689
|
+
};
|
|
5690
|
+
"/v1/attention": {
|
|
5691
|
+
parameters: {
|
|
5692
|
+
query?: never;
|
|
5693
|
+
header?: never;
|
|
5694
|
+
path?: never;
|
|
5695
|
+
cookie?: never;
|
|
5696
|
+
};
|
|
5697
|
+
/**
|
|
5698
|
+
* What currently needs attention on the caller's lines
|
|
5699
|
+
* @description Every line of yours with something wrong: an open incident, a degraded health state, or a fleet probe that has flagged its hardware. One entry per LINE — two faults on one number are one entry. **A BYOD line appears immediately** and carries its reasons. **A rental, pool or shared line appears only once the fault has lasted 15 minutes** (`RENTAL_DURABLE_OFFLINE_MINUTES`, the same threshold as the durable `line.offline` webhook) and carries `reasons: []` with `detail_withheld: true` — per §4.4 a customer with no access to the hardware is told the line is unavailable and being resolved, never which check on which machine failed. `since` is when the fault started; it is null when the underlying detector has no anchor for it. A line-scoped API key sees only the lines in its allowlist.
|
|
5700
|
+
*/
|
|
5701
|
+
get: {
|
|
5702
|
+
parameters: {
|
|
5703
|
+
query?: never;
|
|
5704
|
+
header?: never;
|
|
5705
|
+
path?: never;
|
|
5706
|
+
cookie?: never;
|
|
5707
|
+
};
|
|
5708
|
+
requestBody?: never;
|
|
5709
|
+
responses: {
|
|
5710
|
+
/** @description Lines needing attention, longest-standing first */
|
|
4761
5711
|
200: {
|
|
4762
5712
|
headers: {
|
|
4763
5713
|
[name: string]: unknown;
|
|
4764
5714
|
};
|
|
4765
5715
|
content: {
|
|
4766
|
-
"application/json":
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
};
|
|
4774
|
-
content: {
|
|
4775
|
-
"application/json": components["schemas"]["LookupEnvelope"];
|
|
5716
|
+
"application/json": {
|
|
5717
|
+
/** @enum {boolean} */
|
|
5718
|
+
success: true;
|
|
5719
|
+
data: components["schemas"]["AttentionList"];
|
|
5720
|
+
trace_id: string;
|
|
5721
|
+
request_id: string;
|
|
5722
|
+
};
|
|
4776
5723
|
};
|
|
4777
5724
|
};
|
|
4778
5725
|
/** @description Bad request — validation failed */
|
|
@@ -4813,6 +5760,8 @@ export interface paths {
|
|
|
4813
5760
|
};
|
|
4814
5761
|
};
|
|
4815
5762
|
};
|
|
5763
|
+
put?: never;
|
|
5764
|
+
post?: never;
|
|
4816
5765
|
delete?: never;
|
|
4817
5766
|
options?: never;
|
|
4818
5767
|
head?: never;
|
|
@@ -5407,8 +6356,246 @@ export interface paths {
|
|
|
5407
6356
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
5408
6357
|
};
|
|
5409
6358
|
};
|
|
5410
|
-
/** @description Not found */
|
|
5411
|
-
404: {
|
|
6359
|
+
/** @description Not found */
|
|
6360
|
+
404: {
|
|
6361
|
+
headers: {
|
|
6362
|
+
[name: string]: unknown;
|
|
6363
|
+
};
|
|
6364
|
+
content: {
|
|
6365
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
6366
|
+
};
|
|
6367
|
+
};
|
|
6368
|
+
/** @description Too many requests — rate limit exceeded */
|
|
6369
|
+
429: {
|
|
6370
|
+
headers: {
|
|
6371
|
+
[name: string]: unknown;
|
|
6372
|
+
};
|
|
6373
|
+
content: {
|
|
6374
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
6375
|
+
};
|
|
6376
|
+
};
|
|
6377
|
+
/** @description Internal server error */
|
|
6378
|
+
500: {
|
|
6379
|
+
headers: {
|
|
6380
|
+
[name: string]: unknown;
|
|
6381
|
+
};
|
|
6382
|
+
content: {
|
|
6383
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
6384
|
+
};
|
|
6385
|
+
};
|
|
6386
|
+
};
|
|
6387
|
+
};
|
|
6388
|
+
delete?: never;
|
|
6389
|
+
options?: never;
|
|
6390
|
+
head?: never;
|
|
6391
|
+
patch?: never;
|
|
6392
|
+
trace?: never;
|
|
6393
|
+
};
|
|
6394
|
+
"/v1/trial/init": {
|
|
6395
|
+
parameters: {
|
|
6396
|
+
query?: never;
|
|
6397
|
+
header?: never;
|
|
6398
|
+
path?: never;
|
|
6399
|
+
cookie?: never;
|
|
6400
|
+
};
|
|
6401
|
+
get?: never;
|
|
6402
|
+
put?: never;
|
|
6403
|
+
/**
|
|
6404
|
+
* Start a trial session
|
|
6405
|
+
* @description Create a pairing-pending trial session owned by the caller (dashboard JWT for direct self-serve, or an API key for wholesale/SDK). Returns a one-time pairing token the partner embeds in their onboarding UI; the recipient claims it by sending an inbound message that links them to a pool line. Direct accounts may hold only one live trial at a time.
|
|
6406
|
+
*/
|
|
6407
|
+
post: {
|
|
6408
|
+
parameters: {
|
|
6409
|
+
query?: never;
|
|
6410
|
+
header?: never;
|
|
6411
|
+
path?: never;
|
|
6412
|
+
cookie?: never;
|
|
6413
|
+
};
|
|
6414
|
+
requestBody?: {
|
|
6415
|
+
content: {
|
|
6416
|
+
"application/json": components["schemas"]["TrialInitBody"];
|
|
6417
|
+
};
|
|
6418
|
+
};
|
|
6419
|
+
responses: {
|
|
6420
|
+
/** @description Trial session created — pairing pending */
|
|
6421
|
+
201: {
|
|
6422
|
+
headers: {
|
|
6423
|
+
[name: string]: unknown;
|
|
6424
|
+
};
|
|
6425
|
+
content: {
|
|
6426
|
+
"application/json": components["schemas"]["TrialInitEnvelope"];
|
|
6427
|
+
};
|
|
6428
|
+
};
|
|
6429
|
+
/** @description Bad request — validation failed */
|
|
6430
|
+
400: {
|
|
6431
|
+
headers: {
|
|
6432
|
+
[name: string]: unknown;
|
|
6433
|
+
};
|
|
6434
|
+
content: {
|
|
6435
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
6436
|
+
};
|
|
6437
|
+
};
|
|
6438
|
+
/** @description Unauthenticated — missing or invalid bearer token */
|
|
6439
|
+
401: {
|
|
6440
|
+
headers: {
|
|
6441
|
+
[name: string]: unknown;
|
|
6442
|
+
};
|
|
6443
|
+
content: {
|
|
6444
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
6445
|
+
};
|
|
6446
|
+
};
|
|
6447
|
+
/** @description Conflict — concurrent or terminal state */
|
|
6448
|
+
409: {
|
|
6449
|
+
headers: {
|
|
6450
|
+
[name: string]: unknown;
|
|
6451
|
+
};
|
|
6452
|
+
content: {
|
|
6453
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
6454
|
+
};
|
|
6455
|
+
};
|
|
6456
|
+
/** @description Too many requests — rate limit exceeded */
|
|
6457
|
+
429: {
|
|
6458
|
+
headers: {
|
|
6459
|
+
[name: string]: unknown;
|
|
6460
|
+
};
|
|
6461
|
+
content: {
|
|
6462
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
6463
|
+
};
|
|
6464
|
+
};
|
|
6465
|
+
/** @description Internal server error */
|
|
6466
|
+
500: {
|
|
6467
|
+
headers: {
|
|
6468
|
+
[name: string]: unknown;
|
|
6469
|
+
};
|
|
6470
|
+
content: {
|
|
6471
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
6472
|
+
};
|
|
6473
|
+
};
|
|
6474
|
+
};
|
|
6475
|
+
};
|
|
6476
|
+
delete?: never;
|
|
6477
|
+
options?: never;
|
|
6478
|
+
head?: never;
|
|
6479
|
+
patch?: never;
|
|
6480
|
+
trace?: never;
|
|
6481
|
+
};
|
|
6482
|
+
"/v1/trial/status": {
|
|
6483
|
+
parameters: {
|
|
6484
|
+
query?: never;
|
|
6485
|
+
header?: never;
|
|
6486
|
+
path?: never;
|
|
6487
|
+
cookie?: never;
|
|
6488
|
+
};
|
|
6489
|
+
/**
|
|
6490
|
+
* Check trial pairing status
|
|
6491
|
+
* @description Token-keyed public lookup. Returns the current trial state — `pairing_pending` while waiting for the recipient's first inbound, `paired` once linked, `expired` after the pairing window. On first poll after `paired` the response also reveals the `trial_api_key` (`isnap_test_*`) for the partner to embed.
|
|
6492
|
+
*/
|
|
6493
|
+
get: {
|
|
6494
|
+
parameters: {
|
|
6495
|
+
query: {
|
|
6496
|
+
token: string;
|
|
6497
|
+
};
|
|
6498
|
+
header?: never;
|
|
6499
|
+
path?: never;
|
|
6500
|
+
cookie?: never;
|
|
6501
|
+
};
|
|
6502
|
+
requestBody?: never;
|
|
6503
|
+
responses: {
|
|
6504
|
+
/** @description Current trial status */
|
|
6505
|
+
200: {
|
|
6506
|
+
headers: {
|
|
6507
|
+
[name: string]: unknown;
|
|
6508
|
+
};
|
|
6509
|
+
content: {
|
|
6510
|
+
"application/json": components["schemas"]["TrialStatusEnvelope"];
|
|
6511
|
+
};
|
|
6512
|
+
};
|
|
6513
|
+
/** @description Bad request — validation failed */
|
|
6514
|
+
400: {
|
|
6515
|
+
headers: {
|
|
6516
|
+
[name: string]: unknown;
|
|
6517
|
+
};
|
|
6518
|
+
content: {
|
|
6519
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
6520
|
+
};
|
|
6521
|
+
};
|
|
6522
|
+
/** @description Not found */
|
|
6523
|
+
404: {
|
|
6524
|
+
headers: {
|
|
6525
|
+
[name: string]: unknown;
|
|
6526
|
+
};
|
|
6527
|
+
content: {
|
|
6528
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
6529
|
+
};
|
|
6530
|
+
};
|
|
6531
|
+
/** @description Too many requests — rate limit exceeded */
|
|
6532
|
+
429: {
|
|
6533
|
+
headers: {
|
|
6534
|
+
[name: string]: unknown;
|
|
6535
|
+
};
|
|
6536
|
+
content: {
|
|
6537
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
6538
|
+
};
|
|
6539
|
+
};
|
|
6540
|
+
/** @description Internal server error */
|
|
6541
|
+
500: {
|
|
6542
|
+
headers: {
|
|
6543
|
+
[name: string]: unknown;
|
|
6544
|
+
};
|
|
6545
|
+
content: {
|
|
6546
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
6547
|
+
};
|
|
6548
|
+
};
|
|
6549
|
+
};
|
|
6550
|
+
};
|
|
6551
|
+
put?: never;
|
|
6552
|
+
post?: never;
|
|
6553
|
+
delete?: never;
|
|
6554
|
+
options?: never;
|
|
6555
|
+
head?: never;
|
|
6556
|
+
patch?: never;
|
|
6557
|
+
trace?: never;
|
|
6558
|
+
};
|
|
6559
|
+
"/v1/trial/activity": {
|
|
6560
|
+
parameters: {
|
|
6561
|
+
query?: never;
|
|
6562
|
+
header?: never;
|
|
6563
|
+
path?: never;
|
|
6564
|
+
cookie?: never;
|
|
6565
|
+
};
|
|
6566
|
+
/**
|
|
6567
|
+
* Get trial activity counters
|
|
6568
|
+
* @description Trial-key-only snapshot of the dormancy and outbound-without-inbound counters. Partner dashboards poll this to render the trial's live state ("3/10 sends since last inbound", dormancy timer remaining).
|
|
6569
|
+
*/
|
|
6570
|
+
get: {
|
|
6571
|
+
parameters: {
|
|
6572
|
+
query?: never;
|
|
6573
|
+
header?: never;
|
|
6574
|
+
path?: never;
|
|
6575
|
+
cookie?: never;
|
|
6576
|
+
};
|
|
6577
|
+
requestBody?: never;
|
|
6578
|
+
responses: {
|
|
6579
|
+
/** @description Trial activity snapshot */
|
|
6580
|
+
200: {
|
|
6581
|
+
headers: {
|
|
6582
|
+
[name: string]: unknown;
|
|
6583
|
+
};
|
|
6584
|
+
content: {
|
|
6585
|
+
"application/json": components["schemas"]["TrialActivityEnvelope"];
|
|
6586
|
+
};
|
|
6587
|
+
};
|
|
6588
|
+
/** @description Bad request — validation failed */
|
|
6589
|
+
400: {
|
|
6590
|
+
headers: {
|
|
6591
|
+
[name: string]: unknown;
|
|
6592
|
+
};
|
|
6593
|
+
content: {
|
|
6594
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
6595
|
+
};
|
|
6596
|
+
};
|
|
6597
|
+
/** @description Unauthenticated — missing or invalid bearer token */
|
|
6598
|
+
401: {
|
|
5412
6599
|
headers: {
|
|
5413
6600
|
[name: string]: unknown;
|
|
5414
6601
|
};
|
|
@@ -5436,13 +6623,15 @@ export interface paths {
|
|
|
5436
6623
|
};
|
|
5437
6624
|
};
|
|
5438
6625
|
};
|
|
6626
|
+
put?: never;
|
|
6627
|
+
post?: never;
|
|
5439
6628
|
delete?: never;
|
|
5440
6629
|
options?: never;
|
|
5441
6630
|
head?: never;
|
|
5442
6631
|
patch?: never;
|
|
5443
6632
|
trace?: never;
|
|
5444
6633
|
};
|
|
5445
|
-
"/v1/trial/
|
|
6634
|
+
"/v1/trial/{trial_id}/revoke": {
|
|
5446
6635
|
parameters: {
|
|
5447
6636
|
query?: never;
|
|
5448
6637
|
header?: never;
|
|
@@ -5452,29 +6641,32 @@ export interface paths {
|
|
|
5452
6641
|
get?: never;
|
|
5453
6642
|
put?: never;
|
|
5454
6643
|
/**
|
|
5455
|
-
*
|
|
5456
|
-
* @description
|
|
6644
|
+
* Revoke a trial session
|
|
6645
|
+
* @description Terminate a trial owned by the caller, freeing its pool-line slot (the same handle can immediately start a fresh trial) and invalidating its trial API key. Idempotent — revoking an already-revoked trial returns `already_revoked: true` with a 200. A trial the caller does not own returns 404 (no existence leak). Per-partner rebind policy (WHA-1642) applies ONLY to `reason: rebind` (`partner`/`admin` always pass): a partner with rebind disabled gets 403 `rebind_not_allowed`, and one over its daily rebind cap gets 429 `rebind_cap_reached` carrying `retry_at`.
|
|
5457
6646
|
*/
|
|
5458
6647
|
post: {
|
|
5459
6648
|
parameters: {
|
|
5460
6649
|
query?: never;
|
|
5461
6650
|
header?: never;
|
|
5462
|
-
path
|
|
6651
|
+
path: {
|
|
6652
|
+
/** @description The trl_<base62> public id returned by POST /v1/trial/init. */
|
|
6653
|
+
trial_id: string;
|
|
6654
|
+
};
|
|
5463
6655
|
cookie?: never;
|
|
5464
6656
|
};
|
|
5465
6657
|
requestBody?: {
|
|
5466
6658
|
content: {
|
|
5467
|
-
"application/json": components["schemas"]["
|
|
6659
|
+
"application/json": components["schemas"]["TrialRevokeBody"];
|
|
5468
6660
|
};
|
|
5469
6661
|
};
|
|
5470
6662
|
responses: {
|
|
5471
|
-
/** @description Trial
|
|
5472
|
-
|
|
6663
|
+
/** @description Trial revoked (idempotent) */
|
|
6664
|
+
200: {
|
|
5473
6665
|
headers: {
|
|
5474
6666
|
[name: string]: unknown;
|
|
5475
6667
|
};
|
|
5476
6668
|
content: {
|
|
5477
|
-
"application/json": components["schemas"]["
|
|
6669
|
+
"application/json": components["schemas"]["TrialRevokeEnvelope"];
|
|
5478
6670
|
};
|
|
5479
6671
|
};
|
|
5480
6672
|
/** @description Bad request — validation failed */
|
|
@@ -5495,8 +6687,26 @@ export interface paths {
|
|
|
5495
6687
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
5496
6688
|
};
|
|
5497
6689
|
};
|
|
5498
|
-
/** @description
|
|
5499
|
-
|
|
6690
|
+
/** @description Forbidden — caller authenticated but not allowed */
|
|
6691
|
+
403: {
|
|
6692
|
+
headers: {
|
|
6693
|
+
[name: string]: unknown;
|
|
6694
|
+
};
|
|
6695
|
+
content: {
|
|
6696
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
6697
|
+
};
|
|
6698
|
+
};
|
|
6699
|
+
/** @description Not found */
|
|
6700
|
+
404: {
|
|
6701
|
+
headers: {
|
|
6702
|
+
[name: string]: unknown;
|
|
6703
|
+
};
|
|
6704
|
+
content: {
|
|
6705
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
6706
|
+
};
|
|
6707
|
+
};
|
|
6708
|
+
/** @description Unprocessable — domain rule violation */
|
|
6709
|
+
422: {
|
|
5500
6710
|
headers: {
|
|
5501
6711
|
[name: string]: unknown;
|
|
5502
6712
|
};
|
|
@@ -5530,35 +6740,39 @@ export interface paths {
|
|
|
5530
6740
|
patch?: never;
|
|
5531
6741
|
trace?: never;
|
|
5532
6742
|
};
|
|
5533
|
-
"/v1/
|
|
6743
|
+
"/v1/byod/pair": {
|
|
5534
6744
|
parameters: {
|
|
5535
6745
|
query?: never;
|
|
5536
6746
|
header?: never;
|
|
5537
6747
|
path?: never;
|
|
5538
6748
|
cookie?: never;
|
|
5539
6749
|
};
|
|
6750
|
+
get?: never;
|
|
6751
|
+
put?: never;
|
|
5540
6752
|
/**
|
|
5541
|
-
*
|
|
5542
|
-
* @description
|
|
6753
|
+
* Start a BYOD pairing flow
|
|
6754
|
+
* @description Mint a one-time activation code plus the stable per-platform bridge-installer download links for a customer-owned Mac+iPhone or Android device. The customer runs the bridge, enters the code, and the device-side `POST /device/activate` consumes it to mint a `byod_imessage` or `byod_android` line — the platform is derived there from what the bridge reports.
|
|
5543
6755
|
*/
|
|
5544
|
-
|
|
6756
|
+
post: {
|
|
5545
6757
|
parameters: {
|
|
5546
|
-
query
|
|
5547
|
-
token: string;
|
|
5548
|
-
};
|
|
6758
|
+
query?: never;
|
|
5549
6759
|
header?: never;
|
|
5550
6760
|
path?: never;
|
|
5551
6761
|
cookie?: never;
|
|
5552
6762
|
};
|
|
5553
|
-
requestBody?:
|
|
6763
|
+
requestBody?: {
|
|
6764
|
+
content: {
|
|
6765
|
+
"application/json": components["schemas"]["ByodPairBody"];
|
|
6766
|
+
};
|
|
6767
|
+
};
|
|
5554
6768
|
responses: {
|
|
5555
|
-
/** @description
|
|
5556
|
-
|
|
6769
|
+
/** @description Activation code + bridge download URL */
|
|
6770
|
+
201: {
|
|
5557
6771
|
headers: {
|
|
5558
6772
|
[name: string]: unknown;
|
|
5559
6773
|
};
|
|
5560
6774
|
content: {
|
|
5561
|
-
"application/json": components["schemas"]["
|
|
6775
|
+
"application/json": components["schemas"]["ByodPairEnvelope"];
|
|
5562
6776
|
};
|
|
5563
6777
|
};
|
|
5564
6778
|
/** @description Bad request — validation failed */
|
|
@@ -5570,6 +6784,15 @@ export interface paths {
|
|
|
5570
6784
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
5571
6785
|
};
|
|
5572
6786
|
};
|
|
6787
|
+
/** @description Unauthenticated — missing or invalid bearer token */
|
|
6788
|
+
401: {
|
|
6789
|
+
headers: {
|
|
6790
|
+
[name: string]: unknown;
|
|
6791
|
+
};
|
|
6792
|
+
content: {
|
|
6793
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
6794
|
+
};
|
|
6795
|
+
};
|
|
5573
6796
|
/** @description Not found */
|
|
5574
6797
|
404: {
|
|
5575
6798
|
headers: {
|
|
@@ -5599,26 +6822,26 @@ export interface paths {
|
|
|
5599
6822
|
};
|
|
5600
6823
|
};
|
|
5601
6824
|
};
|
|
5602
|
-
put?: never;
|
|
5603
|
-
post?: never;
|
|
5604
6825
|
delete?: never;
|
|
5605
6826
|
options?: never;
|
|
5606
6827
|
head?: never;
|
|
5607
6828
|
patch?: never;
|
|
5608
6829
|
trace?: never;
|
|
5609
6830
|
};
|
|
5610
|
-
"/v1/
|
|
6831
|
+
"/v1/macos-sessions/rent": {
|
|
5611
6832
|
parameters: {
|
|
5612
6833
|
query?: never;
|
|
5613
6834
|
header?: never;
|
|
5614
6835
|
path?: never;
|
|
5615
6836
|
cookie?: never;
|
|
5616
6837
|
};
|
|
6838
|
+
get?: never;
|
|
6839
|
+
put?: never;
|
|
5617
6840
|
/**
|
|
5618
|
-
*
|
|
5619
|
-
* @description
|
|
6841
|
+
* Rent a hosted macOS session
|
|
6842
|
+
* @description Take one hosted macOS session out of iSnap stock on the calling wholesale partner’s account. The tenancy starts immediately and `anniversary_at` is stamped with the day it was taken — that day of the month is what the session bills on, clamped to the last day of shorter months. Returns `409 no_macos_session_in_stock` when no confirmed, unrented session sits on a delivered Mac; iSnap provisions one and attaches it, and no request needs to be repeated. Direct customers do not use this verb — they buy sessions through `POST /v1/billing/mac-checkout` and are refused here with `403 not_a_wholesale_partner`.
|
|
5620
6843
|
*/
|
|
5621
|
-
|
|
6844
|
+
post: {
|
|
5622
6845
|
parameters: {
|
|
5623
6846
|
query?: never;
|
|
5624
6847
|
header?: never;
|
|
@@ -5627,13 +6850,13 @@ export interface paths {
|
|
|
5627
6850
|
};
|
|
5628
6851
|
requestBody?: never;
|
|
5629
6852
|
responses: {
|
|
5630
|
-
/** @description
|
|
5631
|
-
|
|
6853
|
+
/** @description The rented session */
|
|
6854
|
+
201: {
|
|
5632
6855
|
headers: {
|
|
5633
6856
|
[name: string]: unknown;
|
|
5634
6857
|
};
|
|
5635
6858
|
content: {
|
|
5636
|
-
"application/json": components["schemas"]["
|
|
6859
|
+
"application/json": components["schemas"]["MacosSessionEnvelope"];
|
|
5637
6860
|
};
|
|
5638
6861
|
};
|
|
5639
6862
|
/** @description Bad request — validation failed */
|
|
@@ -5654,6 +6877,24 @@ export interface paths {
|
|
|
5654
6877
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
5655
6878
|
};
|
|
5656
6879
|
};
|
|
6880
|
+
/** @description Forbidden — caller authenticated but not allowed */
|
|
6881
|
+
403: {
|
|
6882
|
+
headers: {
|
|
6883
|
+
[name: string]: unknown;
|
|
6884
|
+
};
|
|
6885
|
+
content: {
|
|
6886
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
6887
|
+
};
|
|
6888
|
+
};
|
|
6889
|
+
/** @description Conflict — concurrent or terminal state */
|
|
6890
|
+
409: {
|
|
6891
|
+
headers: {
|
|
6892
|
+
[name: string]: unknown;
|
|
6893
|
+
};
|
|
6894
|
+
content: {
|
|
6895
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
6896
|
+
};
|
|
6897
|
+
};
|
|
5657
6898
|
/** @description Too many requests — rate limit exceeded */
|
|
5658
6899
|
429: {
|
|
5659
6900
|
headers: {
|
|
@@ -5674,15 +6915,13 @@ export interface paths {
|
|
|
5674
6915
|
};
|
|
5675
6916
|
};
|
|
5676
6917
|
};
|
|
5677
|
-
put?: never;
|
|
5678
|
-
post?: never;
|
|
5679
6918
|
delete?: never;
|
|
5680
6919
|
options?: never;
|
|
5681
6920
|
head?: never;
|
|
5682
6921
|
patch?: never;
|
|
5683
6922
|
trace?: never;
|
|
5684
6923
|
};
|
|
5685
|
-
"/v1/
|
|
6924
|
+
"/v1/macos-sessions/{id}/cancel": {
|
|
5686
6925
|
parameters: {
|
|
5687
6926
|
query?: never;
|
|
5688
6927
|
header?: never;
|
|
@@ -5692,32 +6931,27 @@ export interface paths {
|
|
|
5692
6931
|
get?: never;
|
|
5693
6932
|
put?: never;
|
|
5694
6933
|
/**
|
|
5695
|
-
*
|
|
5696
|
-
* @description
|
|
6934
|
+
* Cancel a rented macOS session
|
|
6935
|
+
* @description End the tenancy at its next anniversary. The session stays usable and keeps billing until `cancel_at`, which is the next occurrence of `anniversary_at` strictly after the cancellation — so cancelling ON the anniversary buys the month that starts that day, never zero days. Idempotent: a second call returns the `cancel_at` the first one set rather than pushing it a month further out. Only the renting partner may cancel; every other caller gets `404`.
|
|
5697
6936
|
*/
|
|
5698
6937
|
post: {
|
|
5699
6938
|
parameters: {
|
|
5700
6939
|
query?: never;
|
|
5701
6940
|
header?: never;
|
|
5702
6941
|
path: {
|
|
5703
|
-
|
|
5704
|
-
trial_id: string;
|
|
6942
|
+
id: string;
|
|
5705
6943
|
};
|
|
5706
6944
|
cookie?: never;
|
|
5707
6945
|
};
|
|
5708
|
-
requestBody?:
|
|
5709
|
-
content: {
|
|
5710
|
-
"application/json": components["schemas"]["TrialRevokeBody"];
|
|
5711
|
-
};
|
|
5712
|
-
};
|
|
6946
|
+
requestBody?: never;
|
|
5713
6947
|
responses: {
|
|
5714
|
-
/** @description
|
|
6948
|
+
/** @description The cancelled session */
|
|
5715
6949
|
200: {
|
|
5716
6950
|
headers: {
|
|
5717
6951
|
[name: string]: unknown;
|
|
5718
6952
|
};
|
|
5719
6953
|
content: {
|
|
5720
|
-
"application/json": components["schemas"]["
|
|
6954
|
+
"application/json": components["schemas"]["MacosSessionEnvelope"];
|
|
5721
6955
|
};
|
|
5722
6956
|
};
|
|
5723
6957
|
/** @description Bad request — validation failed */
|
|
@@ -5738,15 +6972,6 @@ export interface paths {
|
|
|
5738
6972
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
5739
6973
|
};
|
|
5740
6974
|
};
|
|
5741
|
-
/** @description Forbidden — caller authenticated but not allowed */
|
|
5742
|
-
403: {
|
|
5743
|
-
headers: {
|
|
5744
|
-
[name: string]: unknown;
|
|
5745
|
-
};
|
|
5746
|
-
content: {
|
|
5747
|
-
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
5748
|
-
};
|
|
5749
|
-
};
|
|
5750
6975
|
/** @description Not found */
|
|
5751
6976
|
404: {
|
|
5752
6977
|
headers: {
|
|
@@ -5756,8 +6981,8 @@ export interface paths {
|
|
|
5756
6981
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
5757
6982
|
};
|
|
5758
6983
|
};
|
|
5759
|
-
/** @description
|
|
5760
|
-
|
|
6984
|
+
/** @description Conflict — concurrent or terminal state */
|
|
6985
|
+
409: {
|
|
5761
6986
|
headers: {
|
|
5762
6987
|
[name: string]: unknown;
|
|
5763
6988
|
};
|
|
@@ -5791,7 +7016,7 @@ export interface paths {
|
|
|
5791
7016
|
patch?: never;
|
|
5792
7017
|
trace?: never;
|
|
5793
7018
|
};
|
|
5794
|
-
"/v1/
|
|
7019
|
+
"/v1/macos-sessions/{id}/uncancel": {
|
|
5795
7020
|
parameters: {
|
|
5796
7021
|
query?: never;
|
|
5797
7022
|
header?: never;
|
|
@@ -5801,29 +7026,27 @@ export interface paths {
|
|
|
5801
7026
|
get?: never;
|
|
5802
7027
|
put?: never;
|
|
5803
7028
|
/**
|
|
5804
|
-
*
|
|
5805
|
-
* @description
|
|
7029
|
+
* Keep a cancelled macOS session
|
|
7030
|
+
* @description Withdraw a pending cancellation, clearing `cancel_at` and leaving `anniversary_at` untouched — the billing day does not move. Idempotent on a session that is not cancelled. Only possible before the release runs: once `cancel_at` has passed the paid month is over and this answers `409 macos_session_cancellation_already_due` — the release is hourly, so there is a window in which the date has passed and the session is still rented, and un-cancelling inside it would hold a seat the monthly tally has already stopped billing. After the release has run the tenancy is gone and this returns `404`; the session must be rented again.
|
|
5806
7031
|
*/
|
|
5807
7032
|
post: {
|
|
5808
7033
|
parameters: {
|
|
5809
7034
|
query?: never;
|
|
5810
7035
|
header?: never;
|
|
5811
|
-
path
|
|
5812
|
-
|
|
5813
|
-
};
|
|
5814
|
-
requestBody?: {
|
|
5815
|
-
content: {
|
|
5816
|
-
"application/json": components["schemas"]["ByodPairBody"];
|
|
7036
|
+
path: {
|
|
7037
|
+
id: string;
|
|
5817
7038
|
};
|
|
7039
|
+
cookie?: never;
|
|
5818
7040
|
};
|
|
7041
|
+
requestBody?: never;
|
|
5819
7042
|
responses: {
|
|
5820
|
-
/** @description
|
|
5821
|
-
|
|
7043
|
+
/** @description The session, no longer cancelled */
|
|
7044
|
+
200: {
|
|
5822
7045
|
headers: {
|
|
5823
7046
|
[name: string]: unknown;
|
|
5824
7047
|
};
|
|
5825
7048
|
content: {
|
|
5826
|
-
"application/json": components["schemas"]["
|
|
7049
|
+
"application/json": components["schemas"]["MacosSessionEnvelope"];
|
|
5827
7050
|
};
|
|
5828
7051
|
};
|
|
5829
7052
|
/** @description Bad request — validation failed */
|
|
@@ -5853,6 +7076,15 @@ export interface paths {
|
|
|
5853
7076
|
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
5854
7077
|
};
|
|
5855
7078
|
};
|
|
7079
|
+
/** @description Conflict — concurrent or terminal state */
|
|
7080
|
+
409: {
|
|
7081
|
+
headers: {
|
|
7082
|
+
[name: string]: unknown;
|
|
7083
|
+
};
|
|
7084
|
+
content: {
|
|
7085
|
+
"application/json": components["schemas"]["ErrorEnvelope"];
|
|
7086
|
+
};
|
|
7087
|
+
};
|
|
5856
7088
|
/** @description Too many requests — rate limit exceeded */
|
|
5857
7089
|
429: {
|
|
5858
7090
|
headers: {
|
|
@@ -5888,7 +7120,7 @@ export interface paths {
|
|
|
5888
7120
|
};
|
|
5889
7121
|
/**
|
|
5890
7122
|
* Get the app/bridge download manifest (public)
|
|
5891
|
-
* @description Per-platform installer URL,
|
|
7123
|
+
* @description Per-platform installer URL, published version, and availability. Requires no pairing and no auth — use it for setup guides, "add a device" flows, reinstalls, and update prompts. The URLs are the same stable 302-redirect endpoints `POST /v1/byod/pair` returns in `download_urls`, built by one shared builder so they cannot drift. `version` is read from the release feed beside the artifact the redirect resolves to, and is `null` when that feed publishes nothing — never a configured placeholder.
|
|
5892
7124
|
*/
|
|
5893
7125
|
get: {
|
|
5894
7126
|
parameters: {
|
|
@@ -5996,7 +7228,7 @@ export interface components {
|
|
|
5996
7228
|
state_name: string | null;
|
|
5997
7229
|
/** @enum {string} */
|
|
5998
7230
|
billing_tier: "rental_iphone" | "rental_android" | "byod_imessage" | "byod_android" | "shared_pool" | "shared_imessage";
|
|
5999
|
-
/** @description True when the customer owns the underlying hardware (BYOD billing tiers). BYOD lines expose the full line-health surface
|
|
7231
|
+
/** @description True when the customer owns the underlying hardware (BYOD billing tiers). BYOD lines expose the full line-health surface: GET /v1/lines/{id}/health, the immediate line.offline/line.connected with their diagnostic fields, and the device-health-flux events line.degraded and line.capability_changed. Rental lines (false) are told about DURABLE connectivity changes only, and with NO diagnostic detail by design — line.disconnected always; line.offline once an outage has lasted ≥15 minutes (durable:true, carrying only line_id and detected_at — present it as "line temporarily unavailable, being resolved by the provider"); line.connected on hand-over and on recovery from a surfaced outage — never a transient blip, and never the BYOD-only device-health-flux events they cannot act on. */
|
|
6000
7232
|
byod: boolean;
|
|
6001
7233
|
/** @description True when the line cannot INITIATE a conversation: the contact must send the first message, after which the exchange is unrestricted in both directions. It is NOT receive-only — the line replies, reacts and sends attachments normally once contacted. Messaging a handle that has never contacted the line is rejected with 403 outbound_first_forbidden, per recipient and with no time limit once unlocked. Cheaper than the outbound tier; always false on BYOD/pool lines. */
|
|
6002
7234
|
inbound_only: boolean;
|
|
@@ -6010,6 +7242,19 @@ export interface components {
|
|
|
6010
7242
|
stripe_subscription_id: string | null;
|
|
6011
7243
|
activated_at: string | null;
|
|
6012
7244
|
expires_at: string | null;
|
|
7245
|
+
/** @description The day you took this line, and therefore the day of the month it renews on: billed once per month at this instant, never prorated. Stamped when the line becomes yours; `null` means the line has no per-line anniversary — a direct customer's line renews on its Stripe subscription's own anchor, and a pool line is billed to nobody. Set it explicitly with POST /v1/lines/{id}/anniversary for a line you migrated from your own system, whose real start date iSnap cannot know. */
|
|
7246
|
+
anniversary_at: string | null;
|
|
7247
|
+
/** @description The anniversary occurrence at which iSnap will END this line, set by POST /v1/lines/{id}/cancel and cleared by POST /v1/lines/{id}/uncancel. The line stays fully active and usable until this instant — the month is already paid for and is never prorated — and iSnap terminates it itself when the date arrives. `null` means the line is not cancelled. It survives the termination it schedules, so a `cancelled` line still says which date ended it. */
|
|
7248
|
+
cancel_at: string | null;
|
|
7249
|
+
/** @description The billing anchor you stated for this line — the date the customer who pays for it is billed on. Every line that customer holds moves on this same date, so their period and your invoice advance together. `null` means you stated nothing, NOT that the line has no billing date: it then falls back to the activation instant, which is how every line was billed before anchors existed. Set it at provisioning (`POST /v1/pre-orders`, `POST /v1/lines/{id}/activate`) or change it later with `PATCH /v1/lines/{id}` — a change takes effect at the NEXT anchor and never rewrites a period already billed. */
|
|
7250
|
+
billing_anchor_at: string | null;
|
|
7251
|
+
/** @description The next instant this line will be billed on, derived from the anchor above (or from the activation instant when you stated none) and clamped to the last day of a shorter month — a line anchored on the 31st bills on the 28th in February and on the 31st again in March, the clamp never sticks. At that instant the line is charged one full month at the product it carries then; at the FIRST occurrence after activation it is also credited for the days the activation month had already paid for past it, at the activation rate. `null` when the line will not be billed again: never activated, not in a billable status, or cancelled on or before that occurrence. */
|
|
7252
|
+
next_anchor_at: string | null;
|
|
7253
|
+
/** @description The variant change scheduled for this line's next billing anchor, or `null` when none is pending. `inbound_only` is the value the line WILL carry — the live value stays in the top-level `inbound_only` field until `effective_at` arrives, because the line keeps serving the product it is being billed for until then. Schedule one with POST /v1/lines/{id}/variant and `effective: 'next_anchor'`; cancel it with DELETE /v1/lines/{id}/variant. It is cleared when the change is applied, when it is cancelled, and when the line leaves its owner. */
|
|
7254
|
+
pending_variant: {
|
|
7255
|
+
inbound_only: boolean;
|
|
7256
|
+
effective_at: string;
|
|
7257
|
+
} | null;
|
|
6013
7258
|
created_at: string;
|
|
6014
7259
|
metadata: {
|
|
6015
7260
|
[key: string]: unknown;
|
|
@@ -6020,6 +7265,31 @@ export interface components {
|
|
|
6020
7265
|
shared: boolean;
|
|
6021
7266
|
fulfillment_status?: string | null;
|
|
6022
7267
|
};
|
|
7268
|
+
MacosSession: {
|
|
7269
|
+
/** @example mcs_7Kd2Nq8Rb4Xw1Ty6Ue9Ao3Ph5 */
|
|
7270
|
+
id: string;
|
|
7271
|
+
/** @description Whether this session is currently rented by the calling partner. `false` once it has been released back to iSnap stock. */
|
|
7272
|
+
rented: boolean;
|
|
7273
|
+
/**
|
|
7274
|
+
* Format: date-time
|
|
7275
|
+
* @description The day the session was taken, and the day of the month it bills on. Null once the session is released. A day-of-month past the end of a shorter month bills on that month’s last day.
|
|
7276
|
+
* @example 2026-09-07T14:32:00.000Z
|
|
7277
|
+
*/
|
|
7278
|
+
anniversary_at: string | null;
|
|
7279
|
+
/**
|
|
7280
|
+
* Format: date-time
|
|
7281
|
+
* @description When the tenancy ends — always the next occurrence of `anniversary_at` after the cancellation. Null when the session is not cancelled. The session stays usable and keeps billing until this instant.
|
|
7282
|
+
* @example 2026-10-07T14:32:00.000Z
|
|
7283
|
+
*/
|
|
7284
|
+
cancel_at: string | null;
|
|
7285
|
+
/**
|
|
7286
|
+
* @description `pending_provisioning` while the Mac hosting the session has not been delivered yet; `created` once it has.
|
|
7287
|
+
* @enum {string}
|
|
7288
|
+
*/
|
|
7289
|
+
status: "created" | "pending_provisioning";
|
|
7290
|
+
/** Format: date-time */
|
|
7291
|
+
created_at: string;
|
|
7292
|
+
};
|
|
6023
7293
|
ApiKey: {
|
|
6024
7294
|
/** Format: uuid */
|
|
6025
7295
|
id: string;
|
|
@@ -6066,16 +7336,54 @@ export interface components {
|
|
|
6066
7336
|
};
|
|
6067
7337
|
ActivateLine: {
|
|
6068
7338
|
inbound_only?: boolean;
|
|
7339
|
+
/**
|
|
7340
|
+
* Format: date-time
|
|
7341
|
+
* @description The billing anchor of the customer who pays for this line (ISO-8601, UTC) — the ONE date it is billed on. Its day of the month becomes the line’s billing day, clamped to the last day of a shorter month; the time of day is kept, because the anchor is an instant and not a calendar day. State the date your own customer is billed on and every line they hold moves together: at each occurrence the line is charged one full month, and at the FIRST occurrence after activation it is credited for the days the activation month had already paid for past it, at the activation rate. Omit it and the line is billed on its activation instant, which is the behaviour of every line provisioned before anchors existed. Refused (400 `billing_anchor_too_far`) more than 31 days after the activation — that would make the first period longer than a month.
|
|
7342
|
+
* @example 2026-09-11T09:15:00Z
|
|
7343
|
+
*/
|
|
7344
|
+
billing_anchor_at?: string;
|
|
6069
7345
|
};
|
|
6070
7346
|
TransferOwnership: {
|
|
6071
7347
|
/** Format: uuid */
|
|
6072
7348
|
to_user_id: string;
|
|
6073
7349
|
preserve_device_session?: boolean;
|
|
6074
7350
|
};
|
|
7351
|
+
SetLineVariant: {
|
|
7352
|
+
/** @description True for the INBOUND product: the line may then only message a handle that has messaged it FIRST (`outbound_first_forbidden`), and once that handle has, the exchange is unrestricted in both directions. It is NOT receive-only. False for the two-way product. Rental lines only. */
|
|
7353
|
+
inbound_only: boolean;
|
|
7354
|
+
/**
|
|
7355
|
+
* @description WHEN the variant moves. `now` (the default, and the only behaviour before this field existed) writes the variant immediately and it applies to the very next send. `next_anchor` stores the change against the line's next billing anchor and applies nothing today: `inbound_only` keeps its current value, the line keeps serving the product it is being billed for, and `pending_variant` on the line read carries what will change and when. Use `next_anchor` for a DOWNGRADE, so the customer keeps the two-way product through the month they have already paid for; use `now` for an upgrade. A scheduled change is cancelled with DELETE /v1/lines/{id}/variant, and an immediate change does NOT cancel one — the two are separate acts.
|
|
7356
|
+
* @enum {string}
|
|
7357
|
+
*/
|
|
7358
|
+
effective?: "now" | "next_anchor";
|
|
7359
|
+
/**
|
|
7360
|
+
* Format: date-time
|
|
7361
|
+
* @description Only meaningful with `effective: "next_anchor"`. The earliest instant the change may take effect (ISO-8601, UTC); defaults to now. iSnap schedules it at the FIRST anchor occurrence at or after this instant, with the anchor's own day-of-month clamp applied — so state your customer's paid-period end and let iSnap resolve the occurrence rather than computing one yourself. For a monthly customer that is the next anchor, which is the default; for a quarterly or annual customer it is the occurrence three or twelve months out, and the line keeps its two-way capability for the whole period they have paid for. The resolved instant comes back as `pending_variant.effective_at`. An instant in the past is refused with 400 `not_before_in_the_past`.
|
|
7362
|
+
* @example 2027-08-11T14:30:00Z
|
|
7363
|
+
*/
|
|
7364
|
+
not_before?: string;
|
|
7365
|
+
};
|
|
7366
|
+
TerminateLine: {
|
|
7367
|
+
reason?: string;
|
|
7368
|
+
};
|
|
7369
|
+
SetLineAnniversary: {
|
|
7370
|
+
/**
|
|
7371
|
+
* Format: date-time
|
|
7372
|
+
* @description The instant you took this line (ISO-8601, UTC). Its day of the month becomes the line’s renewal day and the date a cancellation waits for; the time of day is kept, because the anniversary is an instant and not a calendar day. Use this for a line migrated from your own system, whose real start date iSnap cannot know — for a line taken through the iSnap API it is stamped automatically and does not need stating. A BYOD line carries one too — it is on the same monthly meter — even though iSnap cannot end it for you at that date. Refused (409 `line_cancellation_pending`) while the line carries a `cancel_at`, which was computed from the anniversary you are replacing: uncancel first, set the date, cancel again.
|
|
7373
|
+
* @example 2026-07-02T09:15:00Z
|
|
7374
|
+
*/
|
|
7375
|
+
anniversary_at: string;
|
|
7376
|
+
};
|
|
6075
7377
|
PatchLine: {
|
|
6076
|
-
metadata
|
|
7378
|
+
metadata?: {
|
|
6077
7379
|
[key: string]: unknown;
|
|
6078
7380
|
};
|
|
7381
|
+
/**
|
|
7382
|
+
* Format: date-time
|
|
7383
|
+
* @description The billing anchor of the customer who pays for this line (ISO-8601, UTC) — the ONE date it is billed on. Its day of the month becomes the line’s billing day, clamped to the last day of a shorter month; the time of day is kept, because the anchor is an instant and not a calendar day. State the date your own customer is billed on and every line they hold moves together: at each occurrence the line is charged one full month, and at the FIRST occurrence after activation it is credited for the days the activation month had already paid for past it, at the activation rate. Omit it and the line is billed on its activation instant, which is the behaviour of every line provisioned before anchors existed. Refused (400 `billing_anchor_too_far`) more than 31 days after the activation — that would make the first period longer than a month.
|
|
7384
|
+
* @example 2026-09-11T09:15:00Z
|
|
7385
|
+
*/
|
|
7386
|
+
billing_anchor_at?: string | null;
|
|
6079
7387
|
};
|
|
6080
7388
|
QuotaEnvelope: {
|
|
6081
7389
|
/** @enum {boolean} */
|
|
@@ -6096,6 +7404,14 @@ export interface components {
|
|
|
6096
7404
|
hourly_message_limit: number;
|
|
6097
7405
|
minute_messages_used: number;
|
|
6098
7406
|
minute_message_limit: number;
|
|
7407
|
+
daily_replies_used: number;
|
|
7408
|
+
daily_reply_limit: number;
|
|
7409
|
+
minute_frees_at: string | null;
|
|
7410
|
+
hourly_frees_at: string | null;
|
|
7411
|
+
daily_total_frees_at: string | null;
|
|
7412
|
+
daily_new_frees_at: string | null;
|
|
7413
|
+
daily_known_frees_at: string | null;
|
|
7414
|
+
daily_reply_frees_at: string | null;
|
|
6099
7415
|
buckets_warning: components["schemas"]["BucketsWarning"];
|
|
6100
7416
|
};
|
|
6101
7417
|
BucketsWarning: {
|
|
@@ -6135,6 +7451,8 @@ export interface components {
|
|
|
6135
7451
|
hourly_message_limit: number;
|
|
6136
7452
|
minute_messages_used: number;
|
|
6137
7453
|
minute_message_limit: number;
|
|
7454
|
+
daily_replies_used: number;
|
|
7455
|
+
daily_reply_limit: number;
|
|
6138
7456
|
buckets_warning: components["schemas"]["BucketsWarning"];
|
|
6139
7457
|
};
|
|
6140
7458
|
QueueItem: {
|
|
@@ -6148,6 +7466,7 @@ export interface components {
|
|
|
6148
7466
|
queue_position: number;
|
|
6149
7467
|
is_new_contact: boolean | null;
|
|
6150
7468
|
target_activity_hour: number | null;
|
|
7469
|
+
timezone: string;
|
|
6151
7470
|
created_at: string;
|
|
6152
7471
|
};
|
|
6153
7472
|
LineHealthEnvelope: {
|
|
@@ -6201,6 +7520,9 @@ export interface components {
|
|
|
6201
7520
|
min_inter_message_seconds: number;
|
|
6202
7521
|
min_inter_new_contact_seconds: number;
|
|
6203
7522
|
max_queue_depth: number;
|
|
7523
|
+
reply_window_hours: number;
|
|
7524
|
+
reply_max_per_inbound: number;
|
|
7525
|
+
daily_reply_limit: number;
|
|
6204
7526
|
timezone: string;
|
|
6205
7527
|
activity_curve: {
|
|
6206
7528
|
hour: number;
|
|
@@ -6213,6 +7535,9 @@ export interface components {
|
|
|
6213
7535
|
daily_total_message_limit: components["schemas"]["LineConfigKnobBounds"];
|
|
6214
7536
|
hourly_message_limit: components["schemas"]["LineConfigKnobBounds"];
|
|
6215
7537
|
minute_message_limit: components["schemas"]["LineConfigKnobBounds"];
|
|
7538
|
+
reply_window_hours: components["schemas"]["LineConfigKnobBounds"];
|
|
7539
|
+
reply_max_per_inbound: components["schemas"]["LineConfigKnobBounds"];
|
|
7540
|
+
daily_reply_limit: components["schemas"]["LineConfigKnobBounds"];
|
|
6216
7541
|
};
|
|
6217
7542
|
LineConfigKnobBounds: {
|
|
6218
7543
|
current: number;
|
|
@@ -6232,6 +7557,9 @@ export interface components {
|
|
|
6232
7557
|
min_inter_message_seconds?: number;
|
|
6233
7558
|
min_inter_new_contact_seconds?: number;
|
|
6234
7559
|
max_queue_depth?: number;
|
|
7560
|
+
reply_window_hours?: number;
|
|
7561
|
+
reply_max_per_inbound?: number;
|
|
7562
|
+
daily_reply_limit?: number;
|
|
6235
7563
|
timezone?: string;
|
|
6236
7564
|
activity_curve?: {
|
|
6237
7565
|
hour: number;
|
|
@@ -6241,20 +7569,19 @@ export interface components {
|
|
|
6241
7569
|
PreOrder: {
|
|
6242
7570
|
/** Format: uuid */
|
|
6243
7571
|
id: string;
|
|
6244
|
-
/** @enum {string} */
|
|
6245
|
-
billing_tier: "rental_iphone" | "rental_android";
|
|
6246
7572
|
preferred_area_codes: string[];
|
|
7573
|
+
inbound_only: boolean;
|
|
7574
|
+
/** @description The billing anchor you stated when placing this pre-order, carried onto the line at confirm. `null` means you stated none and the line is billed on its activation instant. */
|
|
7575
|
+
billing_anchor_at: string | null;
|
|
6247
7576
|
status: components["schemas"]["PreOrderStatus"];
|
|
6248
|
-
stripe_payment_intent_id: string | null;
|
|
6249
7577
|
stripe_client_secret: string | null;
|
|
6250
|
-
amount: number;
|
|
6251
7578
|
estimated_fulfillment: string | null;
|
|
6252
7579
|
device_status?: components["schemas"]["DeviceFulfillmentStatus"];
|
|
6253
7580
|
created_at: string;
|
|
6254
7581
|
updated_at: string;
|
|
6255
7582
|
};
|
|
6256
7583
|
/** @enum {string} */
|
|
6257
|
-
PreOrderStatus: "draft" | "
|
|
7584
|
+
PreOrderStatus: "draft" | "provisioning" | "fulfilled" | "cancelled";
|
|
6258
7585
|
/** @enum {string|null} */
|
|
6259
7586
|
DeviceFulfillmentStatus: "awaiting_hardware" | "received" | "setup_in_progress" | "ready" | "deployed" | null;
|
|
6260
7587
|
PreOrderList: {
|
|
@@ -6298,11 +7625,71 @@ export interface components {
|
|
|
6298
7625
|
*/
|
|
6299
7626
|
device_count: number;
|
|
6300
7627
|
/**
|
|
6301
|
-
* @description Stripe price cadence.
|
|
7628
|
+
* @description Stripe price cadence. Quarterly is 2.7x monthly (10% off) and annual is 10x monthly (2 months free).
|
|
7629
|
+
* @example monthly
|
|
7630
|
+
* @enum {string}
|
|
7631
|
+
*/
|
|
7632
|
+
billing_cycle: "monthly" | "quarterly" | "annual";
|
|
7633
|
+
};
|
|
7634
|
+
MacCheckoutEnvelope: {
|
|
7635
|
+
/** @enum {boolean} */
|
|
7636
|
+
success: true;
|
|
7637
|
+
data: components["schemas"]["MacCheckoutResponse"];
|
|
7638
|
+
trace_id: string;
|
|
7639
|
+
request_id: string;
|
|
7640
|
+
};
|
|
7641
|
+
MacCheckoutResponse: {
|
|
7642
|
+
/**
|
|
7643
|
+
* Format: uri
|
|
7644
|
+
* @description Hosted Stripe Checkout URL — redirect the customer here.
|
|
7645
|
+
*/
|
|
7646
|
+
checkout_url: string;
|
|
7647
|
+
/**
|
|
7648
|
+
* Format: date-time
|
|
7649
|
+
* @description Session expiry (ISO-8601). Stripe default is 24h.
|
|
7650
|
+
*/
|
|
7651
|
+
expires_at: string;
|
|
7652
|
+
/** @description Sessions ordered — echoed back as accepted. */
|
|
7653
|
+
quantity: number;
|
|
7654
|
+
/** @description The pack divisor in force, read from the Stripe Price’s `pack_size` metadata. Quantities must be whole multiples of it, at or above it. */
|
|
7655
|
+
pack_size: number;
|
|
7656
|
+
/** @description Recurring total per period in integer cents, from the Price’s graduated tier ladder. Excludes tax, proration and coupons. */
|
|
7657
|
+
estimated_total_cents: number;
|
|
7658
|
+
};
|
|
7659
|
+
MacCheckoutBody: {
|
|
7660
|
+
/**
|
|
7661
|
+
* @description Number of hosted macOS sessions to rent. Must be a whole number of packs at or above the one-pack minimum — the pack size is read from the Stripe Price and echoed as `pack_size` in the response and in the `422` error `issues[0].min`. A quantity that is not a whole pack is refused `422 mac_quantity_not_a_pack`.
|
|
7662
|
+
* @example 5
|
|
7663
|
+
*/
|
|
7664
|
+
quantity: number;
|
|
7665
|
+
/**
|
|
7666
|
+
* @description Stripe price cadence for the session subscription.
|
|
6302
7667
|
* @example monthly
|
|
6303
7668
|
* @enum {string}
|
|
6304
7669
|
*/
|
|
6305
|
-
billing_cycle: "monthly" | "annual";
|
|
7670
|
+
billing_cycle: "monthly" | "quarterly" | "annual";
|
|
7671
|
+
};
|
|
7672
|
+
SubscriptionQuantityEnvelope: {
|
|
7673
|
+
/** @enum {boolean} */
|
|
7674
|
+
success: true;
|
|
7675
|
+
data: components["schemas"]["SubscriptionQuantityResponse"];
|
|
7676
|
+
trace_id: string;
|
|
7677
|
+
request_id: string;
|
|
7678
|
+
};
|
|
7679
|
+
SubscriptionQuantityResponse: {
|
|
7680
|
+
/** @description The Stripe subscription ID (`sub_*`). */
|
|
7681
|
+
subscription_id: string;
|
|
7682
|
+
/** @description The quantity now set on the adjustable item. */
|
|
7683
|
+
quantity: number;
|
|
7684
|
+
/** @description Recurring total per period in integer cents. `null` when the item’s Price carries no computable per-period total. Excludes tax, proration and coupons. */
|
|
7685
|
+
estimated_total_cents: number | null;
|
|
7686
|
+
};
|
|
7687
|
+
SubscriptionQuantityBody: {
|
|
7688
|
+
/**
|
|
7689
|
+
* @description New quantity for the subscription’s single adjustable item — macOS sessions, or BYOP slots. Both products are subject to the 1:1 rule (see the `422` codes), and the macOS product additionally to the pack rule.
|
|
7690
|
+
* @example 10
|
|
7691
|
+
*/
|
|
7692
|
+
quantity: number;
|
|
6306
7693
|
};
|
|
6307
7694
|
SubscriptionListEnvelope: {
|
|
6308
7695
|
/** @enum {boolean} */
|
|
@@ -6401,6 +7788,7 @@ export interface components {
|
|
|
6401
7788
|
reactions: components["schemas"]["MessageReactionV1"][];
|
|
6402
7789
|
scheduled_for: string | null;
|
|
6403
7790
|
schedule_reason: string | null;
|
|
7791
|
+
reply_lane: boolean;
|
|
6404
7792
|
queue_info: {
|
|
6405
7793
|
queue_position: number;
|
|
6406
7794
|
is_new_contact: boolean;
|
|
@@ -6410,6 +7798,9 @@ export interface components {
|
|
|
6410
7798
|
daily_known_contact_limit: number;
|
|
6411
7799
|
daily_messages_used: number;
|
|
6412
7800
|
daily_total_message_limit: number;
|
|
7801
|
+
reply_lane: boolean;
|
|
7802
|
+
daily_replies_used: number;
|
|
7803
|
+
daily_reply_limit: number;
|
|
6413
7804
|
messages_ahead_in_queue?: number;
|
|
6414
7805
|
daily_slot_of?: string;
|
|
6415
7806
|
target_activity_hour?: number;
|
|
@@ -6424,6 +7815,8 @@ export interface components {
|
|
|
6424
7815
|
delivered_at: string | null;
|
|
6425
7816
|
read_at: string | null;
|
|
6426
7817
|
failed_at: string | null;
|
|
7818
|
+
error_code: string | null;
|
|
7819
|
+
error_message: string | null;
|
|
6427
7820
|
cancelled_at: string | null;
|
|
6428
7821
|
};
|
|
6429
7822
|
/** @enum {string} */
|
|
@@ -6515,7 +7908,7 @@ export interface components {
|
|
|
6515
7908
|
* @description A concrete event type (e.g. `message.received`), a family wildcard (`line.*`), or the catch-all `*`.
|
|
6516
7909
|
* @enum {string}
|
|
6517
7910
|
*/
|
|
6518
|
-
WebhookEventName: "message.queued" | "message.sent" | "message.delivered" | "message.read" | "message.failed" | "message.received" | "message.scheduled" | "message.cancelled" | "message.fallback_triggered" | "reaction.added" | "reaction.received" | "reaction.removed" | "line.connected" | "line.disconnected" | "line.offline" | "line.degraded" | "line.apple_id_flagged" | "line.quota_warning" | "line.quota_exceeded" | "line.capability_changed" | "typing_indicator.started" | "typing_indicator.stopped" | "trial.linked" | "trial.dormant" | "trial.reactivated" | "trial.bind_conflict" | "trial.revoked" | "binding.released" | "pre_order.fulfilled" | "pre_order.cancelled" | "
|
|
7911
|
+
WebhookEventName: "message.queued" | "message.sent" | "message.delivered" | "message.read" | "message.failed" | "message.received" | "message.scheduled" | "message.cancelled" | "message.fallback_triggered" | "reaction.added" | "reaction.received" | "reaction.removed" | "line.connected" | "line.disconnected" | "line.offline" | "line.degraded" | "line.apple_id_flagged" | "line.quota_warning" | "line.quota_exceeded" | "line.capability_changed" | "line.terminated" | "line.variant_changed" | "line.variant_scheduled" | "line.variant_unscheduled" | "typing_indicator.started" | "typing_indicator.stopped" | "trial.linked" | "trial.dormant" | "trial.reactivated" | "trial.bind_conflict" | "trial.revoked" | "binding.released" | "pre_order.fulfilled" | "pre_order.cancelled" | "macos_session.rented" | "macos_session.released" | "webhook.test" | "*" | "message.*" | "reaction.*" | "line.*" | "typing_indicator.*" | "trial.*" | "binding.*" | "pre_order.*" | "macos_session.*" | "webhook.*";
|
|
6519
7912
|
WebhookList: {
|
|
6520
7913
|
webhooks: components["schemas"]["Webhook"][];
|
|
6521
7914
|
};
|
|
@@ -6663,6 +8056,17 @@ export interface components {
|
|
|
6663
8056
|
handle: string;
|
|
6664
8057
|
from_line_id?: string;
|
|
6665
8058
|
};
|
|
8059
|
+
AttentionList: {
|
|
8060
|
+
entries: components["schemas"]["AttentionEntry"][];
|
|
8061
|
+
};
|
|
8062
|
+
AttentionEntry: {
|
|
8063
|
+
line_id: string;
|
|
8064
|
+
phone_number: string | null;
|
|
8065
|
+
ownership: string;
|
|
8066
|
+
since: string | null;
|
|
8067
|
+
reasons: string[];
|
|
8068
|
+
detail_withheld: boolean;
|
|
8069
|
+
};
|
|
6666
8070
|
AreaCodesEnvelope: {
|
|
6667
8071
|
/** @enum {boolean} */
|
|
6668
8072
|
success: true;
|
|
@@ -6681,6 +8085,27 @@ export interface components {
|
|
|
6681
8085
|
region: string;
|
|
6682
8086
|
/** @example US */
|
|
6683
8087
|
country_code: string;
|
|
8088
|
+
/**
|
|
8089
|
+
* @description A ZIP code whose geography this area code serves — the postal address to use at purchase, and the address most likely to have the carrier assign this area code. `null` when no ZIP is on record for this code: choosing the address is then a judgement call for the operator, and this catalogue may not know of an overlay covering the code either, so no regional address can be assumed to yield it.
|
|
8090
|
+
* @example 10019
|
|
8091
|
+
*/
|
|
8092
|
+
purchase_zip: string | null;
|
|
8093
|
+
/**
|
|
8094
|
+
* @description Fallback ZIPs in the same geography, to retry with if the carrier rejects the primary. Empty when no ZIP is on record.
|
|
8095
|
+
* @example [
|
|
8096
|
+
* "10021",
|
|
8097
|
+
* "10023"
|
|
8098
|
+
* ]
|
|
8099
|
+
*/
|
|
8100
|
+
alt_zips: string[];
|
|
8101
|
+
/**
|
|
8102
|
+
* @description Other area codes IN THIS CATALOGUE that overlay the same geography. Non-empty means NO address can guarantee this specific code — the carrier may assign any code in the complex. An empty list is NOT the converse guarantee: it says only that no code this endpoint can offer is known to overlay this one, and an overlay outside the catalogue may still take the number.
|
|
8103
|
+
* @example [
|
|
8104
|
+
* "646",
|
|
8105
|
+
* "917"
|
|
8106
|
+
* ]
|
|
8107
|
+
*/
|
|
8108
|
+
shared_with: string[];
|
|
6684
8109
|
};
|
|
6685
8110
|
Country: {
|
|
6686
8111
|
/** @example US */
|
|
@@ -6907,6 +8332,13 @@ export interface components {
|
|
|
6907
8332
|
[key: string]: unknown;
|
|
6908
8333
|
};
|
|
6909
8334
|
};
|
|
8335
|
+
MacosSessionEnvelope: {
|
|
8336
|
+
/** @enum {boolean} */
|
|
8337
|
+
success: true;
|
|
8338
|
+
data: components["schemas"]["MacosSession"];
|
|
8339
|
+
trace_id: string;
|
|
8340
|
+
request_id: string;
|
|
8341
|
+
};
|
|
6910
8342
|
AppManifestEnvelope: {
|
|
6911
8343
|
/** @enum {boolean} */
|
|
6912
8344
|
success: true;
|
|
@@ -6926,10 +8358,16 @@ export interface components {
|
|
|
6926
8358
|
*/
|
|
6927
8359
|
url: string;
|
|
6928
8360
|
/**
|
|
6929
|
-
* @description
|
|
6930
|
-
* @example
|
|
8361
|
+
* @description Version currently published for this platform, read from the release feed that sits beside the artifact `url` resolves to — so the number announced and the file served cannot name different releases. `null` when that feed publishes nothing or could not be read; `version_status` says which. Never a configured placeholder: a fabricated version makes a failed install and an uninformed console indistinguishable to whoever is checking. Compare it against an installed version to offer an update.
|
|
8362
|
+
* @example 0.0.211
|
|
8363
|
+
*/
|
|
8364
|
+
version: string | null;
|
|
8365
|
+
/**
|
|
8366
|
+
* @description Why `version` holds what it holds. `version` is non-null if and only if this is `published`, so a null is never ambiguous (WHA-2765). `none_published` — the feed answered and publishes no version (a 404, or a feed with no readable item): a real fact about the channel, render "version not published". `unreachable` — the feed could not be read (timeout, DNS failure, a body past the size cap): OUR fault or the update host's, and nobody knows what this channel publishes, so do not tell an operator the version is missing. `misconfigured` — an artifact URL is configured for the platform and no feed URL can be derived from it; someone must fix the deployment. `not_configured` — this deployment ships no artifact for the platform, which is the same fact `available: false` carries. Before this field the last three and the first were one indistinguishable `null`, so a broken appcast URL and a healthy pre-release channel rendered identically.
|
|
8367
|
+
* @example published
|
|
8368
|
+
* @enum {string}
|
|
6931
8369
|
*/
|
|
6932
|
-
|
|
8370
|
+
version_status: "published" | "none_published" | "unreachable" | "misconfigured" | "not_configured";
|
|
6933
8371
|
/**
|
|
6934
8372
|
* @description False when this deployment has no artifact configured for the platform. The entry is still returned, so a consumer can hide the affordance instead of surfacing a link that 404s on click.
|
|
6935
8373
|
* @example true
|