@feastalytics/cli 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -8983,7 +8983,7 @@ var CLI_MANIFEST = {
8983
8983
  {
8984
8984
  "id": "applyFunnelTemplate",
8985
8985
  "domain": "campaigns",
8986
- "description": "Applies a funnel template to an existing campaign that has no funnel set up yet (override.initialScreenId is null). Uses the campaign's existing promotion/imageUrl when the funnel template needs them. For reservation-prepay funnels pass funnelType: 'prepay' AND isReservationFunnel: true \u2014 it is not inferred from funnelType. skipSignUp: true builds the funnel without the sign-up screen.",
8986
+ "description": "Applies a funnel template to an existing campaign that has no funnel set up yet (override.initialScreenId is null). Pass a templateId from listFunnelTemplates: offer-basic (Sign Up routes straight to the offer wallet \u2014 no payment step; use this for offers redeemed in person), offer-prepay / offer-direct-prepay (Sign Up / landing routes to a Stripe payment screen), reservation-offer-basic (Sign Up routes to reservation-or-wallet), reservation-offer-prepay / reservation-offer-direct-prepay (payment then reservation), reservation-only. The promotion's canPrePay flag does NOT change what gets built \u2014 prepay templates always insert the payment screen, and are rejected unless the promotion has canPrePay: true and a price. The legacy funnelType/skipSignUp/isReservationFunnel input is deprecated but still accepted.",
8987
8987
  "type": "mutation",
8988
8988
  "path": [
8989
8989
  "api",
@@ -8992,31 +8992,60 @@ var CLI_MANIFEST = {
8992
8992
  "chooseFunnelTemplate"
8993
8993
  ],
8994
8994
  "inputJsonSchema": {
8995
- "type": "object",
8996
- "properties": {
8997
- "campaignId": {
8998
- "type": "string"
8999
- },
9000
- "funnelType": {
9001
- "type": "string",
9002
- "enum": [
9003
- "reservation",
9004
- "prepay",
9005
- "simpleRewards"
9006
- ]
9007
- },
9008
- "skipSignUp": {
9009
- "type": "boolean"
8995
+ "anyOf": [
8996
+ {
8997
+ "type": "object",
8998
+ "properties": {
8999
+ "campaignId": {
9000
+ "type": "string"
9001
+ },
9002
+ "templateId": {
9003
+ "type": "string",
9004
+ "enum": [
9005
+ "offer-basic",
9006
+ "offer-prepay",
9007
+ "offer-direct-prepay",
9008
+ "reservation-offer-basic",
9009
+ "reservation-offer-prepay",
9010
+ "reservation-offer-direct-prepay",
9011
+ "reservation-only"
9012
+ ]
9013
+ }
9014
+ },
9015
+ "required": [
9016
+ "campaignId",
9017
+ "templateId"
9018
+ ],
9019
+ "additionalProperties": false
9010
9020
  },
9011
- "isReservationFunnel": {
9012
- "type": "boolean"
9021
+ {
9022
+ "type": "object",
9023
+ "properties": {
9024
+ "campaignId": {
9025
+ "type": "string"
9026
+ },
9027
+ "funnelType": {
9028
+ "type": "string",
9029
+ "enum": [
9030
+ "reservation",
9031
+ "prepay",
9032
+ "simpleRewards"
9033
+ ]
9034
+ },
9035
+ "skipSignUp": {
9036
+ "type": "boolean"
9037
+ },
9038
+ "isReservationFunnel": {
9039
+ "type": "boolean"
9040
+ }
9041
+ },
9042
+ "required": [
9043
+ "campaignId",
9044
+ "funnelType"
9045
+ ],
9046
+ "additionalProperties": false
9013
9047
  }
9014
- },
9015
- "required": [
9016
- "campaignId",
9017
- "funnelType"
9018
9048
  ],
9019
- "additionalProperties": false,
9020
9049
  "$schema": "http://json-schema.org/draft-07/schema#"
9021
9050
  }
9022
9051
  },
@@ -10522,6 +10551,119 @@ var CLI_MANIFEST = {
10522
10551
  "resetProgress"
10523
10552
  ],
10524
10553
  "additionalProperties": false
10554
+ },
10555
+ {
10556
+ "type": "object",
10557
+ "properties": {
10558
+ "type": {
10559
+ "type": "string",
10560
+ "const": "setCustomProperty"
10561
+ },
10562
+ "setCustomProperty": {
10563
+ "type": "object",
10564
+ "properties": {
10565
+ "propertyId": {
10566
+ "type": "string"
10567
+ },
10568
+ "operation": {
10569
+ "anyOf": [
10570
+ {
10571
+ "type": "object",
10572
+ "properties": {
10573
+ "type": {
10574
+ "type": "string",
10575
+ "const": "set"
10576
+ },
10577
+ "set": {
10578
+ "type": "object",
10579
+ "properties": {
10580
+ "booleanValue": {
10581
+ "type": [
10582
+ "boolean",
10583
+ "null"
10584
+ ]
10585
+ },
10586
+ "isDateValue": {
10587
+ "anyOf": [
10588
+ {
10589
+ "type": "string",
10590
+ "format": "date-time"
10591
+ },
10592
+ {
10593
+ "type": "null"
10594
+ }
10595
+ ]
10596
+ },
10597
+ "localDayOfYear": {
10598
+ "type": [
10599
+ "string",
10600
+ "null"
10601
+ ]
10602
+ },
10603
+ "numberValue": {
10604
+ "type": [
10605
+ "number",
10606
+ "null"
10607
+ ]
10608
+ },
10609
+ "stringValue": {
10610
+ "type": [
10611
+ "string",
10612
+ "null"
10613
+ ]
10614
+ }
10615
+ },
10616
+ "additionalProperties": false
10617
+ }
10618
+ },
10619
+ "required": [
10620
+ "type",
10621
+ "set"
10622
+ ],
10623
+ "additionalProperties": false
10624
+ },
10625
+ {
10626
+ "type": "object",
10627
+ "properties": {
10628
+ "type": {
10629
+ "type": "string",
10630
+ "const": "increment"
10631
+ },
10632
+ "increment": {
10633
+ "type": "object",
10634
+ "properties": {
10635
+ "amount": {
10636
+ "type": "number"
10637
+ }
10638
+ },
10639
+ "required": [
10640
+ "amount"
10641
+ ],
10642
+ "additionalProperties": false,
10643
+ "description": "Number properties only. Added to the current value, or to 0."
10644
+ }
10645
+ },
10646
+ "required": [
10647
+ "type",
10648
+ "increment"
10649
+ ],
10650
+ "additionalProperties": false
10651
+ }
10652
+ ]
10653
+ }
10654
+ },
10655
+ "required": [
10656
+ "propertyId",
10657
+ "operation"
10658
+ ],
10659
+ "additionalProperties": false
10660
+ }
10661
+ },
10662
+ "required": [
10663
+ "type",
10664
+ "setCustomProperty"
10665
+ ],
10666
+ "additionalProperties": false
10525
10667
  }
10526
10668
  ]
10527
10669
  }
@@ -12301,6 +12443,119 @@ var CLI_MANIFEST = {
12301
12443
  "resetProgress"
12302
12444
  ],
12303
12445
  "additionalProperties": false
12446
+ },
12447
+ {
12448
+ "type": "object",
12449
+ "properties": {
12450
+ "type": {
12451
+ "type": "string",
12452
+ "const": "setCustomProperty"
12453
+ },
12454
+ "setCustomProperty": {
12455
+ "type": "object",
12456
+ "properties": {
12457
+ "propertyId": {
12458
+ "type": "string"
12459
+ },
12460
+ "operation": {
12461
+ "anyOf": [
12462
+ {
12463
+ "type": "object",
12464
+ "properties": {
12465
+ "type": {
12466
+ "type": "string",
12467
+ "const": "set"
12468
+ },
12469
+ "set": {
12470
+ "type": "object",
12471
+ "properties": {
12472
+ "booleanValue": {
12473
+ "type": [
12474
+ "boolean",
12475
+ "null"
12476
+ ]
12477
+ },
12478
+ "isDateValue": {
12479
+ "anyOf": [
12480
+ {
12481
+ "type": "string",
12482
+ "format": "date-time"
12483
+ },
12484
+ {
12485
+ "type": "null"
12486
+ }
12487
+ ]
12488
+ },
12489
+ "localDayOfYear": {
12490
+ "type": [
12491
+ "string",
12492
+ "null"
12493
+ ]
12494
+ },
12495
+ "numberValue": {
12496
+ "type": [
12497
+ "number",
12498
+ "null"
12499
+ ]
12500
+ },
12501
+ "stringValue": {
12502
+ "type": [
12503
+ "string",
12504
+ "null"
12505
+ ]
12506
+ }
12507
+ },
12508
+ "additionalProperties": false
12509
+ }
12510
+ },
12511
+ "required": [
12512
+ "type",
12513
+ "set"
12514
+ ],
12515
+ "additionalProperties": false
12516
+ },
12517
+ {
12518
+ "type": "object",
12519
+ "properties": {
12520
+ "type": {
12521
+ "type": "string",
12522
+ "const": "increment"
12523
+ },
12524
+ "increment": {
12525
+ "type": "object",
12526
+ "properties": {
12527
+ "amount": {
12528
+ "type": "number"
12529
+ }
12530
+ },
12531
+ "required": [
12532
+ "amount"
12533
+ ],
12534
+ "additionalProperties": false,
12535
+ "description": "Number properties only. Added to the current value, or to 0."
12536
+ }
12537
+ },
12538
+ "required": [
12539
+ "type",
12540
+ "increment"
12541
+ ],
12542
+ "additionalProperties": false
12543
+ }
12544
+ ]
12545
+ }
12546
+ },
12547
+ "required": [
12548
+ "propertyId",
12549
+ "operation"
12550
+ ],
12551
+ "additionalProperties": false
12552
+ }
12553
+ },
12554
+ "required": [
12555
+ "type",
12556
+ "setCustomProperty"
12557
+ ],
12558
+ "additionalProperties": false
12304
12559
  }
12305
12560
  ]
12306
12561
  }
@@ -13606,7 +13861,7 @@ var CLI_MANIFEST = {
13606
13861
  {
13607
13862
  "id": "getCreatorConversation",
13608
13863
  "domain": "creators",
13609
- "description": "One creator's full SMS thread, newest first \u2014 what the dashboard's creator chat view renders. userId comes from listCreatorConversations, which is the queue; this is the read you make before summarizing an exchange or drafting a reply for the human to send, because the queue only carries the last message. Each row has the body, direction (from/to the creator's number), and timestamps. Returns empty when the creator has no phone number on file. Read-only: sending the reply and marking the thread read stay in the dashboard.",
13864
+ "description": "One creator's full SMS thread, newest first \u2014 what the dashboard's creator chat view renders. userId comes from listCreatorConversations, which is the queue; this is the read you make before summarizing an exchange or drafting a reply for the human to send, because the queue only carries the last message. Each row has the body, direction (from/to the creator's number), and timestamps. Returns empty when the creator has no phone number on file. Read-only: send the reply with sendText and {type:'creator', userId}; marking the thread read stays in the dashboard.",
13610
13865
  "type": "query",
13611
13866
  "path": [
13612
13867
  "api",
@@ -13750,7 +14005,7 @@ var CLI_MANIFEST = {
13750
14005
  {
13751
14006
  "id": "getMemberConversation",
13752
14007
  "domain": "membersProgram",
13753
- "description": "One member's SMS thread and activity, newest first \u2014 what the dashboard's chat page renders, and the pair to searchUsers the way getCreatorConversation pairs with listCreatorConversations. serialNumber comes from searchUsers. eventTypes: ['sentText','receivedText'] is the conversation; adding scan, order, checkout, rewardAwarded or rewardRedeemed interleaves what happened between the messages. Unfiltered it fans out to every event source and returns the member's whole history unpaginated, so pass eventTypes unless you really want it all. Read-only: replying to a guest stays in the dashboard.",
14008
+ "description": "One member's SMS thread and activity, newest first \u2014 what the dashboard's chat page renders, and the pair to searchUsers the way getCreatorConversation pairs with listCreatorConversations. serialNumber comes from searchUsers. eventTypes: ['sentText','receivedText'] is the conversation; adding scan, order, checkout, rewardAwarded or rewardRedeemed interleaves what happened between the messages. Unfiltered it fans out to every event source and returns the member's whole history unpaginated, so pass eventTypes unless you really want it all. Read-only: reply to the member with sendText and {type:'guest', serialNumber}.",
13754
14009
  "type": "query",
13755
14010
  "path": [
13756
14011
  "api",
@@ -14226,7 +14481,7 @@ var CLI_MANIFEST = {
14226
14481
  {
14227
14482
  "id": "listCreatorConversations",
14228
14483
  "domain": "creators",
14229
- "description": "Every creator's SMS conversation with its unread state \u2014 the 'who is waiting on a reply' queue. `hasUnread` means their last message came in after ours and nobody has marked it read; those need a human. Each row carries the last message body, time and direction, the creator's handles, and `visitStatus`, a derived stage that is more reliable than reading raw columns off creatorVisitApplication. Read the full thread behind a row with getCreatorConversation and its userId. Read-only: replying to a creator and marking a conversation read both stay in the dashboard.",
14484
+ "description": "Every creator's SMS conversation with its unread state \u2014 the 'who is waiting on a reply' queue. `hasUnread` means their last message came in after ours and nobody has marked it read; those need a human. Each row carries the last message body, time and direction, the creator's handles, and `visitStatus`, a derived stage that is more reliable than reading raw columns off creatorVisitApplication. Read the full thread behind a row with getCreatorConversation and its userId, and reply with sendText and {type:'creator', userId}. Read-only: marking a conversation read stays in the dashboard.",
14230
14485
  "type": "query",
14231
14486
  "path": [
14232
14487
  "api",
@@ -14238,7 +14493,7 @@ var CLI_MANIFEST = {
14238
14493
  {
14239
14494
  "id": "listCreatorSubmissions",
14240
14495
  "domain": "creators",
14241
- "description": "Creator content submissions, newest first. 'submitted' and 'revision_requested' together are the review queue. Each row carries the `submissionId` for decideCreatorSubmission. Submissions are outside the queryData catalog, so this is the only way to read them.",
14496
+ "description": "Creator content submissions, newest first. 'submitted' is the review queue; 'revision_requested' is waiting on the creator to resubmit. Each row carries the `submissionId` for decideCreatorSubmission. Submissions are outside the queryData catalog, so this is the only way to read them.",
14242
14497
  "type": "query",
14243
14498
  "path": [
14244
14499
  "api",
@@ -14341,6 +14596,57 @@ var CLI_MANIFEST = {
14341
14596
  "$schema": "http://json-schema.org/draft-07/schema#"
14342
14597
  }
14343
14598
  },
14599
+ {
14600
+ "id": "listFunnelTemplates",
14601
+ "domain": "campaigns",
14602
+ "description": "Lists the funnel templates that can be applied to a campaign, with per-template eligibility for this campaign and a recommended template. Each template describes the guest journey (ordered screens) and whether it collects payment. Prepay templates insert a Stripe payment screen and are only eligible when the campaign's promotion has canPrePay: true and a price; the promotion's canPrePay flag does NOT change what a template builds \u2014 pick a non-payment template (offer-basic) for offers redeemed in person. Use before applyFunnelTemplate.",
14603
+ "type": "query",
14604
+ "path": [
14605
+ "api",
14606
+ "campaigns",
14607
+ "app",
14608
+ "listFunnelTemplates"
14609
+ ],
14610
+ "inputJsonSchema": {
14611
+ "type": "object",
14612
+ "properties": {
14613
+ "campaignId": {
14614
+ "type": "string"
14615
+ }
14616
+ },
14617
+ "required": [
14618
+ "campaignId"
14619
+ ],
14620
+ "additionalProperties": false,
14621
+ "$schema": "http://json-schema.org/draft-07/schema#"
14622
+ }
14623
+ },
14624
+ {
14625
+ "id": "listIgMedia",
14626
+ "domain": "ads",
14627
+ "description": "List recent posts from the Instagram business account linked to a Facebook Page, for use as igMedia creative references in planAds templates. Returns the instagramUserId to put on the igMedia creative ref plus up to 50 recent posts with id, caption, thumbnail, mediaType, permalink and timestamp. Takes a pageId from ads_get_user_pages; a Page with no linked Instagram business account returns instagramAccount null.",
14628
+ "type": "query",
14629
+ "path": [
14630
+ "api",
14631
+ "ads",
14632
+ "facebook",
14633
+ "listIgMedia"
14634
+ ],
14635
+ "inputJsonSchema": {
14636
+ "type": "object",
14637
+ "properties": {
14638
+ "pageId": {
14639
+ "type": "string",
14640
+ "minLength": 1
14641
+ }
14642
+ },
14643
+ "required": [
14644
+ "pageId"
14645
+ ],
14646
+ "additionalProperties": false,
14647
+ "$schema": "http://json-schema.org/draft-07/schema#"
14648
+ }
14649
+ },
14344
14650
  {
14345
14651
  "id": "listMedia",
14346
14652
  "domain": "core",
@@ -14429,6 +14735,33 @@ var CLI_MANIFEST = {
14429
14735
  "$schema": "http://json-schema.org/draft-07/schema#"
14430
14736
  }
14431
14737
  },
14738
+ {
14739
+ "id": "markReimbursementPaid",
14740
+ "domain": "creators",
14741
+ "description": "Record that a creator has been paid back for a meal they bought on a reimbursing board. This moves no money \u2014 it only writes down that the client already sent it by their own means, so never call it unless the client tells you the payment has actually gone out. The submission must be approved and its reimbursement still pending; a submission with no receipt was never on a reimbursing board and is rejected. Read the receipt total off creators.creatorContentSubmission before recording anything.",
14742
+ "type": "mutation",
14743
+ "path": [
14744
+ "api",
14745
+ "dfy",
14746
+ "markReimbursementPaid"
14747
+ ],
14748
+ "inputJsonSchema": {
14749
+ "type": "object",
14750
+ "properties": {
14751
+ "submissionId": {
14752
+ "type": "string"
14753
+ },
14754
+ "reimbursementPaidNote": {
14755
+ "type": "string"
14756
+ }
14757
+ },
14758
+ "required": [
14759
+ "submissionId"
14760
+ ],
14761
+ "additionalProperties": false,
14762
+ "$schema": "http://json-schema.org/draft-07/schema#"
14763
+ }
14764
+ },
14432
14765
  {
14433
14766
  "id": "planAds",
14434
14767
  "domain": "ads",
@@ -14568,7 +14901,7 @@ var CLI_MANIFEST = {
14568
14901
  {
14569
14902
  "id": "publishAds",
14570
14903
  "domain": "ads",
14571
- "description": "Publish a plan produced by planAds. Declare what should be recorded once the ads exist through effects, and the worker runs them as part of the job \u2014 a recruitment publish must pass linkRecruitmentOffer with its offerId and creativeIds, which stamps the creatives, stamps the offer that the monthly sourcing cap and the dashboard's spend both read, and texts the program's approver that sourcing is live; omitting it is refused rather than silently skipped. Doing it afterwards through a separate call is a step that can be missed, and missing it is silent. Pass back the variables, overrides and planHash that planAds returned, unchanged. The server re-derives the tree and refuses to publish if it no longer matches the hash, so re-plan and show the human the difference if that happens. This returns as soon as the work is queued \u2014 poll getJob with the returned jobId and jobType to follow it, and read the job's effect outcomes rather than assuming they ran. Everything is created paused; use setAdCampaignStatus to start it. Requires an explicit confirm.",
14904
+ "description": "Publish a plan produced by planAds. Declare what should be recorded once the ads exist through effects, and the worker runs them as part of the job \u2014 a recruitment publish must pass linkRecruitmentOffer with its offerId and creativeIds, which stamps the creatives, stamps the offer that the monthly sourcing cap and the dashboard's spend both read, and texts the program's approver that sourcing is live, and a directOffer publish must pass linkFeastCampaign with the campaignId it runs for, which is what puts its spend on the campaign's ads panel and KPIs; omitting either is refused rather than silently skipped. Doing it afterwards through a separate call is a step that can be missed, and missing it is silent. Pass back the variables, overrides and planHash that planAds returned, unchanged. The server re-derives the tree and refuses to publish if it no longer matches the hash, so re-plan and show the human the difference if that happens. This returns as soon as the work is queued \u2014 poll getJob with the returned jobId and jobType to follow it, and read the job's effect outcomes rather than assuming they ran. Everything is created paused; use setAdCampaignStatus to start it. Requires an explicit confirm.",
14572
14905
  "type": "mutation",
14573
14906
  "path": [
14574
14907
  "api",
@@ -15109,7 +15442,99 @@ Example - opted-in members with more than 5 visits, newest first:
15109
15442
  }
15110
15443
  },
15111
15444
  {
15112
- "id": "setAdCampaignStatus",
15445
+ "id": "sendText",
15446
+ "domain": "messaging",
15447
+ "description": "Send one SMS to one person from the organization's texting number \u2014 the reply you would otherwise type into the dashboard chat. `to` names who by id, never by phone number: {type:'creator', userId} for a creator, whose userId comes from listCreatorConversations or getCreatorConversation, or {type:'guest', serialNumber} for a loyalty member, whose serialNumber comes from searchUsers or getMemberConversation. The type is not cosmetic \u2014 the two are different people in different tables, and a creator who also holds a pass exists in both, so pass the type that matches the thread you are replying to. The third form, {type:'unknownSender', phoneNumber}, answers someone who texted in without being either \u2014 it is the only form that names a raw number, and it is refused unless that number has an inbound message to this organization on file. A creator must have a visit with this organization and a guest must belong to it, or the call is a 404 rather than a text to a stranger. Guest messages support the {{firstName}}-style handlebars text automations use and are rendered before sending; creator messages are sent verbatim. Sending as a creator's human handler also parks that creator's AI agent for five minutes so it does not talk over you. High priority, sent immediately \u2014 there is no scheduling, no undo, and no bulk form: call it once per recipient.",
15448
+ "type": "mutation",
15449
+ "path": [
15450
+ "api",
15451
+ "text",
15452
+ "sendMessage"
15453
+ ],
15454
+ "inputJsonSchema": {
15455
+ "type": "object",
15456
+ "properties": {
15457
+ "to": {
15458
+ "anyOf": [
15459
+ {
15460
+ "type": "object",
15461
+ "properties": {
15462
+ "type": {
15463
+ "type": "string",
15464
+ "const": "creator"
15465
+ },
15466
+ "userId": {
15467
+ "type": "string",
15468
+ "minLength": 1
15469
+ }
15470
+ },
15471
+ "required": [
15472
+ "type",
15473
+ "userId"
15474
+ ],
15475
+ "additionalProperties": false
15476
+ },
15477
+ {
15478
+ "type": "object",
15479
+ "properties": {
15480
+ "type": {
15481
+ "type": "string",
15482
+ "const": "guest"
15483
+ },
15484
+ "serialNumber": {
15485
+ "type": "string",
15486
+ "minLength": 1
15487
+ }
15488
+ },
15489
+ "required": [
15490
+ "type",
15491
+ "serialNumber"
15492
+ ],
15493
+ "additionalProperties": false
15494
+ },
15495
+ {
15496
+ "type": "object",
15497
+ "properties": {
15498
+ "type": {
15499
+ "type": "string",
15500
+ "const": "unknownSender"
15501
+ },
15502
+ "phoneNumber": {
15503
+ "type": "string",
15504
+ "minLength": 1
15505
+ }
15506
+ },
15507
+ "required": [
15508
+ "type",
15509
+ "phoneNumber"
15510
+ ],
15511
+ "additionalProperties": false
15512
+ }
15513
+ ]
15514
+ },
15515
+ "message": {
15516
+ "type": "string",
15517
+ "minLength": 1,
15518
+ "maxLength": 1600
15519
+ },
15520
+ "mediaUrls": {
15521
+ "type": "array",
15522
+ "items": {
15523
+ "type": "string"
15524
+ },
15525
+ "maxItems": 10
15526
+ }
15527
+ },
15528
+ "required": [
15529
+ "to",
15530
+ "message"
15531
+ ],
15532
+ "additionalProperties": false,
15533
+ "$schema": "http://json-schema.org/draft-07/schema#"
15534
+ }
15535
+ },
15536
+ {
15537
+ "id": "setAdCampaignStatus",
15113
15538
  "domain": "ads",
15114
15539
  "description": "Start or pause a Meta campaign that was published from Feastalytics. ACTIVE cascades to every ad set and ad, because campaigns are published paused at all three levels and a campaign-only activate would spend nothing. Activating spends real money \u2014 confirm with the human first, and check the preflight counts in the response.",
15115
15540
  "type": "mutation",
@@ -15145,7 +15570,7 @@ Example - opted-in members with more than 5 visits, newest first:
15145
15570
  {
15146
15571
  "id": "simulateAutomations",
15147
15572
  "domain": "automations",
15148
- "description": "Dry-run automations against a synthetic event timeline and see what would fire \u2014 no real sends or side effects. First call: omit `events` and pass `flowId`, and the server auto-seeds a timeline from that flow's triggers (a viewCampaign event when the flow has a campaign, then the first eligible trigger event 15s later; receiveAutomation, reply and viewCampaign are never seeded) and returns it as `eventsUsed`. To branch-test or continue the journey, copy `eventsUsed`, edit or append to it, and pass the whole array back as `events`. Either `events` or `flowId` is required. Pass a draft's operations as `edits` to preview unsaved changes. Returns `scheduledTexts` plus `eventsUsed`.",
15573
+ "description": "Dry-run automations against a synthetic event timeline and see what would fire \u2014 no real sends or side effects. Each event is `{type, at}` plus a few optional fields; `at` is an ISO 8601 timestamp and the server fills in the guest, organization and campaign. Valid types: signUp, importedCustomer, viewCampaign, addPass, visit, invalidScan, checkout, reply, buttonClick, offerRedemption, offerExpiration, formSubmission, formPropertySubmission, gotReferred, referred, subscriptionRenewal, receiveAutomation. First call: omit `events` and pass `flowId`, and the server auto-seeds a timeline from that flow's triggers (a viewCampaign event when the flow has a campaign, then the first eligible trigger event 15s later) and returns it as `eventsUsed`. To test another day or continue the journey, change `at` on those events or append more, and pass the array back as `events`. Either `events` or `flowId` is required. Pass a draft's operations as `edits` to preview unsaved changes. Returns `scheduledTexts` plus `eventsUsed`.",
15149
15574
  "type": "mutation",
15150
15575
  "path": [
15151
15576
  "api",
@@ -15162,41 +15587,446 @@ Example - opted-in members with more than 5 visits, newest first:
15162
15587
  {
15163
15588
  "not": {}
15164
15589
  },
15165
- {
15166
- "type": "string"
15167
- }
15168
- ]
15169
- },
15170
- {
15171
- "type": "null"
15172
- }
15173
- ]
15174
- },
15175
- "variantId": {
15176
- "anyOf": [
15177
- {
15178
- "anyOf": [
15179
- {
15180
- "not": {}
15590
+ {
15591
+ "type": "string"
15592
+ }
15593
+ ]
15594
+ },
15595
+ {
15596
+ "type": "null"
15597
+ }
15598
+ ]
15599
+ },
15600
+ "variantId": {
15601
+ "anyOf": [
15602
+ {
15603
+ "anyOf": [
15604
+ {
15605
+ "not": {}
15606
+ },
15607
+ {
15608
+ "type": "string"
15609
+ }
15610
+ ]
15611
+ },
15612
+ {
15613
+ "type": "null"
15614
+ }
15615
+ ]
15616
+ },
15617
+ "flowId": {
15618
+ "type": "string"
15619
+ },
15620
+ "events": {
15621
+ "type": "array",
15622
+ "items": {
15623
+ "anyOf": [
15624
+ {
15625
+ "type": "object",
15626
+ "properties": {
15627
+ "type": {
15628
+ "type": "string",
15629
+ "const": "signUp"
15630
+ },
15631
+ "at": {
15632
+ "type": "string",
15633
+ "format": "date-time",
15634
+ "description": "When the event happens, as an ISO 8601 timestamp"
15635
+ }
15636
+ },
15637
+ "required": [
15638
+ "type",
15639
+ "at"
15640
+ ],
15641
+ "additionalProperties": false,
15642
+ "description": "The guest joins the loyalty program"
15643
+ },
15644
+ {
15645
+ "type": "object",
15646
+ "properties": {
15647
+ "type": {
15648
+ "type": "string",
15649
+ "const": "importedCustomer"
15650
+ },
15651
+ "at": {
15652
+ "$ref": "#/properties/events/items/anyOf/0/properties/at"
15653
+ }
15654
+ },
15655
+ "required": [
15656
+ "type",
15657
+ "at"
15658
+ ],
15659
+ "additionalProperties": false,
15660
+ "description": "The guest is added by an import rather than signing up"
15661
+ },
15662
+ {
15663
+ "type": "object",
15664
+ "properties": {
15665
+ "type": {
15666
+ "type": "string",
15667
+ "const": "viewCampaign"
15668
+ },
15669
+ "at": {
15670
+ "$ref": "#/properties/events/items/anyOf/0/properties/at"
15671
+ },
15672
+ "campaignId": {
15673
+ "type": "string"
15674
+ }
15675
+ },
15676
+ "required": [
15677
+ "type",
15678
+ "at"
15679
+ ],
15680
+ "additionalProperties": false,
15681
+ "description": "The guest opens a campaign page. Defaults to the flow's campaign"
15682
+ },
15683
+ {
15684
+ "type": "object",
15685
+ "properties": {
15686
+ "type": {
15687
+ "type": "string",
15688
+ "const": "addPass"
15689
+ },
15690
+ "at": {
15691
+ "$ref": "#/properties/events/items/anyOf/0/properties/at"
15692
+ },
15693
+ "platform": {
15694
+ "type": "string",
15695
+ "enum": [
15696
+ "apple",
15697
+ "google"
15698
+ ]
15699
+ }
15700
+ },
15701
+ "required": [
15702
+ "type",
15703
+ "at"
15704
+ ],
15705
+ "additionalProperties": false,
15706
+ "description": "The guest adds their pass to a wallet"
15707
+ },
15708
+ {
15709
+ "type": "object",
15710
+ "properties": {
15711
+ "type": {
15712
+ "type": "string",
15713
+ "const": "visit"
15714
+ },
15715
+ "at": {
15716
+ "$ref": "#/properties/events/items/anyOf/0/properties/at"
15717
+ },
15718
+ "locationId": {
15719
+ "type": "string"
15720
+ }
15721
+ },
15722
+ "required": [
15723
+ "type",
15724
+ "at"
15725
+ ],
15726
+ "additionalProperties": false,
15727
+ "description": "The guest scans their pass at a location"
15728
+ },
15729
+ {
15730
+ "type": "object",
15731
+ "properties": {
15732
+ "type": {
15733
+ "type": "string",
15734
+ "const": "invalidScan"
15735
+ },
15736
+ "at": {
15737
+ "$ref": "#/properties/events/items/anyOf/0/properties/at"
15738
+ }
15739
+ },
15740
+ "required": [
15741
+ "type",
15742
+ "at"
15743
+ ],
15744
+ "additionalProperties": false,
15745
+ "description": "The guest scans their pass but the scan does not count"
15746
+ },
15747
+ {
15748
+ "type": "object",
15749
+ "properties": {
15750
+ "type": {
15751
+ "type": "string",
15752
+ "const": "checkout"
15753
+ },
15754
+ "at": {
15755
+ "$ref": "#/properties/events/items/anyOf/0/properties/at"
15756
+ },
15757
+ "campaignId": {
15758
+ "type": "string"
15759
+ },
15760
+ "promoId": {
15761
+ "type": "string"
15762
+ },
15763
+ "amountTotal": {
15764
+ "type": "number"
15765
+ }
15766
+ },
15767
+ "required": [
15768
+ "type",
15769
+ "at"
15770
+ ],
15771
+ "additionalProperties": false,
15772
+ "description": "The guest prepays for an offer"
15773
+ },
15774
+ {
15775
+ "type": "object",
15776
+ "properties": {
15777
+ "type": {
15778
+ "type": "string",
15779
+ "const": "reply"
15780
+ },
15781
+ "at": {
15782
+ "$ref": "#/properties/events/items/anyOf/0/properties/at"
15783
+ },
15784
+ "body": {
15785
+ "type": "string"
15786
+ }
15787
+ },
15788
+ "required": [
15789
+ "type",
15790
+ "at"
15791
+ ],
15792
+ "additionalProperties": false,
15793
+ "description": "The guest texts back. `body` is what reply keywords match on"
15794
+ },
15795
+ {
15796
+ "type": "object",
15797
+ "properties": {
15798
+ "type": {
15799
+ "type": "string",
15800
+ "const": "buttonClick"
15801
+ },
15802
+ "at": {
15803
+ "$ref": "#/properties/events/items/anyOf/0/properties/at"
15804
+ },
15805
+ "eventName": {
15806
+ "type": "string"
15807
+ },
15808
+ "buttonId": {
15809
+ "type": "string"
15810
+ }
15811
+ },
15812
+ "required": [
15813
+ "type",
15814
+ "at"
15815
+ ],
15816
+ "additionalProperties": false,
15817
+ "description": "The guest clicks a tracked button"
15818
+ },
15819
+ {
15820
+ "type": "object",
15821
+ "properties": {
15822
+ "type": {
15823
+ "type": "string",
15824
+ "const": "offerRedemption"
15825
+ },
15826
+ "at": {
15827
+ "$ref": "#/properties/events/items/anyOf/0/properties/at"
15828
+ },
15829
+ "rewardId": {
15830
+ "type": "string"
15831
+ }
15832
+ },
15833
+ "required": [
15834
+ "type",
15835
+ "at"
15836
+ ],
15837
+ "additionalProperties": false,
15838
+ "description": "A reward is awarded to the guest"
15839
+ },
15840
+ {
15841
+ "type": "object",
15842
+ "properties": {
15843
+ "type": {
15844
+ "type": "string",
15845
+ "const": "offerExpiration"
15846
+ },
15847
+ "at": {
15848
+ "$ref": "#/properties/events/items/anyOf/0/properties/at"
15849
+ },
15850
+ "rewardId": {
15851
+ "type": "string"
15852
+ },
15853
+ "expirationDate": {
15854
+ "type": "string",
15855
+ "format": "date-time"
15856
+ }
15857
+ },
15858
+ "required": [
15859
+ "type",
15860
+ "at"
15861
+ ],
15862
+ "additionalProperties": false,
15863
+ "description": "A reward expires"
15864
+ },
15865
+ {
15866
+ "type": "object",
15867
+ "properties": {
15868
+ "type": {
15869
+ "type": "string",
15870
+ "const": "formSubmission"
15871
+ },
15872
+ "at": {
15873
+ "$ref": "#/properties/events/items/anyOf/0/properties/at"
15874
+ },
15875
+ "propertyId": {
15876
+ "type": "string"
15877
+ },
15878
+ "formId": {
15879
+ "type": "string"
15880
+ },
15881
+ "booleanValue": {
15882
+ "type": "boolean"
15883
+ },
15884
+ "numberValue": {
15885
+ "type": "number"
15886
+ },
15887
+ "stringValue": {
15888
+ "type": "string"
15889
+ },
15890
+ "localDayOfYear": {
15891
+ "type": "string"
15892
+ },
15893
+ "isDateValue": {
15894
+ "type": "string",
15895
+ "format": "date-time"
15896
+ }
15897
+ },
15898
+ "required": [
15899
+ "type",
15900
+ "at"
15901
+ ],
15902
+ "additionalProperties": false,
15903
+ "description": "The guest submits a form property"
15904
+ },
15905
+ {
15906
+ "type": "object",
15907
+ "properties": {
15908
+ "type": {
15909
+ "type": "string",
15910
+ "const": "formPropertySubmission"
15911
+ },
15912
+ "at": {
15913
+ "$ref": "#/properties/events/items/anyOf/0/properties/at"
15914
+ },
15915
+ "propertyId": {
15916
+ "$ref": "#/properties/events/items/anyOf/11/properties/propertyId"
15917
+ },
15918
+ "formId": {
15919
+ "$ref": "#/properties/events/items/anyOf/11/properties/formId"
15920
+ },
15921
+ "booleanValue": {
15922
+ "$ref": "#/properties/events/items/anyOf/11/properties/booleanValue"
15923
+ },
15924
+ "numberValue": {
15925
+ "$ref": "#/properties/events/items/anyOf/11/properties/numberValue"
15926
+ },
15927
+ "stringValue": {
15928
+ "$ref": "#/properties/events/items/anyOf/11/properties/stringValue"
15929
+ },
15930
+ "localDayOfYear": {
15931
+ "$ref": "#/properties/events/items/anyOf/11/properties/localDayOfYear"
15932
+ },
15933
+ "isDateValue": {
15934
+ "$ref": "#/properties/events/items/anyOf/11/properties/isDateValue"
15935
+ }
15936
+ },
15937
+ "required": [
15938
+ "type",
15939
+ "at"
15940
+ ],
15941
+ "additionalProperties": false,
15942
+ "description": "The guest submits a form property, evaluated as a condition"
15943
+ },
15944
+ {
15945
+ "type": "object",
15946
+ "properties": {
15947
+ "type": {
15948
+ "type": "string",
15949
+ "const": "gotReferred"
15950
+ },
15951
+ "at": {
15952
+ "$ref": "#/properties/events/items/anyOf/0/properties/at"
15953
+ },
15954
+ "referrerSerialNumber": {
15955
+ "type": "string"
15956
+ }
15957
+ },
15958
+ "required": [
15959
+ "type",
15960
+ "at"
15961
+ ],
15962
+ "additionalProperties": false,
15963
+ "description": "The guest signed up from someone else's referral link"
15964
+ },
15965
+ {
15966
+ "type": "object",
15967
+ "properties": {
15968
+ "type": {
15969
+ "type": "string",
15970
+ "const": "referred"
15971
+ },
15972
+ "at": {
15973
+ "$ref": "#/properties/events/items/anyOf/0/properties/at"
15974
+ },
15975
+ "referrerSerialNumber": {
15976
+ "type": "string"
15977
+ }
15181
15978
  },
15182
- {
15183
- "type": "string"
15184
- }
15185
- ]
15186
- },
15187
- {
15188
- "type": "null"
15189
- }
15190
- ]
15191
- },
15192
- "flowId": {
15193
- "type": "string"
15194
- },
15195
- "events": {
15196
- "type": "array",
15197
- "items": {
15198
- "type": "object",
15199
- "additionalProperties": {}
15979
+ "required": [
15980
+ "type",
15981
+ "at"
15982
+ ],
15983
+ "additionalProperties": false,
15984
+ "description": "Someone else signed up from the guest's referral link"
15985
+ },
15986
+ {
15987
+ "type": "object",
15988
+ "properties": {
15989
+ "type": {
15990
+ "type": "string",
15991
+ "const": "subscriptionRenewal"
15992
+ },
15993
+ "at": {
15994
+ "$ref": "#/properties/events/items/anyOf/0/properties/at"
15995
+ }
15996
+ },
15997
+ "required": [
15998
+ "type",
15999
+ "at"
16000
+ ],
16001
+ "additionalProperties": false,
16002
+ "description": "The guest's subscription renews"
16003
+ },
16004
+ {
16005
+ "type": "object",
16006
+ "properties": {
16007
+ "type": {
16008
+ "type": "string",
16009
+ "const": "receiveAutomation"
16010
+ },
16011
+ "at": {
16012
+ "$ref": "#/properties/events/items/anyOf/0/properties/at"
16013
+ },
16014
+ "automationId": {
16015
+ "type": "string"
16016
+ },
16017
+ "campaignId": {
16018
+ "type": "string"
16019
+ }
16020
+ },
16021
+ "required": [
16022
+ "type",
16023
+ "at",
16024
+ "automationId"
16025
+ ],
16026
+ "additionalProperties": false,
16027
+ "description": "The guest already received an automation. The simulation generates these itself as texts send, so only pass one to replay history"
16028
+ }
16029
+ ]
15200
16030
  }
15201
16031
  },
15202
16032
  "serialNumber": {
@@ -16708,6 +17538,119 @@ Example - opted-in members with more than 5 visits, newest first:
16708
17538
  "resetProgress"
16709
17539
  ],
16710
17540
  "additionalProperties": false
17541
+ },
17542
+ {
17543
+ "type": "object",
17544
+ "properties": {
17545
+ "type": {
17546
+ "type": "string",
17547
+ "const": "setCustomProperty"
17548
+ },
17549
+ "setCustomProperty": {
17550
+ "type": "object",
17551
+ "properties": {
17552
+ "propertyId": {
17553
+ "type": "string"
17554
+ },
17555
+ "operation": {
17556
+ "anyOf": [
17557
+ {
17558
+ "type": "object",
17559
+ "properties": {
17560
+ "type": {
17561
+ "type": "string",
17562
+ "const": "set"
17563
+ },
17564
+ "set": {
17565
+ "type": "object",
17566
+ "properties": {
17567
+ "booleanValue": {
17568
+ "type": [
17569
+ "boolean",
17570
+ "null"
17571
+ ]
17572
+ },
17573
+ "isDateValue": {
17574
+ "anyOf": [
17575
+ {
17576
+ "type": "string",
17577
+ "format": "date-time"
17578
+ },
17579
+ {
17580
+ "type": "null"
17581
+ }
17582
+ ]
17583
+ },
17584
+ "localDayOfYear": {
17585
+ "type": [
17586
+ "string",
17587
+ "null"
17588
+ ]
17589
+ },
17590
+ "numberValue": {
17591
+ "type": [
17592
+ "number",
17593
+ "null"
17594
+ ]
17595
+ },
17596
+ "stringValue": {
17597
+ "type": [
17598
+ "string",
17599
+ "null"
17600
+ ]
17601
+ }
17602
+ },
17603
+ "additionalProperties": false
17604
+ }
17605
+ },
17606
+ "required": [
17607
+ "type",
17608
+ "set"
17609
+ ],
17610
+ "additionalProperties": false
17611
+ },
17612
+ {
17613
+ "type": "object",
17614
+ "properties": {
17615
+ "type": {
17616
+ "type": "string",
17617
+ "const": "increment"
17618
+ },
17619
+ "increment": {
17620
+ "type": "object",
17621
+ "properties": {
17622
+ "amount": {
17623
+ "type": "number"
17624
+ }
17625
+ },
17626
+ "required": [
17627
+ "amount"
17628
+ ],
17629
+ "additionalProperties": false,
17630
+ "description": "Number properties only. Added to the current value, or to 0."
17631
+ }
17632
+ },
17633
+ "required": [
17634
+ "type",
17635
+ "increment"
17636
+ ],
17637
+ "additionalProperties": false
17638
+ }
17639
+ ]
17640
+ }
17641
+ },
17642
+ "required": [
17643
+ "propertyId",
17644
+ "operation"
17645
+ ],
17646
+ "additionalProperties": false
17647
+ }
17648
+ },
17649
+ "required": [
17650
+ "type",
17651
+ "setCustomProperty"
17652
+ ],
17653
+ "additionalProperties": false
16711
17654
  }
16712
17655
  ]
16713
17656
  }
@@ -18427,6 +19370,119 @@ Example - opted-in members with more than 5 visits, newest first:
18427
19370
  "resetProgress"
18428
19371
  ],
18429
19372
  "additionalProperties": false
19373
+ },
19374
+ {
19375
+ "type": "object",
19376
+ "properties": {
19377
+ "type": {
19378
+ "type": "string",
19379
+ "const": "setCustomProperty"
19380
+ },
19381
+ "setCustomProperty": {
19382
+ "type": "object",
19383
+ "properties": {
19384
+ "propertyId": {
19385
+ "type": "string"
19386
+ },
19387
+ "operation": {
19388
+ "anyOf": [
19389
+ {
19390
+ "type": "object",
19391
+ "properties": {
19392
+ "type": {
19393
+ "type": "string",
19394
+ "const": "set"
19395
+ },
19396
+ "set": {
19397
+ "type": "object",
19398
+ "properties": {
19399
+ "booleanValue": {
19400
+ "type": [
19401
+ "boolean",
19402
+ "null"
19403
+ ]
19404
+ },
19405
+ "isDateValue": {
19406
+ "anyOf": [
19407
+ {
19408
+ "type": "string",
19409
+ "format": "date-time"
19410
+ },
19411
+ {
19412
+ "type": "null"
19413
+ }
19414
+ ]
19415
+ },
19416
+ "localDayOfYear": {
19417
+ "type": [
19418
+ "string",
19419
+ "null"
19420
+ ]
19421
+ },
19422
+ "numberValue": {
19423
+ "type": [
19424
+ "number",
19425
+ "null"
19426
+ ]
19427
+ },
19428
+ "stringValue": {
19429
+ "type": [
19430
+ "string",
19431
+ "null"
19432
+ ]
19433
+ }
19434
+ },
19435
+ "additionalProperties": false
19436
+ }
19437
+ },
19438
+ "required": [
19439
+ "type",
19440
+ "set"
19441
+ ],
19442
+ "additionalProperties": false
19443
+ },
19444
+ {
19445
+ "type": "object",
19446
+ "properties": {
19447
+ "type": {
19448
+ "type": "string",
19449
+ "const": "increment"
19450
+ },
19451
+ "increment": {
19452
+ "type": "object",
19453
+ "properties": {
19454
+ "amount": {
19455
+ "type": "number"
19456
+ }
19457
+ },
19458
+ "required": [
19459
+ "amount"
19460
+ ],
19461
+ "additionalProperties": false,
19462
+ "description": "Number properties only. Added to the current value, or to 0."
19463
+ }
19464
+ },
19465
+ "required": [
19466
+ "type",
19467
+ "increment"
19468
+ ],
19469
+ "additionalProperties": false
19470
+ }
19471
+ ]
19472
+ }
19473
+ },
19474
+ "required": [
19475
+ "propertyId",
19476
+ "operation"
19477
+ ],
19478
+ "additionalProperties": false
19479
+ }
19480
+ },
19481
+ "required": [
19482
+ "type",
19483
+ "setCustomProperty"
19484
+ ],
19485
+ "additionalProperties": false
18430
19486
  }
18431
19487
  ]
18432
19488
  }
@@ -22004,7 +23060,7 @@ Example - opted-in members with more than 5 visits, newest first:
22004
23060
  {
22005
23061
  "id": "updateInfluencerBoardConfig",
22006
23062
  "domain": "creators",
22007
- "description": "Create or update a location's creator program. This is an upsert \u2014 there is no separate create tool, and the config is keyed by locationId, one per location \u2014 so calling it for a location with no program creates one, seeding a 5000-cent dining credit and leaving landingPageConfirmed, calendarConfigured and passConfigured false. Omitted fields are left alone. schedulingMode gets no default, so set it on the first call or the Design creator program task stays incomplete: self_schedule_approval lets approved creators book themselves, apply_only collects applications for you to schedule. Note the launch check is looser than the task check \u2014 launchInfluencerCampaign only requires landingPageConfirmed and a positive credit, so a program can go live while its setup task still reads incomplete.",
23063
+ "description": "Create or update a location's creator program. This is an upsert \u2014 there is no separate create tool, and the config is keyed by locationId, one per location \u2014 so calling it for a location with no program creates one, seeding a 5000-cent dining credit and leaving landingPageConfirmed, calendarConfigured, passConfigured and reimbursementEnabled false. Omitted fields are left alone. reimbursementEnabled switches the board from comping the meal to reimbursing a meal the creator paid for, and foodCreditAmountCents becomes the reimbursement cap rather than a dining credit \u2014 it changes what creators are promised on the landing page, brief and rights agreement, so never set it without the client asking for it. schedulingMode gets no default, so set it on the first call or the Design creator program task stays incomplete: self_schedule_approval lets approved creators book themselves, apply_only collects applications for you to schedule. Note the launch check is looser than the task check \u2014 launchInfluencerCampaign only requires landingPageConfirmed and a positive credit, so a program can go live while its setup task still reads incomplete.",
22008
23064
  "type": "mutation",
22009
23065
  "path": [
22010
23066
  "api",
@@ -22043,9 +23099,6 @@ Example - opted-in members with more than 5 visits, newest first:
22043
23099
  "passConfigured": {
22044
23100
  "type": "boolean"
22045
23101
  },
22046
- "googleMapsLink": {
22047
- "type": "string"
22048
- },
22049
23102
  "maxBookingDaysOut": {
22050
23103
  "anyOf": [
22051
23104
  {
@@ -22099,7 +23152,8 @@ Example - opted-in members with more than 5 visits, newest first:
22099
23152
  {
22100
23153
  "type": "null"
22101
23154
  }
22102
- ]
23155
+ ],
23156
+ "description": "Despite the name, this covers the WHOLE visit, not just the run-up to it: anything creators must know or do before (download an app, book a reservation), during (check in with the host), or after (text a photo of the receipt). The text is injected verbatim into both the pre-visit and post-visit SMS agents' prompts, so write it as instructions to the creator and cover every stage in this one field \u2014 there is no separate post-visit instructions field."
22103
23157
  },
22104
23158
  "minFollowerCount": {
22105
23159
  "anyOf": [
@@ -22136,6 +23190,9 @@ Example - opted-in members with more than 5 visits, newest first:
22136
23190
  "type": "null"
22137
23191
  }
22138
23192
  ]
23193
+ },
23194
+ "reimbursementEnabled": {
23195
+ "type": "boolean"
22139
23196
  }
22140
23197
  },
22141
23198
  "required": [
@@ -23829,6 +24886,43 @@ Example - opted-in members with more than 5 visits, newest first:
23829
24886
  "lastVisit"
23830
24887
  ],
23831
24888
  "additionalProperties": false
24889
+ },
24890
+ {
24891
+ "type": "object",
24892
+ "properties": {
24893
+ "type": {
24894
+ "type": "string",
24895
+ "const": "customProperty"
24896
+ },
24897
+ "customProperty": {
24898
+ "type": "object",
24899
+ "properties": {
24900
+ "propertyId": {
24901
+ "type": "string"
24902
+ },
24903
+ "propertyType": {
24904
+ "type": "string",
24905
+ "enum": [
24906
+ "boolean",
24907
+ "dayOfYear",
24908
+ "date",
24909
+ "number",
24910
+ "string"
24911
+ ]
24912
+ }
24913
+ },
24914
+ "required": [
24915
+ "propertyId",
24916
+ "propertyType"
24917
+ ],
24918
+ "additionalProperties": false
24919
+ }
24920
+ },
24921
+ "required": [
24922
+ "type",
24923
+ "customProperty"
24924
+ ],
24925
+ "additionalProperties": false
23832
24926
  }
23833
24927
  ]
23834
24928
  }