Skip to content

API data models

Named response models follow the current server types. Dates serialize as ISO strings. Optional fields may be omitted; null is explicit. These definitions describe shapes, not permission to access another tenant.

interface OAuthConfig {
config: Record<string, {
clientId?: string;
clientIds?: Record<string, string>;
}>;
}
interface AuthResponse {
user: CustomerAuthUser;
customer: AuthCustomer;
session: AuthSession;
redirectUrl?: string;
}
interface CustomerAuthUser {
id: string;
email: string;
firstName: string | null;
lastName: string | null;
name: string;
emailVerified: boolean;
emailUnreachable: boolean;
image?: string | null;
connectedAccounts: ConnectedAccount[];
preferences: UserPreferences;
}
interface ConnectedAccount {
id: string;
provider: 'google' | 'apple' | 'credential' | 'magic_link';
providerId: string;
email?: string;
connectedAt: string;
}
interface UserPreferences {
theme?: 'light' | 'dark' | 'system';
density?: 'comfortable' | 'compact';
[key: string]: unknown;
}
interface AuthCustomer {
customerId: string;
isAnonymous: boolean;
}
interface AuthSession {
token: string;
refreshToken: string;
expiresAt: number;
refreshExpiresAt: number | null;
familyId: string;
generation: number;
authenticatedAt: number;
}
interface MagicLinkRequestResponse {
success: boolean;
message: string;
expiresAt?: number;
emailUnreachable: boolean;
}
interface AccountPreflightCheck {
message: string;
code: string;
type: 'warning' | 'error';
provider?: string;
}
interface AuthMethodCapability {
method: import('../constants.js').AuthProviderMethod;
enabled: boolean;
ready: boolean;
signIn: boolean;
signUp: boolean;
}
interface AppAppearance {
version: string;
mode: AppAppearanceMode;
variables: AppAppearanceVariables;
}
interface AppAppearanceVariables {
accent?: string;
accentFg?: string;
bg?: string;
fg?: string;
muted?: string;
mutedFg?: string;
border?: string;
radius?: string;
shadow?: AppAppearanceShadow;
fontFamily?: AppAppearanceFont;
logo?: string;
authBg?: string;
authBgImage?: string;
brandGradient?: string;
darkBg?: string;
darkFg?: string;
darkAccent?: string;
}
type PaidAccessConfiguration = {
version: 1;
policy: 'account';
} | {
version: 1;
policy: 'app_store';
products: AppStoreAccessProduct[];
appPurchaseRules?: AppStoreAppPurchaseRule[];
};
interface AppStoreAccessProduct {
productIdentifier: string;
kind: AppStoreAccessProductKind;
entitlementIdentifiers: string[];
familySharingEnabled: boolean;
}
interface AppStoreAppPurchaseRule {
originalAppVersionBefore?: string;
originalAppVersionFormat?: AppStoreOriginalVersionFormat;
originalPurchaseDateBefore?: string;
entitlementIdentifiers: string[];
}
type IntegrationPublicConfig = GoogleOAuthPublicConfig | AppleOAuthPublicConfig | StripePublicConfig | AppleIAPPublicConfig | GooglePlayPublicConfig | APNsPublicConfig | FCMPublicConfig | Record<string, unknown>;
interface GoogleOAuthPublicConfig extends BaseIntegrationPublicConfig {
clientId: string;
}
interface AppleOAuthPublicConfig extends BaseIntegrationPublicConfig {
clientId: string;
teamId?: string;
keyId?: string;
servicesId?: string;
}
interface StripePublicConfig extends BaseIntegrationPublicConfig {
stripeAccountId?: string;
webhookEndpointId?: string;
environment?: 'test' | 'live';
feeEstimate?: {
domesticCardBps?: number;
fixedFeeCents?: number;
fixedFeeCurrency?: string;
internationalCardBps?: number;
currencyConversionBps?: number;
};
}
interface AppleIAPPublicConfig extends BaseIntegrationPublicConfig {
environment?: 'sandbox' | 'production';
bundleId?: string;
appAppleId?: string;
issuerId?: string;
keyId?: string;
commissionEstimate?: {
smallBusinessProgram?: boolean;
standardCommissionBps?: number;
smallBusinessCommissionBps?: number;
subscriptionYearTwoCommissionBps?: number;
};
}
interface GooglePlayPublicConfig extends BaseIntegrationPublicConfig {
packageName?: string;
}
interface APNsPublicConfig extends BaseIntegrationPublicConfig {
teamId: string;
keyId: string;
bundleId: string;
environment?: 'development' | 'production';
environments?: Array<'development' | 'production'>;
}
interface FCMPublicConfig extends BaseIntegrationPublicConfig {
projectId: string;
}
interface SendPushNotificationResult {
sent: number;
failed: number;
results: Array<{
deviceTokenId: string;
transport: 'apns' | 'fcm';
success: boolean;
providerMessageId?: string;
error?: string;
}>;
}
interface PaywallResponse {
paywall: {
id: string;
identifier: string;
name: string;
description?: string | null;
config: AnyPaywallConfig;
};
paywallProducts: PaywallProductResponse[];
paywallOffers?: import('./product-offers.js').PaywallProductOfferResponse[];
campaign?: CampaignSelectionResponse;
}
type AnyPaywallConfig = PaywallConfigV1 | PaywallConfigV1_1;
interface PaywallConfig {
version: PaywallConfigV1Version;
theme?: PaywallTheme;
startScreenId?: string;
screens: PaywallScreen[];
}
interface PaywallTheme {
colors?: PaywallThemeColors;
darkColors?: PaywallThemeColors;
textStyles?: PaywallThemeTextStyles;
shadows?: Partial<Record<'screen' | 'hero' | 'featureIcon' | 'paywallProduct' | 'paywallProductSelected' | 'purchaseButton' | 'bottomOverlay' | 'closeButton', PaywallShadow>>;
materials?: {
bottomOverlay?: PaywallMaterial;
};
backgroundGradient?: PaywallGradient;
darkBackgroundGradient?: PaywallGradient;
cornerRadius?: number;
}
interface PaywallScreen {
id: string;
blocks: PaywallBlock[];
}
interface PaywallConfigV1_1 {
version: PaywallConfigV1_1Version;
minSdkVersion?: string;
maxSdkVersion?: string;
theme?: PaywallTheme;
defaultLocale?: string;
localizations?: CreativeLocalizations;
startScreenId?: string;
screens: PaywallScreenV1_1[];
}
type CreativeLocalizations = Record<string, Record<string, string>>;
type PaywallScreenV1_1 = CreativeScreen<PaywallBlockV1_1>;
interface PaywallProductResponse {
id: string;
identifier: string;
product: ProductInfo;
productPrice: ProductPriceInfo | null;
prices?: Partial<Record<PaymentProvider, PriceInfo>>;
}
interface ProductInfo {
id: string;
identifier: string;
name: string;
description?: string | null;
pricingType: PricingType;
pricingPeriod: 'month' | 'year' | null;
}
interface ProductPriceInfo {
id: string;
provider: PaymentProvider;
platform: Platform | null;
providerProductId: string;
providerPriceId?: string | null;
currency?: string | null;
unitAmount?: number | null;
billingPeriod?: 'month' | 'year' | null;
trialOffer?: TrialOfferInfo | null;
}
type PaymentProvider = BillingProvider | PurchaseProvider;
interface PaywallProductOfferResponse {
identifier: string;
productIdentifier: string;
offerKind: ProductOfferKind;
offerMode?: AppleProductOfferMode | null;
duration?: string | null;
numberOfPeriods?: number | null;
autoRenews?: boolean | null;
prices: ProductOfferTerritoryPrice[];
regularPrice?: {
amountMinor: number;
currency: string;
billingPeriod?: 'month' | 'year' | null;
};
}
interface ProductOfferTerritoryPrice {
territory: string;
pricePointId: string;
customerPrice: string;
currency: string;
}
interface CampaignSelectionResponse {
placementId: string;
placementIdentifier: string;
campaignId?: string | null;
campaignIdentifier?: string | null;
campaignAudienceId?: string | null;
campaignAudienceIdentifier?: string | null;
campaignVariantId?: string | null;
campaignVariantIdentifier?: string | null;
campaignAssignmentId?: string | null;
targetType: import('../constants.js').CampaignVariantTargetType;
}
interface EntitlementCatalogResponse {
entitlements: Array<{
identifier: string;
name: string;
description: string | null;
metadata: Record<string, unknown>;
}>;
}
interface PlacementEvaluationResponse {
id: string;
identifier: string;
targetType: import('../constants.js').CampaignVariantTargetType;
campaign?: CampaignSelectionResponse;
paywall?: PaywallResponse;
inAppSurface?: InAppSurfaceResponse;
survey?: import('./surveys.js').SurveyResponse;
payload?: Record<string, unknown>;
}
interface InAppSurfaceResponse {
id: string;
identifier: string;
name: string;
description?: string | null;
placement: string;
config: AnyInAppSurfaceConfig;
}
type AnyInAppSurfaceConfig = InAppSurfaceConfigV1 | InAppSurfaceConfigV1_1;
interface InAppSurfaceConfig {
version: InAppSurfaceConfigV1Version;
presentation: InAppSurfacePresentation;
presentationOptions?: InAppSurfacePresentationOptions;
theme?: PaywallTheme;
startScreenId?: string;
screens: InAppSurfaceScreen[];
}
interface InAppSurfacePresentationOptions {
placement?: 'top' | 'center' | 'bottom';
backdropColor?: string;
darkBackdropColor?: string;
backdropOpacity?: number;
horizontalPadding?: number;
topPadding?: number;
bottomPadding?: number;
maxContentHeightPercent?: number;
}
interface InAppSurfaceScreen {
id: string;
blocks: InAppSurfaceBlock[];
}
type InAppSurfaceBlock = InAppSurfaceStackBlock | InAppSurfaceTextBlock | InAppSurfaceImageBlock | InAppSurfaceIconBlock | InAppSurfaceFeatureListBlock | InAppSurfaceSpacerBlock | InAppSurfaceDividerBlock | InAppSurfaceCarouselBlock | InAppSurfaceTabsBlock | InAppSurfaceSocialProofBlock | InAppSurfaceCountdownBlock | InAppSurfaceTimelineBlock | InAppSurfaceBottomBarBlock | InAppSurfaceButtonBlock;
interface InAppSurfaceConfigV1_1 {
version: InAppSurfaceConfigV1_1Version;
minSdkVersion?: string;
maxSdkVersion?: string;
presentation: InAppSurfacePresentation;
presentationOptions?: InAppSurfacePresentationOptionsV1_1;
theme?: PaywallTheme;
defaultLocale?: string;
localizations?: CreativeLocalizations;
startScreenId?: string;
screens: InAppSurfaceScreenV1_1[];
}
interface InAppSurfacePresentationOptionsV1_1 {
placement?: 'top' | 'center' | 'bottom';
backdropColor?: PaywallColor;
darkBackdropColor?: PaywallColor;
backdropOpacity?: number;
horizontalPadding?: number;
topPadding?: number;
bottomPadding?: number;
maxContentHeightPercent?: number;
}
type InAppSurfaceScreenV1_1 = CreativeScreen<InAppSurfaceBlockV1_1>;
type InAppSurfaceBlockV1_1 = CreativeStackBlock<InAppSurfaceBlockV1_1> | CreativeStickyFooterBlock<InAppSurfaceBlockV1_1> | CreativeCarouselBlock<InAppSurfaceBlockV1_1> | CreativeTabsBlock<InAppSurfaceBlockV1_1> | CreativeTextBlock | CreativeImageBlock | CreativeIconBlock | CreativeFeatureListBlock | CreativeTimelineBlock | CreativeSocialProofBlock | CreativeCountdownBlock | CreativeDividerBlock | CreativeSpacerBlock | CreativeButtonBlock<InAppSurfaceActionV1_1>;
interface CreativeTextBlock extends PaywallBlockBase {
type: 'text';
text: string;
style?: PaywallTextStyle;
color?: PaywallColor;
darkColor?: PaywallColor;
font?: PaywallTypography;
alignment?: PaywallTextAlignment;
}
interface CreativeImageBlock extends PaywallBlockBase {
type: 'image';
source: PaywallImageSource;
contentMode?: PaywallImageContentMode;
color?: PaywallColor;
darkColor?: PaywallColor;
}
interface CreativeIconBlock extends PaywallBlockBase {
type: 'icon';
systemName: string;
color?: PaywallColor;
darkColor?: PaywallColor;
size?: number;
font?: PaywallTypography;
}
interface CreativeFeatureListBlock extends PaywallBlockBase {
type: 'feature_list';
items: PaywallFeatureItem[];
iconStyle?: 'circle' | 'rounded' | 'plain';
iconSize?: PaywallSizeToken;
iconShape?: PaywallShapeToken;
iconCornerRadius?: number;
iconBackgroundOpacity?: number;
iconBorderWidth?: number;
iconBorderColor?: PaywallColor;
iconShadow?: PaywallShadow;
iconFont?: PaywallTypography;
titleFont?: PaywallTypography;
subtitleFont?: PaywallTypography;
gap?: number;
}
interface CreativeTimelineBlock extends PaywallBlockBase {
type: 'timeline';
items: PaywallTimelineItem[];
lineColor?: PaywallColor;
darkLineColor?: PaywallColor;
lineWidth?: number;
iconStyle?: 'circle' | 'rounded' | 'plain';
iconSize?: PaywallSizeToken;
iconShape?: PaywallShapeToken;
iconCornerRadius?: number;
iconBackgroundOpacity?: number;
iconBorderWidth?: number;
iconBorderColor?: PaywallColor;
iconShadow?: PaywallShadow;
iconFont?: PaywallTypography;
titleFont?: PaywallTypography;
subtitleFont?: PaywallTypography;
gap?: number;
}
interface CreativeSocialProofBlock extends PaywallBlockBase {
type: 'social_proof';
text: string;
icon?: string;
font?: PaywallTypography;
color?: PaywallColor;
darkColor?: PaywallColor;
iconColor?: PaywallColor;
darkIconColor?: PaywallColor;
iconSize?: number;
alignment?: PaywallTextAlignment;
}
interface CreativeCountdownBlock extends PaywallBlockBase {
type: 'countdown';
label?: string;
endsAt?: string;
durationSeconds?: number;
alignment?: PaywallTextAlignment;
labelColor?: PaywallColor;
darkLabelColor?: PaywallColor;
valueColor?: PaywallColor;
darkValueColor?: PaywallColor;
labelFont?: PaywallTypography;
valueFont?: PaywallTypography;
}
interface CreativeDividerBlock extends PaywallBlockBase {
type: 'divider';
axis?: PaywallDividerAxis;
size?: number;
thickness?: number;
color?: PaywallColor;
darkColor?: PaywallColor;
}
interface CreativeSpacerBlock extends PaywallBlockBase {
type: 'spacer';
axis?: PaywallDividerAxis;
size?: number;
}
interface CreativeStackBlock<TBlock> extends PaywallBlockBase {
type: 'stack';
axis?: CreativeStackAxis;
alignment?: PaywallStackAlignment;
distribution?: CreativeStackDistribution;
gap?: number;
overflow?: CreativeOverflowMode;
blocks: TBlock[];
}
interface CreativeStickyFooterBlock<TBlock> extends PaywallBlockBase {
type: 'sticky_footer';
material?: PaywallMaterial;
ignoresKeyboard?: boolean;
blocks: TBlock[];
}
interface CreativeCarouselBlock<TBlock> extends PaywallBlockBase {
type: 'carousel';
showIndicators?: boolean;
indicatorColor?: PaywallColor;
darkIndicatorColor?: PaywallColor;
selectedIndicatorColor?: PaywallColor;
darkSelectedIndicatorColor?: PaywallColor;
indicatorSize?: number;
indicatorSpacing?: number;
slides: PaywallCarouselSlide<TBlock>[];
}
interface CreativeTabsBlock<TBlock> extends PaywallBlockBase {
type: 'tabs';
selectedId?: string;
selectedBackgroundColor?: PaywallColor;
darkSelectedBackgroundColor?: PaywallColor;
unselectedBackgroundColor?: PaywallColor;
darkUnselectedBackgroundColor?: PaywallColor;
selectedColor?: PaywallColor;
darkSelectedColor?: PaywallColor;
unselectedColor?: PaywallColor;
darkUnselectedColor?: PaywallColor;
font?: PaywallTypography;
options: PaywallTabsOption<TBlock>[];
}
interface CreativeButtonBlock<TAction> extends PaywallBlockBase {
type: 'button';
text?: string;
systemName?: string;
action: TAction;
alignment?: PaywallTextAlignment;
contentAlignment?: PaywallButtonContentAlignment;
iconPlacement?: PaywallIconPlacement;
iconColor?: PaywallColor;
darkIconColor?: PaywallColor;
iconSize?: number;
color?: PaywallColor;
darkColor?: PaywallColor;
gradientColors?: [string, string];
font?: PaywallTypography;
}
interface SurveyResponse {
id: string;
identifier: string;
name: string;
revisionId: string;
collectionRound: number;
participationId: string;
reservationExpiresAt: string;
placement: string;
config: SurveyConfig;
campaign?: CampaignSelectionResponse;
/** Stable per presentation;
never randomize again during back navigation. */
choiceOrder: Record<string, string[]>;
}
interface SurveyConfig {
version: typeof SURVEY_CONFIG_VERSION;
theme?: PaywallTheme;
defaultLocale?: string;
localizations?: CreativeLocalizations;
screens: CreativeScreen<SurveyBlock>[];
/** Surveys follow screen order;
navigation controls cannot skip validation. */
thankYouMessage: string;
}
interface CreativeScreen<TBlock> {
id: string;
blocks: TBlock[];
}
type SurveyBlock = CreativeStackBlock<SurveyBlock> | CreativeStickyFooterBlock<SurveyBlock> | CreativeCarouselBlock<SurveyBlock> | CreativeTabsBlock<SurveyBlock> | CreativeTextBlock | CreativeImageBlock | CreativeIconBlock | CreativeFeatureListBlock | CreativeTimelineBlock | CreativeSocialProofBlock | CreativeCountdownBlock | CreativeDividerBlock | CreativeSpacerBlock | CreativeButtonBlock<SurveyAction> | SurveyQuestionBlock;
type SurveyAction = {
type: typeof SURVEY_ACTION_TYPES[number];
} & PaywallActionHaptics;
interface SurveyQuestionBlock extends PaywallBlockBase {
type: 'survey_question';
/** Block id is the permanent question ID;
labels are never answer identities. */
question: SurveyQuestion;
}
type SurveyQuestion = SurveyQuestionBase & ({
kind: 'single_choice';
choices: SurveyChoice[];
randomize: boolean;
allowOther: boolean;
otherLabel?: string;
} | {
kind: 'multiple_choice';
choices: SurveyChoice[];
randomize: boolean;
allowOther: boolean;
otherLabel?: string;
maxSelections: number;
} | {
kind: 'text';
placeholder?: string;
maxLength: number;
} | {
kind: 'rating';
min: number;
max: number;
minLabel?: string;
maxLabel?: string;
});
type AppleSyncError = {
transactionId: string;
originalTransactionId?: string;
error: string;
code: string;
stage: string;
retryable: boolean;
};
type EntitlementsMap = Record<string, EntitlementStatus>;
type EvidenceResult = { index: number;
status: (typeof APPLE_EVIDENCE_RESULTS)[number];
entitlementIdentifiers: string[];
expiresAt?: number | null };
type SdkRateLimitScope = 'app_device' | 'event_objects' | 'app_activity' | 'heavy_operations' | 'apple_payments' | 'app_fuse';
type IdEnvironment = 'test' | 'live';
interface AppleSearchAdsAttributionResponse {
status: 'success' | 'skipped_already_set' | 'not_attributed' | 'error';
reason?: string;
terminal: boolean;
retryable: boolean;
retryAfterSeconds?: number;
errorCode?: import('../constants.js').AppleAdsAttributionErrorCode;
attribution?: Record<string, unknown>;
}
interface ProductOfferRedemptionLinkResponse {
status: ProductOfferRedemptionLinkStatus;
offerIdentifier: string;
provider: ProductOfferProvider;
providerEnvironment: AppleProviderEnvironment;
providerProductIdentifier?: string;
operationId?: string;
redemptionUrl?: string;
codeExpiresAt?: string;
}
type ProductOfferRedemptionLinkStatus = 'ready' | 'already_redeemed';
interface SupportThreadPage {
threads: SupportThreadResponse[];
nextCursor: string | null;
}
interface SupportThreadResponse {
id: string;
customerId: string;
category: SupportThreadCategory;
subject: string;
status: SupportThreadStatus;
lastPublicAuthorType: SupportMessageAuthorType;
lastMessageAt: string;
lastCustomerMessageAt: string | null;
lastOperatorMessageAt: string | null;
hasUnreadReply?: boolean;
customerLastReadAt: string | null;
workspaceLastReadAt: string | null;
resolvedAt: string | null;
createdAt: string;
updatedAt: string;
}
interface SupportWriteResult {
thread: SupportThreadDetailResponse;
message: SupportMessageResponse;
created: boolean;
}
interface SupportThreadDetailResponse extends SupportThreadResponse {
messages: SupportMessageResponse[];
contact: SupportContactResponse;
}
interface SupportMessageResponse {
id: string;
threadId: string;
authorType: SupportMessageAuthorType;
platformUserId: string | null;
visibility: SupportMessageVisibility;
body: string;
content?: SupportContent;
contextSnapshot: SupportContextSnapshot | null;
attachments: SupportAttachmentResponse[];
createdAt: string;
}
interface SupportContent extends SupportContentInput {
blocks: SupportContentBlock[];
}
type SupportContentBlock = {
type: 'paragraph';
spans: SupportInlineSpan[];
} | {
type: 'bullet_list' | 'ordered_list';
items: SupportInlineSpan[][];
start?: number;
};
interface SupportContextSnapshot {
clientAccess?: import('../validation/access-observations.js').SupportClientAccess;
schemaVersion: 1;
capturedAt: string;
appId: string;
environment: 'test' | 'live';
customerId: string;
isAnonymous: boolean;
platform: Platform;
appVersion: string | null;
appBuild: string | null;
sdkVersion: string | null;
osVersion: string | null;
deviceModel: string | null;
locale: string | null;
country: string | null;
deviceIdHash: string | null;
entitlements: SupportEntitlementSnapshot[];
diagnostics: SupportDiagnostics;
diagnosticsAvailable: boolean;
}
interface SupportEntitlementSnapshot {
identifier: string;
name: string;
expiresAt: string | null;
}
type SupportDiagnostics = Record<string, SupportDiagnosticValue>;
interface SupportAttachmentResponse {
id: string;
fileName: string;
contentType: string;
byteSize: number;
downloadUrl: string;
createdAt: string;
}
interface SupportContactResponse {
email: string | null;
emailVerified: boolean;
emailManagedByAuth: boolean;
emailUnreachable: boolean;
emailNotificationsEnabled: boolean;
pushNotificationsEnabled: boolean;
}
interface SupportAttachmentUploadPreparation {
uploadToken: string;
uploadUrl: string;
expiresAt: string;
maxBytes: number;
}
interface CrashReportSummary {
id: string;
customerId: string;
reportId: string;
fingerprint: string;
appVersion: string;
buildNumber: string;
sdkVersion: string;
platform: 'ios';
osVersion: string;
deviceModel: string;
signalName: string | null;
signalCode: string | null;
exceptionName: string | null;
exceptionReason: string | null;
crashedThreadNumber: number | null;
frames: CrashReportFrame[];
occurredAt: string;
receivedAt: string;
}
interface CrashReportFrame {
imageName: string;
imageUUID: string | null;
imageOffset: string;
}
interface SurveyCatalogItem {
id: string;
identifier: string;
name: string;
status: SurveyStatus;
updatedAt: string;
revisionId: string;
config: SurveyConfig;
}
interface SurveySubmissionReceipt {
responseId: string;
submissionId: string;
status: 'accepted' | 'deduped';
}
type ProviderConnectionDto = ProviderConnection & {
hasSecret: boolean;
hasStoredSecret: boolean;
capabilities: ProviderCapabilities;
};
type ProviderCapabilities = {
accountDiscovery: boolean;
backgroundSync: boolean;
fileImports: boolean;
resourceActions: boolean;
capabilityKeys: readonly string[];
};
interface PreservedImportPolicy {
revision: string;
enabled: boolean;
entitlementIdentifier: string;
members: Array<{
grantId: string;
customerId: string;
}>;
}
type AgentAuthIdentityInspection = {
environment: IdEnvironment;
normalizedEmail: string;
identity: null | {
id: string;
email: string;
emailVerified: boolean;
createdAt: string;
updatedAt: string;
providers: Array<{
providerId: string;
accountCount: number;
hasPassword: boolean;
passwordUpdatedAt: string | null;
}>;
customerCount: number;
linkedAppIds: string[];
workspaceCustomerCount: number;
sessionCount: number;
activeSessionCount: number;
challengeCount: number;
activeChallengeCount: number;
deletionEligibility: {
eligible: boolean;
environment: 'test_only';
reasonCodes: string[];
};
};
};
interface IosReleaseReadinessReport {
version: '1.0';
generatedAt: string;
status: 'ready' | 'warnings' | 'blocked';
app: {
id: string;
name: string;
projectId: string;
environment: 'test' | 'live';
platform: string | null;
bundleId: string | null;
};
sdk: {
platform: 'ios';
version: string;
paywallConfigVersion: string;
inAppSurfaceConfigVersion: string;
};
summary: {
blockers: number;
warnings: number;
passes: number;
};
findings: IosReleaseReadinessFinding[];
apple: {
connectionId: string | null;
mappingId: string | null;
appStoreAppId: string | null;
products: IosReleaseReadinessAppleProduct[];
};
/** Canonical app fallback generated from current One database truth. */
appFallbackManifest: AppFallbackPaywallManifest | null;
}
interface IosReleaseReadinessFinding {
id: string;
domain: IosReleaseReadinessDomain;
severity: IosReleaseReadinessFindingSeverity;
status: IosReleaseReadinessFindingStatus;
message: string;
evidence?: Record<string, unknown>;
}
type IosReleaseReadinessDomain = 'app' | 'app_store_connect' | 'catalog' | 'entitlements' | 'offers' | 'paywalls' | 'placements' | 'campaigns' | 'surfaces' | 'app_fallback';
type IosReleaseReadinessFindingSeverity = 'blocker' | 'warning' | 'info';
type IosReleaseReadinessFindingStatus = 'pass' | 'fail' | 'needs_attention';
interface IosReleaseReadinessAppleProduct {
id: string;
productId: string;
name: string;
kind: 'in_app_purchase' | 'subscription';
state: string;
subscriptionGroupId?: string;
subscriptionPeriod?: string;
familySharable?: boolean;
introductoryOffers?: Array<{
id: string;
startDate?: string;
endDate?: string;
duration: string;
offerMode: string;
numberOfPeriods: number;
territory?: string;
}>;
}
interface AppFallbackPaywallManifest {
version: AppFallbackPaywallManifestVersion;
generatedForSdkVersion: string;
generatedAt?: string;
paywalls: AppFallbackPaywallEntry[];
}
interface AppFallbackPaywallEntry {
identifier: string;
placement?: string;
platform: Platform;
response: PaywallResponse;
}
interface LegacyCrashSignalSummary {
crashCount: number;
affectedCustomers: number;
firstSeenAt: string | null;
lastSeenAt: string | null;
versions: LegacyCrashSignalVersionSummary[];
}
interface LegacyCrashSignalVersionSummary {
appVersion: string | null;
crashCount: number;
affectedCustomers: number;
firstSeenAt: string;
lastSeenAt: string;
}
interface CrashReportGroup {
fingerprint: string;
appVersion: string;
buildNumber: string;
crashCount: number;
affectedCustomers: number;
firstSeenAt: string;
lastSeenAt: string;
signalName: string | null;
exceptionName: string | null;
representativeReportId: string;
}
interface CrashReportVersionSummary {
appVersion: string;
buildNumber: string;
crashCount: number;
groupCount: number;
affectedCustomers: number;
}
interface CrashReportBreakdownItem {
value: string;
crashCount: number;
}
interface CustomerAccessObservations {
observedAt: string;
retentionDays: number;
coverage: 'server_requests_only';
sdkPublication: 'not_reported' | 'reported';
sdkObservations?: Array<{
installationHash: string | null;
observation: import('../validation/access-observations.js').SDKAccessObservation | null;
}>;
appDecision: 'not_reported';
hasMore: boolean;
installations: Array<{
installationHash: string | null;
latestAttempt: AccessObservation | null;
lastSuccessfulVerification: AccessObservation | null;
lastVerifiedBenefits: AccessObservation | null;
latestFailure: AccessObservation | null;
detailUnavailable: boolean;
}>;
}
interface UsageReadPage {
records: UsageReadRecord[];
nextCursor: {
usageDate: string;
lastObservedAt: string;
id: string;
} | null;
outsideRetention: boolean;
timezone: 'UTC';
}
interface UsageReadRecord {
id: string;
kind: (typeof USAGE_RECORD_KINDS)[number];
usageDate: string;
/** Original telemetry owner, including a verified pre-merge alias. */
ownerCustomerId: string;
deviceModel: string | null;
osVersion: string | null;
producerId: string | null;
revision: string;
platform: string;
deviceIdHash: string;
sessionCount: number;
legacySessionBaseline: number;
legacyForegroundBaseline: number;
foregroundSeconds: number;
firstObservedAt: string;
lastObservedAt: string;
sessionId: string | null;
startedAt: string | null;
endedAt: string | null;
coverage: UsageCoverageState;
instrumentationRevision: string | null;
supportedMetrics: Array<{
key: string;
definitionRevision: number;
}>;
droppedMeasurementCount: number;
droppedDiagnosticCount: number;
endReason: (typeof USAGE_SESSION_END_REASONS)[number] | null;
measurements: UsageStoredMeasurement[];
diagnostics: z.infer<typeof usageDiagnosticSchema>[];
appVersion: string | null;
sdkVersion: string | null;
}
type UsageStoredMeasurement = Omit<UsageMeasurement, 'purchaseContext'> & {
purchaseTransactionId: string | null;
purchaseAttribution: (typeof USAGE_PURCHASE_ATTRIBUTION_STATES)[number];
};
interface UsageSummary {
evidenceScope: 'recorded_snapshots';
timezone: 'UTC';
from: string;
to: string;
completePageSet: boolean;
outsideRetention: boolean;
recordCount: number;
coverage: UsageCoverageState;
sessionCount: number | null;
foregroundSeconds: number | null;
deviceCount: number;
metrics: UsageMetricTotal[];
days: UsageDaySummary[];
}
interface UsageMetricTotal {
key: string;
definitionRevision: number;
scaledValue: string | null;
coverage: UsageCoverageState;
supportedRecords: number;
observedRecords: number;
}
interface UsageDaySummary {
usageDate: string;
coverage: UsageCoverageState;
sessionCount: number | null;
foregroundSeconds: number | null;
deviceCount: number;
firstObservedAt: string | null;
lastObservedAt: string | null;
metrics: UsageMetricTotal[];
diagnosticOccurrences: string | null;
droppedMeasurementCount: number;
droppedDiagnosticCount: number;
}
type AppStoreConnectProduct = {
id: string;
productId: string;
name: string;
kind: 'in_app_purchase' | 'subscription';
state: string;
subscriptionGroupId?: string;
inAppPurchaseType?: string;
subscriptionPeriod?: string;
familySharable?: boolean;
introductoryOffers?: AppStoreConnectIntroductoryOffer[];
};
type AppStoreConnectIntroductoryOffer = {
id: string;
startDate?: string;
endDate?: string;
duration: string;
offerMode: string;
numberOfPeriods: number;
territory?: string;
};
type AppStoreConnectCurrentPrice = {
territory: string;
source: 'manual' | 'automatic' | 'subscription';
pricePointId?: string;
pricePointKey?: string;
startDate?: string;
preserveCurrentPrice?: boolean;
};
type AppStoreConnectPricePoint = {
id: string;
territory: string;
customerPrice: string;
proceeds?: string;
proceedsYear2?: string;
};
type AppStorePricingPreview = {
planId: string;
expiresAt: string;
digest: string;
appId: string;
externalAppId: string;
productId: string;
productKind: AppStoreProductKind;
productResourceId: string;
effectiveDate: string;
subscriberPricePolicy?: AppStoreSubscriberPricePolicy;
strategy: AppStorePricingStrategyInput;
changes: AppStorePricingTerritoryChange[];
blockers: AppStorePricingBlocker[];
summary: {
territoryCount: number;
increases: number;
decreases: number;
unchanged: number;
newPrices: number;
};
};
type AppStorePricingStrategyInput = AppleEqualizedPricingStrategy | PurchasingPowerParityPricingStrategy | FourTierRegionalPricingStrategy;
type AppleEqualizedPricingStrategy = {
kind: 'apple_equalized';
referenceTerritory: string;
referencePricePointId: string;
};
type PurchasingPowerParityPricingStrategy = {
kind: 'purchasing_power_parity';
referenceTerritory: string;
referencePricePointId: string;
datasetVersion: string;
overrides?: AppStoreTerritoryPriceOverride[];
};
type AppStoreTerritoryPriceOverride = {
territory: string;
pricePointId: string;
};
type FourTierRegionalPricingStrategy = {
kind: 'four_tier_regional';
referenceTerritory: string;
classificationVersion: string;
pricePointIds: {
high: string;
upperMiddle: string;
lowerMiddle: string;
low: string;
};
overrides?: AppStoreTerritoryPriceOverride[];
};
type AppStorePricingTerritoryChange = {
territory: string;
currency: string;
currentPricePointId?: string;
currentCustomerPrice?: string;
targetPricePointId: string;
targetCustomerPrice: string;
direction: 'increase' | 'decrease' | 'unchanged' | 'new';
source: 'apple_equalization' | 'purchasing_power_parity' | 'income_tier' | 'manual_override';
sourceYear?: number;
};
type AppStorePricingBlocker = {
code: string;
message: string;
territory?: string;
};
interface ProductOfferProviderConfig {
version: ProductOfferProviderConfigVersion;
provider: ProductOfferProvider;
offerKind: ProductOfferKind;
productResourceId: string;
pricePointId?: string | null;
offerMode?: AppleProductOfferMode | null;
eligibility?: AppleProductOfferEligibility[];
duration?: string | null;
numberOfPeriods?: number | null;
territories?: string[];
prices?: ProductOfferTerritoryPrice[];
autoRenews?: boolean | null;
providerFacts?: Record<string, ProductOfferProviderFact>;
}
type AppStoreConnectOfferCode = {
id: string;
kind: ProductOfferKind;
productResourceId: string;
name: string;
customerEligibilities: string[];
active: boolean;
productionCodeCount: number;
sandboxCodeCount: number;
offerEligibility?: string;
duration?: string;
offerMode?: string;
numberOfPeriods?: number;
totalNumberOfCodes?: number;
autoRenewEnabled?: boolean;
targetSubscriptionPlanType?: string;
};
interface ProviderConnectionOperationData {
[key: string]: unknown;
}
type StoredOfferPlan = CreateOfferPlan | CreateBatchPlan | RefreshOfferPlan | DeactivateOfferPlan | DeactivateBatchPlan;
type CreateOfferPlan = OfferPlanBase & {
operation: 'create_offer';
productOfferId: string;
identifier: string;
productId: string;
productPriceId: string;
providerProductId: string;
providerProductResourceId: string;
referenceName: string;
exclusiveGroupIdentifier?: string;
terms: z.infer<typeof offerTermsSchema>;
existingProviderOfferIds: string[];
};
type OfferPlanBase = {
version: 1;
kind: 'apple_product_offer_mutation';
workspaceId: string;
appId: string;
connectionId: string;
accountId: string;
appMappingId: string;
externalAppId: string;
connectionUpdatedAt: string;
mappingUpdatedAt: string;
providerFingerprint: string;
blockers: Array<{ code: string;
message: string }>;
};
type CreateBatchPlan = ExistingOfferPlanBase & {
operation: 'create_batch';
batchId: string;
providerEnvironment: AppleProviderEnvironment;
requestedCodeCount: number;
expirationDate: string;
existingProviderBatchIds: string[];
};
type RefreshOfferPlan = ExistingOfferPlanBase & {
operation: 'refresh_offer';
priceSchedule: AppStoreConnectOfferPriceDetails[];
};
type AppStoreConnectOfferPriceDetails = AppStoreConnectOfferPrice & {
customerPrice: string;
currency: string;
};
type AppStoreConnectOfferPrice = {
territory: string;
pricePointId: string;
};
type DeactivateOfferPlan = ExistingOfferPlanBase & {
operation: 'deactivate_offer';
priceSchedule: AppStoreConnectOfferPriceDetails[];
};
type DeactivateBatchPlan = ExistingOfferPlanBase & {
operation: 'deactivate_batch';
batchId: string;
providerBatchId: string;
};
type AppStoreReviews = { reviews: AppStoreReview[];
complete: boolean;
fetchedAt: string };
type AppStoreReview = {
id: string;
rating: number;
title: string;
body: string;
reviewer: string;
createdDate: string;
territory: string;
};
type AnalyticsReportRequest = {
id: string;
accessType: AnalyticsAccessType;
stoppedDueToInactivity: boolean;
};
type AnalyticsAccessType = 'ONGOING' | 'ONE_TIME_SNAPSHOT';
type AnalyticsReport = {
id: string;
name: string;
category: string;
};
type AnalyticsReportInstance = {
id: string;
granularity: string;
processingDate: string;
};
interface WorkspaceSupportThreadListItem extends SupportThreadResponse {
appId: string;
appName: string;
environment: 'test' | 'live';
customerEmail: string | null;
needsReply: boolean;
workspaceMarkedUnreadAt: string | null;
labels: WorkspaceSupportLabel[];
}
type WorkspaceSupportLabel = {
id: string;
title: string;
color: SupportLabelColor;
sortOrder: number;
};
type AskOneContentBlock = AskOneSupportBlock | AskOneTextBlock | AskOneMetricSummaryBlock | AskOneTimeSeriesBlock | AskOneBreakdownBlock | AskOneCustomerCollectionBlock | AskOneTransactionCollectionBlock | AskOneTableBlock | AskOneComparisonBlock | AskOneResourceLinkBlock;
interface AskOneSupportBlock {
id: string;
type: 'support';
kind: 'evidence' | 'reply' | 'action';
title: string;
text: string;
appId: string;
threadId: string;
proposalId?: string;
data?: Record<string, unknown>;
}
interface AskOneTextBlock {
id: string;
type: 'text';
text: string;
}
interface AskOneMetricSummaryBlock {
id: string;
type: 'metric_summary';
title: string;
period: AskOnePeriod;
metrics: AskOneMetricItem[];
}
interface AskOnePeriod {
label: string;
startDate: string;
endDate: string;
}
interface AskOneMetricItem {
metricId: string;
label: string;
value: SemanticReportMetricValue;
comparison: AskOneMetricComparison | null;
}
type SemanticReportMetricValue = {
kind: 'count';
value: number;
} | {
kind: 'usd_cents';
value: number;
} | {
kind: 'seconds';
value: number;
} | {
kind: 'ratio';
numerator: number;
denominator: number;
} | {
kind: 'timestamp';
value: string;
};
interface AskOneMetricComparison {
referenceLabel: string;
changeRatio: number;
direction: AskOneComparisonDirection;
sentiment: AskOneComparisonSentiment;
}
interface AskOneTimeSeriesBlock {
id: string;
type: 'time_series';
title: string;
period: AskOnePeriod;
interval: SemanticReportInterval;
metric: {
metricId: string;
label: string;
};
total: SemanticReportMetricValue | null;
points: Array<{
bucket: string;
value: SemanticReportMetricValue;
}>;
}
interface AskOneBreakdownBlock {
id: string;
type: 'breakdown';
title: string;
period: AskOnePeriod;
dimensionId: string;
metric: {
metricId: string;
label: string;
};
items: Array<{
key: string;
label: string;
value: SemanticReportMetricValue;
}>;
}
interface AskOneCustomerCollectionBlock {
id: string;
type: 'customer_collection';
title: string;
period: AskOnePeriod;
items: Array<{
customerId: string;
appId: string;
title: string;
subtitle: string | null;
lifetimeValueUsdCents: number | null;
createdAt: string;
lastActivityAt: string | null;
}>;
continuation: AskOneContinuation | null;
}
interface AskOneContinuation {
sectionId: string;
cursor: string;
label: string;
}
interface AskOneTransactionCollectionBlock {
id: string;
type: 'transaction_collection';
title: string;
period: AskOnePeriod;
items: Array<{
transactionId: string;
appId: string;
customerId: string;
title: string;
subtitle: string;
amountUsdCents: number | null;
purchasedAt: string;
}>;
continuation: AskOneContinuation | null;
}
interface AskOneTableBlock {
id: string;
type: 'table';
title: string;
period: AskOnePeriod;
columns: Array<{
id: string;
label: string;
}>;
rows: Array<{
id: string;
cells: AskOneTableCellValue[];
}>;
}
type AskOneTableCellValue = {
kind: 'text';
value: string;
} | SemanticReportMetricValue;
interface AskOneComparisonBlock {
id: string;
type: 'comparison';
title: string;
primaryPeriod: AskOnePeriod;
referencePeriod: AskOnePeriod;
metrics: AskOneComparisonMetricItem[];
series: AskOneComparisonSeries[];
}
interface AskOneComparisonMetricItem {
metricId: string;
label: string;
primaryValue: SemanticReportMetricValue;
referenceValue: SemanticReportMetricValue;
changeRatio: number;
direction: AskOneComparisonDirection;
sentiment: AskOneComparisonSentiment;
}
interface AskOneComparisonSeries {
id: string;
label: string;
metric: {
metricId: string;
label: string;
};
points: Array<{
bucket: string;
value: SemanticReportMetricValue;
}>;
}
interface AskOneResourceLinkBlock {
id: string;
type: 'resource_link';
title: string;
route: {
kind: AskOneResourceLinkKind;
appId: string | null;
};
}
interface SurveyDeliverySettings {
maxPresentationsPerCustomer: number;
cooldownSeconds: number;
allowManualRepeats: boolean;
}
interface SurveyResultsPage {
summary: {
shown: number;
completed: number;
dismissed: number;
completionRate: number | null;
};
questionSummary?: {
revisionId: string;
questions: Array<{
id: string;
prompt: string;
answered: number;
choices?: Array<{
label: string;
count: number;
}>;
averageRating?: number | null;
}>;
};
responses: Array<{
id: string;
customerId: string;
revisionId: string;
collectionRound: number;
platform: string;
submittedAt: string;
answers: Array<{
questionId: string;
prompt: string;
values: string[];
}>;
}>;
nextCursor: string | null;
}
interface PurchaseHealthReport {
activity?: PurchaseActivityReport;
observedAt: string;
from: string;
through: string;
days: number;
observedIosCustomers: number;
sdkCustomers: number;
missingInstallationCustomers: number;
installations: number;
installationsWithBenefits: number;
installationsWithLoss: number;
customersWithLoss: number;
emptyWithoutAppleEvidence?: number;
currentlyEmptyAfterBenefits: number;
recoveredInstallations: number;
syncErrorCustomers: number;
syncErrorEvents: number;
serverRequests: number;
serverFailedRequests: number;
serverPartialRequests: number;
versions: Array<{
appVersion: string;
sdkVersion: string;
installations: number;
withBenefits: number;
withLoss: number;
emptyWithoutAppleEvidence?: number;
currentlyEmpty: number;
}>;
errors: Array<{
stage: string;
code: string;
customers: number;
reports: number;
}>;
affected: Array<{
customerId: string;
installationHash: string;
appVersion: string;
sdkVersion: string;
firstBenefitAt: string;
lastEmptyAt: string;
latestAt: string;
recovered: boolean;
lastEmptyHasAppleEvidence?: boolean;
lastEmptyVerification?: string;
recoveredAfterMs?: number | null;
}>;
affectedHasMore: boolean;
}
interface PurchaseActivityReport {
totals: PurchaseActivityCounts;
versions: Array<PurchaseActivityCounts & {
appVersion: string;
sdkVersion: string;
}>;
plans: Array<{
identifier: string;
name: string | null;
customers: number;
appVersion: string;
sdkVersion: string;
}>;
issues: Array<{
customerId: string;
appVersion: string;
eventType: string;
stage: string;
code: string;
httpStatus: number | null;
at: string;
accessAfterError: boolean;
}>;
issuesHasMore: boolean;
}
interface PurchaseActivityCounts {
purchaseAttempts: number;
appleCompleted: number;
purchaseErrors: number;
purchaseCancelled: number;
purchaseWaiting: number;
restoreAttempts: number;
restoreConfirmed: number;
restoreErrors: number;
restoreNoPurchase: number;
restoreCancelled: number;
restoreWaiting: number;
}
interface ReceiptPurchaseInspection {
verifiedAtCapture: boolean;
embeddedPurchaseCount?: number;
receiptCreatedAt?: string;
receiptAgeHoursAtCapture?: number;
currentPurchaserVerified?: false;
hasMore?: boolean;
reason?: string;
checks?: Array<{
productIdentifier: string;
appleVerified: boolean;
nonConsumable?: boolean;
revoked?: boolean;
expired?: boolean;
currentPurchaserVerified?: false;
reason?: string;
}>;
}
interface CapturedAppleFailure { code: string;
statusCode?: number;
cause?: CapturedAppleFailure }
type AcquisitionRecommendation = {
kind: AcquisitionRecommendationKind;
d30RoasBps: number | null;
targetRoasBps: number;
scaleAtBps: number;
reduceBelowBps: number;
reasons: string[];
warnings: string[];
};
type AcquisitionRecommendationKind = 'scale' | 'hold' | 'reduce' | 'insufficient_data';