Skip to content

Latest commit

 

History

History
353 lines (265 loc) · 31.3 KB

File metadata and controls

353 lines (265 loc) · 31.3 KB

Launch config reference

Generated from the config schema in src/core/config/ and config types in src/core/types/config.ts by npm run docs:gen — edit the source, then regenerate. For editor autocomplete and validation, run launch config schema --out launch.config.schema.json, then point your config at it: a JSON config adds a "$schema": "./launch.config.schema.json" key, while a .ts config (which can't carry $schema) is wired through VS Code's json.schemas setting or your editor's equivalent. Run launch config validate to check a config against this schema (it also reports cross-field semantic warnings, which never fail the command); pass a .json file to validate it verbatim, including unknown top-level keys.

Top-level fields

Field Type Required Description
profiles Record<string, BuildProfile> Yes Build profiles keyed by name.
credentials string No Registered name of the credentials provider to use. Defaults to local (serves both platforms).
storage string No Registered name of the artifact storage provider to use. Defaults to local.
buildEngine string No Registered name of the build engine. Carries the iOS default fastlane (or eas for the cloud handoff); an Android build swaps that iOS baseline for its twin gradle unless overridden here.
submit string | SubmitByPlatform No Where built artifacts are submitted, in one of two forms: a single registered submitter name (the iOS default app-store-connect, which an Android build swaps for its twin google-play; or eas) — the original, unchanged shape; or a per-platform SubmitByPlatform map, to fan one build out to several stores from this one config (e.g. an Android .aab to google-play and amazon-appstore). The pipeline resolves this to a store list per platform (see resolveSubmitters), so the build target and the store are no longer welded 1:1. See docs/adr/0006-platform-store-split.md.
appRoots string[] No Glob roots to scan for apps. Defaults to the repo root.
products Record<string, AppProducts> No Declarative App Store Connect product catalog, keyed by iOS bundle id. Drives launch sync, which reconciles each app's subscriptions, in-app purchases, and pricing on App Store Connect to match this. Absent for apps that sell nothing. See AppProducts.
notify object No Build/submit completion notifications (webhook + shell hook). Absent = no notifications. See NotifyConfig.
release object No iOS public-release policy for launch release (release type, scheduled date, phased rollout, export compliance, release notes). Absent = the safe defaults (go live after approval, all at once). See ReleaseConfig.
gameCenter Record<string, GameCenterConfig> No Game Center achievements & leaderboards, keyed by iOS bundle id. Drives launch game-center. The single-config form of gamecenter.config.json (still accepted for back-compat). See GameCenterConfig.
appClips Record<string, AppClipsConfig> No App Clip card metadata, keyed by the parent app's iOS bundle id. Drives launch app-clips. The single-config form of appclips.config.json (still accepted for back-compat). See AppClipsConfig.
releaseAttributes Record<string, ReleaseAttributesConfig> No App Store release attributes (age rating, categories, price, review details), keyed by iOS bundle id. Drives launch release-config. The single-config form of release.config.json (still accepted for back-compat). Distinct from release (the release policy). See ReleaseAttributesConfig.
wallet object No Team-level Apple Pay merchant ids & Wallet pass type ids. Drives launch wallet. The single-config form of wallet.config.json (still accepted for back-compat). See WalletConfig.
euDistribution object No Team-level EU alternative-distribution domains (DMA). Drives launch eu-distribution. The single-config form of eu-distribution.config.json (still accepted for back-compat). See EuDistributionConfig.
configFiles object No Optional non-default paths for the sidecar-only surfaces' *.config.json files (availability, accessibility, experiments, custom pages). Lets launch plan / launch drift find a sidecar that isn't at its default filename, since those surfaces have no typed field here. Omit to use defaults. See SurfaceConfigFiles.
aws object No AWS EC2 Mac settings for remote (off-Mac) builds. Only needed when building via --remote aws.
storageConfig object No Bucket/endpoint settings for a cloud StorageProvider (s3 / supabase). Required when storage names a cloud provider — it's where ad-hoc install links and OTA update manifests are hosted. Secrets stay out: access keys resolve from env / the OS secret store, never from here.
artifactDir string No Where the local storage provider writes build binaries and raw objects (install plists, OTA manifests). A relative path resolves against the project root (the launch.config.ts directory); a leading ~/ expands to the home directory; an absolute path is used as-is. Omit to use the global ~/.launch/artifacts (the default — existing projects are unaffected). launch init and the no-args wizard scaffold this as the in-repo ./.launch/artifacts and add it to .gitignore, so build binaries never get committed. Only the local provider observes it — cloud stores key off StorageConfig. The history index stays under ~/.launch, so build history and retention span projects regardless of where the binaries land.
artifactRetentionDays number No How many days a local build binary is kept before the artifact store auto-prunes it to reclaim disk (the newest build per app+platform is always kept, so a promotable artifact never disappears). Runs after each successful local build. Defaults to 30 when omitted; set to 0 to disable the automatic sweep entirely (launch builds prune still works on demand). Only the local provider observes this — cloud stores manage retention through their own bucket lifecycle rules.
envExclude string[] No Env var names that must NEVER be injected into a build — a hard denylist applied across every layer (.env, .env.<profile>, keychain, profile env:, even an explicit --env). A matched name is dropped outright, so it can't reach the build subprocess and therefore can't be baked into the shipped app even by an app.config.js that forwards process.env. Each entry is either an exact, case-sensitive name or a PREFIX* wildcard: OPENAI_* drops every name starting with OPENAI_ (e.g. OPENAI_API_KEY, OPENAI_ORG_ID), so a whole family of backend keys collapses to one line instead of being listed individually. Wildcards anchor at the START — there is no tail/*_KEY form, by design, since that would also snag a publishable EXPO_PUBLIC_..._KEY. This is the home for backend-only values that sit in the app's .env for local tooling but must never ship (e.g. OPENAI_API_KEY, a server-side SENTRY_AUTH_TOKEN). It is distinct from launch secret set: a stored secret is still injected — the build needs it — it's just moved out of plaintext; envExclude means "don't inject this at all". A name matched here is exempt from the .env.example missing-key gate (even when no layer sets it). Omit (or []) to exclude nothing.
mcp object No How launch mcp exposes Launch to AI agents — chiefly which capability tiers it may offer. Absent = least privilege (read-only tools). See McpConfig.

Types

AchievementConfig

One declared Game Center achievement: Apple's create attributes plus its default-locale localization.

Field Type Required Description
vendorIdentifier string Yes Developer-chosen stable id used to match config to Apple's record (never shown to players).
referenceName string Yes Internal name shown in App Store Connect.
points number Yes Points awarded (Apple caps the total across achievements at 1000).
showBeforeEarned boolean No Whether the achievement is visible to players before it's earned (default false).
repeatable boolean No Whether it can be earned more than once (default false).
name string Yes Player-facing title in the localization.
beforeEarnedDescription string Yes Player-facing description shown before the achievement is earned.
afterEarnedDescription string Yes Player-facing description shown after it's earned.
locale string No Locale for the localization above (default en-US).

AppClipConfig

One App Clip's declared card metadata. Both fields are optional and reconciled independently, so a clip may declare just an action, just localizations, or both.

Field Type Required Description
action "OPEN" | "VIEW" | "PLAY" No The card's call-to-action button (OPEN / VIEW / PLAY).
localizations Record<string, AppClipLocalizationConfig> No Per-locale card subtitles, keyed by Apple locale (e.g. en-US).

AppClipLocalizationConfig

One locale of an App Clip card: the subtitle shown under the app name in that locale.

Field Type Required Description
subtitle string Yes

AppClipsConfig

An app's declared App Clips — the appclips.config.json document, or one entry of appClips (keyed by the parent app's iOS bundle id). Each App Clip is keyed by its own bundle id (e.g. com.acme.app.Clip), which is how a config entry is matched to the clip the build produced. Reconciled by launch app-clips.

Field Type Required Description
clips Record<string, AppClipConfig> Yes

AppProducts

The declarative App Store Connect product catalog for ONE app, keyed by iOS bundle id under products. launch sync reconciles the live account to match this: it creates missing groups/subscriptions/IAPs, fills in localizations, and sets prices. launch offers reconciles the subscription offers nested under SubscriptionGroupConfig and the promotedPurchases ordering. All fields are optional so an app can sell only subscriptions, only one-off purchases, or (with none set) nothing.

Field Type Required Description
subscriptionGroups SubscriptionGroupConfig[] No Auto-renewable subscription groups and the subscriptions within them.
inAppPurchases InAppPurchaseConfig[] No One-off in-app purchases.
promotedPurchases PromotedPurchaseConfig[] No Promoted purchases in product-page display order (launch offers reorders the live list to match).

BuildProfile

A named build profile from launch.config.ts (e.g. production, preview). Holds only Launch-specific settings; app facts stay in app.json. A profile maps to a .env file whose values are injected into the build and gates the artifact on size.

Field Type Required Description
name string Yes Profile name as referenced by --profile.
envFile string No Dotenv file to load for this profile, relative to the app dir. Defaults to .env.
env Record<string, string> No Inline env vars for this profile, merged into the build/update/release environment. They sit above the dotenv files (.env.local, .env.<profile>, .env) but below keychain secrets and --env flags in the precedence ladder — see core/env.ts resolveEnv. Use for non-secret, committed config that should travel with the profile; keep real secrets in launch secret.
ssl boolean No Enable SSL pinning for this profile (mirrors the existing build.ts toggle). Defaults to false.
sizeBudgetMB number No Per-device download-size budget in megabytes. When the size report exceeds it, the build soft-gates (asks for confirmation) rather than failing. Defaults to 200 (Apple's cellular line).
track "internal" | "closed" | "open" | "production" No Android-only: default Play track for launch build android when --track is omitted. Defaults to internal (the only safe target for a fresh account). Ignored on iOS.
rollout number No Android-only: default staged-rollout fraction (0–1) for production releases when --rollout is omitted. Defaults to 1.0 (full rollout). Ignored on iOS.

EuDistributionDomainConfig

One authorized EU distribution domain: the host plus a human-readable reference name.

Field Type Required Description
domain string Yes The domain authorized to host distribution packages (e.g. downloads.acme.com).
referenceName string Yes A label shown in App Store Connect to identify the domain.

GameCenterConfig

An app's declared Game Center achievements and leaderboards — the gamecenter.config.json document, or one entry of gameCenter (keyed by iOS bundle id). Either list may be omitted. Reconciled additively by launch game-center.

Field Type Required Description
achievements AchievementConfig[] No
leaderboards LeaderboardConfig[] No

GroupLocalization

One locale's display name for a subscription GROUP. Groups carry only a name (no description); it's shown at the point of purchase grouping the subscription levels. Without one, every subscription in the group is stuck in "Missing Metadata", so at least one is required per group.

Field Type Required Description
locale string Yes App Store locale code, e.g. en-US.
name string Yes Customer-facing group name.

InAppPurchaseConfig

One non-subscription in-app purchase (consumable, non-consumable, or non-renewing subscription). productId is the globally-unique Apple product id and the reconciler's natural key. Add a PlayProductOverride under play to also publish it to Google Play.

Field Type Required Description
productId string Yes Apple product id, e.g. com.acme.coins.100. Globally unique; the reconciler matches on it.
referenceName string Yes Internal reference name shown only in App Store Connect.
type "CONSUMABLE" | "NON_CONSUMABLE" | "NON_RENEWING_SUBSCRIPTION" Yes The purchase kind.
localizations ProductLocalization[] Yes Per-locale display copy; at least one entry is required for a submittable product.
price object No Baseline price. Omit only to price manually in the UI.
play object No Google Play overrides; present this to also publish the product to Play (see PlayProductOverride).

IntroductoryOfferConfig

An introductory offer (Apple's subscriptionIntroductoryOffers) — the one auto-applied first-time discount. Apple allows at most one per (subscription, territory); when territory is omitted it applies to all territories the subscription is sold in. territory is the reconciler's natural key.

Field Type Required Description
duration "THREE_DAYS" | "ONE_WEEK" | "TWO_WEEKS" | "ONE_MONTH" | "TWO_MONTHS" | "THREE_MONTHS" | "SIX_MONTHS" | "ONE_YEAR" Yes Billing duration unit.
offerMode "PAY_AS_YOU_GO" | "PAY_UP_FRONT" | "FREE_TRIAL" Yes How the offer discounts. FREE_TRIAL must omit price.
numberOfPeriods number Yes How many duration units the offer spans.
territory string No Territory this intro offer applies to (the reconciler's key); omit for all territories.
price object No The discounted price in territory. Required unless FREE_TRIAL.
startDate string No ISO date (YYYY-MM-DD) the offer starts; omit to start immediately.
endDate string No ISO date (YYYY-MM-DD) the offer ends; omit for no end.

LeaderboardConfig

One declared Game Center leaderboard: Apple's create attributes plus its default-locale localization name.

Field Type Required Description
vendorIdentifier string Yes
referenceName string Yes
defaultFormatter "INTEGER" | "DECIMAL_POINT_1_PLACE" | "DECIMAL_POINT_2_PLACE" | "DECIMAL_POINT_3_PLACE" | "ELAPSED_TIME_CENTISECOND" | "ELAPSED_TIME_MINUTE" | "ELAPSED_TIME_SECOND" | "MONEY_POUND_DECIMAL" | "MONEY_POUND" | "MONEY_DOLLAR_DECIMAL" | "MONEY_DOLLAR" | "MONEY_EURO_DECIMAL" | "MONEY_EURO" | "MONEY_FRANC_DECIMAL" | "MONEY_FRANC" | "MONEY_KRONER_DECIMAL" | "MONEY_KRONER" | "MONEY_YEN" Yes How scores are formatted (e.g. INTEGER, ELAPSED_TIME_SECOND).
submissionType "BEST_SCORE" | "MOST_RECENT_SCORE" Yes Whether the board keeps each player's best or most recent score.
scoreSortType "ASC" | "DESC" Yes Whether higher (DESC) or lower (ASC) scores rank first.
name string Yes Player-facing title in the localization.
locale string No Locale for the localization above (default en-US).

OfferCodeConfig

A subscription offer-code campaign (Apple's subscriptionOfferCodes) — a redeemable promo that grants an introductory price. name is the reconciler's natural key (unique per subscription); offer-code terms are immutable once created, so the reconciler only ever creates a missing code, never edits one (deactivation is the explicit launch offers deactivate action). One-time-use and custom code batches are generated separately (the imperative launch offers codes subcommands), not declared here.

Field Type Required Description
duration "THREE_DAYS" | "ONE_WEEK" | "TWO_WEEKS" | "ONE_MONTH" | "TWO_MONTHS" | "THREE_MONTHS" | "SIX_MONTHS" | "ONE_YEAR" Yes Offer billing duration unit.
offerMode "PAY_AS_YOU_GO" | "PAY_UP_FRONT" | "FREE_TRIAL" Yes How the offer discounts. FREE_TRIAL must omit prices.
numberOfPeriods number Yes How many duration units the offer spans.
prices OfferPrice[] No Per-territory discounted prices. Required unless offerMode is FREE_TRIAL.
name string Yes Campaign name shown in App Store Connect — unique per subscription; the reconciler's key.
customerEligibilities "NEW" | "EXISTING" | "EXPIRED"[] Yes Which customers may redeem the code.
offerEligibility "STACK_WITH_INTRO_OFFERS" | "REPLACE_INTRO_OFFERS" Yes Whether the code stacks with or replaces the intro offer.

OfferPrice

One territory's discounted price for an offer, resolved to an Apple subscription price point exactly like ProductPrice (the customer-facing amount must equal a point on Apple's fixed ladder). Omit prices entirely for a FREE_TRIAL offer.

Field Type Required Description
territory string No Territory whose price point is matched, e.g. USA. Defaults to USA.
customerPrice number Yes Exact customer-facing price in the territory's currency, e.g. 4.99. Must equal an Apple price point.

PlayPriceConfig

A Google Play price: an exact amount in a currency's micro-units (millionths) plus the ISO currency code. Play has no price-point ladder — "1990000" with currency "USD" is $1.99. Used for both a product's default price and any per-region overrides. Kept distinct from ProductPrice because the two stores model money differently (Apple resolves a fixed price point; Play takes a literal micro-unit amount), so a single shared price field can't serve both.

Field Type Required Description
priceMicros string Yes Amount in micro-units: 1,000,000 = one whole unit of currency.
currency string Yes ISO 4217 currency code, e.g. USD.

PlaySubscriptionOfferConfig

One Google Play offer on a subscription's base plan — a free trial, an introductory price, or both (Play allows up to two offer phases). offerId is the natural key the reconciler matches on. Set freeTrialDuration for a free phase and/or introPrices for a discounted phase; an offer with neither is rejected (it would discount nothing).

Field Type Required Description
offerId string Yes Play offer id (unique within the base plan).
freeTrialDuration string No Free-trial length as an ISO-8601 duration (e.g. P1W, P1M). Omit for no trial phase.
introPrices Record<string, PlayPriceConfig> No Introductory per-region prices (region code → micro-units + currency). Omit for no intro phase.
introRecurrenceCount number No How many billing periods the introductory price repeats for. Defaults to 1.

ProductLocalization

One locale's customer-facing copy for a subscription or in-app purchase — the display name (and optional description) shown on the product page. Apple keeps a product in "Missing Metadata" until it has at least one localization, so the reconciler rejects an empty list rather than silently creating an unsubmittable product. The locale is the natural key the reconciler matches on.

Field Type Required Description
locale string Yes App Store locale code, e.g. en-US.
name string Yes Customer-facing display name (Apple limit: 30 characters).
description string No Customer-facing description (Apple limit: 45 characters). Omitted when not provided.

PromotedPurchaseConfig

One promoted purchase (Apple's promotedPurchases) — an IAP or subscription surfaced on the app's App Store product page. Declaration order in promotedPurchases is the display order Apple shows; launch offers reorders the live list to match. productId references an existing subscription or in-app purchase; the reconciler resolves it to the live resource.

Field Type Required Description
productId string Yes Apple product id of the subscription or in-app purchase to promote.
visibleForAllUsers boolean No Whether the promotion is visible to all users (vs. targeted via the API). Defaults to true.
enabled boolean No Whether the promotion is enabled. Defaults to true.

PromotionalOfferConfig

A promotional offer (Apple's subscriptionPromotionalOffers) — a developer-presented discount surfaced in-app to existing/lapsed subscribers. offerCode is the product-level identifier the app passes to StoreKit at redemption; it is the reconciler's natural key (unique per subscription).

Field Type Required Description
duration "THREE_DAYS" | "ONE_WEEK" | "TWO_WEEKS" | "ONE_MONTH" | "TWO_MONTHS" | "THREE_MONTHS" | "SIX_MONTHS" | "ONE_YEAR" Yes Offer billing duration unit.
offerMode "PAY_AS_YOU_GO" | "PAY_UP_FRONT" | "FREE_TRIAL" Yes How the offer discounts. FREE_TRIAL must omit prices.
numberOfPeriods number Yes How many duration units the offer spans.
prices OfferPrice[] No Per-territory discounted prices. Required unless offerMode is FREE_TRIAL.
name string Yes Internal name shown in App Store Connect.
offerCode string Yes Product-level offer identifier the app references in StoreKit — the reconciler's key.

ReleaseAttributesConfig

An app's declared App Store release attributes — age rating, App Store categories, base price, and App Review details — the release.config.json document, or one entry of releaseAttributes (keyed by iOS bundle id). Every section is optional and reconciled independently by launch release-config, so a file may declare only the attribute(s) you manage as code (e.g. just pricing). Named to avoid colliding with ReleaseConfig, which is the distinct iOS release policy (when/how a version goes live).

Field Type Required Description
ageRating Record<string, string | boolean> No Age-rating answers as Apple's name → value map (enum strings or booleans); only changed keys are sent.
categories ReleaseCategories No
pricing ReleasePricing No
reviewDetails ReviewDetailsConfig No

ReleaseCategories

Declared primary/secondary App Store categories (appCategories ids such as PRODUCTIVITY).

Field Type Required Description
primary string No
secondary string No

ReleasePricing

Declared base price: a customer price (e.g. 9.99) in a base territory Apple equalizes from.

Field Type Required Description
baseTerritory string No Base territory to anchor the price on (default USA).
customerPrice number Yes The customer-facing price in the base territory; must match one of Apple's price-ladder rungs.

ReviewDetailsConfig

Declared App Review details: the contact Apple reaches and the demo account its reviewer signs in with. Field names match Apple's appStoreReviewDetails attributes verbatim. demoAccountPassword is never read back from Apple or logged.

Field Type Required Description
contactFirstName string No
contactLastName string No
contactPhone string No
contactEmail string No
demoAccountRequired boolean No
demoAccountName string No
demoAccountPassword string No The reviewer demo-account password. Prefer an indirection over a plaintext literal so the secret needn't sit in a repo-committed config (per "secrets never touch the repo"): env:VAR_NAME reads it from the environment, keychain:ACCOUNT from the OS keychain — both resolved only at submit time, so a plan never reads or holds it. Any other value is used as a literal (backward compatible).
notes string No

SubmitByPlatform

Field Type Required Description
ios string[] No
android string[] No
tvos string[] No
macos string[] No
visionos string[] No

SubscriptionConfig

One auto-renewable subscription product inside a SubscriptionGroupConfig. productId is the globally-unique Apple product id the app references at runtime and the reconciler's natural key. Add a PlaySubscriptionOverride under play to also publish it to Google Play.

Field Type Required Description
productId string Yes Apple product id, e.g. com.acme.pro.monthly. Globally unique; the reconciler matches on it.
referenceName string Yes Internal reference name shown only in App Store Connect (Apple limit: 64 characters).
subscriptionPeriod "ONE_WEEK" | "ONE_MONTH" | "TWO_MONTHS" | "THREE_MONTHS" | "SIX_MONTHS" | "ONE_YEAR" Yes Billing period for this level.
localizations ProductLocalization[] Yes Per-locale display copy; at least one entry is required for a submittable product.
price object No Baseline price. Omit only to price manually in the UI.
offerCodes OfferCodeConfig[] No Offer-code campaigns to ensure exist on this subscription (launch offers).
promotionalOffers PromotionalOfferConfig[] No Promotional offers to ensure exist on this subscription.
introductoryOffers IntroductoryOfferConfig[] No Introductory offers (at most one per territory) to ensure exist on this subscription.
winBackOffers WinBackOfferConfig[] No Win-back offers to ensure exist on this subscription.
reviewScreenshot string No Path (relative to the app directory) to this subscription's App Review screenshot — the image Apple requires before a subscription can be submitted. launch sync uploads it via the reservation flow, idempotently: it's skipped when the live screenshot's MD5 already matches the local file. Omit to attach it by hand in App Store Connect. Reconciled in core/ascScreenshots.ts, not here.
play object No Google Play overrides; present this to also publish the subscription to Play (see PlaySubscriptionOverride).

SubscriptionGroupConfig

A subscription group — Apple's container for mutually-exclusive subscription levels (a customer holds at most one active subscription per group). referenceName is unique within the app and is the reconciler's natural key for the group.

Field Type Required Description
referenceName string Yes Internal reference name (unique within the app) — the reconciler's natural key for the group.
localizations GroupLocalization[] Yes Per-locale group display name; at least one entry is required (else the group's subs stay unsubmittable).
subscriptions SubscriptionConfig[] Yes The subscription levels in this group.

WalletIdConfig

One declared Apple identifier: the reverse-DNS id plus a human-readable name shown in the portal.

Field Type Required Description
identifier string Yes The identifier to register (e.g. merchant.com.acme.app or pass.com.acme.coupon).
name string Yes A label shown in App Store Connect / the developer portal.

WinBackOfferConfig

A win-back offer (Apple's winBackOffers) — a discount shown on the App Store to lapsed subscribers, gated on how long they previously paid and how long ago they churned. offerId is the reconciler's natural key (unique within the app). Win-back offers carry no images here — promotion artwork is the promotionIntent auto-generated path; custom artwork is a deferred follow-up.

Field Type Required Description
duration "THREE_DAYS" | "ONE_WEEK" | "TWO_WEEKS" | "ONE_MONTH" | "TWO_MONTHS" | "THREE_MONTHS" | "SIX_MONTHS" | "ONE_YEAR" Yes Offer billing duration unit.
offerMode "PAY_AS_YOU_GO" | "PAY_UP_FRONT" | "FREE_TRIAL" Yes How the offer discounts. FREE_TRIAL must omit prices.
numberOfPeriods number Yes How many duration units the offer spans.
prices OfferPrice[] No Per-territory discounted prices. Required unless offerMode is FREE_TRIAL.
offerId string Yes Stable offer identifier the app references — the reconciler's key (unique within the app).
referenceName string Yes Internal reference name shown in App Store Connect.
eligiblePaidMonths number Yes Minimum months the customer must previously have paid to be eligible.
monthsSinceLastSubscribed object Yes Eligible window since the customer last subscribed, in months (inclusive [min, max]).
waitBetweenOffersMonths number No Minimum months to wait between showing successive win-back offers; omit for Apple's default.
startDate string Yes ISO date (YYYY-MM-DD) the offer starts. Required by Apple.
endDate string No ISO date (YYYY-MM-DD) the offer ends; omit for no end.
priority "HIGH" | "NORMAL" No Display priority among competing win-back offers. Defaults to NORMAL.
promotionIntent "NOT_PROMOTED" | "USE_AUTO_GENERATED_ASSETS" No Whether Apple auto-generates promotion artwork (USE_AUTO_GENERATED_ASSETS) or the offer isn't promoted.