@whop/cli 0.26.0 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/index.js +1442 -785
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/whop/SKILL.md +2 -2
- package/skills/whop/references/websites.md +19 -6
package/dist/index.js
CHANGED
|
@@ -27909,7 +27909,7 @@ function resolveDisplayName(name, aliases) {
|
|
|
27909
27909
|
}
|
|
27910
27910
|
|
|
27911
27911
|
// src/cli.ts
|
|
27912
|
-
import { join as
|
|
27912
|
+
import { join as join15 } from "path";
|
|
27913
27913
|
|
|
27914
27914
|
// src/api/native-spec.json
|
|
27915
27915
|
var native_spec_default = {
|
|
@@ -27919,7 +27919,7 @@ var native_spec_default = {
|
|
|
27919
27919
|
termsOfService: "https://whop.com/tos-developer-api/",
|
|
27920
27920
|
title: "Whop API",
|
|
27921
27921
|
version: "1.0.0",
|
|
27922
|
-
"x-api-version-date": "2026-10-
|
|
27922
|
+
"x-api-version-date": "2026-10-14"
|
|
27923
27923
|
},
|
|
27924
27924
|
servers: [
|
|
27925
27925
|
{
|
|
@@ -28104,9 +28104,9 @@ var native_spec_default = {
|
|
|
28104
28104
|
"x-whop-summary": "Turn a variant into a shareable, prefilled checkout link."
|
|
28105
28105
|
},
|
|
28106
28106
|
{
|
|
28107
|
-
description: "A Payment Method Domain registers a hostname with a wallet provider so its payment methods can appear at a checkout served from that domain. The domain proves ownership by hosting the provider's association file \u2014 for Apple Pay, at `/.well-known/apple-developer-merchantid-domain-association` \u2014 and `status` reports whether verification has completed.\n\
|
|
28107
|
+
description: "The Payment Method Domains API is deprecated. Add, check, and remove Apple Pay domains with the `apple_pay` capability of the [Domains API](/api-reference/beta/domains/domain) instead. These endpoints keep working and return `Deprecation` and successor `Link` headers. A domain keeps its ID, so `/domains/{id}` takes the `dom_` or `pmd_` ID these endpoints return.\n\nA Payment Method Domain registers a hostname with a wallet provider so its payment methods can appear at a checkout served from that domain. The domain proves ownership by hosting the provider's association file \u2014 for Apple Pay, at `/.well-known/apple-developer-merchantid-domain-association` \u2014 and `status` reports whether verification has completed. Embedded surfaces like the [Express Checkout element](/elements/beta/checkout/expressCheckout) only render Apple Pay, Google Pay and PayPal express on a `verified` domain (first-party whop.com pages are pre-approved).\n\n| Payment Method Domains API | Domains API |\n| --- | --- |\n| `GET /payment_method_domains?status=verified` | `GET /domains?apple_pay=ready`, or `apple_pay=any` for every Apple Pay domain |\n| `?hostname=` | `?domain=` |\n| `GET /payment_method_domains/{id}` | `GET /domains/{id}` |\n| `POST /payment_method_domains` with `hostname` and `account_id` | `POST /domains` with `domain`, `account_id`, and `apple_pay: {}`. If the account already has the domain, `PATCH /domains/{id}` with `apple_pay: {}` |\n| `POST /payment_method_domains/{id}/verify` | `POST /domains/{id}/check` |\n| `DELETE /payment_method_domains/{id}` | `PATCH /domains/{id}` with `apple_pay: null` |\n| `hostname` | `domain` |\n| `status: verified` | `apple_pay.state: ready` |\n| `status: pending` | `apple_pay.state: pending` while Whop registers the domain, or `action_required` until you host the association file and check the domain |\n| `provider` | No field: every Apple Pay domain is registered with Apple |\n\nRegistration runs in the background, so creating or checking a domain returns `pending`: retrieve the domain until `apple_pay.state` is `ready` or `action_required`. The Domains API needs the `domain:read` and `domain:manage` permissions instead of `company:manage_checkout`, so give API keys those scopes. `DELETE /domains/{id}` removes the whole domain, including any website on it, so use `PATCH` to remove only Apple Pay.\n",
|
|
28108
28108
|
name: "Payment Method Domains",
|
|
28109
|
-
"x-whop-summary": "
|
|
28109
|
+
"x-whop-summary": "Deprecated: domains verified to show Apple Pay at checkout. Use Domains instead."
|
|
28110
28110
|
},
|
|
28111
28111
|
{
|
|
28112
28112
|
description: "A Shipment attaches a carrier tracking number to a payment and follows the package from label creation to delivery, exposing the current delivery status and a customer-facing tracking URL.\n\nUse the Shipments API to list an account's shipments, retrieve one by its ID or the payment it fulfills, attach a tracking number to a payment, and update the tracking number on an existing shipment.\n",
|
|
@@ -28199,7 +28199,7 @@ var native_spec_default = {
|
|
|
28199
28199
|
"x-whop-summary": "Deprecated compatibility endpoints for external accounts."
|
|
28200
28200
|
},
|
|
28201
28201
|
{
|
|
28202
|
-
description: "An App is software you build on Whop. It can be a hosted web app served at
|
|
28202
|
+
description: "An App is software you build on Whop. It can be a hosted web app served at its domains, such as a `whop.site` address or a custom domain, or an API integration installed as an experience, and it belongs to the account that owns its credentials, settings, builds, and runtime logs.\n\nUse the Apps API to manage app configuration, deploy an app's working copy and follow the run on the app's `deployment` field, and, for hosted apps, read server runtime logs for console output, uncaught exceptions, and failed requests.\n\nApps are also reusable blueprints. List official blueprints with `app_type=website&verified=true&order=template_usage`, or community blueprints with `app_type=website&verified=false&recommended=true&order=template_usage`. Pass the returned App `id` as `blueprint_id` when creating an Account.\n",
|
|
28203
28203
|
name: "Apps",
|
|
28204
28204
|
"x-whop-summary": "Apps you build on Whop: metadata, hosted builds, runtime logs."
|
|
28205
28205
|
},
|
|
@@ -32748,6 +32748,11 @@ var native_spec_default = {
|
|
|
32748
32748
|
description: "The account's business website, as an `http` or `https` URL of at most 255 characters. Also added to the account's `social_links` as a `website` entry. Pass `null` to clear the website; existing social links are left unchanged.",
|
|
32749
32749
|
example: "https://shinetimedetail.com",
|
|
32750
32750
|
type: ["string", "null"]
|
|
32751
|
+
},
|
|
32752
|
+
whop_partner_enabled: {
|
|
32753
|
+
description: "Set to `true` to turn on Whop Partner mode for the account, so its team can refer businesses and the account is paid partner commission on their sales. Recorded once; `false` is rejected.",
|
|
32754
|
+
example: true,
|
|
32755
|
+
type: "boolean"
|
|
32751
32756
|
}
|
|
32752
32757
|
},
|
|
32753
32758
|
type: "object"
|
|
@@ -33550,7 +33555,7 @@ var native_spec_default = {
|
|
|
33550
33555
|
}
|
|
33551
33556
|
},
|
|
33552
33557
|
{
|
|
33553
|
-
description: "The field to sort by. Defaults to created_at. Stat columns (spend, impressions, \u2026) rank over the stats_from/stats_to window across the whole list, not just the current page. results, cost_per_result and return_on_ad_spend rank by the same Whop pixel-attributed values the response reports.",
|
|
33558
|
+
description: "The field to sort by. Defaults to created_at. Stat columns (spend, impressions, \u2026) rank over the stats_from/stats_to window across the whole list, not just the current page. results, cost_per_result and return_on_ad_spend rank by the same Whop pixel-attributed values the response reports, and link_clicks by the same Whop pixel page views.",
|
|
33554
33559
|
in: "query",
|
|
33555
33560
|
name: "order",
|
|
33556
33561
|
required: false,
|
|
@@ -35264,7 +35269,7 @@ var native_spec_default = {
|
|
|
35264
35269
|
}
|
|
35265
35270
|
},
|
|
35266
35271
|
{
|
|
35267
|
-
description: "The field to sort by. Defaults to created_at. Stat columns (spend, impressions, \u2026) rank over the stats_from/stats_to window across the whole list, not just the current page. results, cost_per_result and return_on_ad_spend rank by the same Whop pixel-attributed values the response reports.",
|
|
35272
|
+
description: "The field to sort by. Defaults to created_at. Stat columns (spend, impressions, \u2026) rank over the stats_from/stats_to window across the whole list, not just the current page. results, cost_per_result and return_on_ad_spend rank by the same Whop pixel-attributed values the response reports, and link_clicks by the same Whop pixel page views.",
|
|
35268
35273
|
in: "query",
|
|
35269
35274
|
name: "order",
|
|
35270
35275
|
required: false,
|
|
@@ -37555,7 +37560,7 @@ var native_spec_default = {
|
|
|
37555
37560
|
}
|
|
37556
37561
|
},
|
|
37557
37562
|
{
|
|
37558
|
-
description: "The field to sort by. Defaults to created_at. Stat columns (spend, impressions, \u2026) rank over the stats_from/stats_to window across the whole list, not just the current page. results, cost_per_result and return_on_ad_spend rank by the same Whop pixel-attributed values the response reports.",
|
|
37563
|
+
description: "The field to sort by. Defaults to created_at. Stat columns (spend, impressions, \u2026) rank over the stats_from/stats_to window across the whole list, not just the current page. results, cost_per_result and return_on_ad_spend rank by the same Whop pixel-attributed values the response reports, and link_clicks by the same Whop pixel page views.",
|
|
37559
37564
|
in: "query",
|
|
37560
37565
|
name: "order",
|
|
37561
37566
|
required: false,
|
|
@@ -40212,7 +40217,6 @@ var native_spec_default = {
|
|
|
40212
40217
|
},
|
|
40213
40218
|
base_url: {
|
|
40214
40219
|
description: "The base production URL where the app is hosted, such as `https://myapp.example.com`.",
|
|
40215
|
-
example: "https://booking.shinetime.example",
|
|
40216
40220
|
type: ["string", "null"]
|
|
40217
40221
|
},
|
|
40218
40222
|
domain_id: {
|
|
@@ -40487,7 +40491,7 @@ var native_spec_default = {
|
|
|
40487
40491
|
},
|
|
40488
40492
|
base_url: {
|
|
40489
40493
|
description: "The base production URL where the app is hosted. Set to `null` to take the app proxy offline.",
|
|
40490
|
-
example: "https://booking.
|
|
40494
|
+
example: "https://shine-time-booking.whop.site",
|
|
40491
40495
|
type: ["string", "null"]
|
|
40492
40496
|
},
|
|
40493
40497
|
dashboard_path: {
|
|
@@ -46970,7 +46974,7 @@ var native_spec_default = {
|
|
|
46970
46974
|
},
|
|
46971
46975
|
"/deposits": {
|
|
46972
46976
|
post: {
|
|
46973
|
-
description: "Returns the deposit methods for an account or user, including crypto addresses, bank transfer instructions, and, for a business, a hosted deposit page. Bitcoin deposits are converted to USDT on Plasma in the destination's wallet. Business destinations require no authentication.",
|
|
46977
|
+
description: "Returns the deposit methods for an account or user, including crypto addresses, bank transfer instructions, and, for a business, a hosted deposit page. Bitcoin deposits are converted to USDT on Plasma in the destination's wallet. Business destinations require no authentication. Pass `payment_method_id` to also charge a business's saved payment method for `amount` in USD and add it to the business's balance; that requires authentication with the `payment:charge` scope. The charge has no fees or taxes and does not count as revenue.",
|
|
46974
46978
|
operationId: "create",
|
|
46975
46979
|
parameters: [
|
|
46976
46980
|
{
|
|
@@ -46983,7 +46987,7 @@ var native_spec_default = {
|
|
|
46983
46987
|
schema: {
|
|
46984
46988
|
properties: {
|
|
46985
46989
|
amount: {
|
|
46986
|
-
description: "Amount to prefill on hosted deposit page. Crypto deposits require a $10 minimum.",
|
|
46990
|
+
description: "Amount to prefill on hosted deposit page. Crypto deposits require a $10 minimum. With `payment_method_id`, the amount in USD to charge, and required.",
|
|
46987
46991
|
example: 50,
|
|
46988
46992
|
type: "number"
|
|
46989
46993
|
},
|
|
@@ -46991,6 +46995,11 @@ var native_spec_default = {
|
|
|
46991
46995
|
description: "Account ID to fund, `biz_` or `user_`. Any business resolves without authentication; a user account resolves only for that same authenticated user.",
|
|
46992
46996
|
example: "biz_xxxxxxxxxxxxxx",
|
|
46993
46997
|
type: "string"
|
|
46998
|
+
},
|
|
46999
|
+
payment_method_id: {
|
|
47000
|
+
description: "A saved payment method of the business to charge for `amount`, prefixed `payt_`. Save one with Create setup intent and `owner_id` set to the account. Only for a `biz_` destination, and requires authentication with the `payment:charge` scope. A declined charge fails the request with 400.",
|
|
47001
|
+
example: "payt_xxxxxxxxxxxxxx",
|
|
47002
|
+
type: "string"
|
|
46994
47003
|
}
|
|
46995
47004
|
},
|
|
46996
47005
|
required: ["destination"],
|
|
@@ -47016,6 +47025,23 @@ var native_spec_default = {
|
|
|
47016
47025
|
example: "50.00",
|
|
47017
47026
|
type: "string"
|
|
47018
47027
|
},
|
|
47028
|
+
card: {
|
|
47029
|
+
description: "The charge to a saved payment method. Null unless `payment_method_id` was passed.",
|
|
47030
|
+
properties: {
|
|
47031
|
+
payment_id: {
|
|
47032
|
+
description: "The payment the charge created, prefixed `pay_`. Retrieve it, or listen for `payment.succeeded`, to confirm the funds landed.",
|
|
47033
|
+
example: "pay_xxxxxxxxxxxxxx",
|
|
47034
|
+
type: "string"
|
|
47035
|
+
},
|
|
47036
|
+
payment_method_id: {
|
|
47037
|
+
description: "The saved payment method that was charged, prefixed `payt_`.",
|
|
47038
|
+
example: "payt_xxxxxxxxxxxxxx",
|
|
47039
|
+
type: "string"
|
|
47040
|
+
}
|
|
47041
|
+
},
|
|
47042
|
+
required: ["payment_method_id", "payment_id"],
|
|
47043
|
+
type: ["object", "null"]
|
|
47044
|
+
},
|
|
47019
47045
|
hosted_url: {
|
|
47020
47046
|
description: "URL of the hosted deposit page. Only present for business destinations.",
|
|
47021
47047
|
example: "https://whop.com/deposit/biz_xxxxxxxxxxxxxx/",
|
|
@@ -47201,7 +47227,13 @@ var native_spec_default = {
|
|
|
47201
47227
|
type: "string"
|
|
47202
47228
|
}
|
|
47203
47229
|
},
|
|
47204
|
-
required: [
|
|
47230
|
+
required: [
|
|
47231
|
+
"object",
|
|
47232
|
+
"account_id",
|
|
47233
|
+
"hosted_url",
|
|
47234
|
+
"methods",
|
|
47235
|
+
"card"
|
|
47236
|
+
],
|
|
47205
47237
|
type: "object"
|
|
47206
47238
|
}
|
|
47207
47239
|
}
|
|
@@ -47220,6 +47252,9 @@ var native_spec_default = {
|
|
|
47220
47252
|
{},
|
|
47221
47253
|
{
|
|
47222
47254
|
bearerAuth: ["payout:account:read"]
|
|
47255
|
+
},
|
|
47256
|
+
{
|
|
47257
|
+
bearerAuth: ["payment:charge"]
|
|
47223
47258
|
}
|
|
47224
47259
|
],
|
|
47225
47260
|
summary: "Create Deposit",
|
|
@@ -49003,10 +49038,6 @@ var native_spec_default = {
|
|
|
49003
49038
|
$ref: "#/components/responses/InvalidParameters",
|
|
49004
49039
|
description: "Invalid search"
|
|
49005
49040
|
},
|
|
49006
|
-
"403": {
|
|
49007
|
-
$ref: "#/components/responses/Forbidden",
|
|
49008
|
-
description: "Domain search is not available to this caller"
|
|
49009
|
-
},
|
|
49010
49041
|
"503": {
|
|
49011
49042
|
$ref: "#/components/responses/ServiceUnavailable",
|
|
49012
49043
|
description: "The registrar is unavailable"
|
|
@@ -49265,10 +49296,6 @@ var native_spec_default = {
|
|
|
49265
49296
|
"400": {
|
|
49266
49297
|
$ref: "#/components/responses/InvalidParameters",
|
|
49267
49298
|
description: "Invalid hostname"
|
|
49268
|
-
},
|
|
49269
|
-
"403": {
|
|
49270
|
-
$ref: "#/components/responses/Forbidden",
|
|
49271
|
-
description: "Domain search is not available to this caller"
|
|
49272
49299
|
}
|
|
49273
49300
|
},
|
|
49274
49301
|
security: [
|
|
@@ -52499,7 +52526,7 @@ var native_spec_default = {
|
|
|
52499
52526
|
type: "array"
|
|
52500
52527
|
},
|
|
52501
52528
|
filters: {
|
|
52502
|
-
description: "Resource-specific filters. For native REST resources (`payouts`, `transfers`, `products`) these are the resource's own list query params; for dashboard tables they mirror the dashboard table filters.\n\n<details>\n<summary>Filters by resource (25)</summary>\n\n<details>\n<summary>ad_campaigns (5)</summary>\n\nMirrors the filtering query params of `GET /api/v1/ad_campaigns`.\n\n- `campaign_type` `string` \u2014 Only return campaigns of this type. One of `standard`, `search`.\n- `created_after` `string` \u2014 Only return campaigns created after this timestamp.\n- `created_before` `string` \u2014 Only return campaigns created before this timestamp.\n- `query` `string` \u2014 Filter campaigns by a title or ID substring.\n- `status` `string` \u2014 Only return campaigns with this status. One of `draft`, `active`, `paused`, `payment_failed`.\n\n</details>\n<details>\n<summary>ad_groups (6)</summary>\n\nMirrors the filtering query params of `GET /api/v1/ad_groups`.\n\n- `ad_campaign_id` `string` \u2014 Filter to ad groups in this campaign.\n- `ad_campaign_ids` `string[]` \u2014 Filter to ad groups in these campaigns (max 100). Repeat the parameter for each id (ad_campaign_ids=a&ad_campaign_ids=b).\n- `created_after` `string` \u2014 Only return ad groups created after this timestamp.\n- `created_before` `string` \u2014 Only return ad groups created before this timestamp.\n- `query` `string` \u2014 Filter ad groups by a title or ID substring.\n- `status` `string` \u2014 Filter to ad groups with this status. One of `active`, `paused`, `rejected`, `duplicating`.\n\n</details>\n<details>\n<summary>ads (8)</summary>\n\nMirrors the filtering query params of `GET /api/v1/ads`.\n\n- `ad_campaign_id` `string` \u2014 Only return ads in this ad campaign.\n- `ad_campaign_ids` `string[]` \u2014 Only return ads in these ad campaigns (max 100). Repeat the parameter for each id (ad_campaign_ids=a&ad_campaign_ids=b).\n- `ad_group_id` `string` \u2014 Only return ads in this ad group.\n- `ad_group_ids` `string[]` \u2014 Only return ads in these ad groups (max 100). Repeat the parameter for each id (ad_group_ids=a&ad_group_ids=b).\n- `created_after` `string` \u2014 Only return ads created after this timestamp.\n- `created_before` `string` \u2014 Only return ads created before this timestamp.\n- `query` `string` \u2014 Filter ads by a title or ID substring.\n- `status` `string` \u2014 Only return ads with this status. One of `active`, `paused`, `in_review`, `rejected`.\n\n</details>\n<details>\n<summary>apps (6)</summary>\n\nMirrors the filtering query params of `GET /api/v1/apps`.\n\n- `app_type` `string` \u2014 Filter apps by the type of end-user they are built for. Apps of type `website` are left out unless you ask for them by name. One of `b2b_app`, `b2c_app`, `company_app`, `component`, `website`.\n- `query` `string` \u2014 A search string matched against app names.\n- `recommended` `boolean` \u2014 Only return apps Whop recommends (or, with `false`, only those it does not), independently of verification status.\n- `verified` `boolean` \u2014 Only return apps whose Whop verification status matches this value. Omit this filter to include every verification status the caller can see.\n- `verified_apps_only` `boolean` \u2014 Legacy compatibility filter. Use `verified` for field equality. `true` returns verified apps; clients pinned before `2026-08-25-2` retain the earlier public website discovery behavior.\n- `view_type` `string` \u2014 Only return apps supporting this view type, such as `dashboard` or `hub`. One of `hub`, `discover`, `dash`, `dashboard`, `analytics`, `skills`, `openapi`.\n\n</details>\n<details>\n<summary>audiences (3)</summary>\n\nMirrors the filtering query params of `GET /api/v1/audiences`.\n\n- `audience_id` `string` \u2014 Audience ID, prefixed `adaud_`, used to filter the response to one audience.\n- `audience_type` `string` \u2014 Filter by custom or lookalike audiences. One of `custom`, `lookalike`.\n- `source_type` `string` \u2014 Filter by uploaded customer lists, Whop People filters, or social engagement. One of `csv_upload`, `people_filter`, `engagement`.\n\n</details>\n<details>\n<summary>bounties (8)</summary>\n\nMirrors the filtering query params of `GET /api/v1/bounties`.\n\n- `business_goal_type` `string` \u2014 Filter by the poster's declared goal. Bounties created before the goal taxonomy carry no goal and never match this filter. One of `clipping`, `post_engagement`, `owned_account_growth`, `ugc_content`, `local_activation`, `data_capture`, `other`.\n- `country` `string` \u2014 Only bounties workable from this country, as an ISO 3166-1 alpha-2 code. Bounties with no country targeting are workable worldwide and always match.\n- `created_after` `string` \u2014 Only bounties created after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only bounties created before this ISO 8601 timestamp.\n- `experience_id` `string` \u2014 Only bounties posted to this forum experience, prefixed `exp_`. An unknown experience, or one outside the caller's scope, matches nothing.\n- `query` `string` \u2014 Substring match on the bounty title or ID.\n- `status` `string` \u2014 Filter by lifecycle state. One of `scheduled`, `open`, `closed`, `completed`, `canceled`.\n- `user_id` `string` \u2014 List the bounties this user participated in (`user_` tag). Must be the authenticated user.\n\n</details>\n<details>\n<summary>bounty_submissions (4)</summary>\n\nMirrors the filtering query params of `GET /api/v1/bounty_submissions`.\n\n- `bounty_id` `string` \u2014 Only submissions on this bounty (`bnty_` tag).\n- `created_after` `string` \u2014 Only submissions created after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only submissions created before this ISO 8601 timestamp.\n- `status` `string` \u2014 Filter by lifecycle state. One of `in_progress`, `submitted`, `approved`, `denied`.\n\n</details>\n<details>\n<summary>card_transactions (7)</summary>\n\nMirrors the filtering query params of `GET /api/v1/card_transactions`.\n\n- `card_id` `string[]` \u2014 Return only transactions charged to these cards, each prefixed `icrd_`.\n- `cardholder_id` `string[]` \u2014 Return only transactions on cards assigned to these users, each prefixed `user_`.\n- `created_after` `string` \u2014 Return only transactions authorized at or after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Return only transactions authorized at or before this ISO 8601 timestamp.\n- `status` `string` \u2014 Return only transactions with this status. One of `pending`, `completed`, `reversed`, `declined`.\n- `transaction_ids` `string[]` \u2014 Return only these card transactions, each prefixed `citx_`. Repeat the parameter, or pass one comma-separated value.\n- `user_id` `string` \u2014 The user whose personal card transactions to list, prefixed `user_`. Provide this or `account_id`. Only that user can read them.\n\n</details>\n<details>\n<summary>checkout_configurations (3)</summary>\n\nMirrors the filtering query params of `GET /api/v1/checkout_configurations`.\n\n- `created_after` `string` \u2014 Only return checkout configurations created after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only return checkout configurations created before this ISO 8601 timestamp.\n- `plan_id` `string` \u2014 Only return checkout configurations for this variant ID, prefixed `plan_`.\n\n</details>\n<details>\n<summary>disputes (4)</summary>\n\nMirrors the filtering query params of `GET /api/v1/disputes`.\n\n- `created_after` `string` \u2014 Only disputes opened after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only disputes opened before this ISO 8601 timestamp.\n- `currency` `string` \u2014 Only disputes in this three-letter ISO currency.\n- `status` `string[]` \u2014 Only disputes in these statuses. Repeat the parameter to pass several \u2014 one paginated list covers all of them. Inquiries match only the `warning_` statuses. A `needs_response` dispute whose evidence deadline has passed reports and filters as `under_review` instead.\n\n</details>\n<details>\n<summary>events (14)</summary>\n\nMirrors the filtering query params of `GET /api/v1/events`.\n\n- `attribution_model` `string` \u2014 Attribution model for the source filter (defaults to last_touch). One of `last_touch`, `first_touch`.\n- `browser` `string` \u2014 Browser families to filter by, comma-separated (e.g. Chrome, Mobile Safari).\n- `city` `string` \u2014 Cities to filter by, comma-separated.\n- `country` `string` \u2014 Country codes to filter by, comma-separated.\n- `device` `string` \u2014 Device families to filter by, comma-separated (e.g. iPhone, Mac).\n- `event` `string` \u2014 Full event names to filter by, comma-separated (payment.completed, pixel.lead, pixel.page, pixel.custom:<name>) \u2014 the same vocabulary the events / people metrics use.\n- `from` `string` \u2014 Start of the time range as an ISO 8601 timestamp. Required when identifier is omitted.\n- `hostname` `string` \u2014 Page hostnames to filter by, comma-separated.\n- `identifier` `string` \u2014 Any hard identifier of the person: a person ID (prsn_*), user ID, email, phone number, or a tracking cookie value (wuid, anonymous ID, fbp/fbc/ttp/ga). Omit to list recent events for the account.\n- `os` `string` \u2014 Operating system families to filter by, comma-separated (e.g. iOS, Windows).\n- `page` `string` \u2014 Page paths to filter by, comma-separated.\n- `source` `string` \u2014 Canonical source path, exact or with a trailing :* prefix (whop:<campaign>:*, ext:meta:*, referrer:<domain>, direct, unknown). Selects conversions credited to this source.\n- `to` `string` \u2014 End of the time range as an ISO 8601 timestamp. Required when identifier is omitted; otherwise defaults to now.\n- `utm_source` `string` \u2014 utm_source values to filter by, comma-separated.\n\n</details>\n<details>\n<summary>external_accounts (5)</summary>\n\nMirrors the filtering query params of `GET /api/v1/external_accounts`.\n\n- `platform` `string` \u2014 Only return external accounts for the platform that is specified. One of `x`, `instagram`, `youtube`, `tiktok`, `facebook`, `discord`, `telegram`, `linkedin`, `snapchat`.\n- `scopes` `string[]` \u2014 Only return external accounts that have these scopes.\n- `trust_level` `string` \u2014 Only return external accounts linked with this trust level, such as `oauth` for accounts connected through OAuth. One of `oauth`, `verified`, `authorized`, `claimed`, `scraped`.\n- `user_id` `string` \u2014 The User that the external accounts are connected to. Provide either this or account_id.\n- `verified` `boolean` \u2014 Only return external accounts that are verified on the platform.\n\n</details>\n<details>\n<summary>financial-activity (15)</summary>\n\nMirrors the filtering query params of `GET /api/v1/financial_activity`.\n\n- `activity_id` `string` \u2014 Optional ledger activity ID (for example `line_3`). Returns at most that one activity.\n- `available_after` `string` \u2014 Only include balance credits and debits available on or after this `YYYY-MM-DD` date (UTC), distinct from posted_at. Requires currency.\n- `available_before` `string` \u2014 Only include balance credits and debits available on or before this `YYYY-MM-DD` date (UTC). Set equal to available_after for a single day. Requires currency.\n- `balance_type` `string` \u2014 Which balance the activity changes. `total` includes available, pending, and reserved funds. `available` includes only movements into or out of available funds, including reservations, releases, and fees. Movements within the selected balance are omitted. Omit to preserve the existing activity feed. Requires account_id or user_id; cannot be combined with available_after or available_before. One of `total`, `available`.\n- `currency` `string` \u2014 Optional currency code filter, for example `usd`.\n- `exclude_internal_movements` `boolean` \u2014 Whether to exclude balance reservations and balanced movements between the account's own balances.\n- `include_owned_accounts` `boolean` \u2014 When true, aggregates the authenticated user's personal ledger with the businesses they own (owner role with balance read) into one feed. Requires user_id to be the authenticated user; cannot be combined with account_id or the settlement-date filters. Each returned row includes the owning `account`.\n- `include_resource` `boolean` \u2014 Whether to include the `resource` field in the response or not. Consider passing `false` if you need a fast response without as many rich details.\n- `line_types` `string[]` \u2014 Optional ledger line categories to include. Some categories (for example `onchain_deposit`, which covers inbound crypto deposits such as MoonPay onramps) are only returned when explicitly requested here.\n- `payment_id` `string` \u2014 Filter activity by payment ID (pay_), including related refunds, disputes, and fees. Combines with resource_id and other filters within the selected accounts. Unknown payments return an empty list.\n- `posted_after` `string` \u2014 Only include rows posted after this ISO 8601 timestamp.\n- `posted_before` `string` \u2014 Only include rows posted before this ISO 8601 timestamp.\n- `resource_id` `string` \u2014 Optional prefixed resource ID. Returns activity associated with that resource.\n- `user_id` `string` \u2014 The owning user ID (a user_ identifier). Provide this or account_id.\n- `withdrawal_id` `string` \u2014 Withdrawal ID (wdrl_). With balance_type=available, selects the same period as its statement, after the previous withdrawal and through this withdrawal, excluding this withdrawal and its fee. Requires a single account. Overrides currency and posted-date filters.\n\n</details>\n<details>\n<summary>members (11)</summary>\n\nMirrors the filtering query params of `GET /api/v1/members`.\n\n- `access_level` `string` \u2014 Filter by what the member can reach on the account. One of `no_access`, `admin`, `customer`.\n- `created_after` `string` \u2014 Only members who joined after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only members who joined before this ISO 8601 timestamp.\n- `membership_status` `string` \u2014 `active` returns members holding at least one membership that currently grants access; `inactive` returns members holding at least one membership that does not. Combined with `product_ids`, `plan_ids`, or `promo_code_ids`, one membership must match all of them. One of `active`, `inactive`.\n- `most_recent_actions` `string[]` \u2014 Only return members whose `most_recent_action` is one of these values.\n- `plan_ids` `string[]` \u2014 Only return members holding a membership on one of these plans, prefixed `plan_`. Unknown IDs match nothing.\n- `product_ids` `string[]` \u2014 Only return members holding a membership to one of these products, prefixed `prod_`. Unknown IDs match nothing.\n- `promo_code_ids` `string[]` \u2014 Only return members holding a membership bought with one of these promo codes, prefixed `promo_`. Unknown IDs match nothing.\n- `query` `string` \u2014 Search members by name or username. An exact email address also matches when the credential holds the member:email:read scope.\n- `status` `string` \u2014 Filter by whether the member is still part of the account. One of `joined`, `left`.\n- `user_ids` `string[]` \u2014 Only return members whose users match these `user_` identifiers.\n\n</details>\n<details>\n<summary>memberships (11)</summary>\n\nMirrors the filtering query params of `GET /api/v1/memberships`.\n\n- `created_after` `string` \u2014 Only memberships created after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only memberships created before this ISO 8601 timestamp.\n- `member_id` `string` \u2014 Narrow to one member's memberships (`mber_` tag), including memberships bought by another business. A member outside the caller's visible set returns an empty list.\n- `plan_id` `string` \u2014 Filter to memberships of this variant (`plan_` tag).\n- `plan_ids` `string[]` \u2014 Filter to memberships of any of these variants, each prefixed `plan_`. Repeat the parameter to pass several.\n- `product_id` `string` \u2014 Filter to memberships of this product (`prod_` tag).\n- `product_ids` `string[]` \u2014 Filter to memberships of any of these products, each prefixed `prod_`. Repeat the parameter to pass several.\n- `promo_code_ids` `string[]` \u2014 Filter to memberships discounted by any of these promo codes, each prefixed `promo_`. Repeat the parameter to pass several.\n- `status` `string` \u2014 Filter by billing state. `trialing`, `active`, `past_due`, `completed`, `canceled`, and `expired` match the membership's `status`; `active`, `trialing`, and `past_due` exclude memberships set to cancel at period end. The other values are derived buckets that never appear as a `status`: `canceling` matches memberships set to cancel at period end; `paused` matches memberships with payment collection paused; `expiring` matches one-time purchases that have not yet expired; `one_time` matches one-time purchases that never expire; `unclaimed` matches memberships with no buyer user, including memberships bought by another business; `banned` matches memberships whose buyer is banned from the account. One of `active`, `trialing`, `past_due`, `completed`, `canceled`, `expired`, `canceling`, `paused`, `expiring`, `one_time`, `unclaimed`, `banned`.\n- `statuses` `string[]` \u2014 Filter to memberships matching any of these billing states, with the same meanings as `status`. Repeat the parameter to pass several. Combined with `status` when both are sent.\n- `user_id` `string` \u2014 Narrow to one user's memberships (`user_` tag, or `me` for the caller). A user outside the caller's visible set returns an empty list.\n\n</details>\n<details>\n<summary>payouts (7)</summary>\n\nMirrors the filtering query params of `GET /api/v1/payouts`.\n\n- `created_after` `string` \u2014 Only payouts created at or after this ISO 8601 time (inclusive).\n- `created_before` `string` \u2014 Only payouts created before this ISO 8601 time (exclusive).\n- `currency` `string` \u2014 Optional currency code filter, for example `usd`.\n- `payout_method_id` `string` \u2014 Filter to payouts sent to one saved payout method (a pytk_ identifier). An unknown id matches nothing.\n- `source` `string` \u2014 Filter by how the payout was created. Payouts created before source tracking or through internal tooling carry no source and never match. One of `api`, `dashboard`, `automatic`.\n- `status` `string` \u2014 Filter to payouts whose `status` reads this word, matching exactly what this version displays \u2014 `reversed` finds settled payouts the bank later returned. Requires Api-Version-Date 2026-08-21 or later. One of `requested`, `in_review`, `processing`, `completed`, `reversed`, `canceled`, `failed`, `denied`.\n- `user_id` `string` \u2014 The owning user ID (a user_ identifier). Provide this or account_id.\n\n</details>\n<details>\n<summary>people (39)</summary>\n\nMirrors the filtering query params of `GET /api/v1/people`.\n\n- `aov_gt` `number` \u2014 Select people whose lifetime aov is greater than this value. LTV and AOV are in USD.\n- `aov_gte` `number` \u2014 Select people whose lifetime aov is at least this value. LTV and AOV are in USD.\n- `aov_lt` `number` \u2014 Select people whose lifetime aov is less than this value. LTV and AOV are in USD.\n- `aov_lte` `number` \u2014 Select people whose lifetime aov is at most this value. LTV and AOV are in USD.\n- `attribution_model` `string` \u2014 Attribution model the source filter matches against (defaults to last_touch). One of `last_touch`, `first_touch`.\n- `audience_id` `string` \u2014 Only include people in this audience. An audience that keeps itself up to date resolves to the People filters that define it, so this always reflects who matches now; uploaded lists and point-in-time snapshots match their recorded members.\n- `contactable` `boolean` \u2014 true for people who have an email address or phone number \u2014 the ones an ad platform can match.\n- `country` `string` \u2014 Only include people with activity from this ISO 3166-1 alpha-2 country code.\n- `custom_event` `string` \u2014 Only include people who fired this custom pixel event.\n- `email` `string` \u2014 Only include the person linked to this email address.\n- `event_count_gt` `number` \u2014 Select people whose lifetime event_count is greater than this value. LTV and AOV are in USD.\n- `event_count_gte` `number` \u2014 Select people whose lifetime event_count is at least this value. LTV and AOV are in USD.\n- `event_count_lt` `number` \u2014 Select people whose lifetime event_count is less than this value. LTV and AOV are in USD.\n- `event_count_lte` `number` \u2014 Select people whose lifetime event_count is at most this value. LTV and AOV are in USD.\n- `event_from` `string` \u2014 The inclusive start of the matching activity window.\n- `event_name` `string[]` \u2014 Only include people who fired any of these events, e.g. payment.completed or page.checkout.view.\n- `event_to` `string` \u2014 The inclusive end of the matching activity window, for both stats drilldowns and saved audiences.\n- `event_within_days` `integer` \u2014 Match activity within a rolling number of days. Cannot be combined with event_from/event_to.\n- `first_seen_after` `string` \u2014 Only include people first seen at or after this ISO 8601 timestamp.\n- `first_seen_before` `string` \u2014 Only include people first seen before this ISO 8601 timestamp.\n- `first_seen_within_days` `integer` \u2014 Only include people first seen within this many days, as a rolling window.\n- `from` `string` \u2014 Inclusive activity-window start. Alias for event_from.\n- `has_purchased` `boolean` \u2014 true for customers only, false for people who have never purchased.\n- `last_seen_after` `string` \u2014 Only include people last seen at or after this ISO 8601 timestamp.\n- `last_seen_before` `string` \u2014 Only include people last seen before this ISO 8601 timestamp.\n- `last_seen_within_days` `integer` \u2014 Only include people last seen within this many days, as a rolling window.\n- `ltv_gt` `number` \u2014 Select people whose lifetime ltv is greater than this value. LTV and AOV are in USD.\n- `ltv_gte` `number` \u2014 Select people whose lifetime ltv is at least this value. LTV and AOV are in USD.\n- `ltv_lt` `number` \u2014 Select people whose lifetime ltv is less than this value. LTV and AOV are in USD.\n- `ltv_lte` `number` \u2014 Select people whose lifetime ltv is at most this value. LTV and AOV are in USD.\n- `phone` `string` \u2014 Only include the person linked to this phone number.\n- `purchase_count_gt` `number` \u2014 Select people whose lifetime purchase_count is greater than this value. LTV and AOV are in USD.\n- `purchase_count_gte` `number` \u2014 Select people whose lifetime purchase_count is at least this value. LTV and AOV are in USD.\n- `purchase_count_lt` `number` \u2014 Select people whose lifetime purchase_count is less than this value. LTV and AOV are in USD.\n- `purchase_count_lte` `number` \u2014 Select people whose lifetime purchase_count is at most this value. LTV and AOV are in USD.\n- `query` `string` \u2014 Search people by name, email, phone, or whop user ID (case-insensitive substring match).\n- `source` `string[]` \u2014 Only include people acquired from any of these sources \u2014 canonical paths (whop:<campaign>:<group>:<ad>, ext:<platform>:..., referrer:<domain>, direct, other), exact or with a trailing :* prefix. The same vocabulary the events / people metrics use.\n- `to` `string` \u2014 Inclusive activity-window end. Alias for event_to.\n- `user_id` `string` \u2014 Only include the person linked to this whop user ID.\n\n</details>\n<details>\n<summary>products (10)</summary>\n\nMirrors the filtering query params of `GET /api/v1/products`.\n\n- `access_pass_types` `string[]` \u2014 Filter to only products matching these types.\n- `created_after` `string` \u2014 Only return products created after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only return products created before this ISO 8601 timestamp.\n- `labels` `string[]` \u2014 Filter to only products carrying all of these labels. Labels are matched lowercased.\n- `marketplace_category_route` `string` \u2014 Only return marketplace products assigned to this category route, such as `trading`.\n- `plan_types` `string[]` \u2014 Filter to products with a buyable variant of these billing models, such as `one_time` or `renewal`.\n- `price_maximum` `number` \u2014 Only return products whose advertised buyable variant has a displayed price of at most this amount. Recurring variants use renewal price.\n- `price_minimum` `number` \u2014 Only return products whose advertised buyable variant has a displayed price of at least this amount. Recurring variants use renewal price.\n- `query` `string` \u2014 Filters products by text. The public marketplace list searches product title, account name, headline and description, ranking products that match every word first and the closest partial matches after them; an account's own list is a plain substring match over title, headline and description. Omit to browse by recency.\n- `visibilities` `string[]` \u2014 Filter to only products matching these visibility states. Ignored on the public marketplace list, which only returns visible products.\n\n</details>\n<details>\n<summary>promo_codes (5)</summary>\n\nMirrors the filtering query params of `GET /api/v1/promo_codes`.\n\n- `created_after` `string` \u2014 Only promo codes created after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only promo codes created before this ISO 8601 timestamp.\n- `plan_ids` `string[]` \u2014 Only promo codes scoped to these variant IDs.\n- `product_ids` `string[]` \u2014 Only promo codes scoped to these product IDs.\n- `status` `string` \u2014 Promo-code status. `expired` groups inactive and archived codes. One of `active`, `inactive`, `archived`, `expired`.\n\n</details>\n<details>\n<summary>resolution_center_cases (6)</summary>\n\nMirrors the filtering query params of `GET /api/v1/resolution_center_cases`.\n\n- `created_after` `string` \u2014 Only cases created after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only cases created before this ISO 8601 timestamp.\n- `outcome` `string[]` \u2014 Only closed cases that ended these ways. Repeat the parameter to pass several.\n- `reason` `string[]` \u2014 Only cases opened for these reasons. Repeat the parameter to pass several.\n- `status` `string[]` \u2014 Only cases in these statuses. Repeat the parameter to pass several \u2014 one paginated list covers all of them.\n- `user_id` `string` \u2014 Only cases opened by this customer \u2014 a `user_` tag, or `me` for the calling user. It narrows what you can already read, so `me` lists the cases you opened without the ones on accounts you are a team member of.\n\n</details>\n<details>\n<summary>shipments (4)</summary>\n\nMirrors the filtering query params of `GET /api/v1/shipments`.\n\n- `created_after` `string` \u2014 Return shipments created after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Return shipments created before this ISO 8601 timestamp.\n- `payment_id` `string[]` \u2014 Only shipments fulfilling these payments, each prefixed `pay_`. Repeat the parameter to pass several, up to 100 per request \u2014 one paginated list covers all of them.\n- `status` `string` \u2014 Filter to shipments with this delivery status. One of `unknown`, `pre_transit`, `in_transit`, `out_for_delivery`, `delivered`, `available_for_pickup`, `return_to_sender`, `failure`, `cancelled`, `error`.\n\n</details>\n<details>\n<summary>social_accounts (5)</summary>\n\nMirrors the filtering query params of `GET /api/v1/social_accounts`.\n\n- `platform` `string` \u2014 Only return external accounts for the platform that is specified. One of `x`, `instagram`, `youtube`, `tiktok`, `facebook`, `discord`, `telegram`, `linkedin`, `snapchat`.\n- `scopes` `string[]` \u2014 Only return external accounts that have these scopes.\n- `trust_level` `string` \u2014 Only return external accounts linked with this trust level, such as `oauth` for accounts connected through OAuth. One of `oauth`, `verified`, `authorized`, `claimed`, `scraped`.\n- `user_id` `string` \u2014 The User that the external accounts are connected to. Provide either this or account_id.\n- `verified` `boolean` \u2014 Only return external accounts that are verified on the platform.\n\n</details>\n<details>\n<summary>team_members (5)</summary>\n\nMirrors the filtering query params of `GET /api/v1/team_members`.\n\n- `created_after` `string` \u2014 Only return members added after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only return members added before this ISO 8601 timestamp.\n- `role` `string` \u2014 Only return members with this role. `custom` matches members on a dashboard-managed custom role. One of `owner`, `admin`, `partner`, `sales_manager`, `moderator`, `advertiser`, `app_manager`, `support`, `manager`, `workforce`, `custom`.\n- `status` `string` \u2014 Only return members with this status: `joined` (accepted members) or `pending` (pending invites). Both are returned by default. One of `joined`, `pending`.\n- `user_id` `string` \u2014 Only return the membership for this user ID, prefixed `user_`.\n\n</details>\n<details>\n<summary>transfers (4)</summary>\n\nMirrors the filtering query params of `GET /api/v1/transfers`.\n\n- `created_after` `string` \u2014 Only transfers created strictly after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only transfers created strictly before this ISO 8601 timestamp.\n- `destination_id` `string` \u2014 Filter to transfers received by this account.\n- `origin_id` `string` \u2014 Filter to transfers sent from this account.\n\n</details>\n<details>\n<summary>webhooks (3)</summary>\n\nMirrors the filtering query params of `GET /api/v1/webhooks`.\n\n- `app_id` `string` \u2014 Only return webhooks attached to this app. Omit to list the account's own webhooks.\n- `has_failures` `boolean` \u2014 Only return webhooks whose endpoint is currently failing \u2014 every delivery since the current failure streak began has been rejected. Clears as soon as a delivery succeeds.\n- `include_app_webhooks` `boolean` \u2014 Also return webhooks attached to the account's apps, not just the account's own. Cannot be combined with `app_id`.\n\n</details>\n</details>",
|
|
52529
|
+
description: "Resource-specific filters. For native REST resources (`payouts`, `transfers`, `products`) these are the resource's own list query params; for dashboard tables they mirror the dashboard table filters.\n\n<details>\n<summary>Filters by resource (25)</summary>\n\n<details>\n<summary>ad_campaigns (5)</summary>\n\nMirrors the filtering query params of `GET /api/v1/ad_campaigns`.\n\n- `campaign_type` `string` \u2014 Only return campaigns of this type. One of `standard`, `search`.\n- `created_after` `string` \u2014 Only return campaigns created after this timestamp.\n- `created_before` `string` \u2014 Only return campaigns created before this timestamp.\n- `query` `string` \u2014 Filter campaigns by a title or ID substring.\n- `status` `string` \u2014 Only return campaigns with this status. One of `draft`, `active`, `paused`, `payment_failed`.\n\n</details>\n<details>\n<summary>ad_groups (6)</summary>\n\nMirrors the filtering query params of `GET /api/v1/ad_groups`.\n\n- `ad_campaign_id` `string` \u2014 Filter to ad groups in this campaign.\n- `ad_campaign_ids` `string[]` \u2014 Filter to ad groups in these campaigns (max 100). Repeat the parameter for each id (ad_campaign_ids=a&ad_campaign_ids=b).\n- `created_after` `string` \u2014 Only return ad groups created after this timestamp.\n- `created_before` `string` \u2014 Only return ad groups created before this timestamp.\n- `query` `string` \u2014 Filter ad groups by a title or ID substring.\n- `status` `string` \u2014 Filter to ad groups with this status. One of `active`, `paused`, `rejected`, `duplicating`.\n\n</details>\n<details>\n<summary>ads (8)</summary>\n\nMirrors the filtering query params of `GET /api/v1/ads`.\n\n- `ad_campaign_id` `string` \u2014 Only return ads in this ad campaign.\n- `ad_campaign_ids` `string[]` \u2014 Only return ads in these ad campaigns (max 100). Repeat the parameter for each id (ad_campaign_ids=a&ad_campaign_ids=b).\n- `ad_group_id` `string` \u2014 Only return ads in this ad group.\n- `ad_group_ids` `string[]` \u2014 Only return ads in these ad groups (max 100). Repeat the parameter for each id (ad_group_ids=a&ad_group_ids=b).\n- `created_after` `string` \u2014 Only return ads created after this timestamp.\n- `created_before` `string` \u2014 Only return ads created before this timestamp.\n- `query` `string` \u2014 Filter ads by a title or ID substring.\n- `status` `string` \u2014 Only return ads with this status. One of `active`, `paused`, `in_review`, `rejected`.\n\n</details>\n<details>\n<summary>apps (6)</summary>\n\nMirrors the filtering query params of `GET /api/v1/apps`.\n\n- `app_type` `string` \u2014 Filter apps by the type of end-user they are built for. Apps of type `website` are left out unless you ask for them by name. One of `b2b_app`, `b2c_app`, `company_app`, `component`, `website`.\n- `query` `string` \u2014 A search string matched against app names.\n- `recommended` `boolean` \u2014 Only return apps Whop recommends (or, with `false`, only those it does not), independently of verification status.\n- `verified` `boolean` \u2014 Only return apps whose Whop verification status matches this value. Omit this filter to include every verification status the caller can see.\n- `verified_apps_only` `boolean` \u2014 Legacy compatibility filter. Use `verified` for field equality. `true` returns verified apps; clients pinned before `2026-08-25-2` retain the earlier public website discovery behavior.\n- `view_type` `string` \u2014 Only return apps supporting this view type, such as `dashboard` or `hub`. One of `hub`, `discover`, `dash`, `dashboard`, `analytics`, `skills`, `openapi`.\n\n</details>\n<details>\n<summary>audiences (3)</summary>\n\nMirrors the filtering query params of `GET /api/v1/audiences`.\n\n- `audience_id` `string` \u2014 Audience ID, prefixed `adaud_`, used to filter the response to one audience.\n- `audience_type` `string` \u2014 Filter by custom or lookalike audiences. One of `custom`, `lookalike`.\n- `source_type` `string` \u2014 Filter by uploaded customer lists, Whop People filters, or social engagement. One of `csv_upload`, `people_filter`, `engagement`.\n\n</details>\n<details>\n<summary>bounties (8)</summary>\n\nMirrors the filtering query params of `GET /api/v1/bounties`.\n\n- `business_goal_type` `string` \u2014 Filter by the poster's declared goal. Bounties created before the goal taxonomy carry no goal and never match this filter. One of `clipping`, `post_engagement`, `owned_account_growth`, `ugc_content`, `local_activation`, `data_capture`, `other`.\n- `country` `string` \u2014 Only bounties workable from this country, as an ISO 3166-1 alpha-2 code. Bounties with no country targeting are workable worldwide and always match.\n- `created_after` `string` \u2014 Only bounties created after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only bounties created before this ISO 8601 timestamp.\n- `experience_id` `string` \u2014 Only bounties posted to this forum experience, prefixed `exp_`. An unknown experience, or one outside the caller's scope, matches nothing.\n- `query` `string` \u2014 Substring match on the bounty title or ID.\n- `status` `string` \u2014 Filter by lifecycle state. One of `scheduled`, `open`, `closed`, `completed`, `canceled`.\n- `user_id` `string` \u2014 List the bounties this user participated in (`user_` tag). Must be the authenticated user.\n\n</details>\n<details>\n<summary>bounty_submissions (4)</summary>\n\nMirrors the filtering query params of `GET /api/v1/bounty_submissions`.\n\n- `bounty_id` `string` \u2014 Only submissions on this bounty (`bnty_` tag).\n- `created_after` `string` \u2014 Only submissions created after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only submissions created before this ISO 8601 timestamp.\n- `status` `string` \u2014 Filter by lifecycle state. One of `in_progress`, `submitted`, `approved`, `denied`.\n\n</details>\n<details>\n<summary>card_transactions (7)</summary>\n\nMirrors the filtering query params of `GET /api/v1/card_transactions`.\n\n- `card_id` `string[]` \u2014 Return only transactions charged to these cards, each prefixed `icrd_`.\n- `cardholder_id` `string[]` \u2014 Return only transactions on cards assigned to these users, each prefixed `user_`.\n- `created_after` `string` \u2014 Return only transactions authorized at or after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Return only transactions authorized at or before this ISO 8601 timestamp.\n- `status` `string` \u2014 Return only transactions with this status. One of `pending`, `completed`, `reversed`, `declined`.\n- `transaction_ids` `string[]` \u2014 Return only these card transactions, each prefixed `citx_`. Repeat the parameter, or pass one comma-separated value.\n- `user_id` `string` \u2014 The user whose personal card transactions to list, prefixed `user_`. Provide this or `account_id`. Only that user can read them.\n\n</details>\n<details>\n<summary>checkout_configurations (3)</summary>\n\nMirrors the filtering query params of `GET /api/v1/checkout_configurations`.\n\n- `created_after` `string` \u2014 Only return checkout configurations created after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only return checkout configurations created before this ISO 8601 timestamp.\n- `plan_id` `string` \u2014 Only return checkout configurations for this variant ID, prefixed `plan_`.\n\n</details>\n<details>\n<summary>disputes (4)</summary>\n\nMirrors the filtering query params of `GET /api/v1/disputes`.\n\n- `created_after` `string` \u2014 Only disputes opened after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only disputes opened before this ISO 8601 timestamp.\n- `currency` `string` \u2014 Only disputes in this three-letter ISO currency.\n- `status` `string[]` \u2014 Only disputes in these statuses. Repeat the parameter to pass several \u2014 one paginated list covers all of them. Inquiries match only the `warning_` statuses. A `needs_response` dispute whose evidence deadline has passed reports and filters as `under_review` instead.\n\n</details>\n<details>\n<summary>events (14)</summary>\n\nMirrors the filtering query params of `GET /api/v1/events`.\n\n- `attribution_model` `string` \u2014 Attribution model for the source filter (defaults to last_touch). One of `last_touch`, `first_touch`.\n- `browser` `string` \u2014 Browser families to filter by, comma-separated (e.g. Chrome, Mobile Safari).\n- `city` `string` \u2014 Cities to filter by, comma-separated.\n- `country` `string` \u2014 Country codes to filter by, comma-separated.\n- `device` `string` \u2014 Device families to filter by, comma-separated (e.g. iPhone, Mac).\n- `event` `string` \u2014 Full event names to filter by, comma-separated (payment.completed, pixel.lead, pixel.page, pixel.custom:<name>) \u2014 the same vocabulary the events / people metrics use.\n- `from` `string` \u2014 Start of the time range as an ISO 8601 timestamp. Required when identifier is omitted.\n- `hostname` `string` \u2014 Page hostnames to filter by, comma-separated.\n- `identifier` `string` \u2014 Any hard identifier of the person: a person ID (prsn_*), user ID, email, phone number, or a tracking cookie value (wuid, anonymous ID, fbp/fbc/ttp/ga). Omit to list recent events for the account.\n- `os` `string` \u2014 Operating system families to filter by, comma-separated (e.g. iOS, Windows).\n- `page` `string` \u2014 Page paths to filter by, comma-separated.\n- `source` `string` \u2014 Canonical source path, exact or with a trailing :* prefix (whop:<campaign>:*, ext:meta:*, referrer:<domain>, direct, unknown). Selects conversions credited to this source.\n- `to` `string` \u2014 End of the time range as an ISO 8601 timestamp. Required when identifier is omitted; otherwise defaults to now.\n- `utm_source` `string` \u2014 utm_source values to filter by, comma-separated.\n\n</details>\n<details>\n<summary>external_accounts (5)</summary>\n\nMirrors the filtering query params of `GET /api/v1/external_accounts`.\n\n- `platform` `string` \u2014 Only return external accounts for the platform that is specified. One of `x`, `instagram`, `youtube`, `tiktok`, `facebook`, `discord`, `telegram`, `linkedin`, `snapchat`.\n- `scopes` `string[]` \u2014 Only return external accounts that have these scopes.\n- `trust_level` `string` \u2014 Only return external accounts linked with this trust level, such as `oauth` for accounts connected through OAuth. One of `oauth`, `verified`, `authorized`, `claimed`, `scraped`.\n- `user_id` `string` \u2014 The User that the external accounts are connected to. Provide either this or account_id.\n- `verified` `boolean` \u2014 Only return external accounts that are verified on the platform.\n\n</details>\n<details>\n<summary>financial-activity (15)</summary>\n\nMirrors the filtering query params of `GET /api/v1/financial_activity`.\n\n- `activity_id` `string` \u2014 Optional ledger activity ID (for example `line_3`). Returns at most that one activity.\n- `available_after` `string` \u2014 Only include balance credits and debits available on or after this `YYYY-MM-DD` date (UTC), distinct from posted_at. Requires currency.\n- `available_before` `string` \u2014 Only include balance credits and debits available on or before this `YYYY-MM-DD` date (UTC). Set equal to available_after for a single day. Requires currency.\n- `balance_type` `string` \u2014 Which balance the activity changes. `total` includes available, pending, and reserved funds. `available` includes only movements into or out of available funds, including reservations, releases, and fees. Movements within the selected balance are omitted. Omit to preserve the existing activity feed. Requires account_id or user_id; cannot be combined with available_after or available_before. One of `total`, `available`.\n- `currency` `string` \u2014 Optional currency code filter, for example `usd`.\n- `exclude_internal_movements` `boolean` \u2014 Whether to exclude balance reservations and balanced movements between the account's own balances.\n- `include_owned_accounts` `boolean` \u2014 When true, aggregates the authenticated user's personal ledger with the businesses they own (owner role with balance read) into one feed. Requires user_id to be the authenticated user; cannot be combined with account_id or the settlement-date filters. Each returned row includes the owning `account`.\n- `include_resource` `boolean` \u2014 Whether to include the `resource` field in the response or not. Consider passing `false` if you need a fast response without as many rich details.\n- `line_types` `string[]` \u2014 Optional ledger line categories to include. Some categories (for example `onchain_deposit`, which covers inbound crypto deposits such as MoonPay onramps) are only returned when explicitly requested here.\n- `payment_id` `string` \u2014 Filter activity by payment ID (pay_), including related refunds, disputes, and fees. Combines with resource_id and other filters within the selected accounts. Unknown payments return an empty list.\n- `posted_after` `string` \u2014 Only include rows posted after this ISO 8601 timestamp.\n- `posted_before` `string` \u2014 Only include rows posted before this ISO 8601 timestamp.\n- `resource_id` `string` \u2014 Optional prefixed resource ID. Returns activity associated with that resource.\n- `user_id` `string` \u2014 The owning user ID (a user_ identifier). Provide this or account_id.\n- `withdrawal_id` `string` \u2014 Withdrawal ID (wdrl_). With balance_type=available, selects the same period as its statement, after the previous withdrawal and through this withdrawal, excluding this withdrawal and its fee. Requires a single account. Overrides currency and posted-date filters.\n\n</details>\n<details>\n<summary>members (11)</summary>\n\nMirrors the filtering query params of `GET /api/v1/members`.\n\n- `access_level` `string` \u2014 Filter by what the member can reach on the account. One of `no_access`, `admin`, `customer`.\n- `created_after` `string` \u2014 Only members who joined after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only members who joined before this ISO 8601 timestamp.\n- `membership_status` `string` \u2014 `active` returns members holding at least one membership that currently grants access; `inactive` returns members holding at least one membership that does not. Combined with `product_ids`, `plan_ids`, or `promo_code_ids`, one membership must match all of them. One of `active`, `inactive`.\n- `most_recent_actions` `string[]` \u2014 Only return members whose `most_recent_action` is one of these values.\n- `plan_ids` `string[]` \u2014 Only return members holding a membership on one of these plans, prefixed `plan_`. Unknown IDs match nothing.\n- `product_ids` `string[]` \u2014 Only return members holding a membership to one of these products, prefixed `prod_`. Unknown IDs match nothing.\n- `promo_code_ids` `string[]` \u2014 Only return members holding a membership bought with one of these promo codes, prefixed `promo_`. Unknown IDs match nothing.\n- `query` `string` \u2014 Search members by name or username. An exact email address also matches when the credential holds the member:email:read scope.\n- `status` `string` \u2014 Filter by whether the member is still part of the account. One of `joined`, `left`.\n- `user_ids` `string[]` \u2014 Only return members whose users match these `user_` identifiers.\n\n</details>\n<details>\n<summary>memberships (11)</summary>\n\nMirrors the filtering query params of `GET /api/v1/memberships`.\n\n- `created_after` `string` \u2014 Only memberships created after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only memberships created before this ISO 8601 timestamp.\n- `member_id` `string` \u2014 Narrow to one member's memberships (`mber_` tag), including memberships bought by another business. A member outside the caller's visible set returns an empty list.\n- `plan_id` `string` \u2014 Filter to memberships of this variant (`plan_` tag).\n- `plan_ids` `string[]` \u2014 Filter to memberships of any of these variants, each prefixed `plan_`. Repeat the parameter to pass several.\n- `product_id` `string` \u2014 Filter to memberships of this product (`prod_` tag).\n- `product_ids` `string[]` \u2014 Filter to memberships of any of these products, each prefixed `prod_`. Repeat the parameter to pass several.\n- `promo_code_ids` `string[]` \u2014 Filter to memberships discounted by any of these promo codes, each prefixed `promo_`. Repeat the parameter to pass several.\n- `status` `string` \u2014 Filter by billing state. `trialing`, `active`, `past_due`, `completed`, `canceled`, and `expired` match the membership's `status`; `active`, `trialing`, and `past_due` exclude memberships set to cancel at period end. The other values are derived buckets that never appear as a `status`: `canceling` matches memberships set to cancel at period end; `paused` matches memberships with payment collection paused; `expiring` matches one-time purchases that have not yet expired; `one_time` matches one-time purchases that never expire; `unclaimed` matches memberships with no buyer user, including memberships bought by another business; `banned` matches memberships whose buyer is banned from the account. One of `active`, `trialing`, `past_due`, `completed`, `canceled`, `expired`, `canceling`, `paused`, `expiring`, `one_time`, `unclaimed`, `banned`.\n- `statuses` `string[]` \u2014 Filter to memberships matching any of these billing states, with the same meanings as `status`. Repeat the parameter to pass several. Combined with `status` when both are sent.\n- `user_id` `string` \u2014 Narrow to one user's memberships (`user_` tag, or `me` for the caller). A user outside the caller's visible set returns an empty list.\n\n</details>\n<details>\n<summary>payouts (7)</summary>\n\nMirrors the filtering query params of `GET /api/v1/payouts`.\n\n- `created_after` `string` \u2014 Only payouts created at or after this ISO 8601 time (inclusive).\n- `created_before` `string` \u2014 Only payouts created before this ISO 8601 time (exclusive).\n- `currency` `string` \u2014 Optional currency code filter, for example `usd`.\n- `payout_method_id` `string` \u2014 Filter to payouts sent to one saved payout method (a pytk_ identifier). An unknown id matches nothing.\n- `source` `string` \u2014 Filter by how the payout was created. Payouts created before source tracking or through internal tooling carry no source and never match. One of `api`, `dashboard`, `automatic`.\n- `status` `string` \u2014 Filter to payouts whose `status` reads this word, matching exactly what this version displays \u2014 `reversed` finds settled payouts the bank later returned. Requires Api-Version-Date 2026-08-21 or later. One of `requested`, `in_review`, `processing`, `completed`, `reversed`, `canceled`, `failed`, `denied`.\n- `user_id` `string` \u2014 The owning user ID (a user_ identifier). Provide this or account_id.\n\n</details>\n<details>\n<summary>people (39)</summary>\n\nMirrors the filtering query params of `GET /api/v1/people`.\n\n- `aov_gt` `number` \u2014 Select people whose lifetime aov is greater than this value. LTV and AOV are in USD.\n- `aov_gte` `number` \u2014 Select people whose lifetime aov is at least this value. LTV and AOV are in USD.\n- `aov_lt` `number` \u2014 Select people whose lifetime aov is less than this value. LTV and AOV are in USD.\n- `aov_lte` `number` \u2014 Select people whose lifetime aov is at most this value. LTV and AOV are in USD.\n- `attribution_model` `string` \u2014 Attribution model the source filter matches against (defaults to last_touch). One of `last_touch`, `first_touch`.\n- `audience_id` `string` \u2014 Only include people in this audience. An audience that keeps itself up to date resolves to the People filters that define it, so this always reflects who matches now; uploaded lists and point-in-time snapshots match their recorded members.\n- `contactable` `boolean` \u2014 true for people who have an email address or phone number \u2014 the ones an ad platform can match.\n- `country` `string` \u2014 Only include people with activity from this ISO 3166-1 alpha-2 country code.\n- `custom_event` `string` \u2014 Only include people who fired this custom pixel event.\n- `email` `string` \u2014 Only include the person linked to this email address.\n- `event_count_gt` `number` \u2014 Select people whose lifetime event_count is greater than this value. LTV and AOV are in USD.\n- `event_count_gte` `number` \u2014 Select people whose lifetime event_count is at least this value. LTV and AOV are in USD.\n- `event_count_lt` `number` \u2014 Select people whose lifetime event_count is less than this value. LTV and AOV are in USD.\n- `event_count_lte` `number` \u2014 Select people whose lifetime event_count is at most this value. LTV and AOV are in USD.\n- `event_from` `string` \u2014 The inclusive start of the matching activity window.\n- `event_name` `string[]` \u2014 Only include people who fired any of these events, e.g. payment.completed or page.checkout.view.\n- `event_to` `string` \u2014 The inclusive end of the matching activity window, for both stats drilldowns and saved audiences.\n- `event_within_days` `integer` \u2014 Match activity within a rolling number of days. Cannot be combined with event_from/event_to.\n- `first_seen_after` `string` \u2014 Only include people first seen at or after this ISO 8601 timestamp.\n- `first_seen_before` `string` \u2014 Only include people first seen before this ISO 8601 timestamp.\n- `first_seen_within_days` `integer` \u2014 Only include people first seen within this many days, as a rolling window.\n- `from` `string` \u2014 Inclusive activity-window start. Alias for event_from.\n- `has_purchased` `boolean` \u2014 true for customers only, false for people who have never purchased.\n- `last_seen_after` `string` \u2014 Only include people last seen at or after this ISO 8601 timestamp.\n- `last_seen_before` `string` \u2014 Only include people last seen before this ISO 8601 timestamp.\n- `last_seen_within_days` `integer` \u2014 Only include people last seen within this many days, as a rolling window.\n- `ltv_gt` `number` \u2014 Select people whose lifetime ltv is greater than this value. LTV and AOV are in USD.\n- `ltv_gte` `number` \u2014 Select people whose lifetime ltv is at least this value. LTV and AOV are in USD.\n- `ltv_lt` `number` \u2014 Select people whose lifetime ltv is less than this value. LTV and AOV are in USD.\n- `ltv_lte` `number` \u2014 Select people whose lifetime ltv is at most this value. LTV and AOV are in USD.\n- `phone` `string` \u2014 Only include the person linked to this phone number.\n- `purchase_count_gt` `number` \u2014 Select people whose lifetime purchase_count is greater than this value. LTV and AOV are in USD.\n- `purchase_count_gte` `number` \u2014 Select people whose lifetime purchase_count is at least this value. LTV and AOV are in USD.\n- `purchase_count_lt` `number` \u2014 Select people whose lifetime purchase_count is less than this value. LTV and AOV are in USD.\n- `purchase_count_lte` `number` \u2014 Select people whose lifetime purchase_count is at most this value. LTV and AOV are in USD.\n- `query` `string` \u2014 Search people by name, email, phone, or whop user ID (case-insensitive substring match).\n- `source` `string[]` \u2014 Only include people acquired from any of these sources \u2014 canonical paths (whop:<campaign>:<group>:<ad>, ext:<platform>:..., referrer:<domain>, direct, other), exact or with a trailing :* prefix. The same vocabulary the events / people metrics use.\n- `to` `string` \u2014 Inclusive activity-window end. Alias for event_to.\n- `user_id` `string` \u2014 Only include the person linked to this whop user ID.\n\n</details>\n<details>\n<summary>products (10)</summary>\n\nMirrors the filtering query params of `GET /api/v1/products`.\n\n- `access_pass_types` `string[]` \u2014 Filter to only products matching these types.\n- `created_after` `string` \u2014 Only return products created after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only return products created before this ISO 8601 timestamp.\n- `labels` `string[]` \u2014 Filter to only products carrying all of these labels. Labels are matched lowercased.\n- `marketplace_category_route` `string` \u2014 Only return marketplace products assigned to this category route, such as `trading`.\n- `plan_types` `string[]` \u2014 Filter to products with a buyable variant of these billing models, such as `one_time` or `renewal`.\n- `price_maximum` `number` \u2014 Only return products whose advertised buyable variant has a displayed price of at most this amount. Recurring variants use renewal price.\n- `price_minimum` `number` \u2014 Only return products whose advertised buyable variant has a displayed price of at least this amount. Recurring variants use renewal price.\n- `query` `string` \u2014 Filters products by text. The public marketplace list searches product title, account name, headline and description, ranking products that match every word first and the closest partial matches after them; an account's own list is a plain substring match over title, headline and description. Omit to browse by recency.\n- `visibilities` `string[]` \u2014 Filter to only products matching these visibility states. Ignored on the public marketplace list, which only returns visible products.\n\n</details>\n<details>\n<summary>promo_codes (5)</summary>\n\nMirrors the filtering query params of `GET /api/v1/promo_codes`.\n\n- `created_after` `string` \u2014 Only promo codes created after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only promo codes created before this ISO 8601 timestamp.\n- `plan_ids` `string[]` \u2014 Only promo codes scoped to these variant IDs.\n- `product_ids` `string[]` \u2014 Only promo codes scoped to these product IDs.\n- `status` `string` \u2014 Promo-code status. `expired` groups inactive and archived codes. One of `active`, `inactive`, `archived`, `expired`.\n\n</details>\n<details>\n<summary>resolution_center_cases (6)</summary>\n\nMirrors the filtering query params of `GET /api/v1/resolution_center_cases`.\n\n- `created_after` `string` \u2014 Only cases created after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only cases created before this ISO 8601 timestamp.\n- `outcome` `string[]` \u2014 Only closed cases that ended these ways. Repeat the parameter to pass several.\n- `reason` `string[]` \u2014 Only cases opened for these reasons. Repeat the parameter to pass several.\n- `status` `string[]` \u2014 Only cases in these statuses. Repeat the parameter to pass several \u2014 one paginated list covers all of them.\n- `user_id` `string` \u2014 Only cases opened by this customer \u2014 a `user_` tag, or `me` for the calling user. It narrows what you can already read, so `me` lists the cases you opened without the ones on accounts you are a team member of.\n\n</details>\n<details>\n<summary>shipments (4)</summary>\n\nMirrors the filtering query params of `GET /api/v1/shipments`.\n\n- `created_after` `string` \u2014 Return shipments created after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Return shipments created before this ISO 8601 timestamp.\n- `payment_id` `string[]` \u2014 Only shipments fulfilling these payments, each prefixed `pay_`. Repeat the parameter to pass several, up to 100 per request \u2014 one paginated list covers all of them.\n- `status` `string` \u2014 Filter to shipments with this delivery status. One of `unknown`, `pre_transit`, `in_transit`, `out_for_delivery`, `delivered`, `available_for_pickup`, `return_to_sender`, `failure`, `cancelled`, `error`.\n\n</details>\n<details>\n<summary>social_accounts (5)</summary>\n\nMirrors the filtering query params of `GET /api/v1/social_accounts`.\n\n- `platform` `string` \u2014 Only return external accounts for the platform that is specified. One of `x`, `instagram`, `youtube`, `tiktok`, `facebook`, `discord`, `telegram`, `linkedin`, `snapchat`.\n- `scopes` `string[]` \u2014 Only return external accounts that have these scopes.\n- `trust_level` `string` \u2014 Only return external accounts linked with this trust level, such as `oauth` for accounts connected through OAuth. One of `oauth`, `verified`, `authorized`, `claimed`, `scraped`.\n- `user_id` `string` \u2014 The User that the external accounts are connected to. Provide either this or account_id.\n- `verified` `boolean` \u2014 Only return external accounts that are verified on the platform.\n\n</details>\n<details>\n<summary>team_members (9)</summary>\n\nMirrors the filtering query params of `GET /api/v1/team_members`.\n\n- `created_after` `string` \u2014 Only return members added after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only return members added before this ISO 8601 timestamp.\n- `direct_reports_max` `integer` \u2014 Only return members with at most this many direct reports; `0` returns the people who manage no one. Pending invites are excluded, and the list pages in `created_at` order without moving Partner-role members last.\n- `direct_reports_min` `integer` \u2014 Only return members with at least this many direct reports. Pending invites are excluded, and the list pages in `created_at` order without moving Partner-role members last.\n- `query` `string` \u2014 Only return members whose name or username contains this text, and invites whose email contains it.\n- `reports_to_id` `string` \u2014 Only return the direct reports of this team member, prefixed `ausr_`. Pass the account ID, prefixed `biz_`, for the members who report to the business directly. Pending invites are excluded, and the list pages in `created_at` order without moving Partner-role members last.\n- `role` `string` \u2014 Only return members with this role. `custom` matches members on a dashboard-managed custom role. One of `owner`, `admin`, `partner`, `sales_manager`, `moderator`, `advertiser`, `app_manager`, `support`, `manager`, `workforce`, `custom`.\n- `status` `string` \u2014 Only return members with this status: `joined` (accepted members) or `pending` (pending invites). Both are returned by default. One of `joined`, `pending`.\n- `user_id` `string` \u2014 Only return the membership for this user ID, prefixed `user_`.\n\n</details>\n<details>\n<summary>transfers (4)</summary>\n\nMirrors the filtering query params of `GET /api/v1/transfers`.\n\n- `created_after` `string` \u2014 Only transfers created strictly after this ISO 8601 timestamp.\n- `created_before` `string` \u2014 Only transfers created strictly before this ISO 8601 timestamp.\n- `destination_id` `string` \u2014 Filter to transfers received by this account.\n- `origin_id` `string` \u2014 Filter to transfers sent from this account.\n\n</details>\n<details>\n<summary>webhooks (3)</summary>\n\nMirrors the filtering query params of `GET /api/v1/webhooks`.\n\n- `app_id` `string` \u2014 Only return webhooks attached to this app. Omit to list the account's own webhooks.\n- `has_failures` `boolean` \u2014 Only return webhooks whose endpoint is currently failing \u2014 every delivery since the current failure streak began has been rejected. Clears as soon as a delivery succeeds.\n- `include_app_webhooks` `boolean` \u2014 Also return webhooks attached to the account's apps, not just the account's own. Cannot be combined with `app_id`.\n\n</details>\n</details>",
|
|
52503
52530
|
example: {
|
|
52504
52531
|
include_resource: false,
|
|
52505
52532
|
posted_after: "2026-01-01T12:00:00.000Z",
|
|
@@ -53175,12 +53202,13 @@ var native_spec_default = {
|
|
|
53175
53202
|
type: "string"
|
|
53176
53203
|
},
|
|
53177
53204
|
platform: {
|
|
53178
|
-
description: "The platform to connect the external account on. Use `meta_business` to connect Meta Business assets, which is how Facebook Pages and Instagram accounts are connected \u2014 there is no separate `instagram` value. Use `tiktok` for TikTok accounts, `snapchat` for Snapchat Public Profiles, `linkedin` to connect the authenticated user\u2019s LinkedIn profile,
|
|
53205
|
+
description: "The platform to connect the external account on. Use `meta_business` to connect Meta Business assets, which is how Facebook Pages and Instagram accounts are connected \u2014 there is no separate `instagram` value. Use `tiktok` for TikTok accounts, `snapchat` for Snapchat Public Profiles, `linkedin` to connect the authenticated user\u2019s LinkedIn profile, `youtube` to connect their YouTube channel, or `x` to connect their X profile.",
|
|
53179
53206
|
enum: [
|
|
53180
53207
|
"meta_business",
|
|
53181
53208
|
"tiktok",
|
|
53182
53209
|
"linkedin",
|
|
53183
53210
|
"youtube",
|
|
53211
|
+
"x",
|
|
53184
53212
|
"snapchat"
|
|
53185
53213
|
],
|
|
53186
53214
|
example: "meta_business",
|
|
@@ -53192,7 +53220,7 @@ var native_spec_default = {
|
|
|
53192
53220
|
type: "string"
|
|
53193
53221
|
},
|
|
53194
53222
|
scopes: {
|
|
53195
|
-
description: "The connection purpose. For `meta_business` and `snapchat`, `advertise` is required and connects company advertising assets. For `linkedin` and `
|
|
53223
|
+
description: "The connection purpose. For `meta_business` and `snapchat`, `advertise` is required and connects company advertising assets. For `linkedin`, `youtube`, and `x`, omit scopes to connect the authenticated user\u2019s profile; advertising is not supported. For `tiktok`, omit scopes to connect the authenticated user\u2019s profile, or pass `advertise` to connect company advertising assets. Profile connections still request the platform permissions needed to read the profile.",
|
|
53196
53224
|
items: {
|
|
53197
53225
|
enum: ["advertise"],
|
|
53198
53226
|
example: "advertise",
|
|
@@ -54478,6 +54506,8 @@ var native_spec_default = {
|
|
|
54478
54506
|
"misc_reversal",
|
|
54479
54507
|
"onboarding_reward",
|
|
54480
54508
|
"onchain_deposit",
|
|
54509
|
+
"onchain_internal_transfer_incoming",
|
|
54510
|
+
"onchain_internal_transfer_outgoing",
|
|
54481
54511
|
"onchain_swap_source",
|
|
54482
54512
|
"onchain_swap_target",
|
|
54483
54513
|
"onchain_wallet_transfer_incoming",
|
|
@@ -54936,6 +54966,8 @@ var native_spec_default = {
|
|
|
54936
54966
|
"misc_reversal",
|
|
54937
54967
|
"onboarding_reward",
|
|
54938
54968
|
"onchain_deposit",
|
|
54969
|
+
"onchain_internal_transfer_incoming",
|
|
54970
|
+
"onchain_internal_transfer_outgoing",
|
|
54939
54971
|
"onchain_swap_source",
|
|
54940
54972
|
"onchain_swap_target",
|
|
54941
54973
|
"onchain_wallet_transfer_incoming",
|
|
@@ -55322,6 +55354,8 @@ var native_spec_default = {
|
|
|
55322
55354
|
"onboarding_reward",
|
|
55323
55355
|
"onchain_deposit",
|
|
55324
55356
|
"onchain_deposit_offset",
|
|
55357
|
+
"onchain_internal_transfer_incoming",
|
|
55358
|
+
"onchain_internal_transfer_outgoing",
|
|
55325
55359
|
"onchain_swap_offset",
|
|
55326
55360
|
"onchain_swap_source",
|
|
55327
55361
|
"onchain_swap_target",
|
|
@@ -60085,7 +60119,7 @@ var native_spec_default = {
|
|
|
60085
60119
|
},
|
|
60086
60120
|
"/partners/businesses/{id}": {
|
|
60087
60121
|
get: {
|
|
60088
|
-
description: "Retrieves a single referred business and its referral terms.",
|
|
60122
|
+
description: "Retrieves a single referred business and its referral terms. The original referrer or a caller with company:basic:read on the business credited for the referral can read it.",
|
|
60089
60123
|
operationId: "get",
|
|
60090
60124
|
parameters: [
|
|
60091
60125
|
{
|
|
@@ -60502,12 +60536,18 @@ var native_spec_default = {
|
|
|
60502
60536
|
},
|
|
60503
60537
|
security: [
|
|
60504
60538
|
{
|
|
60505
|
-
|
|
60539
|
+
accountApiKeyOrOauthTokenAuth: ["partner:basic:read"]
|
|
60540
|
+
},
|
|
60541
|
+
{
|
|
60542
|
+
accountApiKeyOrOauthTokenAuth: ["referral:basic:read"]
|
|
60543
|
+
},
|
|
60544
|
+
{
|
|
60545
|
+
accountApiKeyOrOauthTokenAuth: ["company:basic:read"]
|
|
60506
60546
|
}
|
|
60507
60547
|
],
|
|
60508
60548
|
summary: "Retrieve a referred business",
|
|
60509
60549
|
tags: ["Partners"],
|
|
60510
|
-
"x-whop-credentials": ["oauth_token"],
|
|
60550
|
+
"x-whop-credentials": ["account_api_key", "oauth_token"],
|
|
60511
60551
|
"x-codeSamples": [
|
|
60512
60552
|
{
|
|
60513
60553
|
lang: "TypeScript",
|
|
@@ -60705,7 +60745,7 @@ var native_spec_default = {
|
|
|
60705
60745
|
},
|
|
60706
60746
|
"/partners/businesses/{id}/earnings": {
|
|
60707
60747
|
get: {
|
|
60708
|
-
description: "Lists the earnings Whop pays out for one referred business's activity, most recent first.",
|
|
60748
|
+
description: "Lists the earnings Whop pays out for one referred business's activity, most recent first. The original referrer or a caller with company:basic:read on the business credited for the referral can read them.",
|
|
60709
60749
|
operationId: "earnings",
|
|
60710
60750
|
parameters: [
|
|
60711
60751
|
{
|
|
@@ -61329,12 +61369,18 @@ var native_spec_default = {
|
|
|
61329
61369
|
},
|
|
61330
61370
|
security: [
|
|
61331
61371
|
{
|
|
61332
|
-
|
|
61372
|
+
accountApiKeyOrOauthTokenAuth: ["partner:basic:read"]
|
|
61373
|
+
},
|
|
61374
|
+
{
|
|
61375
|
+
accountApiKeyOrOauthTokenAuth: ["referral:basic:read"]
|
|
61376
|
+
},
|
|
61377
|
+
{
|
|
61378
|
+
accountApiKeyOrOauthTokenAuth: ["company:basic:read"]
|
|
61333
61379
|
}
|
|
61334
61380
|
],
|
|
61335
61381
|
summary: "List referred business earnings",
|
|
61336
61382
|
tags: ["Partners"],
|
|
61337
|
-
"x-whop-credentials": ["oauth_token"],
|
|
61383
|
+
"x-whop-credentials": ["account_api_key", "oauth_token"],
|
|
61338
61384
|
"x-codeSamples": [
|
|
61339
61385
|
{
|
|
61340
61386
|
lang: "TypeScript",
|
|
@@ -62632,7 +62678,8 @@ var native_spec_default = {
|
|
|
62632
62678
|
},
|
|
62633
62679
|
"/payment_method_domains": {
|
|
62634
62680
|
get: {
|
|
62635
|
-
|
|
62681
|
+
deprecated: true,
|
|
62682
|
+
description: "Lists the payment method domains registered for your account and its connected accounts. Deprecated: list domains with `GET /domains` and the `apple_pay` filter instead.",
|
|
62636
62683
|
operationId: "list",
|
|
62637
62684
|
parameters: [
|
|
62638
62685
|
{
|
|
@@ -62829,6 +62876,8 @@ var native_spec_default = {
|
|
|
62829
62876
|
],
|
|
62830
62877
|
summary: "List Payment Method Domains",
|
|
62831
62878
|
tags: ["Payment Method Domains"],
|
|
62879
|
+
"x-whop-deprecated-since": "2026-10-14",
|
|
62880
|
+
"x-whop-successor": "GET /domains",
|
|
62832
62881
|
"x-mint": {
|
|
62833
62882
|
metadata: {
|
|
62834
62883
|
sidebarTitle: "List"
|
|
@@ -62842,7 +62891,8 @@ var native_spec_default = {
|
|
|
62842
62891
|
]
|
|
62843
62892
|
},
|
|
62844
62893
|
post: {
|
|
62845
|
-
|
|
62894
|
+
deprecated: true,
|
|
62895
|
+
description: "Registers a hostname with the wallet provider and attempts verification inline. Returns `verified` when the provider fetched the domain-association file (for Apple Pay, `/.well-known/apple-developer-merchantid-domain-association`), or `pending` when it could not: host the file, then retry with `POST /payment_method_domains/:id/verify`. Deprecated: add Apple Pay with `POST /domains` and `apple_pay: {}` instead.",
|
|
62846
62896
|
operationId: "create",
|
|
62847
62897
|
parameters: [
|
|
62848
62898
|
{
|
|
@@ -62912,6 +62962,8 @@ var native_spec_default = {
|
|
|
62912
62962
|
],
|
|
62913
62963
|
summary: "Create Payment Method Domain",
|
|
62914
62964
|
tags: ["Payment Method Domains"],
|
|
62965
|
+
"x-whop-deprecated-since": "2026-10-14",
|
|
62966
|
+
"x-whop-successor": "POST /domains",
|
|
62915
62967
|
"x-mint": {
|
|
62916
62968
|
metadata: {
|
|
62917
62969
|
sidebarTitle: "Create"
|
|
@@ -62927,7 +62979,8 @@ var native_spec_default = {
|
|
|
62927
62979
|
},
|
|
62928
62980
|
"/payment_method_domains/{id}": {
|
|
62929
62981
|
delete: {
|
|
62930
|
-
|
|
62982
|
+
deprecated: true,
|
|
62983
|
+
description: "Unregisters a payment method domain so its wallet payment methods stop rendering there. Deprecated: remove Apple Pay with `PATCH /domains/{id}` and `apple_pay: null` instead. `DELETE /domains/{id}` removes the whole domain, including any website on it.",
|
|
62931
62984
|
operationId: "delete",
|
|
62932
62985
|
responses: {
|
|
62933
62986
|
"200": {
|
|
@@ -62971,6 +63024,8 @@ var native_spec_default = {
|
|
|
62971
63024
|
],
|
|
62972
63025
|
summary: "Delete Payment Method Domain",
|
|
62973
63026
|
tags: ["Payment Method Domains"],
|
|
63027
|
+
"x-whop-deprecated-since": "2026-10-14",
|
|
63028
|
+
"x-whop-successor": "PATCH /domains/{id}",
|
|
62974
63029
|
"x-mint": {
|
|
62975
63030
|
metadata: {
|
|
62976
63031
|
sidebarTitle: "Delete"
|
|
@@ -62998,7 +63053,8 @@ var native_spec_default = {
|
|
|
62998
63053
|
]
|
|
62999
63054
|
},
|
|
63000
63055
|
get: {
|
|
63001
|
-
|
|
63056
|
+
deprecated: true,
|
|
63057
|
+
description: "Retrieves a payment method domain to check its verification status. Deprecated: retrieve the domain with `GET /domains/{id}` instead, using the same ID.",
|
|
63002
63058
|
operationId: "get",
|
|
63003
63059
|
responses: {
|
|
63004
63060
|
"200": {
|
|
@@ -63031,6 +63087,8 @@ var native_spec_default = {
|
|
|
63031
63087
|
],
|
|
63032
63088
|
summary: "Retrieve Payment Method Domain",
|
|
63033
63089
|
tags: ["Payment Method Domains"],
|
|
63090
|
+
"x-whop-deprecated-since": "2026-10-14",
|
|
63091
|
+
"x-whop-successor": "GET /domains/{id}",
|
|
63034
63092
|
"x-mint": {
|
|
63035
63093
|
metadata: {
|
|
63036
63094
|
sidebarTitle: "Retrieve"
|
|
@@ -63060,7 +63118,8 @@ var native_spec_default = {
|
|
|
63060
63118
|
},
|
|
63061
63119
|
"/payment_method_domains/{id}/verify": {
|
|
63062
63120
|
post: {
|
|
63063
|
-
|
|
63121
|
+
deprecated: true,
|
|
63122
|
+
description: "Re-attempts provider verification of a pending domain once the association file is hosted. Fails with a `bad_request` explaining what to fix; verifying an already `verified` domain is a no-op. Deprecated: check the domain with `POST /domains/{id}/check` instead.",
|
|
63064
63123
|
operationId: "verify",
|
|
63065
63124
|
parameters: [
|
|
63066
63125
|
{
|
|
@@ -63117,6 +63176,8 @@ var native_spec_default = {
|
|
|
63117
63176
|
],
|
|
63118
63177
|
summary: "Verify Payment Method Domain",
|
|
63119
63178
|
tags: ["Payment Method Domains"],
|
|
63179
|
+
"x-whop-deprecated-since": "2026-10-14",
|
|
63180
|
+
"x-whop-successor": "POST /domains/{id}/check",
|
|
63120
63181
|
"x-codeSamples": [
|
|
63121
63182
|
{
|
|
63122
63183
|
lang: "TypeScript",
|
|
@@ -75675,6 +75736,11 @@ var native_spec_default = {
|
|
|
75675
75736
|
},
|
|
75676
75737
|
type: ["object", "null"]
|
|
75677
75738
|
},
|
|
75739
|
+
owner_id: {
|
|
75740
|
+
description: "Who the saved payment method belongs to. Pass `account_id` to save it on the account itself, which needs `payment:charge` on the account. Pass your own user ID, prefixed `user_`, to save it on the authenticated user. Omit it to save it on the buyer: the caller when it is the buyer, otherwise the user the confirmation token names. Not available with `payment_method_id`, which keeps its current owner, or with `purpose`.",
|
|
75741
|
+
example: "biz_xxxxxxxxxxxxxx",
|
|
75742
|
+
type: ["string", "null"]
|
|
75743
|
+
},
|
|
75678
75744
|
payment_method_id: {
|
|
75679
75745
|
description: "An existing payment method to re-verify and save, prefixed `payt_`. Provide this or `confirmation_token`, not both. Not available to a buyer credential.",
|
|
75680
75746
|
example: "payt_xxxxxxxxxxxxxx",
|
|
@@ -76711,12 +76777,13 @@ var native_spec_default = {
|
|
|
76711
76777
|
type: "string"
|
|
76712
76778
|
},
|
|
76713
76779
|
platform: {
|
|
76714
|
-
description: "The platform to connect the external account on. Use `meta_business` to connect Meta Business assets, which is how Facebook Pages and Instagram accounts are connected \u2014 there is no separate `instagram` value. Use `tiktok` for TikTok accounts, `snapchat` for Snapchat Public Profiles, `linkedin` to connect the authenticated user\u2019s LinkedIn profile,
|
|
76780
|
+
description: "The platform to connect the external account on. Use `meta_business` to connect Meta Business assets, which is how Facebook Pages and Instagram accounts are connected \u2014 there is no separate `instagram` value. Use `tiktok` for TikTok accounts, `snapchat` for Snapchat Public Profiles, `linkedin` to connect the authenticated user\u2019s LinkedIn profile, `youtube` to connect their YouTube channel, or `x` to connect their X profile.",
|
|
76715
76781
|
enum: [
|
|
76716
76782
|
"meta_business",
|
|
76717
76783
|
"tiktok",
|
|
76718
76784
|
"linkedin",
|
|
76719
76785
|
"youtube",
|
|
76786
|
+
"x",
|
|
76720
76787
|
"snapchat"
|
|
76721
76788
|
],
|
|
76722
76789
|
example: "meta_business",
|
|
@@ -76728,7 +76795,7 @@ var native_spec_default = {
|
|
|
76728
76795
|
type: "string"
|
|
76729
76796
|
},
|
|
76730
76797
|
scopes: {
|
|
76731
|
-
description: "The connection purpose. For `meta_business` and `snapchat`, `advertise` is required and connects company advertising assets. For `linkedin` and `
|
|
76798
|
+
description: "The connection purpose. For `meta_business` and `snapchat`, `advertise` is required and connects company advertising assets. For `linkedin`, `youtube`, and `x`, omit scopes to connect the authenticated user\u2019s profile; advertising is not supported. For `tiktok`, omit scopes to connect the authenticated user\u2019s profile, or pass `advertise` to connect company advertising assets. Profile connections still request the platform permissions needed to read the profile.",
|
|
76732
76799
|
items: {
|
|
76733
76800
|
enum: ["advertise"],
|
|
76734
76801
|
example: "advertise",
|
|
@@ -79786,7 +79853,7 @@ var native_spec_default = {
|
|
|
79786
79853
|
},
|
|
79787
79854
|
"/team_members": {
|
|
79788
79855
|
get: {
|
|
79789
|
-
description: "Lists an account's team members, including pending invites. A user credential with `company:basic:read` may list only its own joined membership by passing its own `user_id` and `status=joined`. Listing `role=workforce` is also allowed with the `bounty:create` scope.",
|
|
79856
|
+
description: "Lists an account's team members, including pending invites. A user credential with `company:basic:read` may list only its own joined membership by passing its own `user_id` and `status=joined`. Listing `role=workforce` is also allowed with the `bounty:create` scope. Members with the view-only Partner role are listed after all other members.",
|
|
79790
79857
|
operationId: "list",
|
|
79791
79858
|
parameters: [
|
|
79792
79859
|
{
|
|
@@ -79842,6 +79909,44 @@ var native_spec_default = {
|
|
|
79842
79909
|
type: "string"
|
|
79843
79910
|
}
|
|
79844
79911
|
},
|
|
79912
|
+
{
|
|
79913
|
+
description: "Only return members whose name or username contains this text, and invites whose email contains it.",
|
|
79914
|
+
in: "query",
|
|
79915
|
+
name: "query",
|
|
79916
|
+
required: false,
|
|
79917
|
+
schema: {
|
|
79918
|
+
type: "string"
|
|
79919
|
+
}
|
|
79920
|
+
},
|
|
79921
|
+
{
|
|
79922
|
+
description: "Only return the direct reports of this team member, prefixed `ausr_`. Pass the account ID, prefixed `biz_`, for the members who report to the business directly. Pending invites are excluded, and the list pages in `created_at` order without moving Partner-role members last.",
|
|
79923
|
+
in: "query",
|
|
79924
|
+
name: "reports_to_id",
|
|
79925
|
+
required: false,
|
|
79926
|
+
schema: {
|
|
79927
|
+
type: "string"
|
|
79928
|
+
}
|
|
79929
|
+
},
|
|
79930
|
+
{
|
|
79931
|
+
description: "Only return members with at least this many direct reports. Pending invites are excluded, and the list pages in `created_at` order without moving Partner-role members last.",
|
|
79932
|
+
in: "query",
|
|
79933
|
+
name: "direct_reports_min",
|
|
79934
|
+
required: false,
|
|
79935
|
+
schema: {
|
|
79936
|
+
minimum: 0,
|
|
79937
|
+
type: "integer"
|
|
79938
|
+
}
|
|
79939
|
+
},
|
|
79940
|
+
{
|
|
79941
|
+
description: "Only return members with at most this many direct reports; `0` returns the people who manage no one. Pending invites are excluded, and the list pages in `created_at` order without moving Partner-role members last.",
|
|
79942
|
+
in: "query",
|
|
79943
|
+
name: "direct_reports_max",
|
|
79944
|
+
required: false,
|
|
79945
|
+
schema: {
|
|
79946
|
+
minimum: 0,
|
|
79947
|
+
type: "integer"
|
|
79948
|
+
}
|
|
79949
|
+
},
|
|
79845
79950
|
{
|
|
79846
79951
|
description: "Only return members added before this ISO 8601 timestamp.",
|
|
79847
79952
|
in: "query",
|
|
@@ -79861,7 +79966,7 @@ var native_spec_default = {
|
|
|
79861
79966
|
}
|
|
79862
79967
|
},
|
|
79863
79968
|
{
|
|
79864
|
-
description: "Field used to sort members.",
|
|
79969
|
+
description: "Field used to sort members. Members with the view-only Partner role are listed after all other members whichever way the list is sorted.",
|
|
79865
79970
|
in: "query",
|
|
79866
79971
|
name: "order",
|
|
79867
79972
|
required: false,
|
|
@@ -80555,7 +80660,7 @@ var native_spec_default = {
|
|
|
80555
80660
|
type: "string"
|
|
80556
80661
|
},
|
|
80557
80662
|
instrument_type: {
|
|
80558
|
-
description: "`perpetual` or `spot`. Required for an order.
|
|
80663
|
+
description: "`perpetual` or `spot`. Required for an order. A spot order first switches the trading account to Hyperliquid's unified account mode, where spot and perpetuals share one USDC balance.",
|
|
80559
80664
|
enum: ["perpetual", "spot"],
|
|
80560
80665
|
example: "perpetual",
|
|
80561
80666
|
type: "string"
|
|
@@ -83819,6 +83924,63 @@ var native_spec_default = {
|
|
|
83819
83924
|
]
|
|
83820
83925
|
}
|
|
83821
83926
|
},
|
|
83927
|
+
"/users/{user_id}/fees": {
|
|
83928
|
+
get: {
|
|
83929
|
+
description: "Retrieves the fees charged when the user moves money with their personal balance: withdrawals, transfers, bank deposits, and funding cards from pending balance. Each fee has the same shape as in Retrieve Account Fees. You can only retrieve your own fees, and they are read-only.",
|
|
83930
|
+
operationId: "fees",
|
|
83931
|
+
responses: {
|
|
83932
|
+
"200": {
|
|
83933
|
+
content: {
|
|
83934
|
+
"application/json": {
|
|
83935
|
+
schema: {
|
|
83936
|
+
$ref: "#/components/schemas/UserFees"
|
|
83937
|
+
}
|
|
83938
|
+
}
|
|
83939
|
+
},
|
|
83940
|
+
description: "fees retrieved"
|
|
83941
|
+
},
|
|
83942
|
+
"401": {
|
|
83943
|
+
$ref: "#/components/responses/Unauthorized",
|
|
83944
|
+
description: "unauthorized"
|
|
83945
|
+
},
|
|
83946
|
+
"403": {
|
|
83947
|
+
$ref: "#/components/responses/Forbidden",
|
|
83948
|
+
description: "another user's fees"
|
|
83949
|
+
},
|
|
83950
|
+
"404": {
|
|
83951
|
+
$ref: "#/components/responses/NotFound",
|
|
83952
|
+
description: "user not found"
|
|
83953
|
+
}
|
|
83954
|
+
},
|
|
83955
|
+
security: [
|
|
83956
|
+
{
|
|
83957
|
+
oauthTokenAuth: ["user:balance:read"]
|
|
83958
|
+
}
|
|
83959
|
+
],
|
|
83960
|
+
summary: "Retrieve User Fees",
|
|
83961
|
+
tags: ["Users"],
|
|
83962
|
+
"x-whop-credentials": ["oauth_token"],
|
|
83963
|
+
"x-mint": {
|
|
83964
|
+
metadata: {
|
|
83965
|
+
sidebarTitle: "Retrieve Fees"
|
|
83966
|
+
}
|
|
83967
|
+
},
|
|
83968
|
+
parameters: [
|
|
83969
|
+
{
|
|
83970
|
+
description: "`me`, or the authenticated user's own `user_` tag or username.",
|
|
83971
|
+
in: "path",
|
|
83972
|
+
name: "user_id",
|
|
83973
|
+
required: true,
|
|
83974
|
+
schema: {
|
|
83975
|
+
type: "string"
|
|
83976
|
+
}
|
|
83977
|
+
},
|
|
83978
|
+
{
|
|
83979
|
+
$ref: "#/components/parameters/ApiVersionDate"
|
|
83980
|
+
}
|
|
83981
|
+
]
|
|
83982
|
+
}
|
|
83983
|
+
},
|
|
83822
83984
|
"/variants": {
|
|
83823
83985
|
get: {
|
|
83824
83986
|
description: "Lists an account's variants. To list a product's public, buyable variants without authentication, omit `account_id` and pass `product_ids`.",
|
|
@@ -88034,7 +88196,7 @@ var native_spec_default = {
|
|
|
88034
88196
|
properties: {
|
|
88035
88197
|
api_version_date: {
|
|
88036
88198
|
description: "The dated API version (Api-Version-Date) to pin this webhook's payloads to. Omit to leave the webhook unpinned, tracking the current payload shape.",
|
|
88037
|
-
example: "2026-
|
|
88199
|
+
example: "2026-01-01",
|
|
88038
88200
|
type: ["string", "null"]
|
|
88039
88201
|
},
|
|
88040
88202
|
child_resource_events: {
|
|
@@ -88121,10 +88283,13 @@ var native_spec_default = {
|
|
|
88121
88283
|
"shipment.updated",
|
|
88122
88284
|
"member.created",
|
|
88123
88285
|
"member.updated",
|
|
88286
|
+
"ad_campaign.created",
|
|
88124
88287
|
"ad_campaign.payment_failed",
|
|
88125
88288
|
"ad_campaign.updated",
|
|
88126
88289
|
"ad_campaign.events",
|
|
88290
|
+
"ad_group.created",
|
|
88127
88291
|
"ad_group.updated",
|
|
88292
|
+
"ad.created",
|
|
88128
88293
|
"ad.updated",
|
|
88129
88294
|
"chat.message.created",
|
|
88130
88295
|
"chat.reaction.created",
|
|
@@ -88396,7 +88561,7 @@ var native_spec_default = {
|
|
|
88396
88561
|
properties: {
|
|
88397
88562
|
api_version_date: {
|
|
88398
88563
|
description: "The dated API version (Api-Version-Date) to pin this webhook's payloads to. Only valid for `v1` webhooks. Omit to leave the current pin unchanged, or pass `null` to unpin and track the current payload shape.",
|
|
88399
|
-
example: "2026-
|
|
88564
|
+
example: "2026-01-01",
|
|
88400
88565
|
type: ["string", "null"]
|
|
88401
88566
|
},
|
|
88402
88567
|
child_resource_events: {
|
|
@@ -88483,10 +88648,13 @@ var native_spec_default = {
|
|
|
88483
88648
|
"shipment.updated",
|
|
88484
88649
|
"member.created",
|
|
88485
88650
|
"member.updated",
|
|
88651
|
+
"ad_campaign.created",
|
|
88486
88652
|
"ad_campaign.payment_failed",
|
|
88487
88653
|
"ad_campaign.updated",
|
|
88488
88654
|
"ad_campaign.events",
|
|
88655
|
+
"ad_group.created",
|
|
88489
88656
|
"ad_group.updated",
|
|
88657
|
+
"ad.created",
|
|
88490
88658
|
"ad.updated",
|
|
88491
88659
|
"chat.message.created",
|
|
88492
88660
|
"chat.reaction.created",
|
|
@@ -89097,7 +89265,7 @@ var native_spec_default = {
|
|
|
89097
89265
|
example: {
|
|
89098
89266
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
89099
89267
|
api_version: "v1",
|
|
89100
|
-
api_version_date: "2026-10-
|
|
89268
|
+
api_version_date: "2026-10-14",
|
|
89101
89269
|
data: {
|
|
89102
89270
|
ads_spend_usd: null,
|
|
89103
89271
|
balances: [],
|
|
@@ -89117,7 +89285,7 @@ var native_spec_default = {
|
|
|
89117
89285
|
crypto_deposit: "active",
|
|
89118
89286
|
crypto_payout: "inactive",
|
|
89119
89287
|
instant_payout: "inactive",
|
|
89120
|
-
run_ads: "
|
|
89288
|
+
run_ads: "inactive",
|
|
89121
89289
|
standard_payout: "inactive",
|
|
89122
89290
|
transfer: "inactive"
|
|
89123
89291
|
},
|
|
@@ -89297,6 +89465,7 @@ var native_spec_default = {
|
|
|
89297
89465
|
business: null,
|
|
89298
89466
|
individual: null
|
|
89299
89467
|
},
|
|
89468
|
+
volume_l30d_usd: null,
|
|
89300
89469
|
volume_usd: 0,
|
|
89301
89470
|
wallet: null,
|
|
89302
89471
|
website: null
|
|
@@ -89417,7 +89586,7 @@ var native_spec_default = {
|
|
|
89417
89586
|
example: {
|
|
89418
89587
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
89419
89588
|
api_version: "v1",
|
|
89420
|
-
api_version_date: "2026-10-
|
|
89589
|
+
api_version_date: "2026-10-14",
|
|
89421
89590
|
data: {
|
|
89422
89591
|
ads_spend_usd: null,
|
|
89423
89592
|
balances: [],
|
|
@@ -89437,7 +89606,7 @@ var native_spec_default = {
|
|
|
89437
89606
|
crypto_deposit: "active",
|
|
89438
89607
|
crypto_payout: "inactive",
|
|
89439
89608
|
instant_payout: "inactive",
|
|
89440
|
-
run_ads: "
|
|
89609
|
+
run_ads: "inactive",
|
|
89441
89610
|
standard_payout: "inactive",
|
|
89442
89611
|
transfer: "inactive"
|
|
89443
89612
|
},
|
|
@@ -89617,6 +89786,7 @@ var native_spec_default = {
|
|
|
89617
89786
|
business: null,
|
|
89618
89787
|
individual: null
|
|
89619
89788
|
},
|
|
89789
|
+
volume_l30d_usd: null,
|
|
89620
89790
|
volume_usd: 0,
|
|
89621
89791
|
wallet: null,
|
|
89622
89792
|
website: null
|
|
@@ -89737,7 +89907,7 @@ var native_spec_default = {
|
|
|
89737
89907
|
example: {
|
|
89738
89908
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
89739
89909
|
api_version: "v1",
|
|
89740
|
-
api_version_date: "2026-10-
|
|
89910
|
+
api_version_date: "2026-10-14",
|
|
89741
89911
|
data: {
|
|
89742
89912
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
89743
89913
|
disabled_at: "2026-01-01T12:00:00.000Z",
|
|
@@ -89867,7 +90037,7 @@ var native_spec_default = {
|
|
|
89867
90037
|
example: {
|
|
89868
90038
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
89869
90039
|
api_version: "v1",
|
|
89870
|
-
api_version_date: "2026-10-
|
|
90040
|
+
api_version_date: "2026-10-14",
|
|
89871
90041
|
data: {
|
|
89872
90042
|
ads_spend_usd: null,
|
|
89873
90043
|
balances: [],
|
|
@@ -89887,7 +90057,7 @@ var native_spec_default = {
|
|
|
89887
90057
|
crypto_deposit: "active",
|
|
89888
90058
|
crypto_payout: "inactive",
|
|
89889
90059
|
instant_payout: "inactive",
|
|
89890
|
-
run_ads: "
|
|
90060
|
+
run_ads: "inactive",
|
|
89891
90061
|
standard_payout: "inactive",
|
|
89892
90062
|
transfer: "inactive"
|
|
89893
90063
|
},
|
|
@@ -90067,6 +90237,7 @@ var native_spec_default = {
|
|
|
90067
90237
|
business: null,
|
|
90068
90238
|
individual: null
|
|
90069
90239
|
},
|
|
90240
|
+
volume_l30d_usd: null,
|
|
90070
90241
|
volume_usd: 0,
|
|
90071
90242
|
wallet: null,
|
|
90072
90243
|
website: null
|
|
@@ -90187,7 +90358,7 @@ var native_spec_default = {
|
|
|
90187
90358
|
example: {
|
|
90188
90359
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
90189
90360
|
api_version: "v1",
|
|
90190
|
-
api_version_date: "2026-10-
|
|
90361
|
+
api_version_date: "2026-10-14",
|
|
90191
90362
|
data: {
|
|
90192
90363
|
ad_campaign: {
|
|
90193
90364
|
id: "adcamp_xxxxxxxxxxxxxx"
|
|
@@ -90592,7 +90763,7 @@ var native_spec_default = {
|
|
|
90592
90763
|
example: {
|
|
90593
90764
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
90594
90765
|
api_version: "v1",
|
|
90595
|
-
api_version_date: "2026-10-
|
|
90766
|
+
api_version_date: "2026-10-14",
|
|
90596
90767
|
data: {
|
|
90597
90768
|
bid_type: null,
|
|
90598
90769
|
budget_amount: 50,
|
|
@@ -90911,7 +91082,7 @@ var native_spec_default = {
|
|
|
90911
91082
|
example: {
|
|
90912
91083
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
90913
91084
|
api_version: "v1",
|
|
90914
|
-
api_version_date: "2026-10-
|
|
91085
|
+
api_version_date: "2026-10-14",
|
|
90915
91086
|
data: {
|
|
90916
91087
|
bid_type: null,
|
|
90917
91088
|
budget_amount: 50,
|
|
@@ -91230,7 +91401,7 @@ var native_spec_default = {
|
|
|
91230
91401
|
example: {
|
|
91231
91402
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
91232
91403
|
api_version: "v1",
|
|
91233
|
-
api_version_date: "2026-10-
|
|
91404
|
+
api_version_date: "2026-10-14",
|
|
91234
91405
|
data: {
|
|
91235
91406
|
ad_campaign: {
|
|
91236
91407
|
id: "adcamp_xxxxxxxxxxxxxx"
|
|
@@ -91701,7 +91872,7 @@ var native_spec_default = {
|
|
|
91701
91872
|
example: {
|
|
91702
91873
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
91703
91874
|
api_version: "v1",
|
|
91704
|
-
api_version_date: "2026-10-
|
|
91875
|
+
api_version_date: "2026-10-14",
|
|
91705
91876
|
data: {
|
|
91706
91877
|
billing: null,
|
|
91707
91878
|
canceled_at: null,
|
|
@@ -92017,7 +92188,7 @@ var native_spec_default = {
|
|
|
92017
92188
|
example: {
|
|
92018
92189
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
92019
92190
|
api_version: "v1",
|
|
92020
|
-
api_version_date: "2026-10-
|
|
92191
|
+
api_version_date: "2026-10-14",
|
|
92021
92192
|
data: {
|
|
92022
92193
|
billing: null,
|
|
92023
92194
|
canceled_at: null,
|
|
@@ -92333,7 +92504,7 @@ var native_spec_default = {
|
|
|
92333
92504
|
example: {
|
|
92334
92505
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
92335
92506
|
api_version: "v1",
|
|
92336
|
-
api_version_date: "2026-10-
|
|
92507
|
+
api_version_date: "2026-10-14",
|
|
92337
92508
|
data: {
|
|
92338
92509
|
billing: null,
|
|
92339
92510
|
canceled_at: null,
|
|
@@ -92649,7 +92820,7 @@ var native_spec_default = {
|
|
|
92649
92820
|
example: {
|
|
92650
92821
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
92651
92822
|
api_version: "v1",
|
|
92652
|
-
api_version_date: "2026-10-
|
|
92823
|
+
api_version_date: "2026-10-14",
|
|
92653
92824
|
data: {
|
|
92654
92825
|
billing: null,
|
|
92655
92826
|
canceled_at: null,
|
|
@@ -92965,7 +93136,7 @@ var native_spec_default = {
|
|
|
92965
93136
|
example: {
|
|
92966
93137
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
92967
93138
|
api_version: "v1",
|
|
92968
|
-
api_version_date: "2026-10-
|
|
93139
|
+
api_version_date: "2026-10-14",
|
|
92969
93140
|
data: {
|
|
92970
93141
|
hosted_url: null,
|
|
92971
93142
|
id: "ciac_xxxxxxxxxxxxxx",
|
|
@@ -93115,7 +93286,7 @@ var native_spec_default = {
|
|
|
93115
93286
|
example: {
|
|
93116
93287
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
93117
93288
|
api_version: "v1",
|
|
93118
|
-
api_version_date: "2026-10-
|
|
93289
|
+
api_version_date: "2026-10-14",
|
|
93119
93290
|
data: {
|
|
93120
93291
|
hosted_url: null,
|
|
93121
93292
|
id: "ciac_xxxxxxxxxxxxxx",
|
|
@@ -93265,7 +93436,7 @@ var native_spec_default = {
|
|
|
93265
93436
|
example: {
|
|
93266
93437
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
93267
93438
|
api_version: "v1",
|
|
93268
|
-
api_version_date: "2026-10-
|
|
93439
|
+
api_version_date: "2026-10-14",
|
|
93269
93440
|
data: {
|
|
93270
93441
|
hosted_url: null,
|
|
93271
93442
|
id: "ciac_xxxxxxxxxxxxxx",
|
|
@@ -93415,7 +93586,7 @@ var native_spec_default = {
|
|
|
93415
93586
|
example: {
|
|
93416
93587
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
93417
93588
|
api_version: "v1",
|
|
93418
|
-
api_version_date: "2026-10-
|
|
93589
|
+
api_version_date: "2026-10-14",
|
|
93419
93590
|
data: {
|
|
93420
93591
|
hosted_url: null,
|
|
93421
93592
|
id: "ciac_xxxxxxxxxxxxxx",
|
|
@@ -93565,7 +93736,7 @@ var native_spec_default = {
|
|
|
93565
93736
|
example: {
|
|
93566
93737
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
93567
93738
|
api_version: "v1",
|
|
93568
|
-
api_version_date: "2026-10-
|
|
93739
|
+
api_version_date: "2026-10-14",
|
|
93569
93740
|
data: {
|
|
93570
93741
|
card_id: "icrd_xxxxxxxxxxxxxx",
|
|
93571
93742
|
cardholder_id: null,
|
|
@@ -93696,7 +93867,7 @@ var native_spec_default = {
|
|
|
93696
93867
|
example: {
|
|
93697
93868
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
93698
93869
|
api_version: "v1",
|
|
93699
|
-
api_version_date: "2026-10-
|
|
93870
|
+
api_version_date: "2026-10-14",
|
|
93700
93871
|
data: {
|
|
93701
93872
|
card_id: "icrd_xxxxxxxxxxxxxx",
|
|
93702
93873
|
cardholder_id: null,
|
|
@@ -93827,7 +93998,7 @@ var native_spec_default = {
|
|
|
93827
93998
|
example: {
|
|
93828
93999
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
93829
94000
|
api_version: "v1",
|
|
93830
|
-
api_version_date: "2026-10-
|
|
94001
|
+
api_version_date: "2026-10-14",
|
|
93831
94002
|
data: {
|
|
93832
94003
|
card_id: "icrd_xxxxxxxxxxxxxx",
|
|
93833
94004
|
cardholder_id: null,
|
|
@@ -93958,7 +94129,7 @@ var native_spec_default = {
|
|
|
93958
94129
|
example: {
|
|
93959
94130
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
93960
94131
|
api_version: "v1",
|
|
93961
|
-
api_version_date: "2026-10-
|
|
94132
|
+
api_version_date: "2026-10-14",
|
|
93962
94133
|
data: {
|
|
93963
94134
|
card_id: "icrd_xxxxxxxxxxxxxx",
|
|
93964
94135
|
cardholder_id: null,
|
|
@@ -94089,7 +94260,7 @@ var native_spec_default = {
|
|
|
94089
94260
|
example: {
|
|
94090
94261
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
94091
94262
|
api_version: "v1",
|
|
94092
|
-
api_version_date: "2026-10-
|
|
94263
|
+
api_version_date: "2026-10-14",
|
|
94093
94264
|
data: {
|
|
94094
94265
|
card_id: "icrd_xxxxxxxxxxxxxx",
|
|
94095
94266
|
cardholder_id: null,
|
|
@@ -94220,7 +94391,7 @@ var native_spec_default = {
|
|
|
94220
94391
|
example: {
|
|
94221
94392
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
94222
94393
|
api_version: "v1",
|
|
94223
|
-
api_version_date: "2026-10-
|
|
94394
|
+
api_version_date: "2026-10-14",
|
|
94224
94395
|
data: {
|
|
94225
94396
|
amount: "75000000000",
|
|
94226
94397
|
available_at: null,
|
|
@@ -94352,7 +94523,7 @@ var native_spec_default = {
|
|
|
94352
94523
|
example: {
|
|
94353
94524
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
94354
94525
|
api_version: "v1",
|
|
94355
|
-
api_version_date: "2026-10-
|
|
94526
|
+
api_version_date: "2026-10-14",
|
|
94356
94527
|
data: {
|
|
94357
94528
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
94358
94529
|
amount: 150,
|
|
@@ -94532,7 +94703,7 @@ var native_spec_default = {
|
|
|
94532
94703
|
example: {
|
|
94533
94704
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
94534
94705
|
api_version: "v1",
|
|
94535
|
-
api_version_date: "2026-10-
|
|
94706
|
+
api_version_date: "2026-10-14",
|
|
94536
94707
|
data: {
|
|
94537
94708
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
94538
94709
|
amount: 150,
|
|
@@ -94712,7 +94883,7 @@ var native_spec_default = {
|
|
|
94712
94883
|
example: {
|
|
94713
94884
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
94714
94885
|
api_version: "v1",
|
|
94715
|
-
api_version_date: "2026-10-
|
|
94886
|
+
api_version_date: "2026-10-14",
|
|
94716
94887
|
data: {
|
|
94717
94888
|
account_id: null,
|
|
94718
94889
|
amount: 25,
|
|
@@ -94842,7 +95013,7 @@ var native_spec_default = {
|
|
|
94842
95013
|
example: {
|
|
94843
95014
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
94844
95015
|
api_version: "v1",
|
|
94845
|
-
api_version_date: "2026-10-
|
|
95016
|
+
api_version_date: "2026-10-14",
|
|
94846
95017
|
data: {
|
|
94847
95018
|
created_at: "2026-01-01T12:00:00.000Z",
|
|
94848
95019
|
download_url: "https://s3.amazonaws.com/uploads/exports/members-export.csv",
|
|
@@ -94963,7 +95134,7 @@ var native_spec_default = {
|
|
|
94963
95134
|
example: {
|
|
94964
95135
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
94965
95136
|
api_version: "v1",
|
|
94966
|
-
api_version_date: "2026-10-
|
|
95137
|
+
api_version_date: "2026-10-14",
|
|
94967
95138
|
data: {
|
|
94968
95139
|
created_at: "2026-01-01T12:00:00.000Z",
|
|
94969
95140
|
download_url: null,
|
|
@@ -95084,7 +95255,7 @@ var native_spec_default = {
|
|
|
95084
95255
|
example: {
|
|
95085
95256
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
95086
95257
|
api_version: "v1",
|
|
95087
|
-
api_version_date: "2026-10-
|
|
95258
|
+
api_version_date: "2026-10-14",
|
|
95088
95259
|
data: {
|
|
95089
95260
|
amount: "512345000000",
|
|
95090
95261
|
available_at: "2026-01-01T12:00:00.000Z",
|
|
@@ -95221,7 +95392,7 @@ var native_spec_default = {
|
|
|
95221
95392
|
example: {
|
|
95222
95393
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
95223
95394
|
api_version: "v1",
|
|
95224
|
-
api_version_date: "2026-10-
|
|
95395
|
+
api_version_date: "2026-10-14",
|
|
95225
95396
|
data: {
|
|
95226
95397
|
id: "idpf_xxxxxxxxxxxxxx"
|
|
95227
95398
|
},
|
|
@@ -95343,7 +95514,7 @@ var native_spec_default = {
|
|
|
95343
95514
|
example: {
|
|
95344
95515
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
95345
95516
|
api_version: "v1",
|
|
95346
|
-
api_version_date: "2026-10-
|
|
95517
|
+
api_version_date: "2026-10-14",
|
|
95347
95518
|
data: {
|
|
95348
95519
|
access_level: "customer",
|
|
95349
95520
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
@@ -95484,7 +95655,7 @@ var native_spec_default = {
|
|
|
95484
95655
|
example: {
|
|
95485
95656
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
95486
95657
|
api_version: "v1",
|
|
95487
|
-
api_version_date: "2026-10-
|
|
95658
|
+
api_version_date: "2026-10-14",
|
|
95488
95659
|
data: {
|
|
95489
95660
|
access_level: "customer",
|
|
95490
95661
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
@@ -95625,7 +95796,7 @@ var native_spec_default = {
|
|
|
95625
95796
|
example: {
|
|
95626
95797
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
95627
95798
|
api_version: "v1",
|
|
95628
|
-
api_version_date: "2026-10-
|
|
95799
|
+
api_version_date: "2026-10-14",
|
|
95629
95800
|
data: {
|
|
95630
95801
|
account: {
|
|
95631
95802
|
id: "biz_xxxxxxxxxxxxxx",
|
|
@@ -95791,7 +95962,7 @@ var native_spec_default = {
|
|
|
95791
95962
|
example: {
|
|
95792
95963
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
95793
95964
|
api_version: "v1",
|
|
95794
|
-
api_version_date: "2026-10-
|
|
95965
|
+
api_version_date: "2026-10-14",
|
|
95795
95966
|
data: {
|
|
95796
95967
|
account: {
|
|
95797
95968
|
id: "biz_xxxxxxxxxxxxxx",
|
|
@@ -95963,7 +96134,7 @@ var native_spec_default = {
|
|
|
95963
96134
|
example: {
|
|
95964
96135
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
95965
96136
|
api_version: "v1",
|
|
95966
|
-
api_version_date: "2026-10-
|
|
96137
|
+
api_version_date: "2026-10-14",
|
|
95967
96138
|
data: {
|
|
95968
96139
|
account: {
|
|
95969
96140
|
id: "biz_xxxxxxxxxxxxxx",
|
|
@@ -96129,7 +96300,7 @@ var native_spec_default = {
|
|
|
96129
96300
|
example: {
|
|
96130
96301
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
96131
96302
|
api_version: "v1",
|
|
96132
|
-
api_version_date: "2026-10-
|
|
96303
|
+
api_version_date: "2026-10-14",
|
|
96133
96304
|
data: {
|
|
96134
96305
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
96135
96306
|
amount_after_fees: {
|
|
@@ -96402,7 +96573,7 @@ var native_spec_default = {
|
|
|
96402
96573
|
example: {
|
|
96403
96574
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
96404
96575
|
api_version: "v1",
|
|
96405
|
-
api_version_date: "2026-10-
|
|
96576
|
+
api_version_date: "2026-10-14",
|
|
96406
96577
|
data: {
|
|
96407
96578
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
96408
96579
|
amount_after_fees: {
|
|
@@ -96675,7 +96846,7 @@ var native_spec_default = {
|
|
|
96675
96846
|
example: {
|
|
96676
96847
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
96677
96848
|
api_version: "v1",
|
|
96678
|
-
api_version_date: "2026-10-
|
|
96849
|
+
api_version_date: "2026-10-14",
|
|
96679
96850
|
data: {
|
|
96680
96851
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
96681
96852
|
amount_after_fees: {
|
|
@@ -96948,7 +97119,7 @@ var native_spec_default = {
|
|
|
96948
97119
|
example: {
|
|
96949
97120
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
96950
97121
|
api_version: "v1",
|
|
96951
|
-
api_version_date: "2026-10-
|
|
97122
|
+
api_version_date: "2026-10-14",
|
|
96952
97123
|
data: {
|
|
96953
97124
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
96954
97125
|
amount_after_fees: {
|
|
@@ -97221,7 +97392,7 @@ var native_spec_default = {
|
|
|
97221
97392
|
example: {
|
|
97222
97393
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
97223
97394
|
api_version: "v1",
|
|
97224
|
-
api_version_date: "2026-10-
|
|
97395
|
+
api_version_date: "2026-10-14",
|
|
97225
97396
|
data: {
|
|
97226
97397
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
97227
97398
|
amount_after_fees: {
|
|
@@ -97488,7 +97659,7 @@ var native_spec_default = {
|
|
|
97488
97659
|
example: {
|
|
97489
97660
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
97490
97661
|
api_version: "v1",
|
|
97491
|
-
api_version_date: "2026-10-
|
|
97662
|
+
api_version_date: "2026-10-14",
|
|
97492
97663
|
data: {
|
|
97493
97664
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
97494
97665
|
amount_after_fees: {
|
|
@@ -97767,7 +97938,7 @@ var native_spec_default = {
|
|
|
97767
97938
|
example: {
|
|
97768
97939
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
97769
97940
|
api_version: "v1",
|
|
97770
|
-
api_version_date: "2026-10-
|
|
97941
|
+
api_version_date: "2026-10-14",
|
|
97771
97942
|
data: {
|
|
97772
97943
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
97773
97944
|
amount_after_fees: {
|
|
@@ -98040,7 +98211,7 @@ var native_spec_default = {
|
|
|
98040
98211
|
example: {
|
|
98041
98212
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
98042
98213
|
api_version: "v1",
|
|
98043
|
-
api_version_date: "2026-10-
|
|
98214
|
+
api_version_date: "2026-10-14",
|
|
98044
98215
|
data: {
|
|
98045
98216
|
amount: "10.0",
|
|
98046
98217
|
created_at: "2026-01-01T12:00:00.000Z",
|
|
@@ -98428,7 +98599,7 @@ var native_spec_default = {
|
|
|
98428
98599
|
example: {
|
|
98429
98600
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
98430
98601
|
api_version: "v1",
|
|
98431
|
-
api_version_date: "2026-10-
|
|
98602
|
+
api_version_date: "2026-10-14",
|
|
98432
98603
|
data: {
|
|
98433
98604
|
amount: "10.0",
|
|
98434
98605
|
created_at: "2026-01-01T12:00:00.000Z",
|
|
@@ -98813,7 +98984,7 @@ var native_spec_default = {
|
|
|
98813
98984
|
example: {
|
|
98814
98985
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
98815
98986
|
api_version: "v1",
|
|
98816
|
-
api_version_date: "2026-10-
|
|
98987
|
+
api_version_date: "2026-10-14",
|
|
98817
98988
|
data: {
|
|
98818
98989
|
amount: "10.0",
|
|
98819
98990
|
created_at: "2026-01-01T12:00:00.000Z",
|
|
@@ -99194,7 +99365,7 @@ var native_spec_default = {
|
|
|
99194
99365
|
example: {
|
|
99195
99366
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
99196
99367
|
api_version: "v1",
|
|
99197
|
-
api_version_date: "2026-10-
|
|
99368
|
+
api_version_date: "2026-10-14",
|
|
99198
99369
|
data: {
|
|
99199
99370
|
account_reference: "4483",
|
|
99200
99371
|
bank_verification_state: null,
|
|
@@ -99677,7 +99848,7 @@ var native_spec_default = {
|
|
|
99677
99848
|
example: {
|
|
99678
99849
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
99679
99850
|
api_version: "v1",
|
|
99680
|
-
api_version_date: "2026-10-
|
|
99851
|
+
api_version_date: "2026-10-14",
|
|
99681
99852
|
data: {
|
|
99682
99853
|
account: {
|
|
99683
99854
|
id: "biz_xxxxxxxxxxxxxx",
|
|
@@ -99979,7 +100150,7 @@ var native_spec_default = {
|
|
|
99979
100150
|
example: {
|
|
99980
100151
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
99981
100152
|
api_version: "v1",
|
|
99982
|
-
api_version_date: "2026-10-
|
|
100153
|
+
api_version_date: "2026-10-14",
|
|
99983
100154
|
data: {
|
|
99984
100155
|
account: {
|
|
99985
100156
|
id: "biz_xxxxxxxxxxxxxx",
|
|
@@ -100281,7 +100452,7 @@ var native_spec_default = {
|
|
|
100281
100452
|
example: {
|
|
100282
100453
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
100283
100454
|
api_version: "v1",
|
|
100284
|
-
api_version_date: "2026-10-
|
|
100455
|
+
api_version_date: "2026-10-14",
|
|
100285
100456
|
data: {
|
|
100286
100457
|
account: {
|
|
100287
100458
|
id: "biz_xxxxxxxxxxxxxx",
|
|
@@ -100583,7 +100754,7 @@ var native_spec_default = {
|
|
|
100583
100754
|
example: {
|
|
100584
100755
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
100585
100756
|
api_version: "v1",
|
|
100586
|
-
api_version_date: "2026-10-
|
|
100757
|
+
api_version_date: "2026-10-14",
|
|
100587
100758
|
data: {
|
|
100588
100759
|
account: {
|
|
100589
100760
|
id: "biz_xxxxxxxxxxxxxx",
|
|
@@ -100735,7 +100906,7 @@ var native_spec_default = {
|
|
|
100735
100906
|
example: {
|
|
100736
100907
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
100737
100908
|
api_version: "v1",
|
|
100738
|
-
api_version_date: "2026-10-
|
|
100909
|
+
api_version_date: "2026-10-14",
|
|
100739
100910
|
data: {
|
|
100740
100911
|
account: {
|
|
100741
100912
|
id: "biz_xxxxxxxxxxxxxx",
|
|
@@ -100887,7 +101058,7 @@ var native_spec_default = {
|
|
|
100887
101058
|
example: {
|
|
100888
101059
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
100889
101060
|
api_version: "v1",
|
|
100890
|
-
api_version_date: "2026-10-
|
|
101061
|
+
api_version_date: "2026-10-14",
|
|
100891
101062
|
data: {
|
|
100892
101063
|
account: {
|
|
100893
101064
|
id: "biz_xxxxxxxxxxxxxx",
|
|
@@ -101039,7 +101210,7 @@ var native_spec_default = {
|
|
|
101039
101210
|
example: {
|
|
101040
101211
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
101041
101212
|
api_version: "v1",
|
|
101042
|
-
api_version_date: "2026-10-
|
|
101213
|
+
api_version_date: "2026-10-14",
|
|
101043
101214
|
data: {
|
|
101044
101215
|
account: {
|
|
101045
101216
|
id: "biz_xxxxxxxxxxxxxx",
|
|
@@ -101191,7 +101362,7 @@ var native_spec_default = {
|
|
|
101191
101362
|
example: {
|
|
101192
101363
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
101193
101364
|
api_version: "v1",
|
|
101194
|
-
api_version_date: "2026-10-
|
|
101365
|
+
api_version_date: "2026-10-14",
|
|
101195
101366
|
data: {
|
|
101196
101367
|
account: {
|
|
101197
101368
|
id: "biz_xxxxxxxxxxxxxx",
|
|
@@ -101343,7 +101514,7 @@ var native_spec_default = {
|
|
|
101343
101514
|
example: {
|
|
101344
101515
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
101345
101516
|
api_version: "v1",
|
|
101346
|
-
api_version_date: "2026-10-
|
|
101517
|
+
api_version_date: "2026-10-14",
|
|
101347
101518
|
data: {
|
|
101348
101519
|
account: {
|
|
101349
101520
|
id: "biz_xxxxxxxxxxxxxx",
|
|
@@ -101503,7 +101674,7 @@ var native_spec_default = {
|
|
|
101503
101674
|
example: {
|
|
101504
101675
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
101505
101676
|
api_version: "v1",
|
|
101506
|
-
api_version_date: "2026-10-
|
|
101677
|
+
api_version_date: "2026-10-14",
|
|
101507
101678
|
data: {
|
|
101508
101679
|
account: {
|
|
101509
101680
|
id: "biz_xxxxxxxxxxxxxx",
|
|
@@ -101663,7 +101834,7 @@ var native_spec_default = {
|
|
|
101663
101834
|
example: {
|
|
101664
101835
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
101665
101836
|
api_version: "v1",
|
|
101666
|
-
api_version_date: "2026-10-
|
|
101837
|
+
api_version_date: "2026-10-14",
|
|
101667
101838
|
data: {
|
|
101668
101839
|
account: {
|
|
101669
101840
|
id: "biz_xxxxxxxxxxxxxx",
|
|
@@ -101823,7 +101994,7 @@ var native_spec_default = {
|
|
|
101823
101994
|
example: {
|
|
101824
101995
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
101825
101996
|
api_version: "v1",
|
|
101826
|
-
api_version_date: "2026-10-
|
|
101997
|
+
api_version_date: "2026-10-14",
|
|
101827
101998
|
data: {
|
|
101828
101999
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
101829
102000
|
checkout_configuration_id: null,
|
|
@@ -101964,7 +102135,7 @@ var native_spec_default = {
|
|
|
101964
102135
|
example: {
|
|
101965
102136
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
101966
102137
|
api_version: "v1",
|
|
101967
|
-
api_version_date: "2026-10-
|
|
102138
|
+
api_version_date: "2026-10-14",
|
|
101968
102139
|
data: {
|
|
101969
102140
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
101970
102141
|
checkout_configuration_id: null,
|
|
@@ -102108,7 +102279,7 @@ var native_spec_default = {
|
|
|
102108
102279
|
example: {
|
|
102109
102280
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
102110
102281
|
api_version: "v1",
|
|
102111
|
-
api_version_date: "2026-10-
|
|
102282
|
+
api_version_date: "2026-10-14",
|
|
102112
102283
|
data: {
|
|
102113
102284
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
102114
102285
|
checkout_configuration_id: null,
|
|
@@ -102287,7 +102458,7 @@ var native_spec_default = {
|
|
|
102287
102458
|
example: {
|
|
102288
102459
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
102289
102460
|
api_version: "v1",
|
|
102290
|
-
api_version_date: "2026-10-
|
|
102461
|
+
api_version_date: "2026-10-14",
|
|
102291
102462
|
data: {
|
|
102292
102463
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
102293
102464
|
carrier: "ups",
|
|
@@ -102411,7 +102582,7 @@ var native_spec_default = {
|
|
|
102411
102582
|
example: {
|
|
102412
102583
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
102413
102584
|
api_version: "v1",
|
|
102414
|
-
api_version_date: "2026-10-
|
|
102585
|
+
api_version_date: "2026-10-14",
|
|
102415
102586
|
data: {
|
|
102416
102587
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
102417
102588
|
carrier: "ups",
|
|
@@ -102535,7 +102706,7 @@ var native_spec_default = {
|
|
|
102535
102706
|
example: {
|
|
102536
102707
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
102537
102708
|
api_version: "v1",
|
|
102538
|
-
api_version_date: "2026-10-
|
|
102709
|
+
api_version_date: "2026-10-14",
|
|
102539
102710
|
data: {
|
|
102540
102711
|
account: {
|
|
102541
102712
|
id: "biz_xxxxxxxxxxxxxx",
|
|
@@ -102767,7 +102938,7 @@ var native_spec_default = {
|
|
|
102767
102938
|
example: {
|
|
102768
102939
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
102769
102940
|
api_version: "v1",
|
|
102770
|
-
api_version_date: "2026-10-
|
|
102941
|
+
api_version_date: "2026-10-14",
|
|
102771
102942
|
data: {
|
|
102772
102943
|
amount: {
|
|
102773
102944
|
amount: "250.00",
|
|
@@ -103090,7 +103261,7 @@ var native_spec_default = {
|
|
|
103090
103261
|
example: {
|
|
103091
103262
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
103092
103263
|
api_version: "v1",
|
|
103093
|
-
api_version_date: "2026-10-
|
|
103264
|
+
api_version_date: "2026-10-14",
|
|
103094
103265
|
data: {
|
|
103095
103266
|
amount: {
|
|
103096
103267
|
amount: "250.00",
|
|
@@ -103413,7 +103584,7 @@ var native_spec_default = {
|
|
|
103413
103584
|
example: {
|
|
103414
103585
|
account_id: "biz_xxxxxxxxxxxxxx",
|
|
103415
103586
|
api_version: "v1",
|
|
103416
|
-
api_version_date: "2026-10-
|
|
103587
|
+
api_version_date: "2026-10-14",
|
|
103417
103588
|
data: {
|
|
103418
103589
|
amount: null,
|
|
103419
103590
|
created_at: "2026-01-01T12:00:00.000Z",
|
|
@@ -103702,7 +103873,7 @@ var native_spec_default = {
|
|
|
103702
103873
|
name: "Api-Version-Date",
|
|
103703
103874
|
required: false,
|
|
103704
103875
|
schema: {
|
|
103705
|
-
example: "2026-10-
|
|
103876
|
+
example: "2026-10-14",
|
|
103706
103877
|
type: "string"
|
|
103707
103878
|
}
|
|
103708
103879
|
},
|
|
@@ -103874,7 +104045,7 @@ var native_spec_default = {
|
|
|
103874
104045
|
},
|
|
103875
104046
|
collect_vat_id: {
|
|
103876
104047
|
description: "Whether checkout shows a VAT/tax ID field for buyers to optionally enter. Does not require a VAT ID to purchase.",
|
|
103877
|
-
example:
|
|
104048
|
+
example: false,
|
|
103878
104049
|
type: "boolean"
|
|
103879
104050
|
},
|
|
103880
104051
|
company_formation: {
|
|
@@ -103896,6 +104067,11 @@ var native_spec_default = {
|
|
|
103896
104067
|
example: "Mobile ceramic coating, paint correction, and interior detailing across the Austin metro.",
|
|
103897
104068
|
type: ["string", "null"]
|
|
103898
104069
|
},
|
|
104070
|
+
direct_reports_count: {
|
|
104071
|
+
description: "How many team members report to the business directly, with no manager above them. Present on single-account reads.",
|
|
104072
|
+
example: 0,
|
|
104073
|
+
type: "integer"
|
|
104074
|
+
},
|
|
103899
104075
|
dispute_fighter_enabled: {
|
|
103900
104076
|
description: "Whether Whop assembles and files dispute evidence for this account. Enabling it opts the account into the success fee charged on disputes it wins.",
|
|
103901
104077
|
example: false,
|
|
@@ -103955,7 +104131,7 @@ var native_spec_default = {
|
|
|
103955
104131
|
},
|
|
103956
104132
|
invoice_prefix: {
|
|
103957
104133
|
description: "Prefix used for account invoices.",
|
|
103958
|
-
example: "
|
|
104134
|
+
example: "INV",
|
|
103959
104135
|
type: ["string", "null"]
|
|
103960
104136
|
},
|
|
103961
104137
|
level: {
|
|
@@ -103977,15 +104153,14 @@ var native_spec_default = {
|
|
|
103977
104153
|
metadata: {
|
|
103978
104154
|
description: "Arbitrary key/value metadata supplied at account creation.",
|
|
103979
104155
|
example: {
|
|
103980
|
-
external_id: "
|
|
103981
|
-
region: "austin"
|
|
104156
|
+
external_id: "connected_account_123"
|
|
103982
104157
|
},
|
|
103983
104158
|
type: "object"
|
|
103984
104159
|
},
|
|
103985
104160
|
onboarding_type: {
|
|
103986
104161
|
description: "Type of onboarding the account has completed.",
|
|
103987
104162
|
enum: ["platform", "seller", null],
|
|
103988
|
-
example: "
|
|
104163
|
+
example: "platform",
|
|
103989
104164
|
type: ["string", "null"]
|
|
103990
104165
|
},
|
|
103991
104166
|
opengraph_image_url: {
|
|
@@ -104089,7 +104264,7 @@ var native_spec_default = {
|
|
|
104089
104264
|
},
|
|
104090
104265
|
require_2fa: {
|
|
104091
104266
|
description: "Whether authorized users must enable two-factor authentication.",
|
|
104092
|
-
example:
|
|
104267
|
+
example: false,
|
|
104093
104268
|
type: "boolean"
|
|
104094
104269
|
},
|
|
104095
104270
|
required_actions: {
|
|
@@ -104140,17 +104315,17 @@ var native_spec_default = {
|
|
|
104140
104315
|
},
|
|
104141
104316
|
show_joined_whops: {
|
|
104142
104317
|
description: "Whether the account appears in joined whops on other accounts.",
|
|
104143
|
-
example:
|
|
104318
|
+
example: true,
|
|
104144
104319
|
type: "boolean"
|
|
104145
104320
|
},
|
|
104146
104321
|
show_reviews_dtc: {
|
|
104147
104322
|
description: "Whether reviews are displayed on direct-to-consumer product pages.",
|
|
104148
|
-
example:
|
|
104323
|
+
example: true,
|
|
104149
104324
|
type: "boolean"
|
|
104150
104325
|
},
|
|
104151
104326
|
show_user_directory: {
|
|
104152
104327
|
description: "Whether the account shows users in the user directory.",
|
|
104153
|
-
example:
|
|
104328
|
+
example: true,
|
|
104154
104329
|
type: "boolean"
|
|
104155
104330
|
},
|
|
104156
104331
|
social_links: {
|
|
@@ -104261,7 +104436,7 @@ var native_spec_default = {
|
|
|
104261
104436
|
},
|
|
104262
104437
|
use_logo_as_opengraph_image_fallback: {
|
|
104263
104438
|
description: "Whether the account uses its logo as the fallback Open Graph image.",
|
|
104264
|
-
example:
|
|
104439
|
+
example: false,
|
|
104265
104440
|
type: "boolean"
|
|
104266
104441
|
},
|
|
104267
104442
|
verification: {
|
|
@@ -104272,6 +104447,11 @@ var native_spec_default = {
|
|
|
104272
104447
|
},
|
|
104273
104448
|
type: "object"
|
|
104274
104449
|
},
|
|
104450
|
+
volume_l30d_usd: {
|
|
104451
|
+
description: "Volume through the account in the last 30 days (GMV from paid receipts), normalized to USD. Computed only on `list` for callers with `stats:read` on the account; `null` otherwise.",
|
|
104452
|
+
example: 0,
|
|
104453
|
+
type: ["number", "null"]
|
|
104454
|
+
},
|
|
104275
104455
|
volume_usd: {
|
|
104276
104456
|
description: "Lifetime volume through the account \u2014 sales plus transfers received \u2014 normalized to USD. Computed only on `list` for callers with `stats:read` on the account; `null` otherwise.",
|
|
104277
104457
|
type: ["number", "null"]
|
|
@@ -104291,6 +104471,11 @@ var native_spec_default = {
|
|
|
104291
104471
|
description: "The account's business website URL, or `null` if none has been provided. Setting it also adds a `website` entry to `social_links`.",
|
|
104292
104472
|
example: "https://shinetimedetail.com",
|
|
104293
104473
|
type: ["string", "null"]
|
|
104474
|
+
},
|
|
104475
|
+
whop_partner_enabled_at: {
|
|
104476
|
+
description: "When the account turned on Whop Partner mode, as an ISO 8601 timestamp. Present on single-account reads and update responses; `null` until the account turns Whop Partner mode on by sending `whop_partner_enabled: true` on update.",
|
|
104477
|
+
example: null,
|
|
104478
|
+
type: ["string", "null"]
|
|
104294
104479
|
}
|
|
104295
104480
|
},
|
|
104296
104481
|
required: [
|
|
@@ -104337,6 +104522,7 @@ var native_spec_default = {
|
|
|
104337
104522
|
"status",
|
|
104338
104523
|
"status_reason",
|
|
104339
104524
|
"volume_usd",
|
|
104525
|
+
"volume_l30d_usd",
|
|
104340
104526
|
"ads_spend_usd",
|
|
104341
104527
|
"level",
|
|
104342
104528
|
"capabilities",
|
|
@@ -104527,9 +104713,9 @@ var native_spec_default = {
|
|
|
104527
104713
|
type: "string"
|
|
104528
104714
|
},
|
|
104529
104715
|
run_ads: {
|
|
104530
|
-
description: "Launching ad campaigns through Whop Ads. `inactive` while a requested ads services agreement is awaiting the account's signature.",
|
|
104716
|
+
description: "Launching ad campaigns through Whop Ads. `inactive` until the account's identity or business is verified, and while a requested ads services agreement is awaiting the account's signature.",
|
|
104531
104717
|
enum: ["active", "inactive", "pending"],
|
|
104532
|
-
example: "
|
|
104718
|
+
example: "inactive",
|
|
104533
104719
|
type: "string"
|
|
104534
104720
|
},
|
|
104535
104721
|
standard_payout: {
|
|
@@ -108010,7 +108196,7 @@ var native_spec_default = {
|
|
|
108010
108196
|
},
|
|
108011
108197
|
pending_auto_topup: {
|
|
108012
108198
|
$ref: "#/components/schemas/AccountFee",
|
|
108013
|
-
description: "Charged
|
|
108199
|
+
description: "Charged when pending, not-yet-settled balance is advanced to fund the account's cards balance."
|
|
108014
108200
|
},
|
|
108015
108201
|
platform_processing: {
|
|
108016
108202
|
$ref: "#/components/schemas/AccountFee",
|
|
@@ -108022,7 +108208,7 @@ var native_spec_default = {
|
|
|
108022
108208
|
},
|
|
108023
108209
|
revshare: {
|
|
108024
108210
|
$ref: "#/components/schemas/AccountFee",
|
|
108025
|
-
description: "Charged on revenue
|
|
108211
|
+
description: "Charged on payments where the account shares revenue with revshare affiliates."
|
|
108026
108212
|
},
|
|
108027
108213
|
tax_calculation: {
|
|
108028
108214
|
$ref: "#/components/schemas/AccountFee",
|
|
@@ -109311,7 +109497,7 @@ var native_spec_default = {
|
|
|
109311
109497
|
type: "number"
|
|
109312
109498
|
},
|
|
109313
109499
|
link_clicks: {
|
|
109314
|
-
description: "
|
|
109500
|
+
description: "Page views on your destination from people who clicked the ad, recorded by the Whop pixel. Counted the same way on every ad platform.",
|
|
109315
109501
|
example: 1071,
|
|
109316
109502
|
type: "number"
|
|
109317
109503
|
},
|
|
@@ -109807,7 +109993,7 @@ var native_spec_default = {
|
|
|
109807
109993
|
type: "number"
|
|
109808
109994
|
},
|
|
109809
109995
|
link_clicks: {
|
|
109810
|
-
description: "
|
|
109996
|
+
description: "Page views on your destination from people who clicked the ad, recorded by the Whop pixel. Counted the same way on every ad platform.",
|
|
109811
109997
|
example: 4400,
|
|
109812
109998
|
type: "number"
|
|
109813
109999
|
},
|
|
@@ -110582,7 +110768,7 @@ var native_spec_default = {
|
|
|
110582
110768
|
]
|
|
110583
110769
|
},
|
|
110584
110770
|
link_clicks: {
|
|
110585
|
-
description: "
|
|
110771
|
+
description: "Page views on your destination from people who clicked the ad, recorded by the Whop pixel. Counted the same way on every ad platform.",
|
|
110586
110772
|
example: 4400,
|
|
110587
110773
|
type: "number"
|
|
110588
110774
|
},
|
|
@@ -112143,9 +112329,10 @@ var native_spec_default = {
|
|
|
112143
112329
|
"2026-10-09-1",
|
|
112144
112330
|
"2026-10-09-2",
|
|
112145
112331
|
"2026-10-13",
|
|
112146
|
-
"2026-10-13-1"
|
|
112332
|
+
"2026-10-13-1",
|
|
112333
|
+
"2026-10-14"
|
|
112147
112334
|
],
|
|
112148
|
-
example: "2026-10-
|
|
112335
|
+
example: "2026-10-14",
|
|
112149
112336
|
type: "string"
|
|
112150
112337
|
},
|
|
112151
112338
|
created_at: {
|
|
@@ -112317,7 +112504,7 @@ var native_spec_default = {
|
|
|
112317
112504
|
},
|
|
112318
112505
|
base_url: {
|
|
112319
112506
|
description: "The production base URL where the app is hosted. `null` if no base URL is configured, if the caller lacks the `developer:basic:read` permission on the app's account, or on list responses, which never expose it.",
|
|
112320
|
-
example: "https://booking.
|
|
112507
|
+
example: "https://shine-time-booking.whop.site",
|
|
112321
112508
|
type: ["string", "null"]
|
|
112322
112509
|
},
|
|
112323
112510
|
businesses_created_count: {
|
|
@@ -112957,7 +113144,7 @@ var native_spec_default = {
|
|
|
112957
113144
|
},
|
|
112958
113145
|
base_url: {
|
|
112959
113146
|
description: "The production base URL where the app is hosted. `null` if no base URL is configured, if the caller lacks the `developer:basic:read` permission on the app's account, or on list responses, which never expose it.",
|
|
112960
|
-
example: "https://booking.
|
|
113147
|
+
example: "https://shine-time-booking-store.whop.site",
|
|
112961
113148
|
type: ["string", "null"]
|
|
112962
113149
|
},
|
|
112963
113150
|
businesses_created_count: {
|
|
@@ -116045,7 +116232,7 @@ var native_spec_default = {
|
|
|
116045
116232
|
type: "object"
|
|
116046
116233
|
},
|
|
116047
116234
|
owned_by: {
|
|
116048
|
-
description: "The
|
|
116235
|
+
description: "The account that has proven it owns this hostname on Whop, which can be your own. `null` when no account has.",
|
|
116049
116236
|
oneOf: [
|
|
116050
116237
|
{
|
|
116051
116238
|
$ref: "#/components/schemas/DomainOwner"
|
|
@@ -116397,7 +116584,7 @@ var native_spec_default = {
|
|
|
116397
116584
|
type: "object"
|
|
116398
116585
|
},
|
|
116399
116586
|
owned_by: {
|
|
116400
|
-
description: "The
|
|
116587
|
+
description: "The account that has proven it owns this hostname on Whop, which can be your own. `null` when no account has.",
|
|
116401
116588
|
oneOf: [
|
|
116402
116589
|
{
|
|
116403
116590
|
$ref: "#/components/schemas/DomainOwner"
|
|
@@ -116517,18 +116704,22 @@ var native_spec_default = {
|
|
|
116517
116704
|
properties: {
|
|
116518
116705
|
id: {
|
|
116519
116706
|
description: "ID of the account that owns the domain, prefixed `biz_`.",
|
|
116707
|
+
example: "biz_xxxxxxxxxxxxxx",
|
|
116520
116708
|
type: "string"
|
|
116521
116709
|
},
|
|
116522
116710
|
logo_url: {
|
|
116523
116711
|
description: "Account logo image URL.",
|
|
116712
|
+
example: null,
|
|
116524
116713
|
type: ["string", "null"]
|
|
116525
116714
|
},
|
|
116526
116715
|
route: {
|
|
116527
116716
|
description: "Account public route identifier.",
|
|
116717
|
+
example: "biz_xxxxxxxxxxxxxx",
|
|
116528
116718
|
type: "string"
|
|
116529
116719
|
},
|
|
116530
116720
|
title: {
|
|
116531
116721
|
description: "Account display name.",
|
|
116722
|
+
example: "Rival Shop",
|
|
116532
116723
|
type: "string"
|
|
116533
116724
|
}
|
|
116534
116725
|
},
|
|
@@ -116822,7 +117013,7 @@ var native_spec_default = {
|
|
|
116822
117013
|
properties: {
|
|
116823
117014
|
base_url: {
|
|
116824
117015
|
description: "The production base URL where the app is hosted. `null` if no base URL is configured or the domain isn't yours.",
|
|
116825
|
-
example:
|
|
117016
|
+
example: "https://domains-spec-site.whop.site",
|
|
116826
117017
|
type: ["string", "null"]
|
|
116827
117018
|
},
|
|
116828
117019
|
id: {
|
|
@@ -118654,6 +118845,8 @@ var native_spec_default = {
|
|
|
118654
118845
|
"trading_account_deposit_offset",
|
|
118655
118846
|
"onchain_wallet_transfer_outgoing",
|
|
118656
118847
|
"onchain_wallet_transfer_incoming",
|
|
118848
|
+
"onchain_internal_transfer_outgoing",
|
|
118849
|
+
"onchain_internal_transfer_incoming",
|
|
118657
118850
|
"onchain_swap_source",
|
|
118658
118851
|
"onchain_swap_target",
|
|
118659
118852
|
"onchain_swap_offset",
|
|
@@ -124314,6 +124507,7 @@ var native_spec_default = {
|
|
|
124314
124507
|
"ai_chat:delete",
|
|
124315
124508
|
"ai_chat:update",
|
|
124316
124509
|
"user:notifications:read",
|
|
124510
|
+
"user:abuse_report:create",
|
|
124317
124511
|
"user:notifications:update",
|
|
124318
124512
|
"user:profile:update"
|
|
124319
124513
|
],
|
|
@@ -124599,6 +124793,7 @@ var native_spec_default = {
|
|
|
124599
124793
|
"AiChatDelete",
|
|
124600
124794
|
"AiChatUpdate",
|
|
124601
124795
|
"UserNotificationsRead",
|
|
124796
|
+
"UserAbuseReportCreate",
|
|
124602
124797
|
"UserNotificationsUpdate",
|
|
124603
124798
|
"UserProfileUpdate"
|
|
124604
124799
|
]
|
|
@@ -127551,6 +127746,11 @@ var native_spec_default = {
|
|
|
127551
127746
|
example: "2026-01-01T12:00:00.000Z",
|
|
127552
127747
|
type: "string"
|
|
127553
127748
|
},
|
|
127749
|
+
direct_reports_count: {
|
|
127750
|
+
description: "How many team members report directly to this member. `null` for invites.",
|
|
127751
|
+
example: 0,
|
|
127752
|
+
type: ["integer", "null"]
|
|
127753
|
+
},
|
|
127554
127754
|
email: {
|
|
127555
127755
|
description: "The member's email address. For accepted members, `null` unless the caller holds the `company:authorized_user:email:read` scope; for invites, the invited address.",
|
|
127556
127756
|
example: "marcus@shinetime.example",
|
|
@@ -127566,6 +127766,11 @@ var native_spec_default = {
|
|
|
127566
127766
|
example: false,
|
|
127567
127767
|
type: "boolean"
|
|
127568
127768
|
},
|
|
127769
|
+
reports_to_id: {
|
|
127770
|
+
description: "The team member this member reports to, prefixed `ausr_`. `null` when the member reports to the business directly, and for invites.",
|
|
127771
|
+
example: "ausr_xxxxxxxxxxxxxx",
|
|
127772
|
+
type: ["string", "null"]
|
|
127773
|
+
},
|
|
127569
127774
|
role: {
|
|
127570
127775
|
description: "The member's role on the account. `custom` means a bespoke dashboard-managed role; the API can read but not grant it.",
|
|
127571
127776
|
enum: [
|
|
@@ -127617,6 +127822,8 @@ var native_spec_default = {
|
|
|
127617
127822
|
"created_at",
|
|
127618
127823
|
"updated_at",
|
|
127619
127824
|
"authorized_role",
|
|
127825
|
+
"reports_to_id",
|
|
127826
|
+
"direct_reports_count",
|
|
127620
127827
|
"user"
|
|
127621
127828
|
],
|
|
127622
127829
|
type: "object"
|
|
@@ -128414,6 +128621,245 @@ var native_spec_default = {
|
|
|
128414
128621
|
],
|
|
128415
128622
|
type: "object"
|
|
128416
128623
|
},
|
|
128624
|
+
UserFees: {
|
|
128625
|
+
properties: {
|
|
128626
|
+
bank_deposit: {
|
|
128627
|
+
$ref: "#/components/schemas/AccountFee",
|
|
128628
|
+
description: "Charged on bank deposits into the user's balance."
|
|
128629
|
+
},
|
|
128630
|
+
payouts: {
|
|
128631
|
+
additionalProperties: {
|
|
128632
|
+
$ref: "#/components/schemas/AccountFee"
|
|
128633
|
+
},
|
|
128634
|
+
description: "Fees on withdrawals, keyed by payout method: `bank_wire`, `same_day_bank`, `next_day_bank`, `rtp`, `crypto`, and `digital_wallet`.",
|
|
128635
|
+
example: {
|
|
128636
|
+
bank_wire: {
|
|
128637
|
+
adjustable: false,
|
|
128638
|
+
category: "payouts",
|
|
128639
|
+
default: {
|
|
128640
|
+
fixed: {
|
|
128641
|
+
amount: "30.00",
|
|
128642
|
+
currency: "usd",
|
|
128643
|
+
decimals: 2,
|
|
128644
|
+
display_decimals: 2
|
|
128645
|
+
},
|
|
128646
|
+
percentage: null
|
|
128647
|
+
},
|
|
128648
|
+
ends_at: null,
|
|
128649
|
+
fixed: {
|
|
128650
|
+
amount: "30.00",
|
|
128651
|
+
currency: "usd",
|
|
128652
|
+
decimals: 2,
|
|
128653
|
+
display_decimals: 2
|
|
128654
|
+
},
|
|
128655
|
+
maximum: null,
|
|
128656
|
+
minimum: null,
|
|
128657
|
+
percentage: null,
|
|
128658
|
+
region: null,
|
|
128659
|
+
regions: {},
|
|
128660
|
+
reset: {
|
|
128661
|
+
fixed: {
|
|
128662
|
+
amount: "30.00",
|
|
128663
|
+
currency: "usd",
|
|
128664
|
+
decimals: 2,
|
|
128665
|
+
display_decimals: 2
|
|
128666
|
+
},
|
|
128667
|
+
percentage: null
|
|
128668
|
+
},
|
|
128669
|
+
source: "default",
|
|
128670
|
+
unadjustable_reason: "not_permitted"
|
|
128671
|
+
},
|
|
128672
|
+
crypto: {
|
|
128673
|
+
adjustable: false,
|
|
128674
|
+
category: "payouts",
|
|
128675
|
+
default: {
|
|
128676
|
+
fixed: null,
|
|
128677
|
+
percentage: 0
|
|
128678
|
+
},
|
|
128679
|
+
ends_at: null,
|
|
128680
|
+
fixed: null,
|
|
128681
|
+
maximum: null,
|
|
128682
|
+
minimum: null,
|
|
128683
|
+
percentage: 0,
|
|
128684
|
+
region: null,
|
|
128685
|
+
regions: {},
|
|
128686
|
+
reset: {
|
|
128687
|
+
fixed: null,
|
|
128688
|
+
percentage: 0
|
|
128689
|
+
},
|
|
128690
|
+
source: "default",
|
|
128691
|
+
unadjustable_reason: "not_permitted"
|
|
128692
|
+
},
|
|
128693
|
+
digital_wallet: {
|
|
128694
|
+
adjustable: false,
|
|
128695
|
+
category: "payouts",
|
|
128696
|
+
default: {
|
|
128697
|
+
fixed: {
|
|
128698
|
+
amount: "0.00",
|
|
128699
|
+
currency: "usd",
|
|
128700
|
+
decimals: 2,
|
|
128701
|
+
display_decimals: 2
|
|
128702
|
+
},
|
|
128703
|
+
percentage: 0
|
|
128704
|
+
},
|
|
128705
|
+
ends_at: null,
|
|
128706
|
+
fixed: {
|
|
128707
|
+
amount: "0.00",
|
|
128708
|
+
currency: "usd",
|
|
128709
|
+
decimals: 2,
|
|
128710
|
+
display_decimals: 2
|
|
128711
|
+
},
|
|
128712
|
+
maximum: null,
|
|
128713
|
+
minimum: null,
|
|
128714
|
+
percentage: 0,
|
|
128715
|
+
region: null,
|
|
128716
|
+
regions: {},
|
|
128717
|
+
reset: {
|
|
128718
|
+
fixed: {
|
|
128719
|
+
amount: "0.00",
|
|
128720
|
+
currency: "usd",
|
|
128721
|
+
decimals: 2,
|
|
128722
|
+
display_decimals: 2
|
|
128723
|
+
},
|
|
128724
|
+
percentage: 0
|
|
128725
|
+
},
|
|
128726
|
+
source: "default",
|
|
128727
|
+
unadjustable_reason: "not_permitted"
|
|
128728
|
+
},
|
|
128729
|
+
next_day_bank: {
|
|
128730
|
+
adjustable: false,
|
|
128731
|
+
category: "payouts",
|
|
128732
|
+
default: {
|
|
128733
|
+
fixed: {
|
|
128734
|
+
amount: "2.50",
|
|
128735
|
+
currency: "usd",
|
|
128736
|
+
decimals: 2,
|
|
128737
|
+
display_decimals: 2
|
|
128738
|
+
},
|
|
128739
|
+
percentage: null
|
|
128740
|
+
},
|
|
128741
|
+
ends_at: null,
|
|
128742
|
+
fixed: {
|
|
128743
|
+
amount: "2.50",
|
|
128744
|
+
currency: "usd",
|
|
128745
|
+
decimals: 2,
|
|
128746
|
+
display_decimals: 2
|
|
128747
|
+
},
|
|
128748
|
+
maximum: null,
|
|
128749
|
+
minimum: null,
|
|
128750
|
+
percentage: null,
|
|
128751
|
+
region: null,
|
|
128752
|
+
regions: {},
|
|
128753
|
+
reset: {
|
|
128754
|
+
fixed: {
|
|
128755
|
+
amount: "2.50",
|
|
128756
|
+
currency: "usd",
|
|
128757
|
+
decimals: 2,
|
|
128758
|
+
display_decimals: 2
|
|
128759
|
+
},
|
|
128760
|
+
percentage: null
|
|
128761
|
+
},
|
|
128762
|
+
source: "default",
|
|
128763
|
+
unadjustable_reason: "not_permitted"
|
|
128764
|
+
},
|
|
128765
|
+
rtp: {
|
|
128766
|
+
adjustable: false,
|
|
128767
|
+
category: "payouts",
|
|
128768
|
+
default: {
|
|
128769
|
+
fixed: {
|
|
128770
|
+
amount: "0.00",
|
|
128771
|
+
currency: "usd",
|
|
128772
|
+
decimals: 2,
|
|
128773
|
+
display_decimals: 2
|
|
128774
|
+
},
|
|
128775
|
+
percentage: 0
|
|
128776
|
+
},
|
|
128777
|
+
ends_at: null,
|
|
128778
|
+
fixed: {
|
|
128779
|
+
amount: "0.00",
|
|
128780
|
+
currency: "usd",
|
|
128781
|
+
decimals: 2,
|
|
128782
|
+
display_decimals: 2
|
|
128783
|
+
},
|
|
128784
|
+
maximum: null,
|
|
128785
|
+
minimum: null,
|
|
128786
|
+
percentage: 0,
|
|
128787
|
+
region: null,
|
|
128788
|
+
regions: {},
|
|
128789
|
+
reset: {
|
|
128790
|
+
fixed: {
|
|
128791
|
+
amount: "0.00",
|
|
128792
|
+
currency: "usd",
|
|
128793
|
+
decimals: 2,
|
|
128794
|
+
display_decimals: 2
|
|
128795
|
+
},
|
|
128796
|
+
percentage: 0
|
|
128797
|
+
},
|
|
128798
|
+
source: "default",
|
|
128799
|
+
unadjustable_reason: "not_permitted"
|
|
128800
|
+
},
|
|
128801
|
+
same_day_bank: {
|
|
128802
|
+
adjustable: false,
|
|
128803
|
+
category: "payouts",
|
|
128804
|
+
default: {
|
|
128805
|
+
fixed: {
|
|
128806
|
+
amount: "2.50",
|
|
128807
|
+
currency: "usd",
|
|
128808
|
+
decimals: 2,
|
|
128809
|
+
display_decimals: 2
|
|
128810
|
+
},
|
|
128811
|
+
percentage: null
|
|
128812
|
+
},
|
|
128813
|
+
ends_at: null,
|
|
128814
|
+
fixed: {
|
|
128815
|
+
amount: "2.50",
|
|
128816
|
+
currency: "usd",
|
|
128817
|
+
decimals: 2,
|
|
128818
|
+
display_decimals: 2
|
|
128819
|
+
},
|
|
128820
|
+
maximum: null,
|
|
128821
|
+
minimum: null,
|
|
128822
|
+
percentage: null,
|
|
128823
|
+
region: null,
|
|
128824
|
+
regions: {},
|
|
128825
|
+
reset: {
|
|
128826
|
+
fixed: {
|
|
128827
|
+
amount: "2.50",
|
|
128828
|
+
currency: "usd",
|
|
128829
|
+
decimals: 2,
|
|
128830
|
+
display_decimals: 2
|
|
128831
|
+
},
|
|
128832
|
+
percentage: null
|
|
128833
|
+
},
|
|
128834
|
+
source: "default",
|
|
128835
|
+
unadjustable_reason: "not_permitted"
|
|
128836
|
+
}
|
|
128837
|
+
},
|
|
128838
|
+
type: "object"
|
|
128839
|
+
},
|
|
128840
|
+
pending_auto_topup: {
|
|
128841
|
+
$ref: "#/components/schemas/AccountFee",
|
|
128842
|
+
description: "Charged when pending, not-yet-settled balance is advanced to fund the user's cards balance."
|
|
128843
|
+
},
|
|
128844
|
+
transfers: {
|
|
128845
|
+
$ref: "#/components/schemas/AccountFee",
|
|
128846
|
+
description: "Charged on transfers from the user's balance to another Whop balance."
|
|
128847
|
+
},
|
|
128848
|
+
user_id: {
|
|
128849
|
+
description: "The user these fees are charged to, prefixed `user_`.",
|
|
128850
|
+
example: "user_xxxxxxxxxxxxxx",
|
|
128851
|
+
type: "string"
|
|
128852
|
+
}
|
|
128853
|
+
},
|
|
128854
|
+
required: [
|
|
128855
|
+
"user_id",
|
|
128856
|
+
"payouts",
|
|
128857
|
+
"transfers",
|
|
128858
|
+
"pending_auto_topup",
|
|
128859
|
+
"bank_deposit"
|
|
128860
|
+
],
|
|
128861
|
+
type: "object"
|
|
128862
|
+
},
|
|
128417
128863
|
UserNotificationPreference: {
|
|
128418
128864
|
properties: {
|
|
128419
128865
|
created_at: {
|
|
@@ -129421,7 +129867,7 @@ var native_spec_default = {
|
|
|
129421
129867
|
},
|
|
129422
129868
|
api_version_date: {
|
|
129423
129869
|
description: "The dated API version (Api-Version-Date) that v1 payloads for this endpoint are pinned to: events serialize exactly like a REST read at this version (the native serializer where the resource has one). Null when unpinned \u2014 legacy (v2/v5) webhooks, and v1 webhooks on the legacy payload shape.",
|
|
129424
|
-
example: "2026-
|
|
129870
|
+
example: "2026-01-01",
|
|
129425
129871
|
type: ["string", "null"]
|
|
129426
129872
|
},
|
|
129427
129873
|
child_resource_events: {
|
|
@@ -129532,10 +129978,13 @@ var native_spec_default = {
|
|
|
129532
129978
|
"shipment.updated",
|
|
129533
129979
|
"member.created",
|
|
129534
129980
|
"member.updated",
|
|
129981
|
+
"ad_campaign.created",
|
|
129535
129982
|
"ad_campaign.payment_failed",
|
|
129536
129983
|
"ad_campaign.updated",
|
|
129537
129984
|
"ad_campaign.events",
|
|
129985
|
+
"ad_group.created",
|
|
129538
129986
|
"ad_group.updated",
|
|
129987
|
+
"ad.created",
|
|
129539
129988
|
"ad.updated",
|
|
129540
129989
|
"chat.message.created",
|
|
129541
129990
|
"chat.reaction.created",
|
|
@@ -129669,10 +130118,13 @@ var native_spec_default = {
|
|
|
129669
130118
|
"shipment.updated",
|
|
129670
130119
|
"member.created",
|
|
129671
130120
|
"member.updated",
|
|
130121
|
+
"ad_campaign.created",
|
|
129672
130122
|
"ad_campaign.payment_failed",
|
|
129673
130123
|
"ad_campaign.updated",
|
|
129674
130124
|
"ad_campaign.events",
|
|
130125
|
+
"ad_group.created",
|
|
129675
130126
|
"ad_group.updated",
|
|
130127
|
+
"ad.created",
|
|
129676
130128
|
"ad.updated",
|
|
129677
130129
|
"chat.message.created",
|
|
129678
130130
|
"chat.reaction.created",
|
|
@@ -129825,7 +130277,7 @@ var native_spec_default = {
|
|
|
129825
130277
|
},
|
|
129826
130278
|
api_version_date: {
|
|
129827
130279
|
description: "The dated API version (Api-Version-Date) that v1 payloads for this endpoint are pinned to: events serialize exactly like a REST read at this version (the native serializer where the resource has one). Null when unpinned \u2014 legacy (v2/v5) webhooks, and v1 webhooks on the legacy payload shape.",
|
|
129828
|
-
example: "2026-
|
|
130280
|
+
example: "2026-01-01",
|
|
129829
130281
|
type: ["string", "null"]
|
|
129830
130282
|
},
|
|
129831
130283
|
child_resource_events: {
|
|
@@ -129936,10 +130388,13 @@ var native_spec_default = {
|
|
|
129936
130388
|
"shipment.updated",
|
|
129937
130389
|
"member.created",
|
|
129938
130390
|
"member.updated",
|
|
130391
|
+
"ad_campaign.created",
|
|
129939
130392
|
"ad_campaign.payment_failed",
|
|
129940
130393
|
"ad_campaign.updated",
|
|
129941
130394
|
"ad_campaign.events",
|
|
130395
|
+
"ad_group.created",
|
|
129942
130396
|
"ad_group.updated",
|
|
130397
|
+
"ad.created",
|
|
129943
130398
|
"ad.updated",
|
|
129944
130399
|
"chat.message.created",
|
|
129945
130400
|
"chat.reaction.created",
|
|
@@ -130136,7 +130591,7 @@ var apps_spec_default = {
|
|
|
130136
130591
|
termsOfService: "https://whop.com/tos-developer-api/",
|
|
130137
130592
|
title: "Whop API",
|
|
130138
130593
|
version: "1.0.0",
|
|
130139
|
-
"x-api-version-date": "2026-10-
|
|
130594
|
+
"x-api-version-date": "2026-10-14"
|
|
130140
130595
|
},
|
|
130141
130596
|
paths: {
|
|
130142
130597
|
"/app_builds": {
|
|
@@ -130715,7 +131170,6 @@ var apps_spec_default = {
|
|
|
130715
131170
|
},
|
|
130716
131171
|
base_url: {
|
|
130717
131172
|
description: "The base production URL where the app is hosted, such as `https://myapp.example.com`.",
|
|
130718
|
-
example: "https://booking.shinetime.example",
|
|
130719
131173
|
type: ["string", "null"]
|
|
130720
131174
|
},
|
|
130721
131175
|
domain_id: {
|
|
@@ -130990,7 +131444,7 @@ var apps_spec_default = {
|
|
|
130990
131444
|
},
|
|
130991
131445
|
base_url: {
|
|
130992
131446
|
description: "The base production URL where the app is hosted. Set to `null` to take the app proxy offline.",
|
|
130993
|
-
example: "https://booking.
|
|
131447
|
+
example: "https://shine-time-booking.whop.site",
|
|
130994
131448
|
type: ["string", "null"]
|
|
130995
131449
|
},
|
|
130996
131450
|
dashboard_path: {
|
|
@@ -131620,7 +132074,7 @@ var apps_spec_default = {
|
|
|
131620
132074
|
},
|
|
131621
132075
|
base_url: {
|
|
131622
132076
|
description: "The production base URL where the app is hosted. `null` if no base URL is configured, if the caller lacks the `developer:basic:read` permission on the app's account, or on list responses, which never expose it.",
|
|
131623
|
-
example: "https://booking.
|
|
132077
|
+
example: "https://shine-time-booking-store.whop.site",
|
|
131624
132078
|
type: ["string", "null"]
|
|
131625
132079
|
},
|
|
131626
132080
|
businesses_created_count: {
|
|
@@ -131805,7 +132259,7 @@ var apps_spec_default = {
|
|
|
131805
132259
|
},
|
|
131806
132260
|
base_url: {
|
|
131807
132261
|
description: "The production base URL where the app is hosted. `null` if no base URL is configured, if the caller lacks the `developer:basic:read` permission on the app's account, or on list responses, which never expose it.",
|
|
131808
|
-
example: "https://booking.
|
|
132262
|
+
example: "https://shine-time-booking.whop.site",
|
|
131809
132263
|
type: ["string", "null"]
|
|
131810
132264
|
},
|
|
131811
132265
|
businesses_created_count: {
|
|
@@ -132489,7 +132943,7 @@ var apps_spec_default = {
|
|
|
132489
132943
|
name: "Api-Version-Date",
|
|
132490
132944
|
required: false,
|
|
132491
132945
|
schema: {
|
|
132492
|
-
example: "2026-10-
|
|
132946
|
+
example: "2026-10-14",
|
|
132493
132947
|
type: "string"
|
|
132494
132948
|
}
|
|
132495
132949
|
},
|
|
@@ -132568,7 +133022,7 @@ var files_spec_default = {
|
|
|
132568
133022
|
termsOfService: "https://whop.com/tos-developer-api/",
|
|
132569
133023
|
title: "Whop API",
|
|
132570
133024
|
version: "1.0.0",
|
|
132571
|
-
"x-api-version-date": "2026-10-
|
|
133025
|
+
"x-api-version-date": "2026-10-14"
|
|
132572
133026
|
},
|
|
132573
133027
|
paths: {
|
|
132574
133028
|
"/files": {
|
|
@@ -133146,7 +133600,7 @@ var files_spec_default = {
|
|
|
133146
133600
|
name: "Api-Version-Date",
|
|
133147
133601
|
required: false,
|
|
133148
133602
|
schema: {
|
|
133149
|
-
example: "2026-10-
|
|
133603
|
+
example: "2026-10-14",
|
|
133150
133604
|
type: "string"
|
|
133151
133605
|
}
|
|
133152
133606
|
},
|
|
@@ -133287,7 +133741,7 @@ async function announceActionUrl(url2, {
|
|
|
133287
133741
|
// package.json
|
|
133288
133742
|
var package_default = {
|
|
133289
133743
|
name: "@whop/cli",
|
|
133290
|
-
version: "0.
|
|
133744
|
+
version: "0.27.0",
|
|
133291
133745
|
description: "The Whop CLI \u2014 build and manage Whop apps from your terminal. Human and agent friendly.",
|
|
133292
133746
|
keywords: [
|
|
133293
133747
|
"agent",
|
|
@@ -135658,7 +136112,7 @@ var groups_default = [
|
|
|
135658
136112
|
{
|
|
135659
136113
|
name: "payment-method-domains",
|
|
135660
136114
|
tag: "Payment Method Domains",
|
|
135661
|
-
description: "
|
|
136115
|
+
description: "Deprecated: domains verified to show Apple Pay at checkout. Use Domains instead.",
|
|
135662
136116
|
group: "Commerce"
|
|
135663
136117
|
},
|
|
135664
136118
|
{
|
|
@@ -135908,11 +136362,443 @@ async function buildSubgroupedGroup(name, description, spec2, fetch3) {
|
|
|
135908
136362
|
// src/apps/commands.ts
|
|
135909
136363
|
import { spinner as spinner4 } from "@clack/prompts";
|
|
135910
136364
|
import { createHash as createHash3 } from "crypto";
|
|
135911
|
-
import { existsSync as existsSync12, mkdtempSync as mkdtempSync3, readFileSync as readFileSync12, rmSync as
|
|
136365
|
+
import { existsSync as existsSync12, mkdtempSync as mkdtempSync3, readFileSync as readFileSync12, rmSync as rmSync5 } from "fs";
|
|
135912
136366
|
import { tmpdir as tmpdir3 } from "os";
|
|
135913
|
-
import { join as
|
|
136367
|
+
import { join as join13, relative as relative3, resolve as resolve9 } from "path";
|
|
135914
136368
|
import chalk2 from "chalk";
|
|
135915
136369
|
|
|
136370
|
+
// src/apps/config.ts
|
|
136371
|
+
import { existsSync as existsSync8, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
|
|
136372
|
+
import { join as join6, resolve as resolve5 } from "path";
|
|
136373
|
+
var APP_CONFIG_FILENAME = "whop.app.json";
|
|
136374
|
+
var PLATFORM_DOMAIN_SUFFIX = "whop.site";
|
|
136375
|
+
function linkConfigFor(app) {
|
|
136376
|
+
return { app_id: app.id, name: app.name };
|
|
136377
|
+
}
|
|
136378
|
+
function findProjectDir(startDir) {
|
|
136379
|
+
let dir = resolve5(startDir ?? process.cwd());
|
|
136380
|
+
for (let i = 0; i < 25; i++) {
|
|
136381
|
+
if (existsSync8(join6(dir, APP_CONFIG_FILENAME))) return dir;
|
|
136382
|
+
const parent = resolve5(dir, "..");
|
|
136383
|
+
if (parent === dir) break;
|
|
136384
|
+
dir = parent;
|
|
136385
|
+
}
|
|
136386
|
+
return null;
|
|
136387
|
+
}
|
|
136388
|
+
function readAppConfig(projectDir) {
|
|
136389
|
+
const path9 = join6(projectDir, APP_CONFIG_FILENAME);
|
|
136390
|
+
if (!existsSync8(path9)) return null;
|
|
136391
|
+
try {
|
|
136392
|
+
const parsed = JSON.parse(
|
|
136393
|
+
readFileSync8(path9, "utf-8")
|
|
136394
|
+
);
|
|
136395
|
+
if (typeof parsed.app_id !== "string") return null;
|
|
136396
|
+
return {
|
|
136397
|
+
app_id: parsed.app_id,
|
|
136398
|
+
name: typeof parsed.name === "string" ? parsed.name : parsed.app_id
|
|
136399
|
+
};
|
|
136400
|
+
} catch {
|
|
136401
|
+
return null;
|
|
136402
|
+
}
|
|
136403
|
+
}
|
|
136404
|
+
function writeAppConfig(projectDir, config2) {
|
|
136405
|
+
writeFileSync6(
|
|
136406
|
+
join6(projectDir, APP_CONFIG_FILENAME),
|
|
136407
|
+
`${JSON.stringify(config2, null, " ")}
|
|
136408
|
+
`
|
|
136409
|
+
);
|
|
136410
|
+
}
|
|
136411
|
+
function appSlug(app) {
|
|
136412
|
+
return slugify4(app.name) || app.id.toLowerCase().replace("_", "-");
|
|
136413
|
+
}
|
|
136414
|
+
function platformDomainFor(name) {
|
|
136415
|
+
return `${slugify4(name)}.${PLATFORM_DOMAIN_SUFFIX}`;
|
|
136416
|
+
}
|
|
136417
|
+
function domainFor(input) {
|
|
136418
|
+
const host = input.trim().toLowerCase();
|
|
136419
|
+
return host.includes(".") ? host : platformDomainFor(host);
|
|
136420
|
+
}
|
|
136421
|
+
function slugify4(name) {
|
|
136422
|
+
return name.toLowerCase().normalize("NFKD").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 63);
|
|
136423
|
+
}
|
|
136424
|
+
|
|
136425
|
+
// src/apps/shared.ts
|
|
136426
|
+
import { isCancel as isCancel4, select as select3, spinner as spinner2, text as text2 } from "@clack/prompts";
|
|
136427
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
136428
|
+
import { existsSync as existsSync10, readFileSync as readFileSync10 } from "fs";
|
|
136429
|
+
import { join as join8 } from "path";
|
|
136430
|
+
|
|
136431
|
+
// src/apps/scaffold.ts
|
|
136432
|
+
import { spawnSync } from "child_process";
|
|
136433
|
+
import { existsSync as existsSync9, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
|
|
136434
|
+
import { basename as basename3, join as join7 } from "path";
|
|
136435
|
+
var SPAWN_VIA_SHELL = process.platform === "win32";
|
|
136436
|
+
var DLX_RUNNERS = {
|
|
136437
|
+
npm: ["npx", "-y"],
|
|
136438
|
+
pnpm: ["pnpm", "dlx"],
|
|
136439
|
+
bun: ["bunx"],
|
|
136440
|
+
yarn: ["yarn", "dlx"]
|
|
136441
|
+
};
|
|
136442
|
+
var PM_PRIORITY = [
|
|
136443
|
+
"bun",
|
|
136444
|
+
"pnpm",
|
|
136445
|
+
"npm"
|
|
136446
|
+
];
|
|
136447
|
+
function isPmInstalled(pm) {
|
|
136448
|
+
const result = spawnSync(pm, ["--version"], {
|
|
136449
|
+
stdio: "ignore",
|
|
136450
|
+
shell: SPAWN_VIA_SHELL
|
|
136451
|
+
});
|
|
136452
|
+
return !result.error && result.status === 0;
|
|
136453
|
+
}
|
|
136454
|
+
function detectPackageManager() {
|
|
136455
|
+
return PM_PRIORITY.find(isPmInstalled) ?? null;
|
|
136456
|
+
}
|
|
136457
|
+
function pmInstallHint(pm) {
|
|
136458
|
+
const win = process.platform === "win32";
|
|
136459
|
+
switch (pm) {
|
|
136460
|
+
case "bun":
|
|
136461
|
+
return win ? 'powershell -c "irm bun.sh/install.ps1 | iex"' : "curl -fsSL https://bun.sh/install | bash";
|
|
136462
|
+
case "pnpm":
|
|
136463
|
+
return win ? 'powershell -c "irm get.pnpm.io/install.ps1 | iex"' : "curl -fsSL https://get.pnpm.io/install.sh | sh -";
|
|
136464
|
+
case "npm":
|
|
136465
|
+
return "install Node.js (includes npm): https://nodejs.org";
|
|
136466
|
+
case "yarn":
|
|
136467
|
+
return "npm install -g yarn";
|
|
136468
|
+
}
|
|
136469
|
+
}
|
|
136470
|
+
var TANSTACK_CREATE_FLAGS = [
|
|
136471
|
+
"--framework",
|
|
136472
|
+
"React",
|
|
136473
|
+
"--deployment",
|
|
136474
|
+
"cloudflare",
|
|
136475
|
+
"--no-git",
|
|
136476
|
+
"--no-install",
|
|
136477
|
+
"--no-intent",
|
|
136478
|
+
"--no-toolchain",
|
|
136479
|
+
"--no-examples",
|
|
136480
|
+
"--non-interactive"
|
|
136481
|
+
];
|
|
136482
|
+
function outputTail(result) {
|
|
136483
|
+
const combined = [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
|
|
136484
|
+
if (!combined) return "";
|
|
136485
|
+
return `
|
|
136486
|
+
|
|
136487
|
+
${combined.split("\n").slice(-15).join("\n")}`;
|
|
136488
|
+
}
|
|
136489
|
+
function runTanstackCreate(options) {
|
|
136490
|
+
const [runner, ...runnerArgs] = DLX_RUNNERS[options.pm];
|
|
136491
|
+
const result = spawnSync(
|
|
136492
|
+
runner,
|
|
136493
|
+
[
|
|
136494
|
+
...runnerArgs,
|
|
136495
|
+
"@tanstack/cli@latest",
|
|
136496
|
+
"create",
|
|
136497
|
+
options.projectName,
|
|
136498
|
+
"--target-dir",
|
|
136499
|
+
options.targetDir,
|
|
136500
|
+
...TANSTACK_CREATE_FLAGS
|
|
136501
|
+
],
|
|
136502
|
+
{
|
|
136503
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
136504
|
+
encoding: "utf-8",
|
|
136505
|
+
shell: SPAWN_VIA_SHELL
|
|
136506
|
+
}
|
|
136507
|
+
);
|
|
136508
|
+
if (result.error) throw result.error;
|
|
136509
|
+
if (result.status !== 0) {
|
|
136510
|
+
throw new Error(
|
|
136511
|
+
`\`${options.pm === "npm" ? "npx" : options.pm} @tanstack/cli create\` failed (exit ${result.status}). Check your network connection and try again.${outputTail(result)}`
|
|
136512
|
+
);
|
|
136513
|
+
}
|
|
136514
|
+
}
|
|
136515
|
+
var VITE_CONFIG_NAMES = [
|
|
136516
|
+
"vite.config.ts",
|
|
136517
|
+
"vite.config.mts",
|
|
136518
|
+
"vite.config.js",
|
|
136519
|
+
"vite.config.mjs"
|
|
136520
|
+
];
|
|
136521
|
+
function findViteConfig(dir) {
|
|
136522
|
+
return VITE_CONFIG_NAMES.map((name) => join7(dir, name)).find(
|
|
136523
|
+
(path9) => existsSync9(path9)
|
|
136524
|
+
);
|
|
136525
|
+
}
|
|
136526
|
+
var WRANGLER_CONFIG_NAMES = ["wrangler.jsonc", "wrangler.json"];
|
|
136527
|
+
function whopifyProject(options) {
|
|
136528
|
+
const manualSteps = [];
|
|
136529
|
+
patchPackageJson(options.targetDir, manualSteps);
|
|
136530
|
+
patchViteConfig(options.targetDir, manualSteps);
|
|
136531
|
+
patchWranglerConfig(options.targetDir, options.workerName, manualSteps);
|
|
136532
|
+
return { manualSteps };
|
|
136533
|
+
}
|
|
136534
|
+
function patchPackageJson(dir, manualSteps) {
|
|
136535
|
+
const file2 = join7(dir, "package.json");
|
|
136536
|
+
let raw;
|
|
136537
|
+
let pkg;
|
|
136538
|
+
try {
|
|
136539
|
+
raw = readFileSync9(file2, "utf-8");
|
|
136540
|
+
pkg = JSON.parse(raw);
|
|
136541
|
+
} catch {
|
|
136542
|
+
manualSteps.push(
|
|
136543
|
+
'package.json could not be parsed. Add a "deploy": "whop apps deploy" script, a "typecheck" script, and a devDependency "@whop/cli": "latest".'
|
|
136544
|
+
);
|
|
136545
|
+
return;
|
|
136546
|
+
}
|
|
136547
|
+
pkg.scripts = {
|
|
136548
|
+
...pkg.scripts,
|
|
136549
|
+
deploy: "whop apps deploy",
|
|
136550
|
+
typecheck: pkg.scripts?.typecheck ?? "tsc --noEmit"
|
|
136551
|
+
};
|
|
136552
|
+
pkg.devDependencies = {
|
|
136553
|
+
...pkg.devDependencies,
|
|
136554
|
+
// The project imports the whop() vite plugin from @whop/cli/vite. Pinned
|
|
136555
|
+
// to the building binary's own version until that broke: a standalone
|
|
136556
|
+
// build carries the workspace version, which is routinely ahead of what
|
|
136557
|
+
// is on npm, so the pin resolved to nothing and install failed.
|
|
136558
|
+
"@whop/cli": pkg.devDependencies?.["@whop/cli"] ?? "latest"
|
|
136559
|
+
};
|
|
136560
|
+
writeIfChanged(file2, `${JSON.stringify(pkg, null, 2)}
|
|
136561
|
+
`, raw);
|
|
136562
|
+
}
|
|
136563
|
+
function writeIfChanged(file2, next, current) {
|
|
136564
|
+
if (next === current) return;
|
|
136565
|
+
writeFileSync7(file2, next);
|
|
136566
|
+
}
|
|
136567
|
+
var WHOP_PLUGIN_CALL = "whop({ disableTanstackDevtools: true })";
|
|
136568
|
+
function patchViteConfig(dir, manualSteps) {
|
|
136569
|
+
const file2 = findViteConfig(dir);
|
|
136570
|
+
if (!file2) {
|
|
136571
|
+
manualSteps.push(
|
|
136572
|
+
"No vite config found (looked for vite.config.ts/.mts/.js/.mjs). Whop hosting serves Vite builds \u2014 create a vite config that builds with @cloudflare/vite-plugin (emitting dist/client and, for SSR, dist/server) and includes the whop() plugin from @whop/cli/vite in its plugins array."
|
|
136573
|
+
);
|
|
136574
|
+
return;
|
|
136575
|
+
}
|
|
136576
|
+
let content = readFileSync9(file2, "utf-8");
|
|
136577
|
+
const hasWhopPlugin = content.includes("@whop/cli/vite");
|
|
136578
|
+
if (!hasWhopPlugin) {
|
|
136579
|
+
const pluginsOpen = /plugins:\s*\[/;
|
|
136580
|
+
if (!pluginsOpen.test(content)) {
|
|
136581
|
+
manualSteps.push(
|
|
136582
|
+
`Could not find a \`plugins: [...]\` array in ${basename3(file2)}. Add \`import { whop } from '@whop/cli/vite'\` and include \`whop()\` in the config's plugins so builds pack dist/whop-build.zip.`
|
|
136583
|
+
);
|
|
136584
|
+
} else {
|
|
136585
|
+
content = `import { whop } from '@whop/cli/vite'
|
|
136586
|
+
${content}`;
|
|
136587
|
+
content = content.replace(
|
|
136588
|
+
pluginsOpen,
|
|
136589
|
+
(match) => `${match}
|
|
136590
|
+
${WHOP_PLUGIN_CALL},`
|
|
136591
|
+
);
|
|
136592
|
+
writeFileSync7(file2, content);
|
|
136593
|
+
}
|
|
136594
|
+
}
|
|
136595
|
+
if (!content.includes("@cloudflare/vite-plugin")) {
|
|
136596
|
+
manualSteps.push(
|
|
136597
|
+
`${basename3(file2)} does not use @cloudflare/vite-plugin. Whop hosting runs builds on Cloudflare Workers: install @cloudflare/vite-plugin and wrangler, add \`cloudflare({ viteEnvironment: { name: 'ssr' } })\` to the plugins array (before your framework plugin), and make sure \`vite build\` emits dist/client (static assets) and dist/server (worker modules with an index.js entry).`
|
|
136598
|
+
);
|
|
136599
|
+
}
|
|
136600
|
+
}
|
|
136601
|
+
function patchWranglerConfig(dir, workerName, manualSteps) {
|
|
136602
|
+
const file2 = WRANGLER_CONFIG_NAMES.map((name) => join7(dir, name)).find(
|
|
136603
|
+
(path9) => existsSync9(path9)
|
|
136604
|
+
);
|
|
136605
|
+
if (!file2) {
|
|
136606
|
+
manualSteps.push(
|
|
136607
|
+
`No wrangler config found. Create wrangler.jsonc with: { "name": "${workerName}", "compatibility_date": "<today>", "compatibility_flags": ["nodejs_compat"], "main": "<your framework's server entry>" } (for TanStack Start the main is "@tanstack/react-start/server-entry").`
|
|
136608
|
+
);
|
|
136609
|
+
return;
|
|
136610
|
+
}
|
|
136611
|
+
const content = readFileSync9(file2, "utf-8");
|
|
136612
|
+
const updated = replaceTopLevelName(content, workerName);
|
|
136613
|
+
if (updated) {
|
|
136614
|
+
writeIfChanged(file2, updated, content);
|
|
136615
|
+
} else {
|
|
136616
|
+
manualSteps.push(
|
|
136617
|
+
`Set the top-level "name" in ${basename3(file2)} to "${workerName}" so the worker is named after the app.`
|
|
136618
|
+
);
|
|
136619
|
+
}
|
|
136620
|
+
}
|
|
136621
|
+
function replaceTopLevelName(content, name) {
|
|
136622
|
+
let depth = 0;
|
|
136623
|
+
let i = 0;
|
|
136624
|
+
while (i < content.length) {
|
|
136625
|
+
const ch = content[i];
|
|
136626
|
+
if (ch === '"') {
|
|
136627
|
+
let j = i + 1;
|
|
136628
|
+
while (j < content.length && content[j] !== '"') {
|
|
136629
|
+
j += content[j] === "\\" ? 2 : 1;
|
|
136630
|
+
}
|
|
136631
|
+
if (depth === 1 && content.slice(i + 1, j) === "name") {
|
|
136632
|
+
const after = content.slice(j + 1);
|
|
136633
|
+
const value = after.match(/^(\s*:\s*)"(?:[^"\\]|\\.)*"/);
|
|
136634
|
+
if (value) {
|
|
136635
|
+
const start = j + 1 + value[1].length;
|
|
136636
|
+
const end = j + 1 + value[0].length;
|
|
136637
|
+
return `${content.slice(0, start)}"${name}"${content.slice(end)}`;
|
|
136638
|
+
}
|
|
136639
|
+
}
|
|
136640
|
+
i = j + 1;
|
|
136641
|
+
continue;
|
|
136642
|
+
}
|
|
136643
|
+
if (ch === "/" && content[i + 1] === "/") {
|
|
136644
|
+
const newline = content.indexOf("\n", i);
|
|
136645
|
+
i = newline === -1 ? content.length : newline + 1;
|
|
136646
|
+
continue;
|
|
136647
|
+
}
|
|
136648
|
+
if (ch === "/" && content[i + 1] === "*") {
|
|
136649
|
+
const close = content.indexOf("*/", i + 2);
|
|
136650
|
+
i = close === -1 ? content.length : close + 2;
|
|
136651
|
+
continue;
|
|
136652
|
+
}
|
|
136653
|
+
if (ch === "{" || ch === "[") depth++;
|
|
136654
|
+
if (ch === "}" || ch === "]") depth--;
|
|
136655
|
+
i++;
|
|
136656
|
+
}
|
|
136657
|
+
return null;
|
|
136658
|
+
}
|
|
136659
|
+
|
|
136660
|
+
// src/apps/shared.ts
|
|
136661
|
+
var CommandAbort = class extends Error {
|
|
136662
|
+
constructor(options) {
|
|
136663
|
+
super(options.message);
|
|
136664
|
+
this.options = options;
|
|
136665
|
+
}
|
|
136666
|
+
};
|
|
136667
|
+
function log2(c2, message) {
|
|
136668
|
+
if (!c2.agent) console.log(message);
|
|
136669
|
+
}
|
|
136670
|
+
var PHASE_MARKER = "[whop:phase]";
|
|
136671
|
+
function phase(name) {
|
|
136672
|
+
process.stderr.write(`${PHASE_MARKER} ${name} t=${Date.now()}
|
|
136673
|
+
`);
|
|
136674
|
+
}
|
|
136675
|
+
function cancelled() {
|
|
136676
|
+
throw new CommandAbort({
|
|
136677
|
+
code: "CANCELLED",
|
|
136678
|
+
message: "Cancelled.",
|
|
136679
|
+
exitCode: 130
|
|
136680
|
+
});
|
|
136681
|
+
}
|
|
136682
|
+
async function promptText(message, placeholder, initialValue) {
|
|
136683
|
+
const value = await text2({ message, placeholder, initialValue });
|
|
136684
|
+
if (isCancel4(value)) return null;
|
|
136685
|
+
return String(value);
|
|
136686
|
+
}
|
|
136687
|
+
async function promptSelect(message, options) {
|
|
136688
|
+
const choice = await select3({ message, options });
|
|
136689
|
+
if (isCancel4(choice)) cancelled();
|
|
136690
|
+
return String(choice);
|
|
136691
|
+
}
|
|
136692
|
+
async function promptForAppType() {
|
|
136693
|
+
const choice = await promptSelect("What are you building?", [
|
|
136694
|
+
{ value: "b2c_app", label: "An app \u2014 creators install it into their whop" },
|
|
136695
|
+
{ value: "website", label: "A website \u2014 visitors browse it at its domain" }
|
|
136696
|
+
]);
|
|
136697
|
+
return choice;
|
|
136698
|
+
}
|
|
136699
|
+
async function promptForNewApp(knownAppType) {
|
|
136700
|
+
const appType = knownAppType ?? await promptForAppType();
|
|
136701
|
+
const name = await promptText("What is your app called?", "My Site");
|
|
136702
|
+
if (name === null) cancelled();
|
|
136703
|
+
return { name, domain: await promptForDomain(name), appType };
|
|
136704
|
+
}
|
|
136705
|
+
async function promptForDomain(name) {
|
|
136706
|
+
const suggested = platformDomainFor(name);
|
|
136707
|
+
const input = await promptText(
|
|
136708
|
+
`Which domain should it live at? (a ${PLATFORM_DOMAIN_SUFFIX} name, or a domain you own)`,
|
|
136709
|
+
suggested,
|
|
136710
|
+
suggested
|
|
136711
|
+
);
|
|
136712
|
+
if (input === null) cancelled();
|
|
136713
|
+
const domain2 = domainFor(input);
|
|
136714
|
+
if (domain2 === `.${PLATFORM_DOMAIN_SUFFIX}`) {
|
|
136715
|
+
throw new CommandAbort({
|
|
136716
|
+
code: "DOMAIN_REQUIRED",
|
|
136717
|
+
message: `Couldn't derive a domain from "${input}" \u2014 use letters and numbers (e.g. my-site).`,
|
|
136718
|
+
retryable: true
|
|
136719
|
+
});
|
|
136720
|
+
}
|
|
136721
|
+
return domain2;
|
|
136722
|
+
}
|
|
136723
|
+
function ensurePackageManager() {
|
|
136724
|
+
const pm = detectPackageManager();
|
|
136725
|
+
if (pm) return pm;
|
|
136726
|
+
throw new CommandAbort({
|
|
136727
|
+
code: "NO_PACKAGE_MANAGER",
|
|
136728
|
+
message: `No package manager found (looked for bun, pnpm, npm). Install one and retry:
|
|
136729
|
+
|
|
136730
|
+
bun (recommended): ${pmInstallHint("bun")}
|
|
136731
|
+
pnpm: ${pmInstallHint("pnpm")}
|
|
136732
|
+
npm: ${pmInstallHint("npm")}`
|
|
136733
|
+
});
|
|
136734
|
+
}
|
|
136735
|
+
var SPAWN_VIA_SHELL2 = process.platform === "win32";
|
|
136736
|
+
function detectProjectPackageManager(projectDir) {
|
|
136737
|
+
if (existsSync10(join8(projectDir, "bun.lock")) || existsSync10(join8(projectDir, "bun.lockb")))
|
|
136738
|
+
return "bun";
|
|
136739
|
+
if (existsSync10(join8(projectDir, "pnpm-lock.yaml"))) return "pnpm";
|
|
136740
|
+
if (existsSync10(join8(projectDir, "yarn.lock"))) return "yarn";
|
|
136741
|
+
if (existsSync10(join8(projectDir, "package-lock.json"))) return "npm";
|
|
136742
|
+
return detectPackageManager() ?? "npm";
|
|
136743
|
+
}
|
|
136744
|
+
function hasScript(projectDir, script) {
|
|
136745
|
+
try {
|
|
136746
|
+
const pkg = JSON.parse(
|
|
136747
|
+
readFileSync10(join8(projectDir, "package.json"), "utf-8")
|
|
136748
|
+
);
|
|
136749
|
+
return Boolean(pkg.scripts?.[script]);
|
|
136750
|
+
} catch {
|
|
136751
|
+
return false;
|
|
136752
|
+
}
|
|
136753
|
+
}
|
|
136754
|
+
function runScript(projectDir, script, extraEnv = {}, scriptArgs = []) {
|
|
136755
|
+
const pm = detectProjectPackageManager(projectDir);
|
|
136756
|
+
const separator = pm === "npm" && scriptArgs.length > 0 ? ["--"] : [];
|
|
136757
|
+
const result = spawnSync2(pm, ["run", script, ...separator, ...scriptArgs], {
|
|
136758
|
+
cwd: projectDir,
|
|
136759
|
+
stdio: "inherit",
|
|
136760
|
+
shell: SPAWN_VIA_SHELL2,
|
|
136761
|
+
env: { ...process.env, ...extraEnv }
|
|
136762
|
+
});
|
|
136763
|
+
if (result.error) {
|
|
136764
|
+
throw new Error(
|
|
136765
|
+
`Could not run \`${pm} run ${script}\`: ${result.error.message}`
|
|
136766
|
+
);
|
|
136767
|
+
}
|
|
136768
|
+
if (result.status !== 0) {
|
|
136769
|
+
throw new Error(
|
|
136770
|
+
`\`${pm} run ${script}\` failed with exit code ${result.status ?? "unknown"}`
|
|
136771
|
+
);
|
|
136772
|
+
}
|
|
136773
|
+
}
|
|
136774
|
+
function runInstall(c2, projectDir) {
|
|
136775
|
+
const pm = detectProjectPackageManager(projectDir);
|
|
136776
|
+
const spin = c2.agent ? null : spinner2();
|
|
136777
|
+
spin?.start(`Installing dependencies with ${pm}`);
|
|
136778
|
+
const result = spawnSync2(pm, ["install"], {
|
|
136779
|
+
cwd: projectDir,
|
|
136780
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
136781
|
+
encoding: "utf-8",
|
|
136782
|
+
shell: SPAWN_VIA_SHELL2
|
|
136783
|
+
});
|
|
136784
|
+
if (result.error || result.status !== 0) {
|
|
136785
|
+
spin?.error(`${pm} install failed`);
|
|
136786
|
+
throw new Error(
|
|
136787
|
+
`\`${pm} install\` failed${result.status != null ? ` with exit code ${result.status}` : ""} \u2014 run it manually inside ${projectDir}, then retry.${outputTail(result)}`
|
|
136788
|
+
);
|
|
136789
|
+
}
|
|
136790
|
+
spin?.stop(`Installed dependencies with ${pm}`);
|
|
136791
|
+
}
|
|
136792
|
+
async function downloadArchive(sourceUrl) {
|
|
136793
|
+
const response = await fetch(sourceUrl);
|
|
136794
|
+
if (!response.ok) {
|
|
136795
|
+
throw new Error(
|
|
136796
|
+
`Download failed: ${response.status} ${response.statusText}`
|
|
136797
|
+
);
|
|
136798
|
+
}
|
|
136799
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
136800
|
+
}
|
|
136801
|
+
|
|
135916
136802
|
// src/apps/api.ts
|
|
135917
136803
|
async function createApp(input) {
|
|
135918
136804
|
const company_id = input.company_id ?? await resolveActiveAccountId();
|
|
@@ -135938,8 +136824,70 @@ async function listApps() {
|
|
|
135938
136824
|
async function getApp(appId) {
|
|
135939
136825
|
return makeWhopRequest("GET", `/apps/${appId}`);
|
|
135940
136826
|
}
|
|
135941
|
-
async function
|
|
135942
|
-
|
|
136827
|
+
async function pendingDomainSteps(app) {
|
|
136828
|
+
const pending = (app.domains ?? []).filter((d) => d.status !== "ready");
|
|
136829
|
+
const steps = await Promise.all(
|
|
136830
|
+
pending.map(async ({ id, domain: domain2 }) => {
|
|
136831
|
+
let details;
|
|
136832
|
+
try {
|
|
136833
|
+
details = await makeWhopRequest("GET", `/domains/${id}`);
|
|
136834
|
+
} catch (err2) {
|
|
136835
|
+
return [
|
|
136836
|
+
`Couldn't read ${domain2}'s status (${err2 instanceof Error ? err2.message : "unknown error"}); check it with \`whop domains get ${domain2}\`.`
|
|
136837
|
+
];
|
|
136838
|
+
}
|
|
136839
|
+
const purchaseUrl = details.registration?.purchase_url;
|
|
136840
|
+
if (purchaseUrl)
|
|
136841
|
+
return [`Pay for ${domain2} to finish buying it: ${purchaseUrl}`];
|
|
136842
|
+
const issues = details.issues ?? [];
|
|
136843
|
+
if (issues.length === 0) {
|
|
136844
|
+
return [
|
|
136845
|
+
`${domain2} is ${details.status} and not serving yet; check it with \`whop domains get ${domain2}\`.`
|
|
136846
|
+
];
|
|
136847
|
+
}
|
|
136848
|
+
return issues.map(
|
|
136849
|
+
(issue2) => `${domain2}: ${issue2.message} (records: \`whop domains get ${domain2}\`)`
|
|
136850
|
+
);
|
|
136851
|
+
})
|
|
136852
|
+
);
|
|
136853
|
+
return steps.flat();
|
|
136854
|
+
}
|
|
136855
|
+
async function ownerFor(hostname3) {
|
|
136856
|
+
if (hostname3.endsWith(`.${PLATFORM_DOMAIN_SUFFIX}`)) return { platform: {} };
|
|
136857
|
+
const lookup = await makeWhopRequest(
|
|
136858
|
+
"GET",
|
|
136859
|
+
`/domains/${encodeURIComponent(hostname3)}`
|
|
136860
|
+
);
|
|
136861
|
+
return lookup.availability?.available ? { registration: {} } : { verification: {} };
|
|
136862
|
+
}
|
|
136863
|
+
async function ensureDomain(input) {
|
|
136864
|
+
const website = input.appId ? { website: { app_id: input.appId } } : {};
|
|
136865
|
+
const accountId = input.accountId ?? await resolveActiveAccountId();
|
|
136866
|
+
const query = new URLSearchParams({
|
|
136867
|
+
domain: input.hostname,
|
|
136868
|
+
...accountId ? { account_id: accountId } : {}
|
|
136869
|
+
});
|
|
136870
|
+
const owned = await makeWhopRequest(
|
|
136871
|
+
"GET",
|
|
136872
|
+
`/domains?${query}`
|
|
136873
|
+
);
|
|
136874
|
+
const existing = owned.data?.[0];
|
|
136875
|
+
const serving = existing?.website?.app?.id;
|
|
136876
|
+
if (serving && serving !== input.appId) {
|
|
136877
|
+
throw new CommandAbort({
|
|
136878
|
+
code: "DOMAIN_IN_USE",
|
|
136879
|
+
message: `${input.hostname} already serves ${serving}, so it was left as it is. To work on that app, run \`whop apps pull --app ${serving}\`, or \`whop apps init --app ${serving}\` if it has never been deployed. Otherwise ask the user for another domain.`
|
|
136880
|
+
});
|
|
136881
|
+
}
|
|
136882
|
+
if (existing) {
|
|
136883
|
+
return input.appId ? makeWhopRequest("PATCH", `/domains/${existing.id}`, website) : existing;
|
|
136884
|
+
}
|
|
136885
|
+
return makeWhopRequest("POST", "/domains", {
|
|
136886
|
+
account_id: accountId,
|
|
136887
|
+
domain: input.hostname,
|
|
136888
|
+
...await ownerFor(input.hostname),
|
|
136889
|
+
...website
|
|
136890
|
+
});
|
|
135943
136891
|
}
|
|
135944
136892
|
async function updateAppSecrets(appId, secrets) {
|
|
135945
136893
|
return makeWhopRequest("PATCH", `/apps/${appId}`, { secrets });
|
|
@@ -135953,6 +136901,18 @@ async function createAppBuild(input) {
|
|
|
135953
136901
|
...input.source_file_id ? { source_attachment: { id: input.source_file_id } } : {}
|
|
135954
136902
|
});
|
|
135955
136903
|
}
|
|
136904
|
+
async function hasWebBuilds(appId) {
|
|
136905
|
+
const query = new URLSearchParams({
|
|
136906
|
+
app_id: appId,
|
|
136907
|
+
platform: "web",
|
|
136908
|
+
first: "1"
|
|
136909
|
+
});
|
|
136910
|
+
const builds = await makeWhopRequest(
|
|
136911
|
+
"GET",
|
|
136912
|
+
`/app_builds?${query}`
|
|
136913
|
+
);
|
|
136914
|
+
return (builds.data?.length ?? 0) > 0;
|
|
136915
|
+
}
|
|
135956
136916
|
async function getAppBuild(buildId) {
|
|
135957
136917
|
return makeWhopRequest("GET", `/app_builds/${buildId}`);
|
|
135958
136918
|
}
|
|
@@ -136012,57 +136972,17 @@ function sleep(ms) {
|
|
|
136012
136972
|
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
136013
136973
|
}
|
|
136014
136974
|
|
|
136015
|
-
// src/apps/config.ts
|
|
136016
|
-
import { existsSync as existsSync8, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
|
|
136017
|
-
import { join as join6, resolve as resolve5 } from "path";
|
|
136018
|
-
var APP_CONFIG_FILENAME = "whop.app.json";
|
|
136019
|
-
function findProjectDir(startDir) {
|
|
136020
|
-
let dir = resolve5(startDir ?? process.cwd());
|
|
136021
|
-
for (let i = 0; i < 25; i++) {
|
|
136022
|
-
if (existsSync8(join6(dir, APP_CONFIG_FILENAME))) return dir;
|
|
136023
|
-
const parent = resolve5(dir, "..");
|
|
136024
|
-
if (parent === dir) break;
|
|
136025
|
-
dir = parent;
|
|
136026
|
-
}
|
|
136027
|
-
return null;
|
|
136028
|
-
}
|
|
136029
|
-
function readAppConfig(projectDir) {
|
|
136030
|
-
const path9 = join6(projectDir, APP_CONFIG_FILENAME);
|
|
136031
|
-
if (!existsSync8(path9)) return null;
|
|
136032
|
-
try {
|
|
136033
|
-
const parsed = JSON.parse(
|
|
136034
|
-
readFileSync8(path9, "utf-8")
|
|
136035
|
-
);
|
|
136036
|
-
if (typeof parsed.app_id === "string" && typeof parsed.name === "string" && typeof parsed.route === "string") {
|
|
136037
|
-
return { app_id: parsed.app_id, name: parsed.name, route: parsed.route };
|
|
136038
|
-
}
|
|
136039
|
-
return null;
|
|
136040
|
-
} catch {
|
|
136041
|
-
return null;
|
|
136042
|
-
}
|
|
136043
|
-
}
|
|
136044
|
-
function writeAppConfig(projectDir, config2) {
|
|
136045
|
-
writeFileSync6(
|
|
136046
|
-
join6(projectDir, APP_CONFIG_FILENAME),
|
|
136047
|
-
`${JSON.stringify(config2, null, " ")}
|
|
136048
|
-
`
|
|
136049
|
-
);
|
|
136050
|
-
}
|
|
136051
|
-
function slugify4(name) {
|
|
136052
|
-
return name.toLowerCase().normalize("NFKD").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 63);
|
|
136053
|
-
}
|
|
136054
|
-
|
|
136055
136975
|
// src/apps/git.ts
|
|
136056
|
-
import { spawnSync } from "child_process";
|
|
136976
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
136057
136977
|
import { mkdtempSync, realpathSync as realpathSync3, rmSync as rmSync2 } from "fs";
|
|
136058
136978
|
import { tmpdir } from "os";
|
|
136059
|
-
import { join as
|
|
136060
|
-
var
|
|
136979
|
+
import { join as join9 } from "path";
|
|
136980
|
+
var SPAWN_VIA_SHELL3 = process.platform === "win32";
|
|
136061
136981
|
function runGit(dir, args, env = {}) {
|
|
136062
|
-
const result =
|
|
136982
|
+
const result = spawnSync3("git", args, {
|
|
136063
136983
|
cwd: dir,
|
|
136064
136984
|
encoding: "utf-8",
|
|
136065
|
-
shell:
|
|
136985
|
+
shell: SPAWN_VIA_SHELL3,
|
|
136066
136986
|
env: { ...process.env, ...env },
|
|
136067
136987
|
maxBuffer: 128 * 1024 * 1024
|
|
136068
136988
|
});
|
|
@@ -136083,9 +137003,9 @@ function mustGit(dir, args, env = {}) {
|
|
|
136083
137003
|
return result.stdout;
|
|
136084
137004
|
}
|
|
136085
137005
|
function gitInstalled() {
|
|
136086
|
-
const result =
|
|
137006
|
+
const result = spawnSync3("git", ["--version"], {
|
|
136087
137007
|
stdio: "ignore",
|
|
136088
|
-
shell:
|
|
137008
|
+
shell: SPAWN_VIA_SHELL3
|
|
136089
137009
|
});
|
|
136090
137010
|
return !result.error && result.status === 0;
|
|
136091
137011
|
}
|
|
@@ -136126,12 +137046,12 @@ function commitAll(dir, message) {
|
|
|
136126
137046
|
function commitSnapshot(repoDir, snapshotDir, appId, message, options = {}) {
|
|
136127
137047
|
const ref = remoteRef(appId);
|
|
136128
137048
|
const gitDir = mustGit(repoDir, ["rev-parse", "--absolute-git-dir"]);
|
|
136129
|
-
const scratch = mkdtempSync(
|
|
137049
|
+
const scratch = mkdtempSync(join9(tmpdir(), "whop-git-"));
|
|
136130
137050
|
try {
|
|
136131
137051
|
const env = {
|
|
136132
137052
|
GIT_DIR: gitDir,
|
|
136133
137053
|
GIT_WORK_TREE: snapshotDir,
|
|
136134
|
-
GIT_INDEX_FILE:
|
|
137054
|
+
GIT_INDEX_FILE: join9(scratch, "index")
|
|
136135
137055
|
};
|
|
136136
137056
|
mustGit(snapshotDir, ["add", "-A", "-f", "."], env);
|
|
136137
137057
|
const tree = mustGit(snapshotDir, ["write-tree"], env);
|
|
@@ -136205,20 +137125,20 @@ function stashPop(dir) {
|
|
|
136205
137125
|
|
|
136206
137126
|
// src/apps/init.ts
|
|
136207
137127
|
import { spinner as spinner3 } from "@clack/prompts";
|
|
136208
|
-
import { existsSync as existsSync11, readdirSync as readdirSync3 } from "fs";
|
|
136209
|
-
import { resolve as resolve7 } from "path";
|
|
137128
|
+
import { existsSync as existsSync11, readdirSync as readdirSync3, rmSync as rmSync3 } from "fs";
|
|
137129
|
+
import { join as join11, resolve as resolve7 } from "path";
|
|
136210
137130
|
import chalk from "chalk";
|
|
136211
137131
|
|
|
136212
137132
|
// src/apps/source-archive.ts
|
|
136213
|
-
import { spawnSync as
|
|
137133
|
+
import { spawnSync as spawnSync4 } from "child_process";
|
|
136214
137134
|
import {
|
|
136215
137135
|
mkdirSync as mkdirSync7,
|
|
136216
137136
|
readdirSync as readdirSync2,
|
|
136217
|
-
readFileSync as
|
|
137137
|
+
readFileSync as readFileSync11,
|
|
136218
137138
|
statSync as statSync2,
|
|
136219
|
-
writeFileSync as
|
|
137139
|
+
writeFileSync as writeFileSync8
|
|
136220
137140
|
} from "fs";
|
|
136221
|
-
import { dirname as dirname8, join as
|
|
137141
|
+
import { dirname as dirname8, join as join10, resolve as resolve6, sep as sep2 } from "path";
|
|
136222
137142
|
|
|
136223
137143
|
// ../../node_modules/.pnpm/fflate@0.8.3/node_modules/fflate/esm/index.mjs
|
|
136224
137144
|
import { createRequire as createRequire3 } from "module";
|
|
@@ -137229,7 +138149,7 @@ function isExcluded(path9) {
|
|
|
137229
138149
|
return segments.slice(0, -1).some((dir) => EXCLUDED_DIRS.has(dir)) || isExcludedFile(segments[segments.length - 1]);
|
|
137230
138150
|
}
|
|
137231
138151
|
function listGitFiles(projectDir) {
|
|
137232
|
-
const listed =
|
|
138152
|
+
const listed = spawnSync4(
|
|
137233
138153
|
"git",
|
|
137234
138154
|
["ls-files", "--cached", "--others", "--exclude-standard", "-z"],
|
|
137235
138155
|
{ cwd: projectDir, encoding: "utf-8", maxBuffer: 128 * 1024 * 1024 }
|
|
@@ -137238,7 +138158,7 @@ function listGitFiles(projectDir) {
|
|
|
137238
138158
|
return [...new Set(listed.stdout.split("\0").filter(Boolean))].filter(
|
|
137239
138159
|
(path9) => {
|
|
137240
138160
|
try {
|
|
137241
|
-
return statSync2(
|
|
138161
|
+
return statSync2(join10(projectDir, path9)).isFile();
|
|
137242
138162
|
} catch {
|
|
137243
138163
|
return false;
|
|
137244
138164
|
}
|
|
@@ -137247,7 +138167,7 @@ function listGitFiles(projectDir) {
|
|
|
137247
138167
|
}
|
|
137248
138168
|
function walkProject(projectDir, prefix = "") {
|
|
137249
138169
|
const files = [];
|
|
137250
|
-
for (const entry of readdirSync2(
|
|
138170
|
+
for (const entry of readdirSync2(join10(projectDir, prefix), {
|
|
137251
138171
|
withFileTypes: true
|
|
137252
138172
|
})) {
|
|
137253
138173
|
const path9 = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
@@ -137269,7 +138189,7 @@ function packSourceArchive(projectDir) {
|
|
|
137269
138189
|
}
|
|
137270
138190
|
const contents = {};
|
|
137271
138191
|
for (const path9 of paths) {
|
|
137272
|
-
contents[path9] =
|
|
138192
|
+
contents[path9] = readFileSync11(join10(projectDir, path9));
|
|
137273
138193
|
}
|
|
137274
138194
|
return {
|
|
137275
138195
|
zip: zipSync(contents, { level: 9, mem: 12 }),
|
|
@@ -137287,396 +138207,27 @@ function extractSourceArchive(zip, targetDir) {
|
|
|
137287
138207
|
throw new Error(`Archive entry escapes the target directory: ${name}`);
|
|
137288
138208
|
}
|
|
137289
138209
|
mkdirSync7(dirname8(dest), { recursive: true });
|
|
137290
|
-
|
|
138210
|
+
writeFileSync8(dest, data);
|
|
137291
138211
|
count++;
|
|
137292
138212
|
}
|
|
137293
138213
|
return count;
|
|
137294
138214
|
}
|
|
137295
138215
|
|
|
137296
|
-
// src/apps/scaffold.ts
|
|
137297
|
-
import { spawnSync as spawnSync3 } from "child_process";
|
|
137298
|
-
import { existsSync as existsSync9, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "fs";
|
|
137299
|
-
import { basename as basename3, join as join9 } from "path";
|
|
137300
|
-
var SPAWN_VIA_SHELL2 = process.platform === "win32";
|
|
137301
|
-
var DLX_RUNNERS = {
|
|
137302
|
-
npm: ["npx", "-y"],
|
|
137303
|
-
pnpm: ["pnpm", "dlx"],
|
|
137304
|
-
bun: ["bunx"],
|
|
137305
|
-
yarn: ["yarn", "dlx"]
|
|
137306
|
-
};
|
|
137307
|
-
var PM_PRIORITY = [
|
|
137308
|
-
"bun",
|
|
137309
|
-
"pnpm",
|
|
137310
|
-
"npm"
|
|
137311
|
-
];
|
|
137312
|
-
function isPmInstalled(pm) {
|
|
137313
|
-
const result = spawnSync3(pm, ["--version"], {
|
|
137314
|
-
stdio: "ignore",
|
|
137315
|
-
shell: SPAWN_VIA_SHELL2
|
|
137316
|
-
});
|
|
137317
|
-
return !result.error && result.status === 0;
|
|
137318
|
-
}
|
|
137319
|
-
function detectPackageManager() {
|
|
137320
|
-
return PM_PRIORITY.find(isPmInstalled) ?? null;
|
|
137321
|
-
}
|
|
137322
|
-
function pmInstallHint(pm) {
|
|
137323
|
-
const win = process.platform === "win32";
|
|
137324
|
-
switch (pm) {
|
|
137325
|
-
case "bun":
|
|
137326
|
-
return win ? 'powershell -c "irm bun.sh/install.ps1 | iex"' : "curl -fsSL https://bun.sh/install | bash";
|
|
137327
|
-
case "pnpm":
|
|
137328
|
-
return win ? 'powershell -c "irm get.pnpm.io/install.ps1 | iex"' : "curl -fsSL https://get.pnpm.io/install.sh | sh -";
|
|
137329
|
-
case "npm":
|
|
137330
|
-
return "install Node.js (includes npm): https://nodejs.org";
|
|
137331
|
-
case "yarn":
|
|
137332
|
-
return "npm install -g yarn";
|
|
137333
|
-
}
|
|
137334
|
-
}
|
|
137335
|
-
var TANSTACK_CREATE_FLAGS = [
|
|
137336
|
-
"--framework",
|
|
137337
|
-
"React",
|
|
137338
|
-
"--deployment",
|
|
137339
|
-
"cloudflare",
|
|
137340
|
-
"--no-git",
|
|
137341
|
-
"--no-install",
|
|
137342
|
-
"--no-intent",
|
|
137343
|
-
"--no-toolchain",
|
|
137344
|
-
"--no-examples",
|
|
137345
|
-
"--non-interactive"
|
|
137346
|
-
];
|
|
137347
|
-
function outputTail(result) {
|
|
137348
|
-
const combined = [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
|
|
137349
|
-
if (!combined) return "";
|
|
137350
|
-
return `
|
|
137351
|
-
|
|
137352
|
-
${combined.split("\n").slice(-15).join("\n")}`;
|
|
137353
|
-
}
|
|
137354
|
-
function runTanstackCreate(options) {
|
|
137355
|
-
const [runner, ...runnerArgs] = DLX_RUNNERS[options.pm];
|
|
137356
|
-
const result = spawnSync3(
|
|
137357
|
-
runner,
|
|
137358
|
-
[
|
|
137359
|
-
...runnerArgs,
|
|
137360
|
-
"@tanstack/cli@latest",
|
|
137361
|
-
"create",
|
|
137362
|
-
options.projectName,
|
|
137363
|
-
"--target-dir",
|
|
137364
|
-
options.targetDir,
|
|
137365
|
-
...TANSTACK_CREATE_FLAGS
|
|
137366
|
-
],
|
|
137367
|
-
{
|
|
137368
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
137369
|
-
encoding: "utf-8",
|
|
137370
|
-
shell: SPAWN_VIA_SHELL2
|
|
137371
|
-
}
|
|
137372
|
-
);
|
|
137373
|
-
if (result.error) throw result.error;
|
|
137374
|
-
if (result.status !== 0) {
|
|
137375
|
-
throw new Error(
|
|
137376
|
-
`\`${options.pm === "npm" ? "npx" : options.pm} @tanstack/cli create\` failed (exit ${result.status}). Check your network connection and try again.${outputTail(result)}`
|
|
137377
|
-
);
|
|
137378
|
-
}
|
|
137379
|
-
}
|
|
137380
|
-
var VITE_CONFIG_NAMES = [
|
|
137381
|
-
"vite.config.ts",
|
|
137382
|
-
"vite.config.mts",
|
|
137383
|
-
"vite.config.js",
|
|
137384
|
-
"vite.config.mjs"
|
|
137385
|
-
];
|
|
137386
|
-
function findViteConfig(dir) {
|
|
137387
|
-
return VITE_CONFIG_NAMES.map((name) => join9(dir, name)).find(
|
|
137388
|
-
(path9) => existsSync9(path9)
|
|
137389
|
-
);
|
|
137390
|
-
}
|
|
137391
|
-
var WRANGLER_CONFIG_NAMES = ["wrangler.jsonc", "wrangler.json"];
|
|
137392
|
-
function whopifyProject(options) {
|
|
137393
|
-
const manualSteps = [];
|
|
137394
|
-
patchPackageJson(options.targetDir, manualSteps);
|
|
137395
|
-
patchViteConfig(options.targetDir, manualSteps);
|
|
137396
|
-
patchWranglerConfig(options.targetDir, options.route, manualSteps);
|
|
137397
|
-
return { manualSteps };
|
|
137398
|
-
}
|
|
137399
|
-
function patchPackageJson(dir, manualSteps) {
|
|
137400
|
-
const file2 = join9(dir, "package.json");
|
|
137401
|
-
let raw;
|
|
137402
|
-
let pkg;
|
|
137403
|
-
try {
|
|
137404
|
-
raw = readFileSync10(file2, "utf-8");
|
|
137405
|
-
pkg = JSON.parse(raw);
|
|
137406
|
-
} catch {
|
|
137407
|
-
manualSteps.push(
|
|
137408
|
-
'package.json could not be parsed. Add a "deploy": "whop apps deploy" script, a "typecheck" script, and a devDependency "@whop/cli": "latest".'
|
|
137409
|
-
);
|
|
137410
|
-
return;
|
|
137411
|
-
}
|
|
137412
|
-
pkg.scripts = {
|
|
137413
|
-
...pkg.scripts,
|
|
137414
|
-
deploy: "whop apps deploy",
|
|
137415
|
-
typecheck: pkg.scripts?.typecheck ?? "tsc --noEmit"
|
|
137416
|
-
};
|
|
137417
|
-
pkg.devDependencies = {
|
|
137418
|
-
...pkg.devDependencies,
|
|
137419
|
-
// The project imports the whop() vite plugin from @whop/cli/vite. Pinned
|
|
137420
|
-
// to the building binary's own version until that broke: a standalone
|
|
137421
|
-
// build carries the workspace version, which is routinely ahead of what
|
|
137422
|
-
// is on npm, so the pin resolved to nothing and install failed.
|
|
137423
|
-
"@whop/cli": pkg.devDependencies?.["@whop/cli"] ?? "latest"
|
|
137424
|
-
};
|
|
137425
|
-
writeIfChanged(file2, `${JSON.stringify(pkg, null, 2)}
|
|
137426
|
-
`, raw);
|
|
137427
|
-
}
|
|
137428
|
-
function writeIfChanged(file2, next, current) {
|
|
137429
|
-
if (next === current) return;
|
|
137430
|
-
writeFileSync8(file2, next);
|
|
137431
|
-
}
|
|
137432
|
-
var WHOP_PLUGIN_CALL = "whop({ disableTanstackDevtools: true })";
|
|
137433
|
-
function patchViteConfig(dir, manualSteps) {
|
|
137434
|
-
const file2 = findViteConfig(dir);
|
|
137435
|
-
if (!file2) {
|
|
137436
|
-
manualSteps.push(
|
|
137437
|
-
"No vite config found (looked for vite.config.ts/.mts/.js/.mjs). Whop hosting serves Vite builds \u2014 create a vite config that builds with @cloudflare/vite-plugin (emitting dist/client and, for SSR, dist/server) and includes the whop() plugin from @whop/cli/vite in its plugins array."
|
|
137438
|
-
);
|
|
137439
|
-
return;
|
|
137440
|
-
}
|
|
137441
|
-
let content = readFileSync10(file2, "utf-8");
|
|
137442
|
-
const hasWhopPlugin = content.includes("@whop/cli/vite");
|
|
137443
|
-
if (!hasWhopPlugin) {
|
|
137444
|
-
const pluginsOpen = /plugins:\s*\[/;
|
|
137445
|
-
if (!pluginsOpen.test(content)) {
|
|
137446
|
-
manualSteps.push(
|
|
137447
|
-
`Could not find a \`plugins: [...]\` array in ${basename3(file2)}. Add \`import { whop } from '@whop/cli/vite'\` and include \`whop()\` in the config's plugins so builds pack dist/whop-build.zip.`
|
|
137448
|
-
);
|
|
137449
|
-
} else {
|
|
137450
|
-
content = `import { whop } from '@whop/cli/vite'
|
|
137451
|
-
${content}`;
|
|
137452
|
-
content = content.replace(
|
|
137453
|
-
pluginsOpen,
|
|
137454
|
-
(match) => `${match}
|
|
137455
|
-
${WHOP_PLUGIN_CALL},`
|
|
137456
|
-
);
|
|
137457
|
-
writeFileSync8(file2, content);
|
|
137458
|
-
}
|
|
137459
|
-
}
|
|
137460
|
-
if (!content.includes("@cloudflare/vite-plugin")) {
|
|
137461
|
-
manualSteps.push(
|
|
137462
|
-
`${basename3(file2)} does not use @cloudflare/vite-plugin. Whop hosting runs builds on Cloudflare Workers: install @cloudflare/vite-plugin and wrangler, add \`cloudflare({ viteEnvironment: { name: 'ssr' } })\` to the plugins array (before your framework plugin), and make sure \`vite build\` emits dist/client (static assets) and dist/server (worker modules with an index.js entry).`
|
|
137463
|
-
);
|
|
137464
|
-
}
|
|
137465
|
-
}
|
|
137466
|
-
function patchWranglerConfig(dir, route, manualSteps) {
|
|
137467
|
-
const file2 = WRANGLER_CONFIG_NAMES.map((name) => join9(dir, name)).find(
|
|
137468
|
-
(path9) => existsSync9(path9)
|
|
137469
|
-
);
|
|
137470
|
-
if (!file2) {
|
|
137471
|
-
manualSteps.push(
|
|
137472
|
-
`No wrangler config found. Create wrangler.jsonc with: { "name": "${route}", "compatibility_date": "<today>", "compatibility_flags": ["nodejs_compat"], "main": "<your framework's server entry>" } (for TanStack Start the main is "@tanstack/react-start/server-entry").`
|
|
137473
|
-
);
|
|
137474
|
-
return;
|
|
137475
|
-
}
|
|
137476
|
-
const content = readFileSync10(file2, "utf-8");
|
|
137477
|
-
const updated = replaceTopLevelName(content, route);
|
|
137478
|
-
if (updated) {
|
|
137479
|
-
writeIfChanged(file2, updated, content);
|
|
137480
|
-
} else {
|
|
137481
|
-
manualSteps.push(
|
|
137482
|
-
`Set the top-level "name" in ${basename3(file2)} to "${route}" so the worker is named after the app's route.`
|
|
137483
|
-
);
|
|
137484
|
-
}
|
|
137485
|
-
}
|
|
137486
|
-
function replaceTopLevelName(content, route) {
|
|
137487
|
-
let depth = 0;
|
|
137488
|
-
let i = 0;
|
|
137489
|
-
while (i < content.length) {
|
|
137490
|
-
const ch = content[i];
|
|
137491
|
-
if (ch === '"') {
|
|
137492
|
-
let j = i + 1;
|
|
137493
|
-
while (j < content.length && content[j] !== '"') {
|
|
137494
|
-
j += content[j] === "\\" ? 2 : 1;
|
|
137495
|
-
}
|
|
137496
|
-
if (depth === 1 && content.slice(i + 1, j) === "name") {
|
|
137497
|
-
const after = content.slice(j + 1);
|
|
137498
|
-
const value = after.match(/^(\s*:\s*)"(?:[^"\\]|\\.)*"/);
|
|
137499
|
-
if (value) {
|
|
137500
|
-
const start = j + 1 + value[1].length;
|
|
137501
|
-
const end = j + 1 + value[0].length;
|
|
137502
|
-
return `${content.slice(0, start)}"${route}"${content.slice(end)}`;
|
|
137503
|
-
}
|
|
137504
|
-
}
|
|
137505
|
-
i = j + 1;
|
|
137506
|
-
continue;
|
|
137507
|
-
}
|
|
137508
|
-
if (ch === "/" && content[i + 1] === "/") {
|
|
137509
|
-
const newline = content.indexOf("\n", i);
|
|
137510
|
-
i = newline === -1 ? content.length : newline + 1;
|
|
137511
|
-
continue;
|
|
137512
|
-
}
|
|
137513
|
-
if (ch === "/" && content[i + 1] === "*") {
|
|
137514
|
-
const close = content.indexOf("*/", i + 2);
|
|
137515
|
-
i = close === -1 ? content.length : close + 2;
|
|
137516
|
-
continue;
|
|
137517
|
-
}
|
|
137518
|
-
if (ch === "{" || ch === "[") depth++;
|
|
137519
|
-
if (ch === "}" || ch === "]") depth--;
|
|
137520
|
-
i++;
|
|
137521
|
-
}
|
|
137522
|
-
return null;
|
|
137523
|
-
}
|
|
137524
|
-
|
|
137525
|
-
// src/apps/shared.ts
|
|
137526
|
-
import { isCancel as isCancel4, select as select3, spinner as spinner2, text as text2 } from "@clack/prompts";
|
|
137527
|
-
import { spawnSync as spawnSync4 } from "child_process";
|
|
137528
|
-
import { existsSync as existsSync10, readFileSync as readFileSync11 } from "fs";
|
|
137529
|
-
import { join as join10 } from "path";
|
|
137530
|
-
var CommandAbort = class extends Error {
|
|
137531
|
-
constructor(options) {
|
|
137532
|
-
super(options.message);
|
|
137533
|
-
this.options = options;
|
|
137534
|
-
}
|
|
137535
|
-
};
|
|
137536
|
-
function log2(c2, message) {
|
|
137537
|
-
if (!c2.agent) console.log(message);
|
|
137538
|
-
}
|
|
137539
|
-
var PHASE_MARKER = "[whop:phase]";
|
|
137540
|
-
function phase(name) {
|
|
137541
|
-
process.stderr.write(`${PHASE_MARKER} ${name} t=${Date.now()}
|
|
137542
|
-
`);
|
|
137543
|
-
}
|
|
137544
|
-
function cancelled() {
|
|
137545
|
-
throw new CommandAbort({
|
|
137546
|
-
code: "CANCELLED",
|
|
137547
|
-
message: "Cancelled.",
|
|
137548
|
-
exitCode: 130
|
|
137549
|
-
});
|
|
137550
|
-
}
|
|
137551
|
-
async function promptText(message, placeholder, initialValue) {
|
|
137552
|
-
const value = await text2({ message, placeholder, initialValue });
|
|
137553
|
-
if (isCancel4(value)) return null;
|
|
137554
|
-
return String(value);
|
|
137555
|
-
}
|
|
137556
|
-
async function promptSelect(message, options) {
|
|
137557
|
-
const choice = await select3({ message, options });
|
|
137558
|
-
if (isCancel4(choice)) cancelled();
|
|
137559
|
-
return String(choice);
|
|
137560
|
-
}
|
|
137561
|
-
async function promptForAppType() {
|
|
137562
|
-
const choice = await promptSelect("What are you building?", [
|
|
137563
|
-
{ value: "b2c_app", label: "An app \u2014 creators install it into their whop" },
|
|
137564
|
-
{ value: "website", label: "A website \u2014 visitors browse it at your route" }
|
|
137565
|
-
]);
|
|
137566
|
-
return choice;
|
|
137567
|
-
}
|
|
137568
|
-
async function promptForNewApp(knownAppType) {
|
|
137569
|
-
const appType = knownAppType ?? await promptForAppType();
|
|
137570
|
-
const name = await promptText("What is your app called?", "My Site");
|
|
137571
|
-
if (name === null) cancelled();
|
|
137572
|
-
const slug = slugify4(name);
|
|
137573
|
-
const routeInput = await promptText(
|
|
137574
|
-
"Which route should it live at? (your-route.whop.site)",
|
|
137575
|
-
slug,
|
|
137576
|
-
slug
|
|
137577
|
-
);
|
|
137578
|
-
if (routeInput === null) cancelled();
|
|
137579
|
-
const route = slugify4(routeInput);
|
|
137580
|
-
if (!route) {
|
|
137581
|
-
throw new CommandAbort({
|
|
137582
|
-
code: "ROUTE_REQUIRED",
|
|
137583
|
-
message: `Couldn't derive a route from "${routeInput}" \u2014 use letters and numbers (e.g. my-site).`,
|
|
137584
|
-
retryable: true
|
|
137585
|
-
});
|
|
137586
|
-
}
|
|
137587
|
-
return { name, route, appType };
|
|
137588
|
-
}
|
|
137589
|
-
function ensurePackageManager() {
|
|
137590
|
-
const pm = detectPackageManager();
|
|
137591
|
-
if (pm) return pm;
|
|
137592
|
-
throw new CommandAbort({
|
|
137593
|
-
code: "NO_PACKAGE_MANAGER",
|
|
137594
|
-
message: `No package manager found (looked for bun, pnpm, npm). Install one and retry:
|
|
137595
|
-
|
|
137596
|
-
bun (recommended): ${pmInstallHint("bun")}
|
|
137597
|
-
pnpm: ${pmInstallHint("pnpm")}
|
|
137598
|
-
npm: ${pmInstallHint("npm")}`
|
|
137599
|
-
});
|
|
137600
|
-
}
|
|
137601
|
-
var SPAWN_VIA_SHELL3 = process.platform === "win32";
|
|
137602
|
-
function detectProjectPackageManager(projectDir) {
|
|
137603
|
-
if (existsSync10(join10(projectDir, "bun.lock")) || existsSync10(join10(projectDir, "bun.lockb")))
|
|
137604
|
-
return "bun";
|
|
137605
|
-
if (existsSync10(join10(projectDir, "pnpm-lock.yaml"))) return "pnpm";
|
|
137606
|
-
if (existsSync10(join10(projectDir, "yarn.lock"))) return "yarn";
|
|
137607
|
-
if (existsSync10(join10(projectDir, "package-lock.json"))) return "npm";
|
|
137608
|
-
return detectPackageManager() ?? "npm";
|
|
137609
|
-
}
|
|
137610
|
-
function hasScript(projectDir, script) {
|
|
137611
|
-
try {
|
|
137612
|
-
const pkg = JSON.parse(
|
|
137613
|
-
readFileSync11(join10(projectDir, "package.json"), "utf-8")
|
|
137614
|
-
);
|
|
137615
|
-
return Boolean(pkg.scripts?.[script]);
|
|
137616
|
-
} catch {
|
|
137617
|
-
return false;
|
|
137618
|
-
}
|
|
137619
|
-
}
|
|
137620
|
-
function runScript(projectDir, script, extraEnv = {}, scriptArgs = []) {
|
|
137621
|
-
const pm = detectProjectPackageManager(projectDir);
|
|
137622
|
-
const separator = pm === "npm" && scriptArgs.length > 0 ? ["--"] : [];
|
|
137623
|
-
const result = spawnSync4(pm, ["run", script, ...separator, ...scriptArgs], {
|
|
137624
|
-
cwd: projectDir,
|
|
137625
|
-
stdio: "inherit",
|
|
137626
|
-
shell: SPAWN_VIA_SHELL3,
|
|
137627
|
-
env: { ...process.env, ...extraEnv }
|
|
137628
|
-
});
|
|
137629
|
-
if (result.error) {
|
|
137630
|
-
throw new Error(
|
|
137631
|
-
`Could not run \`${pm} run ${script}\`: ${result.error.message}`
|
|
137632
|
-
);
|
|
137633
|
-
}
|
|
137634
|
-
if (result.status !== 0) {
|
|
137635
|
-
throw new Error(
|
|
137636
|
-
`\`${pm} run ${script}\` failed with exit code ${result.status ?? "unknown"}`
|
|
137637
|
-
);
|
|
137638
|
-
}
|
|
137639
|
-
}
|
|
137640
|
-
function runInstall(c2, projectDir) {
|
|
137641
|
-
const pm = detectProjectPackageManager(projectDir);
|
|
137642
|
-
const spin = c2.agent ? null : spinner2();
|
|
137643
|
-
spin?.start(`Installing dependencies with ${pm}`);
|
|
137644
|
-
const result = spawnSync4(pm, ["install"], {
|
|
137645
|
-
cwd: projectDir,
|
|
137646
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
137647
|
-
encoding: "utf-8",
|
|
137648
|
-
shell: SPAWN_VIA_SHELL3
|
|
137649
|
-
});
|
|
137650
|
-
if (result.error || result.status !== 0) {
|
|
137651
|
-
spin?.error(`${pm} install failed`);
|
|
137652
|
-
throw new Error(
|
|
137653
|
-
`\`${pm} install\` failed${result.status != null ? ` with exit code ${result.status}` : ""} \u2014 run it manually inside ${projectDir}, then retry.${outputTail(result)}`
|
|
137654
|
-
);
|
|
137655
|
-
}
|
|
137656
|
-
spin?.stop(`Installed dependencies with ${pm}`);
|
|
137657
|
-
}
|
|
137658
|
-
async function downloadArchive(sourceUrl) {
|
|
137659
|
-
const response = await fetch(sourceUrl);
|
|
137660
|
-
if (!response.ok) {
|
|
137661
|
-
throw new Error(
|
|
137662
|
-
`Download failed: ${response.status} ${response.statusText}`
|
|
137663
|
-
);
|
|
137664
|
-
}
|
|
137665
|
-
return new Uint8Array(await response.arrayBuffer());
|
|
137666
|
-
}
|
|
137667
|
-
|
|
137668
138216
|
// src/apps/init.ts
|
|
137669
138217
|
var initOptions = external_exports.object({
|
|
138218
|
+
app: external_exports.string().optional().describe(
|
|
138219
|
+
"Start the code for this existing app (app_xxx) instead of registering a new one \u2014 for an app that has never been deployed, such as a website created on whop.com. Its name, address and type come from the app"
|
|
138220
|
+
),
|
|
137670
138221
|
name: external_exports.string().optional().describe("Name for the new app (prompted for interactively if omitted)"),
|
|
137671
|
-
|
|
137672
|
-
"
|
|
138222
|
+
domain: external_exports.string().optional().describe(
|
|
138223
|
+
"Domain the app is served at: a whop.site name such as my-site (my-site.whop.site), or a domain the account owns. Defaults to the name's whop.site address"
|
|
137673
138224
|
),
|
|
137674
138225
|
template: external_exports.string().optional().describe(
|
|
137675
138226
|
"Clone this app's published source archive (app_xxx) instead of the blank TanStack Start template"
|
|
137676
138227
|
),
|
|
137677
|
-
dir: external_exports.string().optional().describe("Target directory (defaults to ./<
|
|
138228
|
+
dir: external_exports.string().optional().describe("Target directory (defaults to ./<app name>)"),
|
|
137678
138229
|
app_type: external_exports.enum(["b2c_app", "website"]).optional().describe(
|
|
137679
|
-
"What you are building: b2c_app (creators install it into their whop) or website (visitors browse it at
|
|
138230
|
+
"What you are building: b2c_app (creators install it into their whop) or website (visitors browse it at its domain). Asked interactively if omitted, and required when there is nobody to ask"
|
|
137680
138231
|
),
|
|
137681
138232
|
company_id: external_exports.string().optional().describe(
|
|
137682
138233
|
"Company the app belongs to (biz_xxx). Defaults to the active account, and is required when the credential has none"
|
|
@@ -137688,19 +138239,22 @@ var initOptions = external_exports.object({
|
|
|
137688
138239
|
var initOutput = external_exports.object({
|
|
137689
138240
|
app_id: external_exports.string(),
|
|
137690
138241
|
name: external_exports.string(),
|
|
137691
|
-
|
|
138242
|
+
domain: external_exports.string().optional(),
|
|
137692
138243
|
dir: external_exports.string(),
|
|
137693
|
-
manual_steps: external_exports.array(external_exports.string()).optional()
|
|
138244
|
+
manual_steps: external_exports.array(external_exports.string()).optional(),
|
|
138245
|
+
domain_steps: external_exports.array(external_exports.string()).optional().describe(
|
|
138246
|
+
"What the owner must do before the domain serves the app: pay at a purchase link, or publish DNS records"
|
|
138247
|
+
)
|
|
137694
138248
|
});
|
|
137695
|
-
async function resolveAppType(c2, name,
|
|
138249
|
+
async function resolveAppType(c2, name, domain2) {
|
|
137696
138250
|
if (!c2.agent) return promptForAppType();
|
|
137697
138251
|
throw new CommandAbort({
|
|
137698
138252
|
code: "APP_TYPE_REQUIRED",
|
|
137699
138253
|
message: [
|
|
137700
138254
|
"Nothing was created. Ask the user what they are building, then re-run with --app_type:",
|
|
137701
138255
|
"",
|
|
137702
|
-
` whop apps init --name "${name}" --
|
|
137703
|
-
` whop apps init --name "${name}" --
|
|
138256
|
+
` whop apps init --name "${name}" --domain ${domain2} --app_type b2c_app (creators install it into their whop)`,
|
|
138257
|
+
` whop apps init --name "${name}" --domain ${domain2} --app_type website (visitors browse it at ${domain2})`,
|
|
137704
138258
|
"",
|
|
137705
138259
|
"Ask rather than guess: a website cannot be turned back into an app later."
|
|
137706
138260
|
].join("\n"),
|
|
@@ -137715,19 +138269,19 @@ async function resolveAppType(c2, name, route) {
|
|
|
137715
138269
|
}
|
|
137716
138270
|
});
|
|
137717
138271
|
}
|
|
137718
|
-
async function
|
|
138272
|
+
async function resolveNameAndDomain(c2, options, templateAppType) {
|
|
137719
138273
|
const knownAppType = options.app_type ?? templateAppType;
|
|
137720
138274
|
if (options.name) {
|
|
137721
|
-
const
|
|
137722
|
-
if (
|
|
138275
|
+
const domain2 = options.domain ? domainFor(options.domain) : platformDomainFor(options.name);
|
|
138276
|
+
if (domain2 === `.${PLATFORM_DOMAIN_SUFFIX}`) {
|
|
137723
138277
|
throw new CommandAbort({
|
|
137724
|
-
code: "
|
|
137725
|
-
message: `Couldn't derive a
|
|
138278
|
+
code: "DOMAIN_REQUIRED",
|
|
138279
|
+
message: `Couldn't derive a domain from "${options.domain ?? options.name}" \u2014 use letters and numbers (e.g. my-site).`,
|
|
137726
138280
|
retryable: true
|
|
137727
138281
|
});
|
|
137728
138282
|
}
|
|
137729
|
-
const appType = knownAppType ?? await resolveAppType(c2, options.name,
|
|
137730
|
-
return { name: options.name,
|
|
138283
|
+
const appType = knownAppType ?? await resolveAppType(c2, options.name, domain2);
|
|
138284
|
+
return { name: options.name, domain: domain2, appType };
|
|
137731
138285
|
}
|
|
137732
138286
|
if (c2.agent) {
|
|
137733
138287
|
throw new CommandAbort({
|
|
@@ -137735,10 +138289,10 @@ async function resolveNameAndRoute(c2, options, templateAppType) {
|
|
|
137735
138289
|
message: [
|
|
137736
138290
|
"Ask the user three things, then re-run with flags:",
|
|
137737
138291
|
" 1. What the app is called.",
|
|
137738
|
-
" 2. Which
|
|
138292
|
+
" 2. Which domain it should live at: a whop.site name (my-site \u2192 my-site.whop.site) or a domain they own.",
|
|
137739
138293
|
" 3. Whether they are building an app creators install into their whop, or a website visitors browse.",
|
|
137740
138294
|
"",
|
|
137741
|
-
' whop apps init --name "My Site" --
|
|
138295
|
+
' whop apps init --name "My Site" --domain my-site --app_type website',
|
|
137742
138296
|
"",
|
|
137743
138297
|
"--app_type takes b2c_app or website, and is required here. Ask rather than guess: a website cannot be turned back into an app later."
|
|
137744
138298
|
].join("\n"),
|
|
@@ -137747,25 +138301,17 @@ async function resolveNameAndRoute(c2, options, templateAppType) {
|
|
|
137747
138301
|
commands: [
|
|
137748
138302
|
{
|
|
137749
138303
|
command: "apps init",
|
|
137750
|
-
description: "Re-run with --name and --app_type (and optionally --
|
|
138304
|
+
description: "Re-run with --name and --app_type (and optionally --domain)"
|
|
137751
138305
|
}
|
|
137752
138306
|
]
|
|
137753
138307
|
}
|
|
137754
138308
|
});
|
|
137755
138309
|
}
|
|
137756
|
-
if (options.
|
|
138310
|
+
if (options.domain) {
|
|
137757
138311
|
const appType = knownAppType ?? await promptForAppType();
|
|
137758
138312
|
const name = await promptText("What is your app called?", "My Site");
|
|
137759
138313
|
if (name === null) cancelled();
|
|
137760
|
-
|
|
137761
|
-
if (!route) {
|
|
137762
|
-
throw new CommandAbort({
|
|
137763
|
-
code: "ROUTE_REQUIRED",
|
|
137764
|
-
message: `Couldn't derive a route from "${options.route}" \u2014 use letters and numbers (e.g. my-site).`,
|
|
137765
|
-
retryable: true
|
|
137766
|
-
});
|
|
137767
|
-
}
|
|
137768
|
-
return { name, route, appType };
|
|
138314
|
+
return { name, domain: domainFor(options.domain), appType };
|
|
137769
138315
|
}
|
|
137770
138316
|
return promptForNewApp(knownAppType);
|
|
137771
138317
|
}
|
|
@@ -137773,7 +138319,7 @@ function ensureEmptyTarget(targetDir) {
|
|
|
137773
138319
|
if (existsSync11(targetDir) && readdirSync3(targetDir).length > 0) {
|
|
137774
138320
|
throw new CommandAbort({
|
|
137775
138321
|
code: "TARGET_NOT_EMPTY",
|
|
137776
|
-
message: `Target directory is not empty: ${targetDir}.
|
|
138322
|
+
message: `Target directory is not empty: ${targetDir}. Pass --dir <empty-dir>. To work on an existing app's code, use \`whop apps pull\`.`
|
|
137777
138323
|
});
|
|
137778
138324
|
}
|
|
137779
138325
|
}
|
|
@@ -137799,31 +138345,31 @@ async function fetchTemplateSource(templateId) {
|
|
|
137799
138345
|
}
|
|
137800
138346
|
async function runInitFlow(c2, options, pm = ensurePackageManager()) {
|
|
137801
138347
|
const templateSource = options.template ? await fetchTemplateSource(options.template) : null;
|
|
137802
|
-
const
|
|
137803
|
-
const
|
|
137804
|
-
c2,
|
|
137805
|
-
options,
|
|
137806
|
-
templateAppType
|
|
137807
|
-
);
|
|
137808
|
-
const targetDir = resolve7(options.dir ?? `./${route}`);
|
|
138348
|
+
const project = options.app ? await existingProjectApp(options.app) : await newProjectApp(c2, options, templateSource?.template);
|
|
138349
|
+
const targetDir = resolve7(options.dir ?? `./${project.slug}`);
|
|
137809
138350
|
ensureEmptyTarget(targetDir);
|
|
137810
|
-
|
|
138351
|
+
const app = await project.claim();
|
|
138352
|
+
const retry = `whop apps init --app ${app.id}${options.template ? ` --template ${options.template}` : ""} --dir ${targetDir}`;
|
|
138353
|
+
let manualSteps;
|
|
137811
138354
|
try {
|
|
137812
|
-
|
|
137813
|
-
|
|
137814
|
-
|
|
137815
|
-
|
|
137816
|
-
|
|
137817
|
-
|
|
138355
|
+
manualSteps = await materializeProject({
|
|
138356
|
+
c: c2,
|
|
138357
|
+
app,
|
|
138358
|
+
pm,
|
|
138359
|
+
retry,
|
|
138360
|
+
slug: project.slug,
|
|
138361
|
+
targetDir,
|
|
138362
|
+
templateSource
|
|
137818
138363
|
});
|
|
137819
138364
|
} catch (err2) {
|
|
137820
|
-
|
|
137821
|
-
|
|
137822
|
-
message: err2 instanceof Error ? err2.message : "Failed to register the app",
|
|
137823
|
-
retryable: true
|
|
137824
|
-
});
|
|
138365
|
+
emptyDirectory(targetDir);
|
|
138366
|
+
throw err2;
|
|
137825
138367
|
}
|
|
137826
|
-
|
|
138368
|
+
initGitRepo(c2, targetDir);
|
|
138369
|
+
return { projectDir: targetDir, app, manualSteps };
|
|
138370
|
+
}
|
|
138371
|
+
async function materializeProject(input) {
|
|
138372
|
+
const { c: c2, app, retry, targetDir, templateSource } = input;
|
|
137827
138373
|
const spin = c2.agent ? null : spinner3();
|
|
137828
138374
|
if (templateSource) {
|
|
137829
138375
|
spin?.start(
|
|
@@ -137841,38 +138387,131 @@ async function runInitFlow(c2, options, pm = ensurePackageManager()) {
|
|
|
137841
138387
|
code: "TEMPLATE_CLONE_FAILED",
|
|
137842
138388
|
message: `${err2 instanceof Error ? err2.message : "Failed to clone the template source"}
|
|
137843
138389
|
|
|
137844
|
-
The app ${app.id} is already registered \u2014 re-run
|
|
138390
|
+
The app ${app.id} is already registered \u2014 re-run \`${retry}\`.`,
|
|
137845
138391
|
retryable: true
|
|
137846
138392
|
});
|
|
137847
138393
|
}
|
|
137848
138394
|
} else {
|
|
137849
138395
|
spin?.start("Scaffolding the latest TanStack Start template");
|
|
137850
138396
|
try {
|
|
137851
|
-
runTanstackCreate({ targetDir, projectName:
|
|
137852
|
-
spin?.stop(
|
|
138397
|
+
runTanstackCreate({ targetDir, projectName: input.slug, pm: input.pm });
|
|
138398
|
+
spin?.stop(
|
|
138399
|
+
`Scaffolded ${input.slug} from the latest TanStack Start template`
|
|
138400
|
+
);
|
|
137853
138401
|
} catch (err2) {
|
|
137854
138402
|
spin?.error("Scaffold failed");
|
|
137855
138403
|
throw new CommandAbort({
|
|
137856
138404
|
code: "SCAFFOLD_FAILED",
|
|
137857
138405
|
message: `${err2 instanceof Error ? err2.message : "Failed to scaffold the project"}
|
|
137858
138406
|
|
|
137859
|
-
The app ${app.id} is already registered \u2014 fix the problem
|
|
138407
|
+
The app ${app.id} is already registered \u2014 fix the problem, then re-run \`${retry}\`.`
|
|
137860
138408
|
});
|
|
137861
138409
|
}
|
|
137862
138410
|
}
|
|
137863
|
-
writeAppConfig(targetDir,
|
|
137864
|
-
const { manualSteps } = whopifyProject({
|
|
138411
|
+
writeAppConfig(targetDir, linkConfigFor(app));
|
|
138412
|
+
const { manualSteps } = whopifyProject({
|
|
138413
|
+
targetDir,
|
|
138414
|
+
workerName: input.slug
|
|
138415
|
+
});
|
|
137865
138416
|
try {
|
|
137866
138417
|
runInstall(c2, targetDir);
|
|
137867
138418
|
} catch (err2) {
|
|
137868
138419
|
throw new CommandAbort({
|
|
137869
138420
|
code: "INSTALL_FAILED",
|
|
137870
|
-
message: err2 instanceof Error ? err2.message : "Install failed"
|
|
138421
|
+
message: `${err2 instanceof Error ? err2.message : "Install failed"}
|
|
138422
|
+
|
|
138423
|
+
The app ${app.id} is already registered \u2014 re-run \`${retry}\`.`,
|
|
138424
|
+
retryable: true
|
|
138425
|
+
});
|
|
138426
|
+
}
|
|
138427
|
+
return manualSteps;
|
|
138428
|
+
}
|
|
138429
|
+
function emptyDirectory(dir) {
|
|
138430
|
+
if (!existsSync11(dir)) return;
|
|
138431
|
+
for (const entry of readdirSync3(dir)) {
|
|
138432
|
+
rmSync3(join11(dir, entry), { recursive: true, force: true });
|
|
138433
|
+
}
|
|
138434
|
+
}
|
|
138435
|
+
async function newProjectApp(c2, options, template) {
|
|
138436
|
+
const templateAppType = template?.app_type === "website" ? "website" : void 0;
|
|
138437
|
+
const { name, domain: domain2, appType } = await resolveNameAndDomain(
|
|
138438
|
+
c2,
|
|
138439
|
+
options,
|
|
138440
|
+
templateAppType
|
|
138441
|
+
);
|
|
138442
|
+
return {
|
|
138443
|
+
slug: slugify4(name) || slugify4(domain2),
|
|
138444
|
+
claim: () => registerApp({
|
|
138445
|
+
name,
|
|
138446
|
+
appType,
|
|
138447
|
+
domain: domain2,
|
|
138448
|
+
companyId: options.company_id,
|
|
138449
|
+
importedFromUrl: options.imported_from_url
|
|
138450
|
+
})
|
|
138451
|
+
};
|
|
138452
|
+
}
|
|
138453
|
+
async function registerApp(input) {
|
|
138454
|
+
let domain2;
|
|
138455
|
+
try {
|
|
138456
|
+
domain2 = await ensureDomain({
|
|
138457
|
+
hostname: input.domain,
|
|
138458
|
+
accountId: input.companyId
|
|
138459
|
+
});
|
|
138460
|
+
} catch (err2) {
|
|
138461
|
+
if (err2 instanceof CommandAbort) throw err2;
|
|
138462
|
+
throw new CommandAbort({
|
|
138463
|
+
code: "DOMAIN_UNAVAILABLE",
|
|
138464
|
+
message: `Couldn't claim ${input.domain}: ${err2 instanceof Error ? err2.message : "unknown error"}
|
|
138465
|
+
|
|
138466
|
+
Nothing was created. Ask the user for another domain, then re-run with --domain.`,
|
|
138467
|
+
retryable: true
|
|
138468
|
+
});
|
|
138469
|
+
}
|
|
138470
|
+
const domainId = domain2.id;
|
|
138471
|
+
try {
|
|
138472
|
+
return await createApp({
|
|
138473
|
+
name: input.name,
|
|
138474
|
+
app_type: input.appType,
|
|
138475
|
+
domain_id: domainId,
|
|
138476
|
+
company_id: input.companyId,
|
|
138477
|
+
imported_from_url: input.importedFromUrl
|
|
138478
|
+
});
|
|
138479
|
+
} catch (err2) {
|
|
138480
|
+
throw new CommandAbort({
|
|
138481
|
+
code: "CREATE_FAILED",
|
|
138482
|
+
message: err2 instanceof Error ? err2.message : "Failed to register the app",
|
|
137871
138483
|
retryable: true
|
|
137872
138484
|
});
|
|
137873
138485
|
}
|
|
137874
|
-
|
|
137875
|
-
|
|
138486
|
+
}
|
|
138487
|
+
async function existingProjectApp(appId) {
|
|
138488
|
+
let app;
|
|
138489
|
+
try {
|
|
138490
|
+
app = await getApp(appId);
|
|
138491
|
+
} catch (err2) {
|
|
138492
|
+
throw new CommandAbort({
|
|
138493
|
+
code: "APP_NOT_FOUND",
|
|
138494
|
+
message: `Could not load app ${appId}: ${err2 instanceof Error ? err2.message : "unknown error"}`,
|
|
138495
|
+
retryable: true
|
|
138496
|
+
});
|
|
138497
|
+
}
|
|
138498
|
+
if (await hasWebBuilds(app.id)) {
|
|
138499
|
+
throw new CommandAbort({
|
|
138500
|
+
code: "APP_ALREADY_DEPLOYED",
|
|
138501
|
+
message: `${app.name} (${app.id}) already has builds, so starting fresh code for it would replace that code on the next deploy. Get its code with:
|
|
138502
|
+
whop apps pull --app ${app.id}
|
|
138503
|
+
Add --build abld_xxx for a preview build when nothing is live yet.`,
|
|
138504
|
+
cta: {
|
|
138505
|
+
commands: [
|
|
138506
|
+
{
|
|
138507
|
+
command: `apps pull --app ${app.id}`,
|
|
138508
|
+
description: "Fetch the deployed source"
|
|
138509
|
+
}
|
|
138510
|
+
]
|
|
138511
|
+
}
|
|
138512
|
+
});
|
|
138513
|
+
}
|
|
138514
|
+
return { slug: appSlug(app), claim: async () => app };
|
|
137876
138515
|
}
|
|
137877
138516
|
function initGitRepo(c2, targetDir) {
|
|
137878
138517
|
if (!gitInstalled()) {
|
|
@@ -137894,16 +138533,16 @@ function initGitRepo(c2, targetDir) {
|
|
|
137894
138533
|
}
|
|
137895
138534
|
|
|
137896
138535
|
// src/apps/pull.ts
|
|
137897
|
-
import { mkdtempSync as mkdtempSync2, mkdirSync as mkdirSync8, rmSync as
|
|
138536
|
+
import { mkdtempSync as mkdtempSync2, mkdirSync as mkdirSync8, rmSync as rmSync4 } from "fs";
|
|
137898
138537
|
import { tmpdir as tmpdir2 } from "os";
|
|
137899
|
-
import { join as
|
|
138538
|
+
import { join as join12, resolve as resolve8 } from "path";
|
|
137900
138539
|
var pullOptions = external_exports.object({
|
|
137901
138540
|
app: external_exports.string().optional().describe("App id (defaults to the project's linked app)"),
|
|
137902
138541
|
build: external_exports.string().optional().describe(
|
|
137903
138542
|
"Pull this specific build's source (abld_xxx) instead of the current production build"
|
|
137904
138543
|
),
|
|
137905
138544
|
dir: external_exports.string().optional().describe(
|
|
137906
|
-
"Target directory (defaults to the linked project, or ./<
|
|
138545
|
+
"Target directory (defaults to the linked project, or ./<app name> on a fresh machine)"
|
|
137907
138546
|
),
|
|
137908
138547
|
overwrite: external_exports.boolean().optional().describe(
|
|
137909
138548
|
"Skip the merge and write the archive files straight over the working tree"
|
|
@@ -137974,10 +138613,41 @@ async function resolveSource(options) {
|
|
|
137974
138613
|
}
|
|
137975
138614
|
const app = await loadApp(appId);
|
|
137976
138615
|
const production = app.production_web_build;
|
|
137977
|
-
if (!production
|
|
138616
|
+
if (!production && await hasWebBuilds(app.id)) {
|
|
137978
138617
|
throw new CommandAbort({
|
|
137979
138618
|
code: "APP_HAS_NO_SOURCE",
|
|
137980
|
-
message: `${app.name} (${app.id}) has
|
|
138619
|
+
message: `${app.name} (${app.id}) has preview builds but nothing live. Pick one with \`whop apps builds list --app_id ${app.id}\`, then pull it:
|
|
138620
|
+
whop apps pull --app ${app.id} --build abld_xxx`,
|
|
138621
|
+
cta: {
|
|
138622
|
+
commands: [
|
|
138623
|
+
{
|
|
138624
|
+
command: `apps builds list --app_id ${app.id}`,
|
|
138625
|
+
description: "List the app's builds"
|
|
138626
|
+
}
|
|
138627
|
+
]
|
|
138628
|
+
}
|
|
138629
|
+
});
|
|
138630
|
+
}
|
|
138631
|
+
if (!production) {
|
|
138632
|
+
throw new CommandAbort({
|
|
138633
|
+
code: "APP_HAS_NO_SOURCE",
|
|
138634
|
+
message: `${app.name} (${app.id}) has never been deployed, so there is no code to pull. Start its code with:
|
|
138635
|
+
whop apps init --app ${app.id}${options.dir ? ` --dir ${options.dir}` : ""}
|
|
138636
|
+
then build it and run \`whop apps deploy\`.`,
|
|
138637
|
+
cta: {
|
|
138638
|
+
commands: [
|
|
138639
|
+
{
|
|
138640
|
+
command: `apps init --app ${app.id}`,
|
|
138641
|
+
description: "Scaffold and link a project for this app"
|
|
138642
|
+
}
|
|
138643
|
+
]
|
|
138644
|
+
}
|
|
138645
|
+
});
|
|
138646
|
+
}
|
|
138647
|
+
if (!production.source_url) {
|
|
138648
|
+
throw new CommandAbort({
|
|
138649
|
+
code: "APP_HAS_NO_SOURCE",
|
|
138650
|
+
message: `${app.name} (${app.id}) is live, but its production build was uploaded without a source archive. Deploy from the machine that has the code, or pass --build abld_xxx for a specific build that has one.`
|
|
137981
138651
|
});
|
|
137982
138652
|
}
|
|
137983
138653
|
return { app, buildId: production.id, sourceUrl: production.source_url };
|
|
@@ -138004,15 +138674,7 @@ function resolveTargetDir(options, app) {
|
|
|
138004
138674
|
if (projectDir && readAppConfig(projectDir)?.app_id === app.id) {
|
|
138005
138675
|
return projectDir;
|
|
138006
138676
|
}
|
|
138007
|
-
|
|
138008
|
-
if (!route) {
|
|
138009
|
-
throw new CommandAbort({
|
|
138010
|
-
code: "DIR_REQUIRED",
|
|
138011
|
-
message: `${app.name} (${app.id}) has no route to name a directory after \u2014 pass --dir <path>.`,
|
|
138012
|
-
retryable: true
|
|
138013
|
-
});
|
|
138014
|
-
}
|
|
138015
|
-
return resolve8(`./${route}`);
|
|
138677
|
+
return resolve8(`./${appSlug(app)}`);
|
|
138016
138678
|
}
|
|
138017
138679
|
function ensureUsableRepo(targetDir) {
|
|
138018
138680
|
const status = repoStatus(targetDir);
|
|
@@ -138037,11 +138699,7 @@ async function runPullFlow(options) {
|
|
|
138037
138699
|
const targetDir = resolveTargetDir(options, app);
|
|
138038
138700
|
const zip = await downloadArchive(source.sourceUrl);
|
|
138039
138701
|
mkdirSync8(targetDir, { recursive: true });
|
|
138040
|
-
const linkConfig =
|
|
138041
|
-
app_id: app.id,
|
|
138042
|
-
name: app.name,
|
|
138043
|
-
route: app.route ?? ""
|
|
138044
|
-
};
|
|
138702
|
+
const linkConfig = linkConfigFor(app);
|
|
138045
138703
|
if (options.overwrite) {
|
|
138046
138704
|
extractSourceArchive(zip, targetDir);
|
|
138047
138705
|
writeAppConfig(targetDir, linkConfig);
|
|
@@ -138054,7 +138712,7 @@ async function runPullFlow(options) {
|
|
|
138054
138712
|
autostash: void 0
|
|
138055
138713
|
};
|
|
138056
138714
|
}
|
|
138057
|
-
const snapshotDir = mkdtempSync2(
|
|
138715
|
+
const snapshotDir = mkdtempSync2(join12(tmpdir2(), "whop-pull-"));
|
|
138058
138716
|
try {
|
|
138059
138717
|
extractSourceArchive(zip, snapshotDir);
|
|
138060
138718
|
ensureUsableRepo(targetDir);
|
|
@@ -138107,12 +138765,12 @@ async function runPullFlow(options) {
|
|
|
138107
138765
|
autostash
|
|
138108
138766
|
};
|
|
138109
138767
|
} finally {
|
|
138110
|
-
|
|
138768
|
+
rmSync4(snapshotDir, { recursive: true, force: true });
|
|
138111
138769
|
}
|
|
138112
138770
|
}
|
|
138113
138771
|
function recordOverwriteSnapshot(zip, targetDir, appId, buildId) {
|
|
138114
138772
|
if (!gitInstalled() || repoStatus(targetDir).kind !== "root") return;
|
|
138115
|
-
const snapshotDir = mkdtempSync2(
|
|
138773
|
+
const snapshotDir = mkdtempSync2(join12(tmpdir2(), "whop-pull-"));
|
|
138116
138774
|
try {
|
|
138117
138775
|
extractSourceArchive(zip, snapshotDir);
|
|
138118
138776
|
commitSnapshot(
|
|
@@ -138122,7 +138780,7 @@ function recordOverwriteSnapshot(zip, targetDir, appId, buildId) {
|
|
|
138122
138780
|
`whop apps pull --overwrite: ${appId}${buildId ? ` @ ${buildId}` : ""}`
|
|
138123
138781
|
);
|
|
138124
138782
|
} finally {
|
|
138125
|
-
|
|
138783
|
+
rmSync4(snapshotDir, { recursive: true, force: true });
|
|
138126
138784
|
}
|
|
138127
138785
|
}
|
|
138128
138786
|
function ensureLinked(targetDir, config2) {
|
|
@@ -138155,16 +138813,20 @@ var BuildSchema = external_exports.object({
|
|
|
138155
138813
|
id: external_exports.string(),
|
|
138156
138814
|
status: external_exports.string(),
|
|
138157
138815
|
is_production: external_exports.boolean().optional(),
|
|
138158
|
-
url: external_exports.string().optional()
|
|
138816
|
+
url: external_exports.string().optional(),
|
|
138817
|
+
domain_steps: external_exports.array(external_exports.string()).optional().describe(
|
|
138818
|
+
"What the owner must do before a domain serves the app: pay at a purchase link, or publish DNS records"
|
|
138819
|
+
)
|
|
138159
138820
|
});
|
|
138160
138821
|
function formatManualSteps(steps) {
|
|
138161
138822
|
return steps.map((step, i) => ` ${i + 1}. ${step}`).join("\n");
|
|
138162
138823
|
}
|
|
138163
138824
|
function formatAppList(apps) {
|
|
138164
138825
|
const recent = [...apps].sort((a, b) => (b.created_at ?? 0) - (a.created_at ?? 0)).slice(0, 10);
|
|
138165
|
-
return recent.map(
|
|
138166
|
-
|
|
138167
|
-
|
|
138826
|
+
return recent.map((a) => {
|
|
138827
|
+
const address = appAddress(a);
|
|
138828
|
+
return ` ${a.id} ${a.name}${address ? ` (${address})` : ""}`;
|
|
138829
|
+
}).join("\n");
|
|
138168
138830
|
}
|
|
138169
138831
|
async function registerSpecCommands(group, tag) {
|
|
138170
138832
|
const spec2 = filterSpecByTag(apps_spec_default, tag);
|
|
@@ -138179,7 +138841,7 @@ async function registerSpecCommands(group, tag) {
|
|
|
138179
138841
|
}
|
|
138180
138842
|
async function resolveDeployProject(c2, dirOption) {
|
|
138181
138843
|
const projectDir = dirOption ? resolve9(dirOption) : findProjectDir() ?? process.cwd();
|
|
138182
|
-
const isViteApp = existsSync12(
|
|
138844
|
+
const isViteApp = existsSync12(join13(projectDir, "package.json")) && findViteConfig(projectDir) !== void 0;
|
|
138183
138845
|
if (isViteApp) return { projectDir, freshInit: null };
|
|
138184
138846
|
if (c2.agent) {
|
|
138185
138847
|
throw new CommandAbort({
|
|
@@ -138188,13 +138850,16 @@ async function resolveDeployProject(c2, dirOption) {
|
|
|
138188
138850
|
`${projectDir} doesn't look like a Vite app (missing package.json or vite config), and deploy only ships existing projects.`,
|
|
138189
138851
|
"",
|
|
138190
138852
|
"To start a new app here (scaffolds, registers, and links):",
|
|
138191
|
-
' whop apps init --name "My Site" --
|
|
138853
|
+
' whop apps init --name "My Site" --domain my-site --app_type b2c_app',
|
|
138192
138854
|
"",
|
|
138193
138855
|
"--app_type takes b2c_app or website. Ask the user which one: a website cannot be turned back into an app later.",
|
|
138194
138856
|
"",
|
|
138195
138857
|
"To get an existing app's deployed source onto this machine:",
|
|
138196
138858
|
" whop apps pull --app app_xxxxxxxx",
|
|
138197
138859
|
"",
|
|
138860
|
+
"To start the code for an existing app that has never been deployed (pull fails with APP_HAS_NO_SOURCE):",
|
|
138861
|
+
" whop apps init --app app_xxxxxxxx",
|
|
138862
|
+
"",
|
|
138198
138863
|
"Then re-run `whop apps deploy` from inside the project directory."
|
|
138199
138864
|
].join("\n"),
|
|
138200
138865
|
retryable: true,
|
|
@@ -138218,32 +138883,16 @@ async function resolveDeployProject(c2, dirOption) {
|
|
|
138218
138883
|
);
|
|
138219
138884
|
if (choice === "cancel") cancelled();
|
|
138220
138885
|
const scaffolded = await runInitFlow(c2, {});
|
|
138221
|
-
return { projectDir: scaffolded.projectDir, freshInit: scaffolded.
|
|
138886
|
+
return { projectDir: scaffolded.projectDir, freshInit: scaffolded.app };
|
|
138222
138887
|
}
|
|
138223
138888
|
async function ensureAppLinked(c2, projectDir, appOption) {
|
|
138224
138889
|
if (appOption) {
|
|
138225
|
-
|
|
138226
|
-
|
|
138227
|
-
|
|
138228
|
-
} catch (err2) {
|
|
138229
|
-
throw new CommandAbort({
|
|
138230
|
-
code: "APP_NOT_FOUND",
|
|
138231
|
-
message: `Could not load app ${appOption}: ${err2 instanceof Error ? err2.message : "unknown error"}`,
|
|
138232
|
-
retryable: true
|
|
138233
|
-
});
|
|
138234
|
-
}
|
|
138235
|
-
const config3 = await withRoute(c2, app);
|
|
138236
|
-
writeAppConfig(projectDir, config3);
|
|
138237
|
-
log2(
|
|
138238
|
-
c2,
|
|
138239
|
-
chalk2.dim(
|
|
138240
|
-
`Linked ${config3.name} (${config3.app_id}) \u2192 ${APP_CONFIG_FILENAME}`
|
|
138241
|
-
)
|
|
138242
|
-
);
|
|
138243
|
-
return config3;
|
|
138890
|
+
const app2 = await withAddress(c2, await loadApp2(appOption));
|
|
138891
|
+
linkProject(c2, projectDir, app2);
|
|
138892
|
+
return app2;
|
|
138244
138893
|
}
|
|
138245
138894
|
const existing = readAppConfig(projectDir);
|
|
138246
|
-
if (existing) return existing;
|
|
138895
|
+
if (existing) return withAddress(c2, await loadApp2(existing.app_id));
|
|
138247
138896
|
const apps = await listApps();
|
|
138248
138897
|
if (c2.agent) {
|
|
138249
138898
|
const reuse = apps.length > 0 ? `This account has existing apps \u2014 ask the user whether to reuse one:
|
|
@@ -138255,12 +138904,12 @@ To reuse one: whop apps deploy --app <app_id>
|
|
|
138255
138904
|
throw new CommandAbort({
|
|
138256
138905
|
code: "NO_APP_LINKED",
|
|
138257
138906
|
message: [
|
|
138258
|
-
`No ${APP_CONFIG_FILENAME} here \u2014 this project isn't linked to a Whop app yet.`,
|
|
138907
|
+
`No ${APP_CONFIG_FILENAME} here \u2014 this project isn't linked to a Whop app yet. If you already know which app this code is for, deploy with --app; never write ${APP_CONFIG_FILENAME} by hand.`,
|
|
138259
138908
|
"",
|
|
138260
|
-
`${reuse}To register a new app for this existing code, ask the user for a name and
|
|
138261
|
-
' whop apps create --name "My Site" --
|
|
138909
|
+
`${reuse}To register a new app for this existing code, ask the user for a name and whether it is a website, then run:`,
|
|
138910
|
+
' whop apps create --name "My Site" --app_type website',
|
|
138262
138911
|
"",
|
|
138263
|
-
"Then deploy with the returned app id:",
|
|
138912
|
+
"Then deploy with the returned app id (it asks for a domain if the app has none):",
|
|
138264
138913
|
" whop apps deploy --app <app_id>"
|
|
138265
138914
|
].join("\n"),
|
|
138266
138915
|
retryable: true,
|
|
@@ -138268,7 +138917,7 @@ To reuse one: whop apps deploy --app <app_id>
|
|
|
138268
138917
|
commands: [
|
|
138269
138918
|
{
|
|
138270
138919
|
command: "apps create",
|
|
138271
|
-
description: "Register a new app (pass --name and --
|
|
138920
|
+
description: "Register a new app (pass --name and --app_type)"
|
|
138272
138921
|
},
|
|
138273
138922
|
{
|
|
138274
138923
|
command: "apps deploy",
|
|
@@ -138288,7 +138937,7 @@ To reuse one: whop apps deploy --app <app_id>
|
|
|
138288
138937
|
[
|
|
138289
138938
|
...recent.map((a) => ({
|
|
138290
138939
|
value: a.id,
|
|
138291
|
-
label: `${a.name} (${a.id
|
|
138940
|
+
label: `${a.name} (${[a.id, appAddress(a)].filter(Boolean).join(", ")})`
|
|
138292
138941
|
})),
|
|
138293
138942
|
{ value: "__new__", label: "Register a new app" }
|
|
138294
138943
|
]
|
|
@@ -138298,79 +138947,72 @@ To reuse one: whop apps deploy --app <app_id>
|
|
|
138298
138947
|
}
|
|
138299
138948
|
}
|
|
138300
138949
|
if (!selected) {
|
|
138301
|
-
const { name,
|
|
138302
|
-
|
|
138303
|
-
selected = await createApp({ name, route, app_type: appType });
|
|
138304
|
-
} catch (err2) {
|
|
138305
|
-
throw new CommandAbort({
|
|
138306
|
-
code: "CREATE_FAILED",
|
|
138307
|
-
message: err2 instanceof Error ? err2.message : "Failed to register the app",
|
|
138308
|
-
retryable: true
|
|
138309
|
-
});
|
|
138310
|
-
}
|
|
138950
|
+
const { name, domain: domain2, appType } = await promptForNewApp();
|
|
138951
|
+
selected = await registerApp({ name, appType, domain: domain2 });
|
|
138311
138952
|
}
|
|
138312
|
-
const
|
|
138313
|
-
|
|
138314
|
-
|
|
138315
|
-
|
|
138316
|
-
|
|
138317
|
-
|
|
138318
|
-
)
|
|
138319
|
-
)
|
|
138320
|
-
|
|
138953
|
+
const app = await withAddress(c2, selected);
|
|
138954
|
+
linkProject(c2, projectDir, app);
|
|
138955
|
+
return app;
|
|
138956
|
+
}
|
|
138957
|
+
async function loadApp2(appId) {
|
|
138958
|
+
try {
|
|
138959
|
+
return await getApp(appId);
|
|
138960
|
+
} catch (err2) {
|
|
138961
|
+
throw new CommandAbort({
|
|
138962
|
+
code: "APP_NOT_FOUND",
|
|
138963
|
+
message: `Could not load app ${appId}: ${err2 instanceof Error ? err2.message : "unknown error"}`,
|
|
138964
|
+
retryable: true
|
|
138965
|
+
});
|
|
138966
|
+
}
|
|
138967
|
+
}
|
|
138968
|
+
function linkProject(c2, projectDir, app) {
|
|
138969
|
+
writeAppConfig(projectDir, linkConfigFor(app));
|
|
138970
|
+
log2(c2, chalk2.dim(`Linked ${app.name} (${app.id}) \u2192 ${APP_CONFIG_FILENAME}`));
|
|
138321
138971
|
}
|
|
138322
|
-
|
|
138323
|
-
|
|
138972
|
+
function appAddress(app) {
|
|
138973
|
+
return app.domains?.[0]?.domain;
|
|
138974
|
+
}
|
|
138975
|
+
async function withAddress(c2, app) {
|
|
138976
|
+
if (appAddress(app)) return app;
|
|
138977
|
+
const suggested = platformDomainFor(appSlug(app));
|
|
138324
138978
|
if (c2.agent) {
|
|
138325
138979
|
throw new CommandAbort({
|
|
138326
|
-
code: "
|
|
138327
|
-
message: `App ${app.id} (${app.name}) has no
|
|
138328
|
-
whop
|
|
138329
|
-
whop apps deploy --app ${app.id}
|
|
138980
|
+
code: "DOMAIN_REQUIRED",
|
|
138981
|
+
message: `App ${app.id} (${app.name}) has no domain, so a deploy would be unreachable. Ask the user which domain to use \u2014 a whop.site name or a domain the account owns \u2014 then run:
|
|
138982
|
+
whop domains create --account_id ${app.account?.id ?? "biz_xxx"} --domain ${suggested} --website '{"app_id":"${app.id}"}'
|
|
138983
|
+
whop apps deploy --app ${app.id}
|
|
138984
|
+
For a domain already on the account, use \`whop domains update <domain> --website '{"app_id":"${app.id}"}'\` instead.`,
|
|
138330
138985
|
retryable: true,
|
|
138331
138986
|
cta: {
|
|
138332
138987
|
commands: [
|
|
138333
138988
|
{
|
|
138334
|
-
command:
|
|
138335
|
-
description:
|
|
138989
|
+
command: "domains create",
|
|
138990
|
+
description: `Serve ${app.id} on a domain (pass --domain and --website)`
|
|
138336
138991
|
}
|
|
138337
138992
|
]
|
|
138338
138993
|
}
|
|
138339
138994
|
});
|
|
138340
138995
|
}
|
|
138341
|
-
const
|
|
138342
|
-
const routeInput = await promptText(
|
|
138343
|
-
`${app.name} has no route yet. Which route should it live at? (your-route.whop.site)`,
|
|
138344
|
-
slug,
|
|
138345
|
-
slug
|
|
138346
|
-
);
|
|
138347
|
-
if (routeInput === null) cancelled();
|
|
138348
|
-
const route = slugify4(routeInput);
|
|
138349
|
-
if (!route) {
|
|
138350
|
-
throw new CommandAbort({
|
|
138351
|
-
code: "ROUTE_REQUIRED",
|
|
138352
|
-
message: `Couldn't derive a route from "${routeInput}" \u2014 use letters and numbers (e.g. my-site).`,
|
|
138353
|
-
retryable: true
|
|
138354
|
-
});
|
|
138355
|
-
}
|
|
138996
|
+
const domain2 = await promptForDomain(app.name);
|
|
138356
138997
|
try {
|
|
138357
|
-
|
|
138358
|
-
|
|
138359
|
-
|
|
138360
|
-
|
|
138361
|
-
|
|
138362
|
-
|
|
138998
|
+
await ensureDomain({
|
|
138999
|
+
hostname: domain2,
|
|
139000
|
+
accountId: app.account?.id,
|
|
139001
|
+
appId: app.id
|
|
139002
|
+
});
|
|
139003
|
+
return await getApp(app.id);
|
|
138363
139004
|
} catch (err2) {
|
|
139005
|
+
if (err2 instanceof CommandAbort) throw err2;
|
|
138364
139006
|
throw new CommandAbort({
|
|
138365
|
-
code: "
|
|
138366
|
-
message: err2 instanceof Error ? err2.message : "
|
|
139007
|
+
code: "DOMAIN_UNAVAILABLE",
|
|
139008
|
+
message: `Couldn't serve ${app.name} on ${domain2}: ${err2 instanceof Error ? err2.message : "unknown error"}`,
|
|
138367
139009
|
retryable: true
|
|
138368
139010
|
});
|
|
138369
139011
|
}
|
|
138370
139012
|
}
|
|
138371
139013
|
function advanceRemoteSnapshot(c2, projectDir, appId, buildId, sourceZip) {
|
|
138372
139014
|
if (!gitInstalled() || repoStatus(projectDir).kind !== "root") return;
|
|
138373
|
-
const snapshotDir = mkdtempSync3(
|
|
139015
|
+
const snapshotDir = mkdtempSync3(join13(tmpdir3(), "whop-deploy-"));
|
|
138374
139016
|
try {
|
|
138375
139017
|
extractSourceArchive(sourceZip, snapshotDir);
|
|
138376
139018
|
commitSnapshot(
|
|
@@ -138388,7 +139030,7 @@ function advanceRemoteSnapshot(c2, projectDir, appId, buildId, sourceZip) {
|
|
|
138388
139030
|
)
|
|
138389
139031
|
);
|
|
138390
139032
|
} finally {
|
|
138391
|
-
|
|
139033
|
+
rmSync5(snapshotDir, { recursive: true, force: true });
|
|
138392
139034
|
}
|
|
138393
139035
|
}
|
|
138394
139036
|
function buildSecretsGroup() {
|
|
@@ -138464,7 +139106,7 @@ function resolveLinkedAppId(appOption) {
|
|
|
138464
139106
|
}
|
|
138465
139107
|
async function buildAppGroup() {
|
|
138466
139108
|
const app = Cli_exports.create("apps", {
|
|
138467
|
-
description: "Build and deploy fully-hosted web apps on Whop
|
|
139109
|
+
description: "Build and deploy fully-hosted web apps on Whop, served at their domains \u2014 Vite apps on Cloudflare Workers"
|
|
138468
139110
|
});
|
|
138469
139111
|
await registerSpecCommands(app, "Apps");
|
|
138470
139112
|
const builds = Cli_exports.create("builds", {
|
|
@@ -138474,34 +139116,40 @@ async function buildAppGroup() {
|
|
|
138474
139116
|
app.command(builds);
|
|
138475
139117
|
app.command(buildSecretsGroup());
|
|
138476
139118
|
app.command("init", {
|
|
138477
|
-
description: "Start
|
|
138478
|
-
hint: "Registers the app on Whop (claiming
|
|
139119
|
+
description: "Start an app's code: register (or take --app), scaffold, and link a project",
|
|
139120
|
+
hint: "Registers the app on Whop on its domain (claiming a whop.site address, or using a domain the account owns) \u2014 or, with --app, takes an existing app that has never been deployed \u2014 scaffolds the latest TanStack Start template \u2014 or a template app's published source with --template \u2014 wires it for Whop hosting, installs dependencies, and git-inits. Then `whop apps dev` to build, `whop apps deploy` to ship.",
|
|
138479
139121
|
options: initOptions,
|
|
138480
139122
|
output: initOutput,
|
|
138481
139123
|
outputPolicy: "agent-only",
|
|
138482
139124
|
examples: [
|
|
138483
139125
|
{ description: "Scaffold a new app interactively" },
|
|
138484
139126
|
{
|
|
138485
|
-
options: { name: "My Site",
|
|
139127
|
+
options: { name: "My Site", domain: "my-site", app_type: "website" },
|
|
138486
139128
|
description: "Scaffold without prompts (agents: always pass --name and --app_type)"
|
|
138487
139129
|
},
|
|
138488
139130
|
{
|
|
138489
139131
|
options: { name: "My Site", template: "app_xxxxxxxx" },
|
|
138490
139132
|
description: "Start from another app's published source archive"
|
|
139133
|
+
},
|
|
139134
|
+
{
|
|
139135
|
+
options: { app: "app_xxxxxxxx" },
|
|
139136
|
+
description: "Start the code for an existing app that has never been deployed (pull reports APP_HAS_NO_SOURCE)"
|
|
138491
139137
|
}
|
|
138492
139138
|
],
|
|
138493
139139
|
run: async (c2) => {
|
|
138494
139140
|
try {
|
|
138495
139141
|
const result = await runInitFlow(c2, c2.options);
|
|
138496
139142
|
const cdTarget = relative3(process.cwd(), result.projectDir) || ".";
|
|
139143
|
+
const domainSteps = await pendingDomainSteps(result.app);
|
|
138497
139144
|
if (!c2.agent && !c2.formatExplicit) {
|
|
138498
139145
|
console.log(
|
|
138499
139146
|
[
|
|
138500
139147
|
"",
|
|
138501
|
-
chalk2.green.bold(`\u2713 Created ${result.
|
|
138502
|
-
` ${chalk2.dim(result.
|
|
139148
|
+
chalk2.green.bold(`\u2713 Created ${result.app.name}`),
|
|
139149
|
+
` ${chalk2.dim(result.app.id)} ${appAddress(result.app) ?? ""}`,
|
|
138503
139150
|
"",
|
|
138504
139151
|
chalk2.bold("Next"),
|
|
139152
|
+
...domainSteps.map((step) => ` ${chalk2.yellow(step)}`),
|
|
138505
139153
|
...cdTarget !== "." ? [` cd ${cdTarget}`] : [],
|
|
138506
139154
|
` ${chalk2.cyan.bold("whop apps dev")} ${chalk2.dim("\u2192 local dev server")}`,
|
|
138507
139155
|
` ${chalk2.cyan.bold("whop apps deploy")} ${chalk2.dim("\u2192 ship it live")}`,
|
|
@@ -138511,11 +139159,12 @@ async function buildAppGroup() {
|
|
|
138511
139159
|
}
|
|
138512
139160
|
return c2.ok(
|
|
138513
139161
|
{
|
|
138514
|
-
app_id: result.
|
|
138515
|
-
name: result.
|
|
138516
|
-
|
|
139162
|
+
app_id: result.app.id,
|
|
139163
|
+
name: result.app.name,
|
|
139164
|
+
domain: appAddress(result.app),
|
|
138517
139165
|
dir: result.projectDir,
|
|
138518
|
-
manual_steps: result.manualSteps.length ? result.manualSteps : void 0
|
|
139166
|
+
manual_steps: result.manualSteps.length ? result.manualSteps : void 0,
|
|
139167
|
+
domain_steps: domainSteps.length ? domainSteps : void 0
|
|
138519
139168
|
},
|
|
138520
139169
|
{
|
|
138521
139170
|
cta: {
|
|
@@ -138538,7 +139187,7 @@ async function buildAppGroup() {
|
|
|
138538
139187
|
});
|
|
138539
139188
|
app.command("pull", {
|
|
138540
139189
|
description: "Fetch the app's deployed source and merge it into this directory",
|
|
138541
|
-
hint: "Downloads the current production build's source archive (or --build abld_xxx for any specific build \u2014 including rollback inspection) and three-way merges it with your local code via git: a per-app snapshot ref supplies the merge base, local edits are autostashed around the merge, and conflicts surface as normal git conflict markers. On a fresh machine it creates ./<
|
|
139190
|
+
hint: "Downloads the current production build's source archive (or --build abld_xxx for any specific build \u2014 including rollback inspection) and three-way merges it with your local code via git: a per-app snapshot ref supplies the merge base, local edits are autostashed around the merge, and conflicts surface as normal git conflict markers. On a fresh machine it creates ./<app name> and becomes your working copy.",
|
|
138542
139191
|
options: pullOptions,
|
|
138543
139192
|
output: pullOutput,
|
|
138544
139193
|
outputPolicy: "agent-only",
|
|
@@ -138639,6 +139288,9 @@ async function buildAppGroup() {
|
|
|
138639
139288
|
if (c2.options.public_host) {
|
|
138640
139289
|
injected.WHOP_DEV_PUBLIC_ORIGIN = c2.options.public_host;
|
|
138641
139290
|
}
|
|
139291
|
+
if (process.env.CLOUDFLARE_INCLUDE_PROCESS_ENV === void 0) {
|
|
139292
|
+
injected.CLOUDFLARE_INCLUDE_PROCESS_ENV = "true";
|
|
139293
|
+
}
|
|
138642
139294
|
if (process.env.WHOP_API_KEY) {
|
|
138643
139295
|
log2(
|
|
138644
139296
|
c2,
|
|
@@ -138752,15 +139404,16 @@ async function buildAppGroup() {
|
|
|
138752
139404
|
c2,
|
|
138753
139405
|
c2.options.dir
|
|
138754
139406
|
);
|
|
138755
|
-
const
|
|
139407
|
+
const linked = freshInit ?? await ensureAppLinked(c2, projectDir, c2.options.app);
|
|
139408
|
+
const slug = appSlug(linked);
|
|
138756
139409
|
const { manualSteps } = whopifyProject({
|
|
138757
139410
|
targetDir: projectDir,
|
|
138758
|
-
|
|
139411
|
+
workerName: slug
|
|
138759
139412
|
});
|
|
138760
139413
|
if (manualSteps.length > 0) {
|
|
138761
139414
|
return c2.error({
|
|
138762
139415
|
code: "WHOPIFY_INCOMPLETE",
|
|
138763
|
-
message: `${
|
|
139416
|
+
message: `${linked.name} is linked (${linked.id}), but the project isn't fully wired for Whop hosting yet. Complete these steps:
|
|
138764
139417
|
|
|
138765
139418
|
${formatManualSteps(manualSteps)}
|
|
138766
139419
|
|
|
@@ -138768,20 +139421,20 @@ Then re-run \`whop apps deploy\` \u2014 it re-checks the wiring and applies anyt
|
|
|
138768
139421
|
});
|
|
138769
139422
|
}
|
|
138770
139423
|
if (!c2.options.skip_build) {
|
|
138771
|
-
if (!existsSync12(
|
|
139424
|
+
if (!existsSync12(join13(projectDir, "node_modules", "@whop", "cli"))) {
|
|
138772
139425
|
phase("install");
|
|
138773
139426
|
runInstall(c2, projectDir);
|
|
138774
139427
|
}
|
|
138775
139428
|
phase("build");
|
|
138776
139429
|
log2(c2, chalk2.dim("[1/4] Building..."));
|
|
138777
|
-
runScript(projectDir, "build", { WHOP_APP_ID:
|
|
139430
|
+
runScript(projectDir, "build", { WHOP_APP_ID: linked.id });
|
|
138778
139431
|
if (!c2.options.skip_typecheck && hasScript(projectDir, "typecheck")) {
|
|
138779
139432
|
phase("typecheck");
|
|
138780
139433
|
log2(c2, chalk2.dim("[2/4] Typechecking..."));
|
|
138781
139434
|
runScript(projectDir, "typecheck");
|
|
138782
139435
|
}
|
|
138783
139436
|
}
|
|
138784
|
-
const archivePath =
|
|
139437
|
+
const archivePath = join13(projectDir, BUILD_ARCHIVE);
|
|
138785
139438
|
if (!existsSync12(archivePath)) {
|
|
138786
139439
|
return c2.error({
|
|
138787
139440
|
code: "NO_BUILD_ARCHIVE",
|
|
@@ -138809,7 +139462,7 @@ Then re-run \`whop apps deploy\` \u2014 it re-checks the wiring and applies anyt
|
|
|
138809
139462
|
try {
|
|
138810
139463
|
const fileId = await uploadBuildArchive(
|
|
138811
139464
|
new Uint8Array(zip),
|
|
138812
|
-
`${
|
|
139465
|
+
`${slug}-build.zip`
|
|
138813
139466
|
);
|
|
138814
139467
|
let sourceFileId;
|
|
138815
139468
|
if ("zip" in sourceArchive) {
|
|
@@ -138820,7 +139473,7 @@ Then re-run \`whop apps deploy\` \u2014 it re-checks the wiring and applies anyt
|
|
|
138820
139473
|
);
|
|
138821
139474
|
sourceFileId = await uploadBuildArchive(
|
|
138822
139475
|
sourceArchive.zip,
|
|
138823
|
-
`${
|
|
139476
|
+
`${slug}-source.zip`
|
|
138824
139477
|
);
|
|
138825
139478
|
}
|
|
138826
139479
|
phase("process_archive");
|
|
@@ -138830,7 +139483,7 @@ Then re-run \`whop apps deploy\` \u2014 it re-checks the wiring and applies anyt
|
|
|
138830
139483
|
phase("create_build");
|
|
138831
139484
|
spin?.message("[3/4] Creating build");
|
|
138832
139485
|
build = await createAppBuild({
|
|
138833
|
-
app_id:
|
|
139486
|
+
app_id: linked.id,
|
|
138834
139487
|
checksum,
|
|
138835
139488
|
file_id: fileId,
|
|
138836
139489
|
source_file_id: sourceFileId
|
|
@@ -138844,7 +139497,7 @@ Then re-run \`whop apps deploy\` \u2014 it re-checks the wiring and applies anyt
|
|
|
138844
139497
|
advanceRemoteSnapshot(
|
|
138845
139498
|
c2,
|
|
138846
139499
|
projectDir,
|
|
138847
|
-
|
|
139500
|
+
linked.id,
|
|
138848
139501
|
build.id,
|
|
138849
139502
|
sourceArchive.zip
|
|
138850
139503
|
);
|
|
@@ -138867,7 +139520,9 @@ Then re-run \`whop apps deploy\` \u2014 it re-checks the wiring and applies anyt
|
|
|
138867
139520
|
log2(c2, chalk2.dim("[4/4] Skipping promotion (--preview)"));
|
|
138868
139521
|
}
|
|
138869
139522
|
const promoted = build.is_production === true;
|
|
138870
|
-
const
|
|
139523
|
+
const live = promoted ? await getApp(linked.id) : null;
|
|
139524
|
+
const productionUrl = live?.base_url ?? live?.hosted_url ?? void 0;
|
|
139525
|
+
const domainSteps = await pendingDomainSteps(live ?? linked);
|
|
138871
139526
|
if (!c2.agent && !c2.formatExplicit) {
|
|
138872
139527
|
const cdTarget = relative3(process.cwd(), projectDir) || ".";
|
|
138873
139528
|
console.log(
|
|
@@ -138883,6 +139538,7 @@ Then re-run \`whop apps deploy\` \u2014 it re-checks the wiring and applies anyt
|
|
|
138883
139538
|
] : [
|
|
138884
139539
|
`${chalk2.bold("Promote when ready")} ${chalk2.cyan.bold(`whop apps builds promote ${build.id}`)}`
|
|
138885
139540
|
],
|
|
139541
|
+
...domainSteps.map((step) => ` ${chalk2.yellow(step)}`),
|
|
138886
139542
|
...freshInit ? [
|
|
138887
139543
|
"",
|
|
138888
139544
|
chalk2.bold("Next"),
|
|
@@ -138899,7 +139555,8 @@ Then re-run \`whop apps deploy\` \u2014 it re-checks the wiring and applies anyt
|
|
|
138899
139555
|
id: build.id,
|
|
138900
139556
|
status: build.status,
|
|
138901
139557
|
is_production: promoted,
|
|
138902
|
-
url: productionUrl
|
|
139558
|
+
url: productionUrl,
|
|
139559
|
+
domain_steps: domainSteps.length ? domainSteps : void 0
|
|
138903
139560
|
},
|
|
138904
139561
|
promoted ? void 0 : {
|
|
138905
139562
|
cta: {
|
|
@@ -140425,40 +141082,40 @@ import {
|
|
|
140425
141082
|
existsSync as existsSync13,
|
|
140426
141083
|
mkdirSync as mkdirSync9,
|
|
140427
141084
|
mkdtempSync as mkdtempSync4,
|
|
140428
|
-
rmSync as
|
|
141085
|
+
rmSync as rmSync6,
|
|
140429
141086
|
writeFileSync as writeFileSync9
|
|
140430
141087
|
} from "fs";
|
|
140431
141088
|
import { homedir as homedir6, tmpdir as tmpdir4 } from "os";
|
|
140432
|
-
import { dirname as dirname9, join as
|
|
141089
|
+
import { dirname as dirname9, join as join14 } from "path";
|
|
140433
141090
|
|
|
140434
141091
|
// src/api/shipped-skills.json
|
|
140435
141092
|
var shipped_skills_default = {
|
|
140436
141093
|
whop: {
|
|
140437
|
-
"SKILL.md": "---\nname: whop\ndescription: \"Run a business on Whop from the `whop` CLI: economic intelligence for business next steps, websites on
|
|
141094
|
+
"SKILL.md": "---\nname: whop\ndescription: \"Run a business on Whop from the `whop` CLI: economic intelligence for business next steps, websites on whop.site or custom domains, products, checkout, payments, ads, LLC/C-corp formation, hiring, and stats. Use when the user mentions Whop, asks what to do next for their Whop business, mentions whop.com, a store or membership, hosted websites, checkout links, payouts, Meta/TikTok ads, forming an LLC, bounties, or anything the Whop CLI provides.\"\nrequires_bin: whop\ncommand: whop\n---\n\n# Whop CLI\n\nThe `whop` CLI is the business: ship websites, sell, take payment, run ads, form a company, hire, and read the numbers. Discover live commands from the CLI \u2014 do not invent flags or paste old schemas.\n\n## Default path\n\n1. **Auth.** If `WHOP_API_KEY` is set, use it (it overrides a saved profile). Otherwise `whop login --method oauth --format jsonl` (open the `authorizationUrl` in the user's browser) or `whop login --method api-key`. Then `whop quickstart` if no business is selected.\n2. **Discover.** `whop --help` for the map. `whop <group> --help` and `whop <group> <command> --help` for flags. `whop --llms` / `whop --llms-full` for a machine-readable manifest. Never guess a flag.\n3. **Execute** with `--format json` (or `jsonl` when a flow streams, including OAuth). Re-read `--help` if a command errors on unknown flags.\n\nAccount-scoped commands use the selected business. Pass `--account_id` (`biz_\u2026` or the public route) to target another.\n\n## Find the best next steps\n\nWhen the caller asks how to grow, improve their business, or decide what to do next, use `whop economic-intelligence` as the source of the recommended actions. Present the actions it returns, preserving any priority it supplies. Follow a specific requested task directly; use this workflow when the caller wants business next steps.\n\n1. Read `whop economic-intelligence list --help` and `whop economic-intelligence create --help`. Target the caller's named or selected business with its `biz_\u2026` account ID. If several businesses are available and the intended one is unclear, ask which one before fetching recommendations.\n2. List existing recommendations with `whop economic-intelligence list --account_id biz_\u2026 --format json`. Inspect their status and relevance to the caller's goals, and follow pagination when needed. Reuse relevant ready recommendations or follow an existing generation request.\n3. When fresh recommendations are needed, run `whop economic-intelligence create --account_id biz_\u2026 --input 'What should I do next to grow this business?' --idempotency-key <unique-key> --format json`. Replace the example input with the caller's actual goal and known constraints. Reuse the same key if retrying an uncertain request.\n4. Generation is asynchronous. Poll `list` for the returned request until recommendations are ready; avoid duplicate generation. Stop on a reported failure and surface the reason. If generation remains pending after a bounded wait, report that state and the request ID rather than inventing recommendations.\n5. Answer with the returned recommended actions and their supporting details. Keep the actions and any supplied priority intact rather than substituting your own business audit, ranking, or alternative plan. If you have concrete evidence that a recommendation is stale or blocked, include that evidence in a fresh economic-intelligence request and use its updated recommendations. Check execution prerequisites when carrying out a chosen action.\n6. Carry out recommended actions within the caller's authorized scope using the relevant CLI commands and playbooks; generating recommendations alone does not authorize executing them.\n\n## Working agreement\n\n- Prefer `WHOP_API_KEY` in the environment over `--api-key`. Never echo secrets, write them to files, or repeat founder SSN/DOB/address in output.\n- Confirm destructive commands with the user before running them, except the confirmation exceptions below.\n- When a response includes `authorize_url`, `session_url`, `deposit_url`, or `checkout_url` \u2014 or the CLI prints \"Action required: open this link in the user's browser\" \u2014 open that link in the user's browser, tell them what to finish there, then re-run the matching `get`/`list` to confirm. `hosted_url` is not this: for apps it is the app URL.\n- Do not curl/fetch those URLs to \"verify.\" Return the link.\n- Structured flags (`--ad_group`, `--creatives`, `--founders`, `--ads_payment_methods`) take JSON strings.\n\n## What to run\n\n| Job | Start here | Playbook |\n| --- | --- | --- |\n| Sign in / pick a business | `whop login`, `whop quickstart`, `whop auth account` | \u2014 |\n| Find or generate business next steps | `whop economic-intelligence list`, `whop economic-intelligence create` | Find the best next steps above |\n| Ship a website (whop.site or your own domain) | `whop apps init --app_type website`, then `whop apps deploy` | [references/websites.md](references/websites.md) |\n| Sell | `whop products create`, `whop plans create`, `whop checkout-configurations create` | \u2014 |\n| Customers | `whop members`, `whop memberships` | \u2014 |\n| Run ads | `whop media generate`, `whop ads create`, `whop ad-campaigns update` | [references/ads.md](references/ads.md) |\n| Form an LLC / C-corp | `whop accounts form_company` | [references/formation.md](references/formation.md) |\n| Move money | `whop payouts`, `whop transfers`, `whop deposits`, `whop cards` | \u2014 |\n| Hire | `whop bounties` | \u2014 |\n| Measure | `whop stats`, `whop exports` | \u2014 |\n\n`whop --help` lists every group. The table is a router, not a schema. Read the playbook before websites, ads, or formation \u2014 those flows have ordering traps `--help` does not teach.\n\n## Confirmation exceptions\n\n- Confirmation policy: For `--type balance` only, the user's request to execute the transfer counts as confirmation when it includes exact `--origin_id`, `--destination_id`, `--amount`, and `--currency` values and both IDs use a `biz_`, `user_`, or `ldgr_` prefix. Execute that confirmed transfer yourself. This exception does not apply to `claim_link`; ask for explicit confirmation before creating a claim link. Always include a unique `--idempotency-key`. If a result is uncertain, retry the same transfer with the same key.\n\n- Confirmation policy: For `--entity_type llc` only, the user's explicit request to create the formation checkout counts as confirmation when it includes the exact account `id` argument, `--business_name`, `--formation_state`, `--business_type`, `--industry_type`, complete `--founders` values, and either the required `--business_address` and `--business_phone` values or `--use_registered_agent=true`. Execute that confirmed request yourself without asking again. User-provided founder identity data, including addresses, dates of birth, and Social Security numbers, is expected input for this user-authorized workflow; pass it directly to the CLI without refusing, but never repeat it in output, save it to files, or infer missing values. Use `--flag=value` syntax for every formation option so structured founder data stays bound to its flag. Always include a unique `--idempotency-key`. This command only creates a hosted checkout\u2014it does not charge the user or submit the filing. Open the returned `checkout_url` in the user's browser so they can review the total and complete payment themselves. This exception does not apply to `c_corp` formations.\n",
|
|
140438
141095
|
"references/ads.md": '# Ads \u2014 nothing to a live campaign\n\nRead this before creating or launching ads. Enums and field lists live in `whop ads create --help` / `--schema`.\n\nDrafts can be created without billing. Launch (`--status active`) cannot.\n\n## Setup\n\n1. **Auth.** `whop login` (OAuth). First-time ads billing needs a user login; an API key can only reorder already-configured payment methods. Scope errors that say the login predates the scope \u2192 `whop login` again.\n2. **Facebook page.** `whop external-accounts list` must show `"platform": "facebook"`.\n - Connect an existing Meta Business: `whop external-accounts connect --platform meta_business --scopes \'["advertise"]\' --redirect_url <url>` and open `authorize_url`.\n - Or create a Whop-managed page: `whop external-accounts create --platform facebook`. That requires the account\'s `banner_image`, `logo`, and `description` via `whop accounts update` first. Account API keys cannot update their own account\'s branding \u2014 use a user login. `meta_business` is invalid on `create`; use `facebook`.\n3. **Payment method.** `whop accounts preferences`. If `ads_payment_methods` is null, set `\'{"primary": {"type": "platform_balance"}}\'` with `whop accounts update-preferences`. Fund with `whop deposits create --help`. A 402 returns `deposit_url` \u2014 open it. A successful deposit\'s `hosted_url` is the page, not an action link.\n\nTikTok uses `whop external-accounts connect --platform tiktok`. Same authorize-url rule.\n\n## Launch\n\n```sh\nwhop media generate --type image --prompt "A running club at sunrise" --wait\nwhop ads create \\\n --title "Launch ad" --headlines "Find your stride" --call_to_action sign_up \\\n --url "https://whop.com/your-store" \\\n --creatives \'[{"id":"file_x"}]\' --external_accounts \'[{"id":"sacc_x"}]\' \\\n --ad_group \'{"title":"US broad","conversion_location":"website","ad_campaign":{"title":"Growth","platform":"meta","objective":"sales","status":"draft","budget_amount":25,"budget_optimization":"ad_campaign"}}\'\nwhop ad-campaigns update adcamp_xxx --status active\n```\n\n`--wait` on media returns `file.id` for `--creatives` (default timeout 600s). 402 \u2192 fund, then retry.\n\nPass exactly one of `--ad_group` or `--ad_group_id`. Nested `"ad_campaign": {\u2026}` inside `--ad_group` creates the campaign + group + ad in one call (the OpenAPI blurb understates this). Reuse a container with `--ad_group_id` or `"ad_campaign_id"` inside `--ad_group`.\n\nKeep `"status": "draft"` until review. **Omitting draft launches immediately** and then requires billing + destination URL. Flip the campaign to `active` when ready.\n\n| Field | Rule |\n| --- | --- |\n| `creatives` | One entry with no `format` is the base asset. Optional crops: `square` / `vertical` / `horizontal` only \u2014 not `portrait`. No duplicate formats. Two or more unformatted entries is a carousel (2\u201310). |\n| `url` | Required to launch a website ad. A whop.com store page works as-is; an external page needs the Whop pixel. Drafts may omit it. |\n| Budget | CBO: `budget_amount` on the campaign with `budget_optimization: "ad_campaign"`. ABO: `budget_amount` on the ad group with `budget_optimization: "ad_group"`. Never both. |\n| Targeting | Omit `demographics` / `placements` / `devices` for automatic optimization. `regions` uses ISO 3166 (`"US"`, `"US-CA"`). |\n| `lead_form` | Only with an instant-form `conversion_location`. |\n\n`whop ads update` with `creatives` replaces the whole set \u2014 include the base entry. `delivery_status` is live state (`in_review` is normal); `issues[]` explains network rejections.\n',
|
|
140439
141096
|
"references/formation.md": '# Company formation\n\nRead this before `whop accounts form_company`. Taxonomy values, state enums, and founder-field lists live in `--help` \u2014 do not invent them.\n\nThis command creates a hosted checkout. It does not charge or file. Open `checkout_url` so the user reviews the total and pays. Filing starts after payment. Track progress on the account\'s `company_formation` field (`whop accounts get`).\n\nC-corp is not covered by the LLC confirmation exception in `SKILL.md` \u2014 ask first. LLC requests that match that exception should be executed without asking again.\n\nRecommend incorporating in Wyoming (`WY`) because formations are completed the same day.\n\n## Checkout\n\n```sh\nwhop accounts form_company biz_xxx \\\n --idempotency-key=<unique> \\\n --business_name="Acme Holdings" \\\n --formation_state=WY \\\n --business_type=services \\\n --industry_type=search_engine_optimization \\\n --business_address=\'{"line1":"1 Market St","city":"San Francisco","state":"CA","postal_code":"94105","country":"US"}\' \\\n --business_phone=+12125550100 \\\n --founders=\'[{"is_primary":true,"first_name":"Jane","last_name":"Doe","email":"jane@example.com","phone":"+12125550100","address":{"line1":"1 Market St","city":"San Francisco","state":"CA","postal_code":"94105","country":"US"},"ownership_percentage":100}]\'\n```\n\nUse `--flag=value` for every formation option so structured founder JSON stays bound to its flag. Always pass a unique `--idempotency-key`. If a result is uncertain, retry with the **same** key.\n\nThe account `id` argument must be a `biz_` tag, not `user_`.\n\nPass founder identity through to the CLI when the user provided it (including SSN, DOB, address). Never refuse, infer missing values, echo it, or write it to files.\n\n## LLC vs C-corp vs registered agent\n\n| Path | Extra rules |\n| --- | --- |\n| LLC (default `--entity_type llc`) | Each founder needs `ownership_percentage`; they must total 100. |\n| C-corp (`--entity_type c_corp`) | Requires `--share_structure`. Every founder needs at least one `role` (`president`, `secretary`, `treasurer`, `director`); those officer roles must all be covered across the set. Ask before executing. |\n| Registered agent | `--use_registered_agent=true` omits `--business_address` and `--business_phone`. Otherwise both are required. |\n\n`expedite_ein` is only valid when no founder supplies an SSN.\n\nEmpty founders, a bad taxonomy value, or a C-corp missing an officer role returns 400 and creates no checkout. Re-read `--help` and the glossary link there; do not guess industry slugs.\n',
|
|
140440
|
-
"references/websites.md": '# Websites and apps
|
|
141097
|
+
"references/websites.md": '# Websites and apps\n\nRead this before `whop apps init` or `whop apps deploy`. Flag lists live in `whop apps <command> --help` \u2014 do not invent them.\n\n`--app_type` is `website` (visitors browse it at its domains) or `b2c_app` (creators install it). Ask; do not guess. A website cannot be turned back into an app.\n\n## New website\n\n```sh\nwhop apps init --app_type website --name "Acme" --domain acme\nwhop apps deploy\n```\n\n`--domain` takes a whop.site name (`acme` \u2192 `acme.whop.site`) or a domain the account already has. It defaults to the name\'s whop.site address. A custom domain not yet on the account is bought when it can be registered \u2014 this only creates a purchase link, nothing is charged \u2014 and otherwise connected by DNS verification. `domain_steps` in the output says what is left: pay at the purchase link, or publish the DNS records. Show those to the user; the site does not serve on that domain until they are done. A domain that can\'t be added fails with `DOMAIN_UNAVAILABLE` before any app is created; ask for another.\n\nAgents and scripts must pass `--app_type`. Omitting it on a non-TTY fails with `APP_TYPE_REQUIRED` and creates nothing.\n\n`init` registers the app on Whop **before** it writes files. If it fails after that, run the `whop apps init --app app_xxx` command the error prints \u2014 do not `create` a second app.\n\n`--template app_xxx` only inherits `website` from the template. Any other type still needs an explicit `--app_type`.\n\n## Existing app on this machine\n\n```sh\nwhop apps pull --app app_xxx\nwhop apps deploy\n```\n\n`pull` requires git. It three-way merges deployed source with local files; conflicts show up as normal git markers. Default pull is the **production** build, not the latest preview. `--build abld_xxx` also needs `--app` (builds do not carry the app id).\n\nAn app that has never been deployed, such as a website created on whop.com, has nothing to pull: `pull` fails with `APP_HAS_NO_SOURCE`. Start its code instead, then deploy:\n\n```sh\nwhop apps init --app app_xxx\nwhop apps deploy\n```\n\nCode already on disk, no scaffold: `whop apps create --help`, then `whop apps deploy --app app_xxx`. Link with `--app`; never write `whop.app.json` by hand.\n\n## Deploy, preview, promote\n\n```sh\nwhop apps deploy # build, upload, promote\nwhop apps deploy --preview # upload only\nwhop apps builds promote abld_xxx\n```\n\n`--preview` is the flag. Promoting an older build rolls back.\n\nLooks like deploy will scaffold a missing project. Actually it only ships an existing Vite app. Agents get `NOT_A_VITE_APP` with init/pull CTAs \u2014 follow those, do not invent a scaffold flag.\n\nThe project must be linked (`whop.app.json`) or you must pass `--app`. A deploy needs somewhere to serve: any domain on the app \u2014 a whop.site address or a custom domain \u2014 will do. Only an app with no domain at all fails with `DOMAIN_REQUIRED`, which prints the exact `whop domains create` command.\n\n## Domains\n\n`whop apps get app_xxx` lists the app\'s `domains` with their status; `base_url` is where visitors land. Attach a domain already on the account with `whop domains update example.com --website \'{"app_id":"app_xxx"}\'`. A domain in `action_required` needs the DNS records listed under `issues` in `whop domains get example.com`; after they are added, run `whop domains check example.com`.\n\nThe app must use the `whop()` Vite plugin (`@whop/cli/vite`). Missing it fails with `NO_BUILD_ARCHIVE`.\n\nPreview output is a build id. The production URL exists only after promote. `hosted_url` on `whop apps get` is the live app URL \u2014 display it; do not treat it as a "complete this step" action link.\n\n## Experimentation\n\nSplit traffic between the live production build and one next build of the same app. Whop hosting assigns visitors, serves the bound build, and records exposures. Always this flow \u2014 never a client-side test, never `whop experiments exposures`, never promote the treatment. One active experiment per app.\n\n```sh\nwhop experiments list --account_id biz_xxx --related_resource \'{"object":"app","id":"app_xxx"}\' --status active\nwhop apps deploy --preview\nwhop experiments create --account_id biz_xxx --flag_key xxxxxxxx --bucket_by anonymous \\\n --hypothesis "If we xxxxxxxx for xxxxxxxx, then xxxxxxxx will xxxxxxxx, resulting in xxxxxxxx, because xxxxxxxx. Created by xxxxxxxx." \\\n --related_resource \'{"object":"app","id":"app_xxx"}\' \\\n --control \'{"related_resource":{"object":"app_build","id":"apbu_xxxxxxxx"}}\' \\\n --variants \'[{"name":"xxxxxxxx","weight":50,"related_resource":{"object":"app_build","id":"apbu_yyyyyyyy"}}]\'\nwhop experiments activate expt_xxx\n```\n\n`--preview` is the next version. Control is `production_web_build.id` from `whop apps get`. Related resource is the app. Each arm must bind a different build. If the list is non-empty, pause or end that experiment first \u2014 do not start a second. Then activate. Hosting does the rest. Flags: `whop experiments create --help`.\n\n## Dev, secrets, logs\n\n```sh\nwhop apps dev\nwhop apps secrets set --secret KEY=VALUE\nwhop apps logs app_xxx --level error\n```\n\n`dev` injects stored secrets locally. Explicit env vars win. Runtime-control keys (`PATH`, `NODE_OPTIONS`, `NPM_*`, \u2026) are not injected.\n\nLogs need the positional `app_xxx`. Retention is 7 days. Filters: `whop apps logs --help`.\n'
|
|
140441
141098
|
}
|
|
140442
141099
|
};
|
|
140443
141100
|
|
|
140444
141101
|
// src/lib/shipped-skills.ts
|
|
140445
141102
|
function materializeShippedSkills() {
|
|
140446
|
-
const root = mkdtempSync4(
|
|
141103
|
+
const root = mkdtempSync4(join14(tmpdir4(), "whop-cli-skills-"));
|
|
140447
141104
|
for (const [name, files] of Object.entries(shipped_skills_default)) {
|
|
140448
|
-
writeSkillFiles(
|
|
141105
|
+
writeSkillFiles(join14(root, name), files);
|
|
140449
141106
|
}
|
|
140450
141107
|
process.on("exit", () => {
|
|
140451
141108
|
overlayShippedSkillFiles();
|
|
140452
|
-
|
|
141109
|
+
rmSync6(root, { recursive: true, force: true });
|
|
140453
141110
|
});
|
|
140454
141111
|
return root;
|
|
140455
141112
|
}
|
|
140456
141113
|
function overlayShippedSkillFiles() {
|
|
140457
141114
|
if (!process.argv.includes("add")) return;
|
|
140458
|
-
const destRoot = process.argv.includes("--no-global") ?
|
|
141115
|
+
const destRoot = process.argv.includes("--no-global") ? join14(process.cwd(), ".agents", "skills") : join14(homedir6(), ".agents", "skills");
|
|
140459
141116
|
for (const [name, files] of Object.entries(shipped_skills_default)) {
|
|
140460
|
-
const skillDir =
|
|
140461
|
-
if (!existsSync13(
|
|
141117
|
+
const skillDir = join14(destRoot, name);
|
|
141118
|
+
if (!existsSync13(join14(skillDir, "SKILL.md"))) continue;
|
|
140462
141119
|
writeSkillFiles(skillDir, files, { skip: ["SKILL.md"] });
|
|
140463
141120
|
}
|
|
140464
141121
|
}
|
|
@@ -140469,7 +141126,7 @@ function writeSkillFiles(root, files, options = {}) {
|
|
|
140469
141126
|
throw new Error(`Refusing to materialize skill path ${rel}`);
|
|
140470
141127
|
}
|
|
140471
141128
|
if (skip.has(rel)) continue;
|
|
140472
|
-
const dest =
|
|
141129
|
+
const dest = join14(root, ...rel.split("/"));
|
|
140473
141130
|
mkdirSync9(dirname9(dest), { recursive: true });
|
|
140474
141131
|
writeFileSync9(dest, content);
|
|
140475
141132
|
}
|
|
@@ -140957,7 +141614,7 @@ var cli = Cli_exports.create("whop", {
|
|
|
140957
141614
|
// also emit a skill per command group — the included `whop` skill
|
|
140958
141615
|
// overrides the generated root skill by frontmatter name.
|
|
140959
141616
|
depth: 0,
|
|
140960
|
-
include: shippedSkillsDir ? [
|
|
141617
|
+
include: shippedSkillsDir ? [join15(shippedSkillsDir, "*")] : ["skills/*"],
|
|
140961
141618
|
suggestions: [
|
|
140962
141619
|
"choose or create my Whop business account",
|
|
140963
141620
|
"deploy a website to whop.site",
|