Skip to content

Pricing types are stale: missing tiered pay-per-event and tiered pay-per-result, plus a wrong required flag #927

Description

@l2ysho

The pricing-related types in src/resource_clients/actor.ts are behind both the API and the Python client. As a result, TypeScript consumers reading eventPriceUsd or pricePerUnitUsd get a non-optional number and .toFixed(...) crashes on tiered Store Actors — surfaced downstream in
apify/apify-cli#1171.

Gaps (vs apify-client-python)

Field Python JS today Status
ActorChargeEvent.eventPriceUsd float | None = None number (required) wrong — crashes consumers
ActorChargeEvent.eventTieredPricingUsd dict[str, TieredPricingPerEventEntry] | None missing missing
ActorChargeEvent.isPrimaryEvent / isOneTimeEvent bool | None missing missing
PricePerDatasetItemActorPricingInfo.pricePerUnitUsd float | None = None number (required) wrong
PricePerDatasetItemActorPricingInfo.tieredPricing dict[str, TieredPricingPerDatasetItemEntry] | None missing missing
TieredPricingPerEventEntry dataclass missing missing
TieredPricingPerDatasetItemEntry dataclass missing missing
CommonActorPricingInfo.isPriceChangeNotificationSuppressed / forceContainsSignificantPriceChange bool | None missing missing

Within both ActorChargeEvent and PricePerDatasetItemActorPricingInfo, the flat field and the tiered field are mutually exclusive (per the API docs and the Python docstring).

Proposed changes

export interface TieredPricingPerEventEntry {
    tieredEventPriceUsd: number;
}

export interface TieredPricingPerDatasetItemEntry {
    tieredPricePerUnitUsd: number;
}

export interface ActorChargeEvent {
    eventTitle: string;
    eventDescription: string;
    /** Flat price per event in USD. Mutually exclusive with `eventTieredPricingUsd`. */
    eventPriceUsd?: number;
    /** Tier-keyed pricing. Mutually exclusive with `eventPriceUsd`. */
    eventTieredPricingUsd?: Record<string, TieredPricingPerEventEntry>;
    isPrimaryEvent?: boolean;
    isOneTimeEvent?: boolean;
}

export interface PricePerDatasetItemActorPricingInfo extends CommonActorPricingInfo {
    pricingModel: 'PRICE_PER_DATASET_ITEM';
    unitName: string;
    /** Flat price per unit in USD. Mutually exclusive with `tieredPricing`. */
    pricePerUnitUsd?: number;
    /** Tier-keyed pricing. Mutually exclusive with `pricePerUnitUsd`. */
    tieredPricing?: Record<string, TieredPricingPerDatasetItemEntry>;
}

interface CommonActorPricingInfo {
    apifyMarginPercentage: number;
    createdAt: Date;
    startedAt: Date;
    notifiedAboutFutureChangeAt?: Date;
    notifiedAboutChangeAt?: Date;
    reasonForChange?: string;
    isPriceChangeNotificationSuppressed?: boolean;
    forceContainsSignificantPriceChange?: boolean;
}

Repro

# Returns a tiered PAY_PER_EVENT actor — eventPriceUsd is undefined, eventTieredPricingUsd is set.
curl https://api.apify.com/v2/acts/lukaskrivka~google-maps-with-contact-details | jq '.data.pricingInfos[-1]'

Breaking change note

Making eventPriceUsd / pricePerUnitUsd optional is technically breaking — but the current types lie about the API. Any consumer that was reading them unguarded was already crashing at runtime on tiered actors (that's #1171). Worth flagging in the changelog.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    t-toolingIssues with this label are in the ownership of the tooling team.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions