palbase 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/ai/index.js +2 -2
  2. package/dist/backend/engine.js +2 -2
  3. package/dist/backend/env.js +1 -1
  4. package/dist/backend/index.js +3 -3
  5. package/dist/backend/stack.js +1 -1
  6. package/dist/backend/test.js +2 -2
  7. package/dist/chunks/{3VASGTIN.js → 4A6S7JKW.js} +2 -2
  8. package/dist/chunks/{JAWWIVZH.js → 4LGRTNOK.js} +2 -2
  9. package/dist/chunks/6BUQ7N4I.js +2 -0
  10. package/dist/chunks/7D5J3M3D.js +87 -0
  11. package/dist/chunks/A4VJFSSX.js +2 -0
  12. package/dist/chunks/AR6WQDU5.js +2 -0
  13. package/dist/chunks/{45J7YXRB.js → BPWQDLXP.js} +1 -1
  14. package/dist/chunks/{DAOLIUNZ.js → IQIXNAI4.js} +1 -1
  15. package/dist/chunks/{UAY56IQR.js → LLBV62FM.js} +2 -2
  16. package/dist/chunks/{E5Q4VTW4.js → MJ35SVVY.js} +2 -2
  17. package/dist/chunks/{QXUMLO7O.js → NDJAXNM6.js} +2 -2
  18. package/dist/chunks/RK6M2LNY.js +2 -0
  19. package/dist/chunks/{6FWCNTAM.js → UNOLIHKD.js} +1 -1
  20. package/dist/chunks/{3OGEBGYZ.js → W2GV6UU3.js} +2 -2
  21. package/dist/chunks/{LYEFPLJZ.js → YQYMP55L.js} +1 -1
  22. package/dist/cli.js +90 -90
  23. package/dist/refuse/ai.js +1 -1
  24. package/dist/refuse/backend.js +1 -1
  25. package/dist/refuse/server.js +1 -1
  26. package/dist/server/index.js +2 -2
  27. package/dist/server/testing.js +2 -2
  28. package/dist/web/index.js +2 -2
  29. package/dist/web/palbe.js +2 -2
  30. package/dist/web/paywall.js +2 -0
  31. package/dist/web/vite.js +2 -2
  32. package/package.json +6 -2
  33. package/types/internal/src/modules/ai.d.ts +811 -0
  34. package/types/internal/src/modules/events.d.ts +2 -2
  35. package/types/internal/src/modules/purchases.d.ts +2609 -133
  36. package/types/internal/src/modules/storage.d.ts +1 -1
  37. package/types/web/src/client.d.ts +6 -0
  38. package/types/web/src/index.d.ts +3 -0
  39. package/types/web/src/paywall/assets.d.ts +51 -0
  40. package/types/web/src/paywall/attributes.d.ts +13 -0
  41. package/types/web/src/paywall/icons.d.ts +5 -0
  42. package/types/web/src/paywall/index.d.ts +7 -0
  43. package/types/web/src/paywall/placement.d.ts +99 -0
  44. package/types/web/src/paywall/prices.d.ts +40 -0
  45. package/types/web/src/paywall/render.d.ts +93 -0
  46. package/types/web/src/paywall/resolve.d.ts +184 -0
  47. package/types/web/src/purchases.d.ts +34 -2
  48. package/dist/chunks/3XT4L2XV.js +0 -2
  49. package/dist/chunks/HKJU2FKE.js +0 -2
  50. package/dist/chunks/IKVOXHEE.js +0 -2
@@ -540,6 +540,48 @@ export type CheckoutRequest = {
540
540
  */
541
541
  success_url: string;
542
542
  };
543
+ /**
544
+ * What calling a leader takes — every variant seen by min_viewers subjects, the leader's chance to win min_chance — and what the results still lack, reason by reason: none, they are confident.
545
+ */
546
+ export type Confidence = {
547
+ /**
548
+ * The chance to win the leader needs (0 to 1).
549
+ */
550
+ min_chance: number;
551
+ /**
552
+ * The subjects each variant needs to have been seen by.
553
+ */
554
+ min_viewers: number;
555
+ /**
556
+ * What is still lacking; empty when confident.
557
+ */
558
+ reasons: ConfidenceReason[];
559
+ };
560
+ /**
561
+ * One thing the results lack to call their leader.
562
+ */
563
+ export type ConfidenceReason = {
564
+ /**
565
+ * Its chance to win, for leader_unsure.
566
+ */
567
+ chance?: number;
568
+ /**
569
+ * no_viewers: no one saw a variant yet; too_few_viewers: a variant was seen by fewer than min_viewers (variant, viewers); leader_unsure: the leader's chance to win is under min_chance (variant, chance).
570
+ */
571
+ code: "no_viewers" | "too_few_viewers" | "leader_unsure";
572
+ /**
573
+ * The reason in words ("variant b has 40 viewers (needs 100)").
574
+ */
575
+ message: string;
576
+ /**
577
+ * The variant it is about.
578
+ */
579
+ variant?: string;
580
+ /**
581
+ * Its viewers, for too_few_viewers.
582
+ */
583
+ viewers?: number;
584
+ };
543
585
  /**
544
586
  * An In-App Purchase key handed over with a grant, for one of the environment's iOS apps.
545
587
  */
@@ -1087,6 +1129,165 @@ export type ErrorResponse = {
1087
1129
  */
1088
1130
  status: number;
1089
1131
  };
1132
+ /**
1133
+ * An experiment on a placement. Its variants never change while it runs, so no one's variant does.
1134
+ */
1135
+ export type Experiment = {
1136
+ /**
1137
+ * placement: everyone at the placement, decided before its rules; rules: the viewers the rules targeting it send it.
1138
+ */
1139
+ audience: "placement" | "rules";
1140
+ /**
1141
+ * When it ended.
1142
+ */
1143
+ ended_at?: string;
1144
+ /**
1145
+ * Who ended it.
1146
+ */
1147
+ ended_by?: string;
1148
+ /**
1149
+ * The experiment's id.
1150
+ */
1151
+ id: string;
1152
+ /**
1153
+ * Its name.
1154
+ */
1155
+ name: string;
1156
+ /**
1157
+ * The placement it runs on.
1158
+ */
1159
+ placement: string;
1160
+ /**
1161
+ * When it started.
1162
+ */
1163
+ started_at: string;
1164
+ /**
1165
+ * Who started it (the key).
1166
+ */
1167
+ started_by: string;
1168
+ /**
1169
+ * running; stopped (what it showed becomes the first variant's paywall); won (the winner's).
1170
+ */
1171
+ status: "running" | "stopped" | "won";
1172
+ /**
1173
+ * The variants, the first the one a stop keeps.
1174
+ */
1175
+ variants: ExperimentVariant[];
1176
+ /**
1177
+ * The variant declared the winner.
1178
+ */
1179
+ winner?: string;
1180
+ };
1181
+ /**
1182
+ * An experiment to start.
1183
+ */
1184
+ export type ExperimentRequest = {
1185
+ /**
1186
+ * placement (when none): everyone at the placement — made when new —, decided before its rules; rules: the viewers the placement's rules targeting it send it — the placement is one already.
1187
+ */
1188
+ audience?: "placement" | "rules";
1189
+ /**
1190
+ * Its name (1 to 100 characters).
1191
+ */
1192
+ name: string;
1193
+ /**
1194
+ * The placement it runs on (for everyone there, made when new).
1195
+ */
1196
+ placement: string;
1197
+ /**
1198
+ * 2 to 4 variants, each its own published paywall; the first is the one a stop keeps.
1199
+ */
1200
+ variants: ExperimentVariant[];
1201
+ };
1202
+ /**
1203
+ * What each variant's audience did, and which leads.
1204
+ */
1205
+ export type ExperimentResults = {
1206
+ /**
1207
+ * When the numbers were counted.
1208
+ */
1209
+ computed_at: string;
1210
+ confidence: Confidence;
1211
+ /**
1212
+ * Whether declaring the leader the winner is sound: confidence has no reason left.
1213
+ */
1214
+ confident: boolean;
1215
+ /**
1216
+ * The experiment.
1217
+ */
1218
+ experiment_id: string;
1219
+ /**
1220
+ * The variant with the highest chance to win; absent before anyone saw one.
1221
+ */
1222
+ leader?: string;
1223
+ /**
1224
+ * Whether the stores' test purchases count.
1225
+ */
1226
+ sandbox: boolean;
1227
+ /**
1228
+ * The experiment's status.
1229
+ */
1230
+ status: "running" | "stopped" | "won";
1231
+ /**
1232
+ * Each variant, in the experiment's order.
1233
+ */
1234
+ variants: VariantResult[];
1235
+ /**
1236
+ * The days after first seeing a variant a purchase counts for it.
1237
+ */
1238
+ window_days: number;
1239
+ };
1240
+ /**
1241
+ * A variant: a paywall shown to its share of the placement's audience — its weight over the variants' weights together.
1242
+ */
1243
+ export type ExperimentVariant = {
1244
+ /**
1245
+ * The variant's key (a, b, control …): lowercase letters, digits and _, at most 20.
1246
+ */
1247
+ key: string;
1248
+ /**
1249
+ * The paywall it shows (published).
1250
+ */
1251
+ paywall_id: string;
1252
+ /**
1253
+ * Its weight.
1254
+ */
1255
+ weight: number;
1256
+ };
1257
+ /**
1258
+ * A page of the project's experiments, newest first.
1259
+ */
1260
+ export type Experiments = {
1261
+ /**
1262
+ * The experiments.
1263
+ */
1264
+ experiments: Experiment[];
1265
+ /**
1266
+ * The next page's cursor; absent on the last.
1267
+ */
1268
+ next_cursor?: string;
1269
+ };
1270
+ /**
1271
+ * What an app showed at a placement, as it was given it. variant and rule_id are claims, checked against the placement: one that does not hold is not written.
1272
+ */
1273
+ export type ExposureRequest = {
1274
+ /**
1275
+ * The paywall.
1276
+ */
1277
+ paywall_id: string;
1278
+ /**
1279
+ * The rule the answer named, when it named one.
1280
+ */
1281
+ rule_id?: string;
1282
+ /**
1283
+ * The variant the answer named, when it named one.
1284
+ */
1285
+ variant?: string;
1286
+ /**
1287
+ * Its version.
1288
+ */
1289
+ version: number;
1290
+ };
1090
1291
  /**
1091
1292
  * A granted (promotional) entitlement.
1092
1293
  */
@@ -1450,213 +1651,1911 @@ export type OwnershipTransferredEvent = {
1450
1651
  via: "restore";
1451
1652
  };
1452
1653
  /**
1453
- * How a product is paid for.
1654
+ * A paywall as Studio edits it: its draft, and what was published of it.
1454
1655
  */
1455
- export type Plan = {
1456
- /**
1457
- * A non-renewing product's duration, an ISO 8601 duration such as P1M.
1458
- */
1459
- duration?: string;
1460
- intro?: IntroOffer;
1656
+ export type Paywall = {
1461
1657
  /**
1462
- * Its key: lowercase letters, digits and _, starting with a letter.
1658
+ * When it was made.
1463
1659
  */
1464
- key: string;
1660
+ created_at: string;
1465
1661
  /**
1466
- * A subscription's billing period, an ISO 8601 duration: the App Store sells by P1W, P1M, P2M, P3M, P6M, P1Y; Google Play adds P4W, P4M, P8M; Stripe bills at most once a year.
1662
+ * Who made it (the key).
1467
1663
  */
1468
- period?: string;
1469
- price: Price;
1470
- };
1471
- /**
1472
- * A confirmation, with the hash of the plan shown.
1473
- */
1474
- export type PlanConfirmation = {
1664
+ created_by: string;
1665
+ draft: PaywallDefinition;
1475
1666
  /**
1476
- * The Stripe part's hash; with no Stripe account connected, the App Store part's.
1667
+ * Rises with every save of the draft; If-Match names it.
1477
1668
  */
1478
- hash: string;
1479
- };
1480
- /**
1481
- * One write a store will get to come to the catalog.
1482
- */
1483
- export type PlanStep = {
1669
+ draft_revision: number;
1484
1670
  /**
1485
- * What it writes, as the store names it.
1671
+ * The paywall's id.
1486
1672
  */
1487
- fields?: {
1488
- [key: string]: unknown;
1489
- };
1673
+ id: string;
1490
1674
  /**
1491
- * Whether it makes something the store never lets go of: a product id at Apple or Google stays taken even once deleted.
1675
+ * Its name (the draft's).
1492
1676
  */
1493
- irreversible: boolean;
1677
+ name: string;
1494
1678
  /**
1495
- * What the person should know of it: how a price is resolved, why it waits.
1679
+ * What there is to say of the draft against the catalog as it is: warnings — a package the catalog does not sell yet is one here and stops a publish.
1496
1680
  */
1497
- note?: string;
1681
+ problems: PaywallProblem[];
1498
1682
  /**
1499
- * What it does: create_product, update_product, create_price (Stripe); create_subscription_group, create_subscription, create_in_app_purchase (the App Store); create_subscription, create_onetime_product (Google Play).
1683
+ * When the newest version was published.
1500
1684
  */
1501
- op: string;
1685
+ published_at?: string;
1502
1686
  /**
1503
- * The catalog's plan.
1687
+ * The newest version published; 0 before the first.
1504
1688
  */
1505
- plan?: string;
1689
+ published_version: number;
1506
1690
  /**
1507
- * The catalog's product.
1691
+ * When the draft was last saved.
1508
1692
  */
1509
- product: string;
1693
+ updated_at: string;
1510
1694
  /**
1511
- * The store's id of what it writes.
1695
+ * Who saved it last.
1512
1696
  */
1513
- store_id?: string;
1697
+ updated_by: string;
1514
1698
  };
1515
1699
  /**
1516
- * Where Stripe's portal sends the customer back.
1700
+ * What a button does.
1517
1701
  */
1518
- export type PortalRequest = {
1702
+ export type PaywallAction = {
1519
1703
  /**
1520
- * A registered web app's origin, or a native app's own scheme.
1704
+ * Package.
1521
1705
  */
1522
- return_url: string;
1523
- };
1524
- /**
1525
- * Stripe's customer portal, opened for the customer.
1526
- */
1527
- export type PortalSession = {
1706
+ package?: string;
1528
1707
  /**
1529
- * Where to send the customer.
1708
+ * Sheet.
1530
1709
  */
1531
- url: string;
1710
+ sheet?: string;
1711
+ /**
1712
+ * Type.
1713
+ */
1714
+ type: "close" | "restore" | "open_url" | "terms" | "privacy" | "offer_code" | "sheet" | "select_package";
1715
+ /**
1716
+ * Url.
1717
+ */
1718
+ url?: string;
1532
1719
  };
1533
1720
  /**
1534
- * The one price entered: each store prices the other currencies its own way (Apple's price points, Google's conversion, Stripe's), except those set by hand.
1721
+ * How the component appears; a renderer skips it when the system asks to reduce motion.
1535
1722
  */
1536
- export type Price = {
1723
+ export type PaywallAnimation = {
1537
1724
  /**
1538
- * The amount in the currency's minor units (999 is 9.99).
1725
+ * Delay ms.
1539
1726
  */
1540
- amount: number;
1727
+ delay_ms?: number;
1541
1728
  /**
1542
- * Its ISO 4217 currency (USD).
1729
+ * Duration ms.
1543
1730
  */
1544
- currency: string;
1731
+ duration_ms?: number;
1545
1732
  /**
1546
- * Amounts set by hand in other currencies, in their minor units.
1733
+ * Easing.
1547
1734
  */
1548
- overrides?: {
1549
- [key: string]: number;
1550
- };
1735
+ easing?: "ease_out" | "ease_in_out" | "spring";
1736
+ /**
1737
+ * Type.
1738
+ */
1739
+ type: "fade" | "slide_up" | "slide_down" | "slide_leading" | "slide_trailing" | "scale";
1551
1740
  };
1552
1741
  /**
1553
- * One thing sold, on every channel it names.
1742
+ * An image, a video, a font or an HTML block the project keeps in its own storage — a public bucket — and registered for its paywalls. A definition names it asset:<id>.
1554
1743
  */
1555
- export type Product = {
1744
+ export type PaywallAsset = {
1556
1745
  /**
1557
- * Where it is sold — ios (the App Store), android (Google Play), web (Stripe) — each with what is its own there; {} when it is sold there as it is.
1746
+ * The project's bucket it is in: paywall-assets.
1558
1747
  */
1559
- channels: {
1560
- [key: string]: Channel;
1561
- };
1562
- credits?: ProductCredits;
1748
+ bucket: string;
1563
1749
  /**
1564
- * The entitlements it gives (a consumable gives none).
1750
+ * Its size.
1565
1751
  */
1566
- entitlements?: string[];
1752
+ bytes: number;
1567
1753
  /**
1568
- * A subscription's group: the subscriptions a customer can move between (Apple's subscription group, the plans a Stripe customer can switch to). The App Store sells every subscription in one.
1754
+ * Its content type, from its bytes.
1569
1755
  */
1570
- group?: string;
1756
+ content_type: string;
1571
1757
  /**
1572
- * Its key: lowercase letters, digits and _, starting with a letter, at most 40. The stores know a plan of it as <product>.<plan> (40 characters at most).
1758
+ * When it was registered.
1573
1759
  */
1574
- key: string;
1760
+ created_at: string;
1575
1761
  /**
1576
- * Its text by language: the base locale's at least.
1762
+ * Who registered it (the key).
1577
1763
  */
1578
- locales: {
1579
- [key: string]: Locale;
1580
- };
1764
+ created_by: string;
1581
1765
  /**
1582
- * How it is paid for: a subscription's periods and prices; one price for anything else.
1766
+ * An HTML block's files.
1583
1767
  */
1584
- plans: Plan[];
1768
+ files?: number;
1585
1769
  /**
1586
- * How much of each limit it gives.
1770
+ * The asset's id.
1587
1771
  */
1588
- quota?: QuotaAllowance[];
1772
+ id: string;
1589
1773
  /**
1590
- * A subscription's level in its group, 1 or more: higher is more.
1774
+ * What its bytes are: an image (png, jpeg, webp), a video (mp4, mov), a font (ttf, otf, woff2), or an HTML block's zip.
1591
1775
  */
1592
- tier?: number;
1776
+ kind: "image" | "video" | "font" | "html";
1593
1777
  /**
1594
- * Its kind: subscription (renews until canceled), non_consumable (bought once, kept), consumable (bought again and again: credits), non_renewing (a period bought once).
1778
+ * What an HTML block's files hold together.
1595
1779
  */
1596
- type: string;
1597
- };
1598
- /**
1599
- * The credits a product gives: per purchase for a consumable, per period for a subscription.
1600
- */
1601
- export type ProductCredits = {
1780
+ opened_bytes?: number;
1602
1781
  /**
1603
- * How many.
1782
+ * Its path in the bucket.
1604
1783
  */
1605
- amount: number;
1784
+ path: string;
1606
1785
  /**
1607
- * The credit (a key of the catalog's credits).
1786
+ * How a definition names it: asset:<id>.
1608
1787
  */
1609
- currency: string;
1788
+ ref: string;
1610
1789
  /**
1611
- * A subscription's: none (a period's credits end with the period) or all (they stay). Credits bought never end.
1790
+ * The SHA-256 of its bytes, hex: an app draws what it downloads only when it is this.
1612
1791
  */
1613
- rollover?: string;
1792
+ sha256: string;
1793
+ /**
1794
+ * Its public https address.
1795
+ */
1796
+ url: string;
1614
1797
  };
1615
1798
  /**
1616
- * purchases.purchase.completed: a purchase new to the ledger: a subscription's start or a one-time product, in any store.
1799
+ * An asset a definition names, as an app downloads it before it shows the paywall.
1617
1800
  */
1618
- export type PurchaseCompletedEvent = {
1619
- /**
1620
- * The purchase's id in the ledger.
1621
- */
1622
- chain_id: string;
1801
+ export type PaywallAssetRef = {
1623
1802
  /**
1624
- * The customer.
1803
+ * Its size.
1625
1804
  */
1626
- customer_id: string;
1805
+ bytes: number;
1627
1806
  /**
1628
- * Whether it is a store's test purchase.
1807
+ * The asset: a definition names it asset:<id>.
1629
1808
  */
1630
- is_sandbox: boolean;
1809
+ id: string;
1631
1810
  /**
1632
- * Its plan; empty when unmapped.
1811
+ * What it is.
1633
1812
  */
1634
- plan: string;
1813
+ kind: "image" | "video" | "font" | "html";
1635
1814
  /**
1636
- * The catalog's product; empty when unmapped.
1815
+ * The SHA-256 its bytes must have: an asset whose download is not this is not drawn.
1637
1816
  */
1638
- product: string;
1817
+ sha256: string;
1639
1818
  /**
1640
- * Where it was bought.
1819
+ * Its https address.
1641
1820
  */
1642
- store: "app_store" | "play_store" | "stripe";
1821
+ url: string;
1643
1822
  };
1644
1823
  /**
1645
- * A one-time purchase the customer owns.
1824
+ * An object of the project's public bucket paywall-assets to register, uploaded first with the project's storage (palbase-js). Studio and the CLI make the bucket (public) when it is missing; the module reads nothing else.
1646
1825
  */
1647
- export type PurchaseInfo = {
1826
+ export type PaywallAssetRequest = {
1648
1827
  /**
1649
- * Its id in the ledger.
1828
+ * What the object is meant to be: a registration whose bytes are another kind is refused (asset_kind_mismatch).
1650
1829
  */
1651
- id: string;
1830
+ kind?: "image" | "video" | "font" | "html";
1652
1831
  /**
1653
- * Whether it is a store's test purchase.
1832
+ * The object's path in the paywall-assets bucket (a leading / is the bucket's root). A . or .. segment, an empty one or a control character is refused, never resolved.
1654
1833
  */
1655
- is_sandbox: boolean;
1834
+ path: string;
1835
+ };
1836
+ /**
1837
+ * The project's paywall assets (at most 500), newest first.
1838
+ */
1839
+ export type PaywallAssets = {
1656
1840
  /**
1657
- * The catalog's product; absent when the catalog does not map what the store sold.
1841
+ * The assets.
1658
1842
  */
1659
- product?: string;
1843
+ assets: PaywallAsset[];
1844
+ };
1845
+ /**
1846
+ * A border.
1847
+ */
1848
+ export type PaywallBorder = {
1849
+ /**
1850
+ * Color.
1851
+ */
1852
+ color: string;
1853
+ /**
1854
+ * Width.
1855
+ */
1856
+ width: number;
1857
+ };
1858
+ /**
1859
+ * A button that does an action: closes the paywall, restores purchases, opens an address, the terms or the privacy policy, the store's offer code sheet, one of the paywall's sheets, or selects a package.
1860
+ */
1861
+ export type PaywallButton = {
1862
+ action: PaywallAction;
1863
+ animation?: PaywallAnimation;
1864
+ content: PaywallComponent;
1865
+ /**
1866
+ * Names the component, unique in the paywall: an app's code can draw its own part in its place.
1867
+ */
1868
+ id?: string;
1869
+ states?: PaywallStates;
1870
+ style?: PaywallStyle;
1871
+ /**
1872
+ * The component.
1873
+ */
1874
+ type: "button";
1875
+ visible?: PaywallCondition;
1876
+ };
1877
+ /**
1878
+ * Pages the customer swipes through, the next peeking in, advancing on their own, with an indicator.
1879
+ */
1880
+ export type PaywallCarousel = {
1881
+ animation?: PaywallAnimation;
1882
+ /**
1883
+ * Auto advance ms.
1884
+ */
1885
+ auto_advance_ms?: number;
1886
+ /**
1887
+ * Height.
1888
+ */
1889
+ height?: PaywallSizeKeyword | PaywallLength;
1890
+ /**
1891
+ * Names the component, unique in the paywall: an app's code can draw its own part in its place.
1892
+ */
1893
+ id?: string;
1894
+ indicator?: PaywallIndicator;
1895
+ /**
1896
+ * Loop.
1897
+ */
1898
+ loop?: boolean;
1899
+ /**
1900
+ * Pages.
1901
+ */
1902
+ pages: PaywallComponent[];
1903
+ /**
1904
+ * Peek.
1905
+ */
1906
+ peek?: number;
1907
+ /**
1908
+ * Spacing.
1909
+ */
1910
+ spacing?: number;
1911
+ states?: PaywallStates;
1912
+ style?: PaywallStyle;
1913
+ /**
1914
+ * The component.
1915
+ */
1916
+ type: "carousel";
1917
+ visible?: PaywallCondition;
1918
+ };
1919
+ /**
1920
+ * A color: a token of the theme's colors (the light or the dark value, as the app appears), or #RRGGBB / #RRGGBBAA.
1921
+ */
1922
+ export type PaywallColorValue = string;
1923
+ /**
1924
+ * The theme's colors by name, for each appearance; both name the same colors, at least background, surface, text, muted, accent and on_accent.
1925
+ */
1926
+ export type PaywallColors = {
1927
+ dark: PaywallPalette;
1928
+ light: PaywallPalette;
1929
+ };
1930
+ /**
1931
+ * A component, by its type. A newer schema adds components; an app never draws a definition with one it does not know.
1932
+ */
1933
+ export type PaywallComponent = PaywallButton | PaywallCarousel | PaywallCountdown | PaywallCustomHtml | PaywallDivider | PaywallFeatures | PaywallIcon | PaywallImage | PaywallPackage | PaywallPurchaseButton | PaywallSpacer | PaywallStack | PaywallSwitch | PaywallTabs | PaywallText | PaywallTimeline | PaywallVideo;
1934
+ /**
1935
+ * When the component is shown: every field named holds at once.
1936
+ */
1937
+ export type PaywallCondition = {
1938
+ /**
1939
+ * Appearance.
1940
+ */
1941
+ appearance?: "light" | "dark";
1942
+ /**
1943
+ * Intro eligible.
1944
+ */
1945
+ intro_eligible?: boolean;
1946
+ /**
1947
+ * Locale.
1948
+ */
1949
+ locale?: string[];
1950
+ /**
1951
+ * Platform.
1952
+ */
1953
+ platform?: ("ios" | "android" | "web")[];
1954
+ /**
1955
+ * Selected package.
1956
+ */
1957
+ selected_package?: string[];
1958
+ /**
1959
+ * Tab.
1960
+ */
1961
+ tab?: string;
1962
+ };
1963
+ /**
1964
+ * Each corner its own, in points or a token of the theme's radii.
1965
+ */
1966
+ export type PaywallCorners = {
1967
+ /**
1968
+ * Bottom leading.
1969
+ */
1970
+ bottom_leading?: PaywallPoints | PaywallToken;
1971
+ /**
1972
+ * Bottom trailing.
1973
+ */
1974
+ bottom_trailing?: PaywallPoints | PaywallToken;
1975
+ /**
1976
+ * Top leading.
1977
+ */
1978
+ top_leading?: PaywallPoints | PaywallToken;
1979
+ /**
1980
+ * Top trailing.
1981
+ */
1982
+ top_trailing?: PaywallPoints | PaywallToken;
1983
+ };
1984
+ /**
1985
+ * A countdown to an instant, or for a time from the moment the paywall opened: one content while it counts — its texts name {{countdown}}, {{days}}, {{hours}}, {{minutes}}, {{seconds}} —, another once it ended.
1986
+ */
1987
+ export type PaywallCountdown = {
1988
+ animation?: PaywallAnimation;
1989
+ counting: PaywallComponent;
1990
+ ended?: PaywallComponent;
1991
+ /**
1992
+ * Names the component, unique in the paywall: an app's code can draw its own part in its place.
1993
+ */
1994
+ id?: string;
1995
+ states?: PaywallStates;
1996
+ style?: PaywallStyle;
1997
+ target: PaywallTarget;
1998
+ /**
1999
+ * The component.
2000
+ */
2001
+ type: "countdown";
2002
+ visible?: PaywallCondition;
2003
+ };
2004
+ /**
2005
+ * A decorative HTML block from an archive the project uploaded (an animation, a Lottie or Rive scene): drawn in a sandbox of an origin of its own: it reaches neither the page around it, nor the app, nor the purchase, and loads only what came in its archive (a content security policy) — it may still navigate its own frame away. It is told the selected package, the language and the appearance, and is hidden from screen readers. It cannot buy anything.
2006
+ */
2007
+ export type PaywallCustomHtml = {
2008
+ animation?: PaywallAnimation;
2009
+ /**
2010
+ * Height.
2011
+ */
2012
+ height: PaywallSizeKeyword | PaywallLength;
2013
+ /**
2014
+ * Names the component, unique in the paywall: an app's code can draw its own part in its place.
2015
+ */
2016
+ id?: string;
2017
+ /**
2018
+ * Src.
2019
+ */
2020
+ src: string;
2021
+ states?: PaywallStates;
2022
+ style?: PaywallStyle;
2023
+ /**
2024
+ * The component.
2025
+ */
2026
+ type: "custom_html";
2027
+ visible?: PaywallCondition;
2028
+ };
2029
+ /**
2030
+ * A paywall: a design system (the theme's colors, type scale, radii and spacing) and a free layout of components that name it — a fixed header and footer around the part that scrolls, and sheets it opens. Every component takes a style, a condition to be shown, a style for when it is selected, and an entrance animation. Prices are never in it: an app fills `{{price}}` and the other variables from its store. Its assets (asset:<id>) are the project's, given as https addresses in the app's answer and listed for the app to download before it shows the paywall. The server refuses what it does not know and holds a definition to bounds: 128 KiB of JSON, 400 components, 16 deep, 500 characters a text, 40 languages, 8 stops a gradient, 2 seconds an animation, 10 carousel pages, 5 tabs, 5 sheets.
2031
+ */
2032
+ export type PaywallDefinition = {
2033
+ /**
2034
+ * The language a text falls back to: a tag such as en or pt-BR.
2035
+ */
2036
+ default_locale: string;
2037
+ footer?: PaywallComponent;
2038
+ header?: PaywallComponent;
2039
+ locales?: PaywallLocales;
2040
+ /**
2041
+ * The paywall's name, for the people who edit it (1 to 100 characters).
2042
+ */
2043
+ name: string;
2044
+ root: PaywallComponent;
2045
+ /**
2046
+ * The schema the definition is written in: 2. An app says the newest schema it draws (X-Palbase-Paywall-Schema) and is given the newest version written in it or an older one; an app that draws no schema this server takes is told to update (426).
2047
+ */
2048
+ schema: number;
2049
+ sheets?: PaywallSheets;
2050
+ theme: PaywallTheme;
2051
+ };
2052
+ /**
2053
+ * A thin line across its stack.
2054
+ */
2055
+ export type PaywallDivider = {
2056
+ animation?: PaywallAnimation;
2057
+ /**
2058
+ * Color.
2059
+ */
2060
+ color?: string;
2061
+ /**
2062
+ * Names the component, unique in the paywall: an app's code can draw its own part in its place.
2063
+ */
2064
+ id?: string;
2065
+ states?: PaywallStates;
2066
+ style?: PaywallStyle;
2067
+ /**
2068
+ * Thickness.
2069
+ */
2070
+ thickness?: number;
2071
+ /**
2072
+ * The component.
2073
+ */
2074
+ type: "divider";
2075
+ visible?: PaywallCondition;
2076
+ };
2077
+ /**
2078
+ * Each edge its own, in points or a token of the theme's spacing.
2079
+ */
2080
+ export type PaywallEdges = {
2081
+ /**
2082
+ * Bottom.
2083
+ */
2084
+ bottom?: PaywallPoints | PaywallToken;
2085
+ /**
2086
+ * Leading.
2087
+ */
2088
+ leading?: PaywallPoints | PaywallToken;
2089
+ /**
2090
+ * Top.
2091
+ */
2092
+ top?: PaywallPoints | PaywallToken;
2093
+ /**
2094
+ * Trailing.
2095
+ */
2096
+ trailing?: PaywallPoints | PaywallToken;
2097
+ };
2098
+ /**
2099
+ * The error envelope of a refused definition, with every problem when it breaks a rule (`invalid_paywall`).
2100
+ */
2101
+ export type PaywallError = {
2102
+ /**
2103
+ * Machine-readable error code (snake_case)
2104
+ */
2105
+ error: string;
2106
+ /**
2107
+ * Human-readable explanation
2108
+ */
2109
+ error_description: string;
2110
+ /**
2111
+ * Every problem, by path: with `invalid_paywall`, absent otherwise.
2112
+ */
2113
+ problems?: PaywallProblem[];
2114
+ /**
2115
+ * Correlation ID for log/audit lookup
2116
+ */
2117
+ request_id: string;
2118
+ /**
2119
+ * Seconds to wait before retrying; present on a refusal that ends with time.
2120
+ */
2121
+ retry_after?: number;
2122
+ /**
2123
+ * HTTP status code (mirrors the response status)
2124
+ */
2125
+ status: number;
2126
+ };
2127
+ /**
2128
+ * A feature.
2129
+ */
2130
+ export type PaywallFeature = {
2131
+ icon: PaywallIconName;
2132
+ text: PaywallString;
2133
+ };
2134
+ /**
2135
+ * What the purchase gives, each with an icon.
2136
+ */
2137
+ export type PaywallFeatures = {
2138
+ animation?: PaywallAnimation;
2139
+ /**
2140
+ * Color.
2141
+ */
2142
+ color?: string;
2143
+ /**
2144
+ * Icon color.
2145
+ */
2146
+ icon_color?: string;
2147
+ /**
2148
+ * Names the component, unique in the paywall: an app's code can draw its own part in its place.
2149
+ */
2150
+ id?: string;
2151
+ /**
2152
+ * Items.
2153
+ */
2154
+ items: PaywallFeature[];
2155
+ /**
2156
+ * Spacing.
2157
+ */
2158
+ spacing?: number;
2159
+ states?: PaywallStates;
2160
+ style?: PaywallStyle;
2161
+ /**
2162
+ * The component.
2163
+ */
2164
+ type: "features";
2165
+ visible?: PaywallCondition;
2166
+ };
2167
+ /**
2168
+ * A size in points, scaled with the platform's body style.
2169
+ */
2170
+ export type PaywallFontSize = number;
2171
+ /**
2172
+ * An icon every renderer draws.
2173
+ */
2174
+ export type PaywallIcon = {
2175
+ animation?: PaywallAnimation;
2176
+ /**
2177
+ * Color.
2178
+ */
2179
+ color?: string;
2180
+ /**
2181
+ * Names the component, unique in the paywall: an app's code can draw its own part in its place.
2182
+ */
2183
+ id?: string;
2184
+ name: PaywallIconName;
2185
+ /**
2186
+ * Size.
2187
+ */
2188
+ size?: number;
2189
+ states?: PaywallStates;
2190
+ style?: PaywallStyle;
2191
+ /**
2192
+ * The component.
2193
+ */
2194
+ type: "icon";
2195
+ visible?: PaywallCondition;
2196
+ };
2197
+ /**
2198
+ * An icon every renderer draws (SF Symbols on iOS).
2199
+ */
2200
+ export type PaywallIconName = "ad_free" | "arrow_right" | "bell" | "bolt" | "book" | "calendar" | "chart" | "chat" | "check" | "check_circle" | "clock" | "close" | "cloud" | "crown" | "download" | "gift" | "globe" | "heart" | "infinity" | "lock" | "lock_open" | "music" | "people" | "person" | "photo" | "play" | "quote" | "shield" | "sparkles" | "star" | "trophy" | "video";
2201
+ /**
2202
+ * An image the app downloads before it shows the paywall: an https address, or an image the project uploaded.
2203
+ */
2204
+ export type PaywallImage = {
2205
+ alt?: PaywallString;
2206
+ animation?: PaywallAnimation;
2207
+ /**
2208
+ * Aspect.
2209
+ */
2210
+ aspect?: number;
2211
+ /**
2212
+ * Decorative.
2213
+ */
2214
+ decorative?: boolean;
2215
+ /**
2216
+ * Fit.
2217
+ */
2218
+ fit?: "fit" | "fill";
2219
+ /**
2220
+ * Names the component, unique in the paywall: an app's code can draw its own part in its place.
2221
+ */
2222
+ id?: string;
2223
+ mask?: PaywallMask;
2224
+ /**
2225
+ * Overlay.
2226
+ */
2227
+ overlay?: PaywallLinear | PaywallRadial;
2228
+ /**
2229
+ * Src.
2230
+ */
2231
+ src: string;
2232
+ states?: PaywallStates;
2233
+ style?: PaywallStyle;
2234
+ /**
2235
+ * The component.
2236
+ */
2237
+ type: "image";
2238
+ visible?: PaywallCondition;
2239
+ };
2240
+ /**
2241
+ * An image behind the component.
2242
+ */
2243
+ export type PaywallImageFill = {
2244
+ /**
2245
+ * Fit.
2246
+ */
2247
+ fit?: "fit" | "fill";
2248
+ /**
2249
+ * Src.
2250
+ */
2251
+ src: string;
2252
+ /**
2253
+ * Type.
2254
+ */
2255
+ type: "image";
2256
+ };
2257
+ /**
2258
+ * A carousel's page indicator.
2259
+ */
2260
+ export type PaywallIndicator = {
2261
+ /**
2262
+ * Active color.
2263
+ */
2264
+ active_color?: string;
2265
+ /**
2266
+ * Color.
2267
+ */
2268
+ color?: string;
2269
+ /**
2270
+ * Size.
2271
+ */
2272
+ size?: number;
2273
+ /**
2274
+ * Spacing.
2275
+ */
2276
+ spacing?: number;
2277
+ /**
2278
+ * Its style.
2279
+ */
2280
+ style?: "dots" | "bars" | "none";
2281
+ };
2282
+ /**
2283
+ * A length in points.
2284
+ */
2285
+ export type PaywallLength = number;
2286
+ /**
2287
+ * A linear gradient: its angle (0 up, clockwise, 180 down) and 2 to 8 stops.
2288
+ */
2289
+ export type PaywallLinear = {
2290
+ /**
2291
+ * Angle.
2292
+ */
2293
+ angle?: number;
2294
+ /**
2295
+ * Stops.
2296
+ */
2297
+ stops: PaywallStop[];
2298
+ /**
2299
+ * Type.
2300
+ */
2301
+ type: "linear";
2302
+ };
2303
+ /**
2304
+ * The project's paywalls (at most 100), oldest first.
2305
+ */
2306
+ export type PaywallList = {
2307
+ /**
2308
+ * The paywalls.
2309
+ */
2310
+ paywalls: PaywallSummary[];
2311
+ };
2312
+ /**
2313
+ * The text itself, in every language.
2314
+ */
2315
+ export type PaywallLiteral = string;
2316
+ /**
2317
+ * The texts in each language (at most 40), by language tag: a component's `{"t": key}` is the app's language's, or the default locale's when it lacks the key.
2318
+ */
2319
+ export type PaywallLocales = {
2320
+ [key: string]: PaywallTexts;
2321
+ };
2322
+ /**
2323
+ * The image's shape: a rectangle with corners, a circle, or a rectangle whose bottom edge curves in (concave) or out (convex).
2324
+ */
2325
+ export type PaywallMask = {
2326
+ /**
2327
+ * Depth.
2328
+ */
2329
+ depth?: number;
2330
+ /**
2331
+ * Radius.
2332
+ */
2333
+ radius?: PaywallPoints | PaywallToken;
2334
+ /**
2335
+ * Shape.
2336
+ */
2337
+ shape: "rect" | "circle" | "concave" | "convex";
2338
+ };
2339
+ /**
2340
+ * A package on sale, laid out as the project likes: tapping it selects it; its content's styles for when it is selected apply while it is.
2341
+ */
2342
+ export type PaywallPackage = {
2343
+ animation?: PaywallAnimation;
2344
+ /**
2345
+ * The components.
2346
+ */
2347
+ children?: PaywallComponent[];
2348
+ /**
2349
+ * Names the component, unique in the paywall: an app's code can draw its own part in its place.
2350
+ */
2351
+ id?: string;
2352
+ /**
2353
+ * Plan.
2354
+ */
2355
+ plan: string;
2356
+ /**
2357
+ * Product.
2358
+ */
2359
+ product: string;
2360
+ /**
2361
+ * Selected when the paywall opens (at most one).
2362
+ */
2363
+ selected?: boolean;
2364
+ states?: PaywallStates;
2365
+ style?: PaywallStyle;
2366
+ /**
2367
+ * The component.
2368
+ */
2369
+ type: "package";
2370
+ visible?: PaywallCondition;
2371
+ };
2372
+ /**
2373
+ * Colors by token (lowercase letters, digits and _, at most 32), each #RRGGBB or #RRGGBBAA.
2374
+ */
2375
+ export type PaywallPalette = {
2376
+ [key: string]: string;
2377
+ };
2378
+ /**
2379
+ * Points.
2380
+ */
2381
+ export type PaywallPoints = number;
2382
+ /**
2383
+ * One thing wrong with a definition.
2384
+ */
2385
+ export type PaywallProblem = {
2386
+ /**
2387
+ * What it is (unknown_field, unknown_component, too_long, invalid_url, unknown_package, unknown_token, unknown_asset, asset_missing, asset_changed, asset_unverified …).
2388
+ */
2389
+ code: string;
2390
+ /**
2391
+ * What to do about it.
2392
+ */
2393
+ message: string;
2394
+ /**
2395
+ * Where it is (root.children[2].items[0].product).
2396
+ */
2397
+ path: string;
2398
+ /**
2399
+ * A warning does not stop a save or a publish (App Review's expectations, a package the catalog does not sell yet in a draft).
2400
+ */
2401
+ warning?: boolean;
2402
+ };
2403
+ /**
2404
+ * purchases.paywall.published: a paywall's draft was published as its next version; the apps that ask for a placement showing it get it.
2405
+ */
2406
+ export type PaywallPublishedEvent = {
2407
+ /**
2408
+ * Its name.
2409
+ */
2410
+ name: string;
2411
+ /**
2412
+ * The paywall.
2413
+ */
2414
+ paywall_id: string;
2415
+ /**
2416
+ * The schema it is written in.
2417
+ */
2418
+ schema: number;
2419
+ /**
2420
+ * The version published.
2421
+ */
2422
+ version: number;
2423
+ };
2424
+ /**
2425
+ * The button that buys the selected package — or its own package —: the store's sheet (StoreKit) or checkout (Stripe) opens.
2426
+ */
2427
+ export type PaywallPurchaseButton = {
2428
+ animation?: PaywallAnimation;
2429
+ content: PaywallComponent;
2430
+ /**
2431
+ * Names the component, unique in the paywall: an app's code can draw its own part in its place.
2432
+ */
2433
+ id?: string;
2434
+ /**
2435
+ * Package.
2436
+ */
2437
+ package?: string;
2438
+ states?: PaywallStates;
2439
+ style?: PaywallStyle;
2440
+ /**
2441
+ * The component.
2442
+ */
2443
+ type: "purchase_button";
2444
+ visible?: PaywallCondition;
2445
+ };
2446
+ /**
2447
+ * A radial gradient: its center and radius as shares of the component, and 2 to 8 stops.
2448
+ */
2449
+ export type PaywallRadial = {
2450
+ /**
2451
+ * Center x.
2452
+ */
2453
+ center_x?: number;
2454
+ /**
2455
+ * Center y.
2456
+ */
2457
+ center_y?: number;
2458
+ /**
2459
+ * Radius.
2460
+ */
2461
+ radius?: number;
2462
+ /**
2463
+ * Stops.
2464
+ */
2465
+ stops: PaywallStop[];
2466
+ /**
2467
+ * Type.
2468
+ */
2469
+ type: "radial";
2470
+ };
2471
+ /**
2472
+ * A definition to save as a paywall's draft.
2473
+ */
2474
+ export type PaywallRequest = {
2475
+ definition: PaywallDefinition;
2476
+ };
2477
+ /**
2478
+ * Points by token (lowercase letters, digits and _, at most 32).
2479
+ */
2480
+ export type PaywallScale = {
2481
+ [key: string]: number;
2482
+ };
2483
+ /**
2484
+ * The error envelope of an app whose SDK draws no paywall schema this server takes (`paywall_schema_too_old`): it draws its own paywall, and updating the SDK shows the project's.
2485
+ */
2486
+ export type PaywallSchemaError = {
2487
+ /**
2488
+ * Machine-readable error code (snake_case)
2489
+ */
2490
+ error: string;
2491
+ /**
2492
+ * Human-readable explanation
2493
+ */
2494
+ error_description: string;
2495
+ /**
2496
+ * The oldest schema an SDK must draw to be given this project's paywalls.
2497
+ */
2498
+ min_schema: number;
2499
+ /**
2500
+ * Correlation ID for log/audit lookup
2501
+ */
2502
+ request_id: string;
2503
+ /**
2504
+ * HTTP status code (mirrors the response status)
2505
+ */
2506
+ status: number;
2507
+ };
2508
+ /**
2509
+ * A shadow.
2510
+ */
2511
+ export type PaywallShadow = {
2512
+ /**
2513
+ * Color.
2514
+ */
2515
+ color: string;
2516
+ /**
2517
+ * Radius.
2518
+ */
2519
+ radius?: number;
2520
+ /**
2521
+ * X.
2522
+ */
2523
+ x?: number;
2524
+ /**
2525
+ * Y.
2526
+ */
2527
+ y?: number;
2528
+ };
2529
+ /**
2530
+ * A second page a button opens over the paywall.
2531
+ */
2532
+ export type PaywallSheet = {
2533
+ root: PaywallComponent;
2534
+ title?: PaywallString;
2535
+ };
2536
+ /**
2537
+ * The sheets by id (lowercase letters, digits, _ and -, starting with a letter).
2538
+ */
2539
+ export type PaywallSheets = {
2540
+ [key: string]: PaywallSheet;
2541
+ };
2542
+ /**
2543
+ * fit: the content's size; fill: all the parent gives; a share of the parent ("50%").
2544
+ */
2545
+ export type PaywallSizeKeyword = string;
2546
+ /**
2547
+ * Space: a fixed size, or all that is left along its stack when absent.
2548
+ */
2549
+ export type PaywallSpacer = {
2550
+ animation?: PaywallAnimation;
2551
+ /**
2552
+ * Names the component, unique in the paywall: an app's code can draw its own part in its place.
2553
+ */
2554
+ id?: string;
2555
+ /**
2556
+ * Size.
2557
+ */
2558
+ size?: PaywallPoints | PaywallToken;
2559
+ states?: PaywallStates;
2560
+ style?: PaywallStyle;
2561
+ /**
2562
+ * The component.
2563
+ */
2564
+ type: "spacer";
2565
+ visible?: PaywallCondition;
2566
+ };
2567
+ /**
2568
+ * A part of a text: bold, italic, underlined, struck through, colored, a link.
2569
+ */
2570
+ export type PaywallSpan = {
2571
+ /**
2572
+ * Bold.
2573
+ */
2574
+ bold?: boolean;
2575
+ /**
2576
+ * Color.
2577
+ */
2578
+ color?: string;
2579
+ /**
2580
+ * Italic.
2581
+ */
2582
+ italic?: boolean;
2583
+ /**
2584
+ * Link.
2585
+ */
2586
+ link?: string;
2587
+ /**
2588
+ * Strikethrough.
2589
+ */
2590
+ strikethrough?: boolean;
2591
+ text: PaywallString;
2592
+ /**
2593
+ * Underline.
2594
+ */
2595
+ underline?: boolean;
2596
+ };
2597
+ /**
2598
+ * Components laid out one after another — down, across — or over each other (z). The root, the header and the footer are each one; the root scrolls between the fixed header and footer.
2599
+ */
2600
+ export type PaywallStack = {
2601
+ /**
2602
+ * Align.
2603
+ */
2604
+ align?: "start" | "center" | "end" | "stretch";
2605
+ animation?: PaywallAnimation;
2606
+ /**
2607
+ * Axis.
2608
+ */
2609
+ axis?: "vertical" | "horizontal" | "z";
2610
+ /**
2611
+ * The components.
2612
+ */
2613
+ children?: PaywallComponent[];
2614
+ /**
2615
+ * Distribution.
2616
+ */
2617
+ distribution?: "start" | "center" | "end" | "space_between" | "space_around" | "space_evenly";
2618
+ /**
2619
+ * Names the component, unique in the paywall: an app's code can draw its own part in its place.
2620
+ */
2621
+ id?: string;
2622
+ /**
2623
+ * Scroll.
2624
+ */
2625
+ scroll?: boolean;
2626
+ /**
2627
+ * Spacing.
2628
+ */
2629
+ spacing?: PaywallPoints | PaywallToken;
2630
+ states?: PaywallStates;
2631
+ style?: PaywallStyle;
2632
+ /**
2633
+ * The component.
2634
+ */
2635
+ type: "stack";
2636
+ visible?: PaywallCondition;
2637
+ };
2638
+ /**
2639
+ * The component's style while what it is in is selected: the package it is in (or is), the tab whose label it is.
2640
+ */
2641
+ export type PaywallStates = {
2642
+ selected?: PaywallStyle;
2643
+ };
2644
+ /**
2645
+ * A gradient's color at a point along it (0 to 1).
2646
+ */
2647
+ export type PaywallStop = {
2648
+ /**
2649
+ * At.
2650
+ */
2651
+ at: number;
2652
+ /**
2653
+ * Color.
2654
+ */
2655
+ color: string;
2656
+ };
2657
+ /**
2658
+ * A text: the string itself, or `{"t": key}` of the language table. Either may hold variables the app fills from its store — `{{price}}`, `{{price_per_month}}`, `{{period}}`, `{{trial}}`, `{{savings}}`, `{{product_name}}` — of the package an item is, or of the selected package anywhere else. A text that names a variable its package has no value for (no trial, no savings) is not drawn.
2659
+ */
2660
+ export type PaywallString = PaywallLiteral | PaywallTextKey;
2661
+ /**
2662
+ * What every component takes: padding and margin by edge, a size, a fill, a border, corners each their own, a shadow, an opacity. Points and colors name the theme's tokens or are given as they are.
2663
+ */
2664
+ export type PaywallStyle = {
2665
+ /**
2666
+ * Background.
2667
+ */
2668
+ background?: PaywallColorValue | PaywallLinear | PaywallRadial | PaywallImageFill | PaywallVideoFill;
2669
+ border?: PaywallBorder;
2670
+ /**
2671
+ * Corners.
2672
+ */
2673
+ corners?: PaywallPoints | PaywallToken | PaywallCorners;
2674
+ /**
2675
+ * Height.
2676
+ */
2677
+ height?: PaywallSizeKeyword | PaywallLength;
2678
+ /**
2679
+ * Margin.
2680
+ */
2681
+ margin?: PaywallPoints | PaywallToken | PaywallEdges;
2682
+ /**
2683
+ * Max width.
2684
+ */
2685
+ max_width?: number;
2686
+ /**
2687
+ * Opacity.
2688
+ */
2689
+ opacity?: number;
2690
+ /**
2691
+ * Padding.
2692
+ */
2693
+ padding?: PaywallPoints | PaywallToken | PaywallEdges;
2694
+ shadow?: PaywallShadow;
2695
+ /**
2696
+ * Width.
2697
+ */
2698
+ width?: PaywallSizeKeyword | PaywallLength;
2699
+ };
2700
+ /**
2701
+ * A paywall in the project's list.
2702
+ */
2703
+ export type PaywallSummary = {
2704
+ /**
2705
+ * Its draft's revision.
2706
+ */
2707
+ draft_revision: number;
2708
+ /**
2709
+ * The paywall's id.
2710
+ */
2711
+ id: string;
2712
+ /**
2713
+ * Its name.
2714
+ */
2715
+ name: string;
2716
+ /**
2717
+ * When the newest version was published.
2718
+ */
2719
+ published_at?: string;
2720
+ /**
2721
+ * The newest version published; 0 before the first.
2722
+ */
2723
+ published_version: number;
2724
+ /**
2725
+ * When the draft was last saved.
2726
+ */
2727
+ updated_at: string;
2728
+ };
2729
+ /**
2730
+ * A switch between two contents — a yearly and a monthly offer —, each selecting its own package when it is shown.
2731
+ */
2732
+ export type PaywallSwitch = {
2733
+ animation?: PaywallAnimation;
2734
+ /**
2735
+ * Default.
2736
+ */
2737
+ default?: boolean;
2738
+ /**
2739
+ * Names the component, unique in the paywall: an app's code can draw its own part in its place.
2740
+ */
2741
+ id?: string;
2742
+ label?: PaywallString;
2743
+ off: PaywallComponent;
2744
+ /**
2745
+ * Off package.
2746
+ */
2747
+ off_package?: string;
2748
+ on: PaywallComponent;
2749
+ /**
2750
+ * On package.
2751
+ */
2752
+ on_package?: string;
2753
+ states?: PaywallStates;
2754
+ style?: PaywallStyle;
2755
+ /**
2756
+ * Tint.
2757
+ */
2758
+ tint?: string;
2759
+ /**
2760
+ * The component.
2761
+ */
2762
+ type: "switch";
2763
+ visible?: PaywallCondition;
2764
+ };
2765
+ /**
2766
+ * A tab: its label, its content, and the package it selects when it is shown.
2767
+ */
2768
+ export type PaywallTab = {
2769
+ content: PaywallComponent;
2770
+ /**
2771
+ * Names the component, unique in the paywall: an app's code can draw its own part in its place.
2772
+ */
2773
+ id: string;
2774
+ label: PaywallComponent;
2775
+ /**
2776
+ * Package.
2777
+ */
2778
+ package?: string;
2779
+ };
2780
+ /**
2781
+ * Tabs, each its own content and default package; the labels, in a bar, are components whose style when selected is the shown tab's.
2782
+ */
2783
+ export type PaywallTabs = {
2784
+ animation?: PaywallAnimation;
2785
+ bar?: PaywallStyle;
2786
+ /**
2787
+ * Default.
2788
+ */
2789
+ default?: string;
2790
+ /**
2791
+ * Names the component, unique in the paywall: an app's code can draw its own part in its place.
2792
+ */
2793
+ id?: string;
2794
+ states?: PaywallStates;
2795
+ style?: PaywallStyle;
2796
+ /**
2797
+ * Tabs.
2798
+ */
2799
+ tabs: PaywallTab[];
2800
+ /**
2801
+ * The component.
2802
+ */
2803
+ type: "tabs";
2804
+ visible?: PaywallCondition;
2805
+ };
2806
+ /**
2807
+ * What a countdown counts to: an instant (at), or a time from the moment the paywall opened (after_open_seconds) — one of them.
2808
+ */
2809
+ export type PaywallTarget = {
2810
+ /**
2811
+ * After open seconds.
2812
+ */
2813
+ after_open_seconds?: number;
2814
+ /**
2815
+ * At.
2816
+ */
2817
+ at?: string;
2818
+ };
2819
+ /**
2820
+ * A text: one string, or spans — bold, italic, colored parts and links —, in a type style of the theme or its own.
2821
+ */
2822
+ export type PaywallText = {
2823
+ /**
2824
+ * Align.
2825
+ */
2826
+ align?: "start" | "center" | "end";
2827
+ animation?: PaywallAnimation;
2828
+ /**
2829
+ * Color.
2830
+ */
2831
+ color?: PaywallColorValue | PaywallLinear | PaywallRadial;
2832
+ /**
2833
+ * Font.
2834
+ */
2835
+ font?: string;
2836
+ /**
2837
+ * Names the component, unique in the paywall: an app's code can draw its own part in its place.
2838
+ */
2839
+ id?: string;
2840
+ /**
2841
+ * Letter spacing.
2842
+ */
2843
+ letter_spacing?: number;
2844
+ /**
2845
+ * Line height.
2846
+ */
2847
+ line_height?: number;
2848
+ /**
2849
+ * Max lines.
2850
+ */
2851
+ max_lines?: number;
2852
+ /**
2853
+ * Size.
2854
+ */
2855
+ size?: PaywallFontSize | PaywallToken;
2856
+ /**
2857
+ * Spans.
2858
+ */
2859
+ spans?: PaywallSpan[];
2860
+ states?: PaywallStates;
2861
+ style?: PaywallStyle;
2862
+ text?: PaywallString;
2863
+ /**
2864
+ * The component.
2865
+ */
2866
+ type: "text";
2867
+ /**
2868
+ * Uppercase.
2869
+ */
2870
+ uppercase?: boolean;
2871
+ visible?: PaywallCondition;
2872
+ /**
2873
+ * Weight.
2874
+ */
2875
+ weight?: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
2876
+ };
2877
+ /**
2878
+ * A text of the language table.
2879
+ */
2880
+ export type PaywallTextKey = {
2881
+ /**
2882
+ * The text's key.
2883
+ */
2884
+ t: string;
2885
+ };
2886
+ /**
2887
+ * One language's texts, by key (lowercase letters, digits, `_` `.` `-`, at most 64): each at most 500 characters, with variables.
2888
+ */
2889
+ export type PaywallTexts = {
2890
+ [key: string]: string;
2891
+ };
2892
+ /**
2893
+ * The paywall's design system: colors for light and dark, a type scale, radii and spacing; the components name them.
2894
+ */
2895
+ export type PaywallTheme = {
2896
+ colors: PaywallColors;
2897
+ radii?: PaywallScale;
2898
+ spacing?: PaywallScale;
2899
+ typography?: PaywallTypeScale;
2900
+ };
2901
+ /**
2902
+ * Steps in time — a trial's today, its reminder, its first charge —, each with an icon, joined by a line.
2903
+ */
2904
+ export type PaywallTimeline = {
2905
+ animation?: PaywallAnimation;
2906
+ /**
2907
+ * Color.
2908
+ */
2909
+ color?: string;
2910
+ /**
2911
+ * Icon color.
2912
+ */
2913
+ icon_color?: string;
2914
+ /**
2915
+ * Names the component, unique in the paywall: an app's code can draw its own part in its place.
2916
+ */
2917
+ id?: string;
2918
+ /**
2919
+ * Items.
2920
+ */
2921
+ items: PaywallTimelineItem[];
2922
+ /**
2923
+ * Line color.
2924
+ */
2925
+ line_color?: string;
2926
+ /**
2927
+ * Line width.
2928
+ */
2929
+ line_width?: number;
2930
+ /**
2931
+ * Spacing.
2932
+ */
2933
+ spacing?: number;
2934
+ states?: PaywallStates;
2935
+ style?: PaywallStyle;
2936
+ /**
2937
+ * The component.
2938
+ */
2939
+ type: "timeline";
2940
+ visible?: PaywallCondition;
2941
+ };
2942
+ /**
2943
+ * A step of a timeline.
2944
+ */
2945
+ export type PaywallTimelineItem = {
2946
+ /**
2947
+ * Color.
2948
+ */
2949
+ color?: string;
2950
+ icon: PaywallIconName;
2951
+ text?: PaywallString;
2952
+ title: PaywallString;
2953
+ };
2954
+ /**
2955
+ * A token of the theme's scale.
2956
+ */
2957
+ export type PaywallToken = string;
2958
+ /**
2959
+ * Type styles by token (lowercase letters, digits and _, at most 32).
2960
+ */
2961
+ export type PaywallTypeScale = {
2962
+ [key: string]: PaywallTypography;
2963
+ };
2964
+ /**
2965
+ * A type style of the theme: what a text whose size names it is drawn in. It scales with its text style (Dynamic Type on iOS, the root font size on the web).
2966
+ */
2967
+ export type PaywallTypography = {
2968
+ /**
2969
+ * Font.
2970
+ */
2971
+ font?: string;
2972
+ /**
2973
+ * Letter spacing.
2974
+ */
2975
+ letter_spacing?: number;
2976
+ /**
2977
+ * Line height.
2978
+ */
2979
+ line_height?: number;
2980
+ /**
2981
+ * Size.
2982
+ */
2983
+ size: number;
2984
+ /**
2985
+ * Text style.
2986
+ */
2987
+ text_style?: "large_title" | "title" | "title2" | "title3" | "headline" | "body" | "callout" | "subheadline" | "footnote" | "caption";
2988
+ /**
2989
+ * Weight.
2990
+ */
2991
+ weight?: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
2992
+ };
2993
+ /**
2994
+ * A definition that passes, and what is left to say of it.
2995
+ */
2996
+ export type PaywallValidation = {
2997
+ /**
2998
+ * The warnings, by path.
2999
+ */
3000
+ problems: PaywallProblem[];
3001
+ };
3002
+ /**
3003
+ * A published version of a paywall.
3004
+ */
3005
+ export type PaywallVersion = {
3006
+ definition?: PaywallDefinition;
3007
+ /**
3008
+ * The paywall.
3009
+ */
3010
+ paywall_id: string;
3011
+ /**
3012
+ * When it was published.
3013
+ */
3014
+ published_at: string;
3015
+ /**
3016
+ * Who published it (the key).
3017
+ */
3018
+ published_by: string;
3019
+ /**
3020
+ * The schema it is written in.
3021
+ */
3022
+ schema: number;
3023
+ /**
3024
+ * The version: 1, 2, …
3025
+ */
3026
+ version: number;
3027
+ };
3028
+ /**
3029
+ * A page of a paywall's versions, newest first, without their definitions.
3030
+ */
3031
+ export type PaywallVersions = {
3032
+ /**
3033
+ * The next page's cursor; absent on the last.
3034
+ */
3035
+ next_cursor?: string;
3036
+ /**
3037
+ * The versions.
3038
+ */
3039
+ versions: PaywallVersion[];
3040
+ };
3041
+ /**
3042
+ * A video the app downloads before it shows the paywall; muted and looping unless it says otherwise.
3043
+ */
3044
+ export type PaywallVideo = {
3045
+ alt?: PaywallString;
3046
+ animation?: PaywallAnimation;
3047
+ /**
3048
+ * Aspect.
3049
+ */
3050
+ aspect?: number;
3051
+ /**
3052
+ * Autoplay.
3053
+ */
3054
+ autoplay?: boolean;
3055
+ /**
3056
+ * Controls.
3057
+ */
3058
+ controls?: boolean;
3059
+ /**
3060
+ * Fit.
3061
+ */
3062
+ fit?: "fit" | "fill";
3063
+ /**
3064
+ * Names the component, unique in the paywall: an app's code can draw its own part in its place.
3065
+ */
3066
+ id?: string;
3067
+ /**
3068
+ * Loop.
3069
+ */
3070
+ loop?: boolean;
3071
+ /**
3072
+ * Mute.
3073
+ */
3074
+ mute?: boolean;
3075
+ /**
3076
+ * Poster.
3077
+ */
3078
+ poster?: string;
3079
+ /**
3080
+ * Src.
3081
+ */
3082
+ src: string;
3083
+ states?: PaywallStates;
3084
+ style?: PaywallStyle;
3085
+ /**
3086
+ * The component.
3087
+ */
3088
+ type: "video";
3089
+ visible?: PaywallCondition;
3090
+ };
3091
+ /**
3092
+ * A muted video behind the component.
3093
+ */
3094
+ export type PaywallVideoFill = {
3095
+ /**
3096
+ * Loop.
3097
+ */
3098
+ loop?: boolean;
3099
+ /**
3100
+ * Poster.
3101
+ */
3102
+ poster?: string;
3103
+ /**
3104
+ * Src.
3105
+ */
3106
+ src: string;
3107
+ /**
3108
+ * Type.
3109
+ */
3110
+ type: "video";
3111
+ };
3112
+ /**
3113
+ * A place in an app a paywall is shown, as the app names it: its default paywall, the experiment running on it for everyone there, and how many rules it has.
3114
+ */
3115
+ export type Placement = {
3116
+ /**
3117
+ * The experiment running on it for everyone there (audience placement).
3118
+ */
3119
+ experiment_id?: string;
3120
+ /**
3121
+ * The placement's key.
3122
+ */
3123
+ key: string;
3124
+ /**
3125
+ * Its default paywall: what it shows whoever none of its rules holds for. Absent while an experiment for everyone runs on a placement that had none.
3126
+ */
3127
+ paywall_id?: string;
3128
+ /**
3129
+ * How many rules it has (GET …/rules reads them).
3130
+ */
3131
+ rule_count: number;
3132
+ /**
3133
+ * When it was last given a paywall or an experiment.
3134
+ */
3135
+ updated_at: string;
3136
+ /**
3137
+ * Who did (the key).
3138
+ */
3139
+ updated_by: string;
3140
+ };
3141
+ /**
3142
+ * What an app draws at a placement: the paywall's newest version written in a schema the app draws, where it came from (the experiment running for the whole placement, a rule, the placement's default) and the rule, the subject's variant when it is in an experiment, and the store ids of what it sells — the app takes each price from its store (StoreKit, Stripe) and fills the variables with it.
3143
+ */
3144
+ export type PlacementPaywall = {
3145
+ /**
3146
+ * The project's assets the definition names (asset:<id>), each once: the app downloads them when it gets the paywall — before it shows it —, checks each one's SHA-256 and size, and draws an asset only from its checked download. One it could not get, or whose bytes are not these, it does without: an image is not drawn, a font is the system's, a video is its poster or the background's color, an HTML block is not drawn.
3147
+ */
3148
+ assets: PaywallAssetRef[];
3149
+ definition: PaywallDefinition;
3150
+ offerings: Offerings;
3151
+ /**
3152
+ * The paywall.
3153
+ */
3154
+ paywall_id: string;
3155
+ /**
3156
+ * The placement.
3157
+ */
3158
+ placement: string;
3159
+ /**
3160
+ * The rule that decided, when one did: report it with the exposure.
3161
+ */
3162
+ rule_id?: string;
3163
+ /**
3164
+ * The schema the definition is written in: at most the one the app said it draws.
3165
+ */
3166
+ schema: number;
3167
+ /**
3168
+ * Where it came from: experiment (the one running for the whole placement), rule, or default.
3169
+ */
3170
+ source: "experiment" | "rule" | "default";
3171
+ /**
3172
+ * The subject's variant when it is in an experiment; report it with the exposure. The same subject gets the same one every time.
3173
+ */
3174
+ variant?: string;
3175
+ /**
3176
+ * Its version; report it with the exposure.
3177
+ */
3178
+ version: number;
3179
+ };
3180
+ /**
3181
+ * What the placement shows the viewer at the moment, where it came from, and what each rule came to.
3182
+ */
3183
+ export type PlacementPreview = {
3184
+ /**
3185
+ * The moment.
3186
+ */
3187
+ at: string;
3188
+ /**
3189
+ * The experiment the viewer is in.
3190
+ */
3191
+ experiment_id?: string;
3192
+ /**
3193
+ * The paywall shown.
3194
+ */
3195
+ paywall_id?: string;
3196
+ /**
3197
+ * The rule that decided.
3198
+ */
3199
+ rule_id?: string;
3200
+ /**
3201
+ * experiment (the one running for the whole placement), rule, default, or none (nothing: the app draws its own).
3202
+ */
3203
+ source: "experiment" | "rule" | "default" | "none";
3204
+ steps: RuleStep[];
3205
+ /**
3206
+ * The viewer's variant.
3207
+ */
3208
+ variant?: string;
3209
+ };
3210
+ /**
3211
+ * The paywall a placement shows.
3212
+ */
3213
+ export type PlacementRequest = {
3214
+ /**
3215
+ * The paywall.
3216
+ */
3217
+ paywall_id: string;
3218
+ };
3219
+ /**
3220
+ * One of a placement's rules: when all its conditions hold for a viewer — none holds for everyone —, it shows its target.
3221
+ */
3222
+ export type PlacementRule = {
3223
+ /**
3224
+ * At most 10, all of which must hold.
3225
+ */
3226
+ conditions?: RuleCondition[];
3227
+ /**
3228
+ * When it stops being in effect (UTC).
3229
+ */
3230
+ ends_at?: string;
3231
+ /**
3232
+ * The rule's id: kept across edits, named by the answers and the exposures. None for a new rule; one is given.
3233
+ */
3234
+ id?: string;
3235
+ /**
3236
+ * Its name (1 to 100 characters).
3237
+ */
3238
+ name: string;
3239
+ /**
3240
+ * When a scheduled rule starts being in effect (UTC).
3241
+ */
3242
+ starts_at?: string;
3243
+ /**
3244
+ * live: in effect now (until ends_at); scheduled: in effect from starts_at (until ends_at); inactive: not in effect.
3245
+ */
3246
+ state: "live" | "scheduled" | "inactive";
3247
+ /**
3248
+ * What it is now (answers say it; a request's is not read): in_effect, pending (scheduled, not started), ended, inactive.
3249
+ */
3250
+ status?: "in_effect" | "pending" | "ended" | "inactive";
3251
+ target: RuleTarget;
3252
+ };
3253
+ /**
3254
+ * A placement's rules, in the order they are read: the first in effect that holds for a viewer wins.
3255
+ */
3256
+ export type PlacementRules = {
3257
+ /**
3258
+ * The placement.
3259
+ */
3260
+ placement: string;
3261
+ /**
3262
+ * Their revision, also their ETag: send it back as If-Match.
3263
+ */
3264
+ revision: number;
3265
+ rules: PlacementRule[];
3266
+ };
3267
+ /**
3268
+ * A placement's rules, all of them, in the order they are to be read (at most 50).
3269
+ */
3270
+ export type PlacementRulesRequest = {
3271
+ rules: PlacementRule[];
3272
+ };
3273
+ /**
3274
+ * The project's placements (at most 200), by key.
3275
+ */
3276
+ export type Placements = {
3277
+ /**
3278
+ * The placements.
3279
+ */
3280
+ placements: Placement[];
3281
+ };
3282
+ /**
3283
+ * How a product is paid for.
3284
+ */
3285
+ export type Plan = {
3286
+ /**
3287
+ * A non-renewing product's duration, an ISO 8601 duration such as P1M.
3288
+ */
3289
+ duration?: string;
3290
+ intro?: IntroOffer;
3291
+ /**
3292
+ * Its key: lowercase letters, digits and _, starting with a letter.
3293
+ */
3294
+ key: string;
3295
+ /**
3296
+ * A subscription's billing period, an ISO 8601 duration: the App Store sells by P1W, P1M, P2M, P3M, P6M, P1Y; Google Play adds P4W, P4M, P8M; Stripe bills at most once a year.
3297
+ */
3298
+ period?: string;
3299
+ price: Price;
3300
+ };
3301
+ /**
3302
+ * A confirmation, with the hash of the plan shown.
3303
+ */
3304
+ export type PlanConfirmation = {
3305
+ /**
3306
+ * The Stripe part's hash; with no Stripe account connected, the App Store part's.
3307
+ */
3308
+ hash: string;
3309
+ };
3310
+ /**
3311
+ * One write a store will get to come to the catalog.
3312
+ */
3313
+ export type PlanStep = {
3314
+ /**
3315
+ * What it writes, as the store names it.
3316
+ */
3317
+ fields?: {
3318
+ [key: string]: unknown;
3319
+ };
3320
+ /**
3321
+ * Whether it makes something the store never lets go of: a product id at Apple or Google stays taken even once deleted.
3322
+ */
3323
+ irreversible: boolean;
3324
+ /**
3325
+ * What the person should know of it: how a price is resolved, why it waits.
3326
+ */
3327
+ note?: string;
3328
+ /**
3329
+ * What it does: create_product, update_product, create_price (Stripe); create_subscription_group, create_subscription, create_in_app_purchase (the App Store); create_subscription, create_onetime_product (Google Play).
3330
+ */
3331
+ op: string;
3332
+ /**
3333
+ * The catalog's plan.
3334
+ */
3335
+ plan?: string;
3336
+ /**
3337
+ * The catalog's product.
3338
+ */
3339
+ product: string;
3340
+ /**
3341
+ * The store's id of what it writes.
3342
+ */
3343
+ store_id?: string;
3344
+ };
3345
+ /**
3346
+ * Where Stripe's portal sends the customer back.
3347
+ */
3348
+ export type PortalRequest = {
3349
+ /**
3350
+ * A registered web app's origin, or a native app's own scheme.
3351
+ */
3352
+ return_url: string;
3353
+ };
3354
+ /**
3355
+ * Stripe's customer portal, opened for the customer.
3356
+ */
3357
+ export type PortalSession = {
3358
+ /**
3359
+ * Where to send the customer.
3360
+ */
3361
+ url: string;
3362
+ };
3363
+ /**
3364
+ * A viewer to try: what its app would send, and who it is. user_id's entitlements and first seen are read from the project, unless entitlements and first_seen_days are given; user_id, else installation_id, is the subject an experiment's variant is drawn for.
3365
+ */
3366
+ export type PreviewContext = {
3367
+ /**
3368
+ * The registered app (X-Palbase-App).
3369
+ */
3370
+ app?: string;
3371
+ /**
3372
+ * The app's version (X-Palbase-Client-Version).
3373
+ */
3374
+ app_version?: string;
3375
+ /**
3376
+ * What the app says of the viewer (X-Palbase-Attributes): at most 20 keys, 2 KiB, strings, numbers, booleans.
3377
+ */
3378
+ attributes?: {
3379
+ [key: string]: unknown;
3380
+ };
3381
+ /**
3382
+ * The country (X-Palbase-Storefront, else the address's): ISO 3166-1 alpha-2 or alpha-3.
3383
+ */
3384
+ country?: string;
3385
+ /**
3386
+ * The viewer's active entitlements, instead of user_id's.
3387
+ */
3388
+ entitlements?: string[];
3389
+ /**
3390
+ * Whole days since the viewer was first seen, instead of user_id's.
3391
+ */
3392
+ first_seen_days?: number;
3393
+ /**
3394
+ * The installation (X-Palbase-Installation).
3395
+ */
3396
+ installation_id?: string;
3397
+ /**
3398
+ * The locale, a BCP 47 tag (Accept-Language).
3399
+ */
3400
+ locale?: string;
3401
+ /**
3402
+ * ios, android or web (X-Platform).
3403
+ */
3404
+ platform?: string;
3405
+ /**
3406
+ * The SDK's name (X-Palbase-SDK's), with sdk_version.
3407
+ */
3408
+ sdk?: string;
3409
+ /**
3410
+ * The SDK's version, with sdk.
3411
+ */
3412
+ sdk_version?: string;
3413
+ /**
3414
+ * The signed-in user.
3415
+ */
3416
+ user_id?: string;
3417
+ };
3418
+ /**
3419
+ * What to try: a viewer, a moment (now when none), and the rules being edited (the saved ones when none).
3420
+ */
3421
+ export type PreviewRequest = {
3422
+ /**
3423
+ * The moment (UTC): a scheduled rule's start, an end.
3424
+ */
3425
+ at?: string;
3426
+ context: PreviewContext;
3427
+ /**
3428
+ * Rules not yet saved, to try instead of the placement's.
3429
+ */
3430
+ rules?: PlacementRule[];
3431
+ };
3432
+ /**
3433
+ * The one price entered: each store prices the other currencies its own way (Apple's price points, Google's conversion, Stripe's), except those set by hand.
3434
+ */
3435
+ export type Price = {
3436
+ /**
3437
+ * The amount in the currency's minor units (999 is 9.99).
3438
+ */
3439
+ amount: number;
3440
+ /**
3441
+ * Its ISO 4217 currency (USD).
3442
+ */
3443
+ currency: string;
3444
+ /**
3445
+ * Amounts set by hand in other currencies, in their minor units.
3446
+ */
3447
+ overrides?: {
3448
+ [key: string]: number;
3449
+ };
3450
+ };
3451
+ /**
3452
+ * One thing sold, on every channel it names.
3453
+ */
3454
+ export type Product = {
3455
+ /**
3456
+ * Where it is sold — ios (the App Store), android (Google Play), web (Stripe) — each with what is its own there; {} when it is sold there as it is.
3457
+ */
3458
+ channels: {
3459
+ [key: string]: Channel;
3460
+ };
3461
+ credits?: ProductCredits;
3462
+ /**
3463
+ * The entitlements it gives (a consumable gives none).
3464
+ */
3465
+ entitlements?: string[];
3466
+ /**
3467
+ * A subscription's group: the subscriptions a customer can move between (Apple's subscription group, the plans a Stripe customer can switch to). The App Store sells every subscription in one.
3468
+ */
3469
+ group?: string;
3470
+ /**
3471
+ * Its key: lowercase letters, digits and _, starting with a letter, at most 40. The stores know a plan of it as <product>.<plan> (40 characters at most).
3472
+ */
3473
+ key: string;
3474
+ /**
3475
+ * Its text by language: the base locale's at least.
3476
+ */
3477
+ locales: {
3478
+ [key: string]: Locale;
3479
+ };
3480
+ /**
3481
+ * How it is paid for: a subscription's periods and prices; one price for anything else.
3482
+ */
3483
+ plans: Plan[];
3484
+ /**
3485
+ * How much of each limit it gives.
3486
+ */
3487
+ quota?: QuotaAllowance[];
3488
+ /**
3489
+ * A subscription's level in its group, 1 or more: higher is more.
3490
+ */
3491
+ tier?: number;
3492
+ /**
3493
+ * Its kind: subscription (renews until canceled), non_consumable (bought once, kept), consumable (bought again and again: credits), non_renewing (a period bought once).
3494
+ */
3495
+ type: string;
3496
+ };
3497
+ /**
3498
+ * The credits a product gives: per purchase for a consumable, per period for a subscription.
3499
+ */
3500
+ export type ProductCredits = {
3501
+ /**
3502
+ * How many.
3503
+ */
3504
+ amount: number;
3505
+ /**
3506
+ * The credit (a key of the catalog's credits).
3507
+ */
3508
+ currency: string;
3509
+ /**
3510
+ * A subscription's: none (a period's credits end with the period) or all (they stay). Credits bought never end.
3511
+ */
3512
+ rollover?: string;
3513
+ };
3514
+ /**
3515
+ * purchases.purchase.completed: a purchase new to the ledger: a subscription's start or a one-time product, in any store.
3516
+ */
3517
+ export type PurchaseCompletedEvent = {
3518
+ /**
3519
+ * The purchase's id in the ledger.
3520
+ */
3521
+ chain_id: string;
3522
+ /**
3523
+ * The customer.
3524
+ */
3525
+ customer_id: string;
3526
+ /**
3527
+ * Whether it is a store's test purchase.
3528
+ */
3529
+ is_sandbox: boolean;
3530
+ /**
3531
+ * Its plan; empty when unmapped.
3532
+ */
3533
+ plan: string;
3534
+ /**
3535
+ * The catalog's product; empty when unmapped.
3536
+ */
3537
+ product: string;
3538
+ /**
3539
+ * Where it was bought.
3540
+ */
3541
+ store: "app_store" | "play_store" | "stripe";
3542
+ };
3543
+ /**
3544
+ * A one-time purchase the customer owns.
3545
+ */
3546
+ export type PurchaseInfo = {
3547
+ /**
3548
+ * Its id in the ledger.
3549
+ */
3550
+ id: string;
3551
+ /**
3552
+ * Whether it is a store's test purchase.
3553
+ */
3554
+ is_sandbox: boolean;
3555
+ /**
3556
+ * The catalog's product; absent when the catalog does not map what the store sold.
3557
+ */
3558
+ product?: string;
1660
3559
  /**
1661
3560
  * When it was bought.
1662
3561
  */
@@ -1827,29 +3726,195 @@ export type ReadinessCheck = {
1827
3726
  */
1828
3727
  export type RefundChangedEvent = {
1829
3728
  /**
1830
- * The purchase's id in the ledger.
3729
+ * The purchase's id in the ledger.
3730
+ */
3731
+ chain_id: string;
3732
+ /**
3733
+ * The customer.
3734
+ */
3735
+ customer_id: string;
3736
+ /**
3737
+ * Why.
3738
+ */
3739
+ kind: "refund" | "family" | "chargeback" | "other";
3740
+ /**
3741
+ * The taking back was reversed (a dispute won).
3742
+ */
3743
+ reversed: boolean;
3744
+ /**
3745
+ * How much of the payment was taken back, in thousandths (1000: all of it).
3746
+ */
3747
+ share_milli: number;
3748
+ /**
3749
+ * The payment taken back.
3750
+ */
3751
+ transaction_id: string;
3752
+ };
3753
+ /**
3754
+ * What was paid in one currency, net of what was refunded.
3755
+ */
3756
+ export type Revenue = {
3757
+ /**
3758
+ * The amount in millionths of the currency's unit, as the stores report prices: the App Store's list price, Stripe's charged total, Google Play's recurring price.
3759
+ */
3760
+ amount_micros: number;
3761
+ /**
3762
+ * The currency (ISO 4217).
3763
+ */
3764
+ currency: string;
3765
+ };
3766
+ /**
3767
+ * One thing a rule asks of a viewer. `field` is what it reads, `op` how:
3768
+ * - `country` (`in`, `not_in`; `values` ISO 3166-1 alpha-2, alpha-3 read as alpha-2): the store's country the app sends (X-Palbase-Storefront), else the country of the request's address.
3769
+ * - `platform` (`in`, `not_in`; `values` ios, android, web): X-Platform, else `?channel=`.
3770
+ * - `app` (`in`, `not_in`; `values` registered apps' ids): X-Palbase-App.
3771
+ * - `app_version` (`eq`, `neq`, `gt`, `gte`, `lt`, `lte`; `value` a version string): X-Palbase-Client-Version, compared as Semantic Versioning orders versions (2.1 is 2.1.0; a pre-release before its release).
3772
+ * - `sdk_version` (the same operators; `sdk` the SDK's name, `value` a version): X-Palbase-SDK — a viewer on another SDK does not meet it.
3773
+ * - `locale` (`in`, `not_in`; `values` BCP 47 tags): the first tag of Accept-Language; tr covers tr-TR, en-GB covers en-GB alone.
3774
+ * - `entitlement` (`has`: any of `values`; `lacks`: none of them; the catalog's entitlement keys): the server's — the signed-in user's active entitlements; a viewer without a customer has none.
3775
+ * - `first_seen_days` (`gt`, `gte`, `lt`, `lte`; `value` whole days, 0 to 3650): the server's — whole days since the user was first seen here.
3776
+ * - `attribute` (`key`; `in`, `not_in` with `values`, `exists`, `not_exists`, `gt`, `gte`, `lt`, `lte` with a number `value`): X-Palbase-Attributes, what the app says of the viewer — targeting only.
3777
+ * A value the request does not carry meets no condition on it, `not_in` neither (`not_exists` aside).
3778
+ * Targeting picks what to show; it is not access control: the storefront, the attributes and the versions are what the client says of itself — no price or region entitlement may hang on them.
3779
+ */
3780
+ export type RuleCondition = {
3781
+ /**
3782
+ * What it reads.
3783
+ */
3784
+ field: "country" | "platform" | "app" | "app_version" | "sdk_version" | "locale" | "entitlement" | "first_seen_days" | "attribute";
3785
+ /**
3786
+ * The attribute's key (an attribute condition's alone).
3787
+ */
3788
+ key?: string;
3789
+ /**
3790
+ * How.
3791
+ */
3792
+ op: "in" | "not_in" | "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "has" | "lacks" | "exists" | "not_exists";
3793
+ /**
3794
+ * The SDK the version is of, as X-Palbase-SDK names it (an sdk_version condition's alone).
3795
+ */
3796
+ sdk?: string;
3797
+ /**
3798
+ * An order's operand: a version (app_version, sdk_version), a number (first_seen_days, an attribute).
3799
+ */
3800
+ value?: RuleVersion | RuleNumber;
3801
+ /**
3802
+ * A set's members (1 to 50), or the entitlements of has and lacks.
3803
+ */
3804
+ values?: string[];
3805
+ };
3806
+ /**
3807
+ * What one condition came to.
3808
+ */
3809
+ export type RuleConditionResult = {
3810
+ /**
3811
+ * What it reads.
3812
+ */
3813
+ field: string;
3814
+ /**
3815
+ * Its place in the rule's conditions.
3816
+ */
3817
+ index: number;
3818
+ /**
3819
+ * Whether it holds.
3820
+ */
3821
+ met: boolean;
3822
+ /**
3823
+ * The viewer carries no value for it (so it does not hold).
3824
+ */
3825
+ unknown?: boolean;
3826
+ };
3827
+ /**
3828
+ * A number, as first_seen_days (whole days) and an attribute's order compare it.
3829
+ */
3830
+ export type RuleNumber = number;
3831
+ /**
3832
+ * One thing wrong with a placement's rules.
3833
+ */
3834
+ export type RuleProblem = {
3835
+ /**
3836
+ * What it is (invalid_rule_name, invalid_state, invalid_schedule, invalid_target, unknown_field, invalid_op, invalid_value, invalid_values, too_many_rules, too_many_conditions, duplicate_rule_id, unknown_paywall, unpublished_paywall, experiment_not_targetable …).
3837
+ */
3838
+ code: string;
3839
+ /**
3840
+ * What to do about it.
3841
+ */
3842
+ message: string;
3843
+ /**
3844
+ * Where it is (rules[1].conditions[0].values[2]).
3845
+ */
3846
+ path: string;
3847
+ };
3848
+ /**
3849
+ * What one rule came to for the viewer.
3850
+ */
3851
+ export type RuleStep = {
3852
+ /**
3853
+ * Each condition's, when the rule was in effect and its target could be shown.
3854
+ */
3855
+ conditions?: RuleConditionResult[];
3856
+ /**
3857
+ * The rule's name.
3858
+ */
3859
+ name: string;
3860
+ /**
3861
+ * matched (it decided); unmet (not in effect, or a condition does not hold); unavailable (its experiment no longer runs); not_reached (decided before it).
3862
+ */
3863
+ outcome: "matched" | "unmet" | "unavailable" | "not_reached";
3864
+ /**
3865
+ * The rule.
3866
+ */
3867
+ rule_id: string;
3868
+ /**
3869
+ * What it is at the moment: in_effect, pending, ended, inactive.
3870
+ */
3871
+ status: "in_effect" | "pending" | "ended" | "inactive";
3872
+ };
3873
+ /**
3874
+ * What a rule shows: a published paywall, or the variant of the experiment running on the placement for the rules (audience `rules`). Exactly one.
3875
+ */
3876
+ export type RuleTarget = {
3877
+ /**
3878
+ * The experiment: the viewer gets its variant, the same every time.
3879
+ */
3880
+ experiment_id?: string;
3881
+ /**
3882
+ * The paywall: published.
3883
+ */
3884
+ paywall_id?: string;
3885
+ };
3886
+ /**
3887
+ * A version, as app_version and sdk_version compare it: one to four numbers, a pre-release after - (2.1.0, 2.1, 3.0.0-beta.1).
3888
+ */
3889
+ export type RuleVersion = string;
3890
+ /**
3891
+ * The error envelope of refused rules, with every problem when they break a rule (`invalid_rules`).
3892
+ */
3893
+ export type RulesError = {
3894
+ /**
3895
+ * Machine-readable error code (snake_case)
1831
3896
  */
1832
- chain_id: string;
3897
+ error: string;
1833
3898
  /**
1834
- * The customer.
3899
+ * Human-readable explanation
1835
3900
  */
1836
- customer_id: string;
3901
+ error_description: string;
1837
3902
  /**
1838
- * Why.
3903
+ * Every problem, by path: with `invalid_rules`, absent otherwise.
1839
3904
  */
1840
- kind: "refund" | "family" | "chargeback" | "other";
3905
+ problems?: RuleProblem[];
1841
3906
  /**
1842
- * The taking back was reversed (a dispute won).
3907
+ * Correlation ID for log/audit lookup
1843
3908
  */
1844
- reversed: boolean;
3909
+ request_id: string;
1845
3910
  /**
1846
- * How much of the payment was taken back, in thousandths (1000: all of it).
3911
+ * Seconds to wait before retrying; present on a refusal that ends with time.
1847
3912
  */
1848
- share_milli: number;
3913
+ retry_after?: number;
1849
3914
  /**
1850
- * The payment taken back.
3915
+ * HTTP status code (mirrors the response status)
1851
3916
  */
1852
- transaction_id: string;
3917
+ status: number;
1853
3918
  };
1854
3919
  /**
1855
3920
  * The error envelope of a refused save, with every problem when the catalog breaks a rule (`invalid_catalog`).
@@ -2281,6 +4346,64 @@ export type SubscriptionInfo = {
2281
4346
  */
2282
4347
  will_renew: boolean;
2283
4348
  };
4349
+ /**
4350
+ * One variant's numbers.
4351
+ */
4352
+ export type VariantResult = {
4353
+ /**
4354
+ * The probability that its conversion rate is the highest (0 to 1), Bayesian: each rate is Beta(1 + converters, 1 + viewers − converters) and the chance is how often its draw is the highest. It answers "how likely is this one best?" for any number of variants, at any sample, while the experiment runs.
4355
+ */
4356
+ chance_to_win: number;
4357
+ /**
4358
+ * converters over viewers. A viewer never signed in cannot be followed to a purchase: the rate is the same lower bound on every variant.
4359
+ */
4360
+ conversion_rate: number;
4361
+ /**
4362
+ * How many of its viewers made one.
4363
+ */
4364
+ converters: number;
4365
+ /**
4366
+ * How many times it was shown (a subject once in ten minutes).
4367
+ */
4368
+ exposures: number;
4369
+ /**
4370
+ * Its paywall.
4371
+ */
4372
+ paywall_id: string;
4373
+ /**
4374
+ * The purchases the stores confirmed (a subscription's start, a one-time product) that its viewers made within the window after first seeing it — each counted once, for the first variant its buyer saw.
4375
+ */
4376
+ purchases: number;
4377
+ /**
4378
+ * What its purchases were paid to date, renewals included, net of refunds, by currency.
4379
+ */
4380
+ revenue: Revenue[];
4381
+ /**
4382
+ * The variant.
4383
+ */
4384
+ variant: string;
4385
+ /**
4386
+ * How many subjects saw it: users, guests, and installations no one had signed in on.
4387
+ */
4388
+ viewers: number;
4389
+ /**
4390
+ * Its weight.
4391
+ */
4392
+ weight: number;
4393
+ };
4394
+ /**
4395
+ * The variant that won, and how it is rolled out.
4396
+ */
4397
+ export type WinnerRequest = {
4398
+ /**
4399
+ * For an experiment for everyone at the placement: roll the winner out as a live rule at the top of the placement's rules (for everyone, to narrow later) and keep the placement's default; otherwise the winner becomes the default.
4400
+ */
4401
+ as_rule?: boolean;
4402
+ /**
4403
+ * The variant's key.
4404
+ */
4405
+ variant: string;
4406
+ };
2284
4407
  /**
2285
4408
  * The certificate the environment takes Xcode's StoreKit Testing purchases signed with: test purchases made on a developer's Mac with no App Store at all, the sandbox's. It is public: Xcode saves it for whoever asks (Editor › Save Public Certificate).
2286
4409
  */
@@ -2353,6 +4476,10 @@ export interface Events {
2353
4476
  * purchases.ownership.transferred: a purchase moved from one customer to another: the second restored the App Store purchases of the Apple ID it was made with.
2354
4477
  */
2355
4478
  "purchases.ownership.transferred": OwnershipTransferredEvent;
4479
+ /**
4480
+ * purchases.paywall.published: a paywall's draft was published as its next version; the apps that ask for a placement showing it get it.
4481
+ */
4482
+ "purchases.paywall.published": PaywallPublishedEvent;
2356
4483
  /**
2357
4484
  * purchases.purchase.completed: a purchase new to the ledger: a subscription's start or a one-time product, in any store.
2358
4485
  */
@@ -2804,6 +4931,86 @@ export declare function client(t: Transport): {
2804
4931
  body?: SpendAction; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
2805
4932
  signal?: AbortSignal;
2806
4933
  }): Promise<Reply<200, SpendReceipt>>;
4934
+ /**
4935
+ * List the experiments
4936
+ *
4937
+ * The project's experiments, newest first, a page at a time; ?placement= keeps one placement's.
4938
+ */
4939
+ listExperiments(input?: {
4940
+ query?: {
4941
+ placement?: string; /** How many experiments a page holds (20 unless said). */
4942
+ limit?: number; /** The `next_cursor` of the page before. */
4943
+ cursor?: string;
4944
+ }; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
4945
+ signal?: AbortSignal;
4946
+ }): Promise<Reply<200, Experiments>>;
4947
+ /**
4948
+ * Start an experiment
4949
+ *
4950
+ * Starts an experiment on a placement: from then on the placement shows each subject in its audience — the signed-in user (a guest included), else the installation — its variant's paywall, the same every time (a hash of the experiment and the subject, placed on the weights; nothing is stored). Every variant's paywall must be published (422 `invalid_experiment`); one experiment runs on a placement at a time (409 `experiment_running`). An experiment for the rules (audience `rules`) shows the viewers the placement's rules targeting it send it — the placement is one already (404 `placement_not_found`); one for everyone (audience `placement`, when none is named) is decided before the placement's rules, and the placement keeps its default for when it ends.
4951
+ */
4952
+ startExperiment(input: {
4953
+ headers?: {
4954
+ "Idempotency-Key"?: string;
4955
+ };
4956
+ body: ExperimentRequest; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
4957
+ signal?: AbortSignal;
4958
+ }): Promise<Reply<201, Experiment>>;
4959
+ /**
4960
+ * Read an experiment
4961
+ *
4962
+ * An experiment: its placement, its variants and its status.
4963
+ */
4964
+ getExperiment(input: {
4965
+ path: {
4966
+ experiment_id: string;
4967
+ }; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
4968
+ signal?: AbortSignal;
4969
+ }): Promise<Reply<200, Experiment>>;
4970
+ /**
4971
+ * Read an experiment's results
4972
+ *
4973
+ * What each variant's audience did: exposures and viewers (distinct subjects); the purchases the stores confirmed that its viewers made within `window_days` (7 unless said) after first seeing it — the ledger's, never what an app reports — and how many viewers made one; the conversion rate; what was paid for them to date, net of refunds, by currency; and each variant's chance to convert best. `leader` is the likeliest best, `confident` whether declaring it the winner is sound. A store's test purchases count only with sandbox=true (a development environment's are all test purchases).
4974
+ */
4975
+ getExperimentResults(input: {
4976
+ path: {
4977
+ experiment_id: string;
4978
+ };
4979
+ query?: {
4980
+ window_days?: number; /** Count the stores' test purchases too. */
4981
+ sandbox?: boolean;
4982
+ }; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
4983
+ signal?: AbortSignal;
4984
+ }): Promise<Reply<200, ExperimentResults>>;
4985
+ /**
4986
+ * Stop an experiment
4987
+ *
4988
+ * Stops a running experiment, at once: what it showed becomes its first variant's paywall — the placement's default for an experiment for everyone there, the rules' target for one for the rules. Its results stay.
4989
+ */
4990
+ stopExperiment(input: {
4991
+ path: {
4992
+ experiment_id: string;
4993
+ };
4994
+ headers?: {
4995
+ "Idempotency-Key"?: string;
4996
+ }; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
4997
+ signal?: AbortSignal;
4998
+ }): Promise<Reply<200, Experiment>>;
4999
+ /**
5000
+ * Declare an experiment's winner
5001
+ *
5002
+ * Ends a running experiment with a winner, at once: for everyone at the placement, the winner's paywall becomes the placement's default — or, with `as_rule`, a live rule at the top of its rules shows it to everyone (to narrow later) and the default stays; for the rules, the rules that targeted the experiment show the winner's paywall. Its results stay.
5003
+ */
5004
+ declareExperimentWinner(input: {
5005
+ path: {
5006
+ experiment_id: string;
5007
+ };
5008
+ headers?: {
5009
+ "Idempotency-Key"?: string;
5010
+ };
5011
+ body: WinnerRequest; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
5012
+ signal?: AbortSignal;
5013
+ }): Promise<Reply<200, Experiment>>;
2807
5014
  /**
2808
5015
  * Read what the customer has
2809
5016
  *
@@ -2840,6 +5047,275 @@ export declare function client(t: Transport): {
2840
5047
  }; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
2841
5048
  signal?: AbortSignal;
2842
5049
  }): Promise<Reply<200, Offerings>>;
5050
+ /**
5051
+ * List the paywalls
5052
+ *
5053
+ * The project's paywalls, oldest first, with the newest version published of each.
5054
+ */
5055
+ listPaywalls(input?: {
5056
+ signal?: AbortSignal;
5057
+ }): Promise<Reply<200, PaywallList>>;
5058
+ /**
5059
+ * Make a paywall
5060
+ *
5061
+ * Makes a paywall with its first draft; nothing is published, and no app sees it until it is published and a placement shows it. The draft is checked as a draft: a rule broken refuses it (422 `invalid_paywall`, with every problem); a package the catalog does not sell yet is a warning. A project has at most 100 paywalls (409 `too_many_paywalls`).
5062
+ */
5063
+ createPaywall(input: {
5064
+ headers?: {
5065
+ "Idempotency-Key"?: string;
5066
+ };
5067
+ body: PaywallRequest; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
5068
+ signal?: AbortSignal;
5069
+ }): Promise<Reply<201, Paywall>>;
5070
+ /**
5071
+ * List the paywall assets
5072
+ *
5073
+ * The project's paywall assets, newest first.
5074
+ */
5075
+ listPaywallAssets(input?: {
5076
+ signal?: AbortSignal;
5077
+ }): Promise<Reply<200, PaywallAssets>>;
5078
+ /**
5079
+ * Register a paywall asset
5080
+ *
5081
+ * Registers an object of the project's public bucket paywall-assets for its paywalls: Studio and the CLI upload it with the project's storage first (and make the bucket when it is missing), then register its path here. The module builds the object's address itself, from the project's own storage — never from an address it is given — and reads it there as every app will, saying what it is by its bytes, never by its name or the type it was stored with: an image (png, jpeg or webp, at most 2 MiB; never svg), a video (mp4 or mov, 50 MiB), a font (ttf, otf or woff2, 5 MiB), or an HTML block's zip (5 MiB; at most 200 files and 20 MiB opened, read to the end; index.html at its root; no file leaving the root, no link). It stops reading past the bound. It keeps the asset's SHA-256 and size: an app draws what it downloads only when it is that, and a paywall naming an asset whose object was since changed or removed is warned of in a draft and refused when published. A project has at most 500 assets.
5082
+ */
5083
+ registerPaywallAsset(input: {
5084
+ headers?: {
5085
+ "Idempotency-Key"?: string;
5086
+ };
5087
+ body: PaywallAssetRequest; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
5088
+ signal?: AbortSignal;
5089
+ }): Promise<Reply<201, PaywallAsset>>;
5090
+ /**
5091
+ * Delete a paywall asset
5092
+ *
5093
+ * Forgets an asset no paywall names — in a draft, or in any version kept (409 `asset_in_use`). The object stays in the project's storage.
5094
+ */
5095
+ deletePaywallAsset(input: {
5096
+ path: {
5097
+ asset_id: string;
5098
+ };
5099
+ headers?: {
5100
+ "Idempotency-Key"?: string;
5101
+ }; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
5102
+ signal?: AbortSignal;
5103
+ }): Promise<Reply<204, undefined>>;
5104
+ /**
5105
+ * Check a paywall
5106
+ *
5107
+ * Checks a definition as publishing it would, without saving anything: every rule of its schema, and every package against the catalog as it is. A definition that passes is answered with its warnings (what App Review expects of a subscription's paywall: a restore button, the legal links); one that breaks a rule is refused with every problem (422 `invalid_paywall`).
5108
+ */
5109
+ validatePaywall(input: {
5110
+ headers?: {
5111
+ "Idempotency-Key"?: string;
5112
+ };
5113
+ body: PaywallDefinition; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
5114
+ signal?: AbortSignal;
5115
+ }): Promise<Reply<200, PaywallValidation>>;
5116
+ /**
5117
+ * Read a paywall
5118
+ *
5119
+ * A paywall: its draft (the ETag is its revision), what was published of it, and what there is to say of the draft against the catalog as it is.
5120
+ */
5121
+ getPaywall(input: {
5122
+ path: {
5123
+ paywall_id: string;
5124
+ }; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
5125
+ signal?: AbortSignal;
5126
+ }): Promise<Reply<200, Paywall>>;
5127
+ /**
5128
+ * Delete a paywall
5129
+ *
5130
+ * Deletes a paywall and its versions. A paywall a placement shows, or a running experiment does, is not deleted (409 `paywall_in_use`). What was counted of it stays in its experiments' results.
5131
+ */
5132
+ deletePaywall(input: {
5133
+ path: {
5134
+ paywall_id: string;
5135
+ };
5136
+ headers?: {
5137
+ "Idempotency-Key"?: string;
5138
+ }; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
5139
+ signal?: AbortSignal;
5140
+ }): Promise<Reply<204, undefined>>;
5141
+ /**
5142
+ * Save a paywall's draft
5143
+ *
5144
+ * Replaces the paywall's draft; what the apps show changes only when it is published. If-Match names the draft revision it was edited from: of two people editing at once, the second is told (412 `paywall_changed`), not overwritten. The draft is checked as a draft (422 `invalid_paywall`, with every problem).
5145
+ */
5146
+ savePaywallDraft(input: {
5147
+ path: {
5148
+ paywall_id: string;
5149
+ };
5150
+ headers: {
5151
+ "If-Match": string; /** Makes the write safe to send again (at most 255 characters). A retry with the same key and the same request gets the first answer back, marked `Idempotent-Replayed: true`, and changes nothing; the same key with a different request is refused with 422, and while the first request still runs a retry gets 409 with Retry-After. Answers are kept for 24 hours. */
5152
+ "Idempotency-Key"?: string;
5153
+ };
5154
+ body: PaywallRequest; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
5155
+ signal?: AbortSignal;
5156
+ }): Promise<Reply<200, Paywall>>;
5157
+ /**
5158
+ * Publish a paywall
5159
+ *
5160
+ * Publishes the paywall's draft as its next version, checked as the apps will get it: every package must be sold by the catalog (422 `invalid_paywall`, with every problem). If-Match names the draft revision that was looked at (412 `paywall_changed` when it moved since). The apps asking for a placement that shows the paywall get the new version at once — those whose SDK draws its schema. A draft the same as the newest version publishes nothing new (200). The newest 50 versions are kept, and the newest of each schema. Emits `purchases.paywall.published`. Every asset the draft names is looked at in the project's storage: one no longer there (`asset_missing`) or no longer the bytes registered (`asset_changed`) refuses the publish.
5161
+ */
5162
+ publishPaywall(input: {
5163
+ path: {
5164
+ paywall_id: string;
5165
+ };
5166
+ headers: {
5167
+ "If-Match": string; /** Makes the write safe to send again (at most 255 characters). A retry with the same key and the same request gets the first answer back, marked `Idempotent-Replayed: true`, and changes nothing; the same key with a different request is refused with 422, and while the first request still runs a retry gets 409 with Retry-After. Answers are kept for 24 hours. */
5168
+ "Idempotency-Key"?: string;
5169
+ }; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
5170
+ signal?: AbortSignal;
5171
+ }): Promise<Reply<200, PaywallVersion> | Reply<201, PaywallVersion>>;
5172
+ /**
5173
+ * List a paywall's versions
5174
+ *
5175
+ * The paywall's published versions, newest first, a page at a time, without their definitions.
5176
+ */
5177
+ listPaywallVersions(input: {
5178
+ path: {
5179
+ paywall_id: string;
5180
+ };
5181
+ query?: {
5182
+ limit?: number; /** The `next_cursor` of the page before. */
5183
+ cursor?: string;
5184
+ }; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
5185
+ signal?: AbortSignal;
5186
+ }): Promise<Reply<200, PaywallVersions>>;
5187
+ /**
5188
+ * Read a paywall's version
5189
+ *
5190
+ * A published version, its definition as it was published.
5191
+ */
5192
+ getPaywallVersion(input: {
5193
+ path: {
5194
+ paywall_id: string; /** The version. */
5195
+ version: number;
5196
+ }; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
5197
+ signal?: AbortSignal;
5198
+ }): Promise<Reply<200, PaywallVersion>>;
5199
+ /**
5200
+ * List the placements
5201
+ *
5202
+ * The project's placements, by key: the default paywall each shows, the experiment running on it for everyone, how many rules it has.
5203
+ */
5204
+ listPlacements(input?: {
5205
+ signal?: AbortSignal;
5206
+ }): Promise<Reply<200, Placements>>;
5207
+ /**
5208
+ * Give a placement a paywall
5209
+ *
5210
+ * Gives a placement its default paywall, making the placement when it is new: what it shows whoever none of its rules holds for. The apps that ask for it get the paywall's newest version they can draw; a paywall never published is nothing yet (they get 204 and draw their own). While an experiment runs for everyone at the placement, the experiment decides, and its end the default (409 `experiment_running`). A project has at most 200 placements (409 `too_many_placements`).
5211
+ */
5212
+ setPlacement(input: {
5213
+ path: {
5214
+ placement: string;
5215
+ };
5216
+ headers?: {
5217
+ "Idempotency-Key"?: string;
5218
+ };
5219
+ body: PlacementRequest; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
5220
+ signal?: AbortSignal;
5221
+ }): Promise<Reply<200, Placement>>;
5222
+ /**
5223
+ * Delete a placement
5224
+ *
5225
+ * Forgets a placement and its rules: the apps that ask for it get nothing (404) and draw their own. Not while an experiment runs on it (409 `experiment_running`).
5226
+ */
5227
+ deletePlacement(input: {
5228
+ path: {
5229
+ placement: string;
5230
+ };
5231
+ headers?: {
5232
+ "Idempotency-Key"?: string;
5233
+ }; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
5234
+ signal?: AbortSignal;
5235
+ }): Promise<Reply<204, undefined>>;
5236
+ /**
5237
+ * Report a paywall shown
5238
+ *
5239
+ * Counts that the app showed a version of a paywall at a placement, to the signed-in user (a guest included) or else the installation (X-Palbase-Installation; 400 `installation_required` without either). `variant` and `rule_id` are what the answer named — claims, checked against the placement as it is: the rule is written when it is one of the placement's and shows the paywall reported (or sends to the experiment of the variant counted); the variant counts when its experiment runs for the whole placement, or the rule reported sends to it, and it is the subject's own variant there. A claim that does not hold leaves the exposure to the paywall alone — none is refused: what was shown before the viewer bought, before a schedule turned, before the rules were edited still counts. The same subject, paywall version and placement count once in ten minutes; in a project, one address (an IPv6 /64 is one) reports at most 60 a minute, and at most 20 a minute are taken for one subject (429 `too_many_exposures`, Retry-After); another project's are its own, and reading the placement's paywall is never limited by them. Purchases are never reported here: they are the ones the stores confirmed, read from the ledger.
5240
+ */
5241
+ recordPaywallExposure(input: {
5242
+ path: {
5243
+ placement: string;
5244
+ };
5245
+ headers?: {
5246
+ "X-Palbase-Installation"?: string;
5247
+ };
5248
+ body: ExposureRequest; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
5249
+ signal?: AbortSignal;
5250
+ }): Promise<Reply<204, undefined>>;
5251
+ /**
5252
+ * Read a placement's paywall
5253
+ *
5254
+ * What an app draws at a placement. Who sees what: an experiment running for the whole placement decides first — the subject, the signed-in user (a guest included) else the installation (X-Palbase-Installation), gets its variant, the same every time; without either the first variant is drawn, in no experiment —; then the placement's rules, in order: the first in effect whose conditions all hold shows its paywall, or its experiment's variant; then the placement's default. The rules read what the app declares — X-Platform, X-Palbase-App, X-Palbase-Client-Version, X-Palbase-SDK, X-Palbase-Storefront, Accept-Language, X-Palbase-Attributes — and what the server knows: the user's entitlements, the days since the user was first seen, the request's address's country when no storefront is named. `source` and `rule_id` say which decided. Targeting picks what to show; it is not access control: the storefront, the attributes and the versions are what the client says of itself — no price or region entitlement may hang on them. The app says the newest paywall schema its SDK draws (X-Palbase-Paywall-Schema; this server's, 2, when absent) and is given the newest version of that paywall written in it or an older one: an app on an older SDK keeps getting the last version it can draw. When there is none — the paywall never published, or only in a newer schema — the answer is 204 and the app draws its own (from the offerings). An SDK that draws no schema this server takes (under 2) is told to update: 426 `paywall_schema_too_old`, and it draws its own. `offerings` are what the paywall sells, each channel's store ids (`?channel=` keeps one): the app prices them from its store. The ETag names the answer: sent back as If-None-Match, an unchanged one is 304. Any of the project's keys reads it, the publishable one included.
5255
+ */
5256
+ getPlacementPaywall(input: {
5257
+ path: {
5258
+ placement: string;
5259
+ };
5260
+ query?: {
5261
+ channel?: "ios" | "android" | "web";
5262
+ };
5263
+ headers?: {
5264
+ "X-Palbase-Paywall-Schema"?: number; /** The installation's id, as the SDK keeps it: who the paywall is shown to before anyone signs in. A signed-in user (a guest included) is who it is shown to, the installation aside. */
5265
+ "X-Palbase-Installation"?: string; /** The ETag of the answer the app holds (a header over 1 KiB is not read). */
5266
+ "If-None-Match"?: string; /** The app's platform: ios, android or web (a placement's platform rules read it; `?channel=` when absent). */
5267
+ "X-Platform"?: string; /** The app's version, as its users see it (CFBundleShortVersionString, versionName): app_version rules read it. */
5268
+ "X-Palbase-Client-Version"?: string; /** The registered app's id: app rules read it. */
5269
+ "X-Palbase-App"?: string; /** The SDK's name and version, name/version (palbase-swift/1.4.0): sdk_version rules read it. */
5270
+ "X-Palbase-SDK"?: string; /** The store's country — StoreKit's Storefront.countryCode, Play's billing country —, ISO 3166-1 alpha-2 or alpha-3: country rules read it, the request's address's country when absent. */
5271
+ "X-Palbase-Storefront"?: string; /** What the app says of the viewer, for attribute rules (targeting only): a JSON object of at most 20 keys (a letter, then letters, digits and _ . -, at most 40), values strings (at most 256), numbers or booleans; at most 2 KiB, non-ASCII escaped (\uXXXX). */
5272
+ "X-Palbase-Attributes"?: string; /** The app's languages: locale rules read the first. */
5273
+ "Accept-Language"?: string;
5274
+ }; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
5275
+ signal?: AbortSignal;
5276
+ }): Promise<Reply<200, PlacementPaywall> | Reply<204, undefined> | Reply<304, undefined>>;
5277
+ /**
5278
+ * Preview what a placement shows a viewer
5279
+ *
5280
+ * What the placement shows a viewer, and why: the experiment running for the whole placement, the rule that decided, or the default — with what every rule came to, condition by condition. The console's live preview: by the saved rules, or by rules being edited (`rules`), at a moment (`at`). Nothing is counted or changed.
5281
+ */
5282
+ previewPlacement(input: {
5283
+ path: {
5284
+ placement: string;
5285
+ };
5286
+ headers?: {
5287
+ "Idempotency-Key"?: string;
5288
+ };
5289
+ body: PreviewRequest; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
5290
+ signal?: AbortSignal;
5291
+ }): Promise<Reply<200, PlacementPreview>>;
5292
+ /**
5293
+ * Read a placement's rules
5294
+ *
5295
+ * A placement's rules, in the order they are read, each with what it is now (status). The ETag is their revision.
5296
+ */
5297
+ getPlacementRules(input: {
5298
+ path: {
5299
+ placement: string;
5300
+ }; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
5301
+ signal?: AbortSignal;
5302
+ }): Promise<Reply<200, PlacementRules>>;
5303
+ /**
5304
+ * Replace a placement's rules
5305
+ *
5306
+ * Replaces a placement's rules, all of them, in the order they are to be read: the first in effect whose conditions all hold for a viewer shows its target — a published paywall, or the variant of the experiment running on the placement for the rules —, after an experiment running for the whole placement and before the placement's default. At most 50 rules of at most 10 conditions. If-Match names the revision they were edited from: of two people editing at once, the second is told (412 `rules_changed`), not overwritten. Targeting picks what to show; it is not access control: the storefront, the attributes and the versions are what the client says of itself — no price or region entitlement may hang on them.
5307
+ */
5308
+ setPlacementRules(input: {
5309
+ path: {
5310
+ placement: string;
5311
+ };
5312
+ headers: {
5313
+ "If-Match": string; /** Makes the write safe to send again (at most 255 characters). A retry with the same key and the same request gets the first answer back, marked `Idempotent-Replayed: true`, and changes nothing; the same key with a different request is refused with 422, and while the first request still runs a retry gets 409 with Retry-After. Answers are kept for 24 hours. */
5314
+ "Idempotency-Key"?: string;
5315
+ };
5316
+ body: PlacementRulesRequest; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
5317
+ signal?: AbortSignal;
5318
+ }): Promise<Reply<200, PlacementRules>>;
2843
5319
  /**
2844
5320
  * Read the settings
2845
5321
  *