From 2acb9c6840b9462ed757b4754741b692ae971525 Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Mon, 22 Sep 2025 12:24:29 +0200 Subject: [PATCH 01/28] docs: Add links to correct monetization docs --- .../actor-runs/actor-runs@{runId}@charge.yaml | 2 ++ sources/academy/ai/ai-agents.mdx | 6 ++++++ .../how_actor_monetization_works.md | 18 +++++++++++++++--- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/apify-api/openapi/paths/actor-runs/actor-runs@{runId}@charge.yaml b/apify-api/openapi/paths/actor-runs/actor-runs@{runId}@charge.yaml index 68e533057a..0d7b050428 100644 --- a/apify-api/openapi/paths/actor-runs/actor-runs@{runId}@charge.yaml +++ b/apify-api/openapi/paths/actor-runs/actor-runs@{runId}@charge.yaml @@ -7,6 +7,8 @@ post: The event you are charging for must be one of the configured events in your Actor. If the Actor is not set up as pay per event, or if the event is not configured, the endpoint will return an error. The endpoint must be called from the Actor run itself, with the same API token that the run was started with. + For more details about PPE pricing, see our [PPE documentation](/platform/actors/publishing/monetize/pay-per-event). + operationId: PostChargeRun parameters: - name: runId diff --git a/sources/academy/ai/ai-agents.mdx b/sources/academy/ai/ai-agents.mdx index 4e53884a28..157bf7ac66 100644 --- a/sources/academy/ai/ai-agents.mdx +++ b/sources/academy/ai/ai-agents.mdx @@ -251,6 +251,12 @@ Common issues and solutions: Apify's pay-per-event (PPE) pricing model allows charging users based on specific triggered events through the API or SDKs. +:::info How pay-per-event pricing works + +If you want more details about PPE pricing, please refer to our [PPE documentation](/platform/actors/publishing/monetize/pay-per-event). + +::: + ### Step 1: Define chargeable events You can configure charges for events like the Actor starting, a task completing successfully, or custom events such as specific API calls. diff --git a/sources/academy/platform/get_most_of_actors/store_basics/how_actor_monetization_works.md b/sources/academy/platform/get_most_of_actors/store_basics/how_actor_monetization_works.md index c7e986d1df..795b9a12d7 100644 --- a/sources/academy/platform/get_most_of_actors/store_basics/how_actor_monetization_works.md +++ b/sources/academy/platform/get_most_of_actors/store_basics/how_actor_monetization_works.md @@ -33,7 +33,11 @@ Monetizing your Actor on the Apify platform involves several key steps: - 2nd user starts their trial but pays next month. - 3rd user on a free plan finishes the trial without upgrading to a paid plan and can’t use the Actor further. -Learn more about the rental pricing model in our [documentation](/platform/actors/publishing/monetize#rental-pricing-model). +:::info Rental pricing details + +If you want more details about rental pricing, please refer to our [rental pricing documentation](/platform/actors/publishing/monetize/rental). + +::: ### Pay-per-result pricing model @@ -49,7 +53,11 @@ Learn more about the rental pricing model in our [documentation](/platform/actor - Dataset storage: $1 per 1,000 GB-hours - _Example_: you set a price of $1 per 1,000 results. Two users generate 50,000 and 20,000 results, paying $50 and $20, respectively. If the platform usage costs are $5 and $2, your profit is $49. -Learn more about the pay-per-result pricing model in our [documentation](/platform/actors/publishing/monetize#pay-per-result-pricing-model). +:::info Pay-per-result details + +If you want more details about PPR pricing, please refer to our [PPR documentation](/platform/actors/publishing/monetize/pay-per-result). + +::: ### Pay-per-event pricing model @@ -77,7 +85,11 @@ Learn more about the pay-per-result pricing model in our [documentation](/platfo - This comes up to $1.625 of total revenue - That means if platform usage costs are $0.365 for user A and $0.162 for user B your profit is $4.748 -Learn more about the pay-per-event pricing model in our [documentation](/platform/actors/publishing/monetize#pay-per-event-pricing-model). +:::info Pay-per-event details + +If you want more details about PPE pricing, please refer to our [PPE documentation](/platform/actors/publishing/monetize/pay-per-event). + +::: ## Setting up monetization From 659aab50a59df7e711b0b29dfdc59549212ab30a Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Mon, 22 Sep 2025 12:29:04 +0200 Subject: [PATCH 02/28] docs: Fix vale error --- .../store_basics/how_actor_monetization_works.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sources/academy/platform/get_most_of_actors/store_basics/how_actor_monetization_works.md b/sources/academy/platform/get_most_of_actors/store_basics/how_actor_monetization_works.md index 795b9a12d7..b212ee9611 100644 --- a/sources/academy/platform/get_most_of_actors/store_basics/how_actor_monetization_works.md +++ b/sources/academy/platform/get_most_of_actors/store_basics/how_actor_monetization_works.md @@ -116,7 +116,7 @@ The easiest way to understand your tool's value is to look around. Are there sim Try competitor tools yourself (to assess the value and the quality they provide), check their SEO (to see how much traffic they get), and note ballpark figures. Think about what your Actor can do that competitors might be missing. -Also, remember that your Actor is a package deal with the Apify platform. So all the platform's features automatically transfer onto your Actor and its value. Scheduling, monitoring runs, ways of exporting data, proxies, and integrations can all add value to your Actor (on top of its own functionalities). Be sure to factor this into your tool's value proposition and communicate that to the potential user. +Also, remember that your Actor is a package deal with the Apify platform. All the platform's features automatically transfer onto your Actor and its value. Scheduling, monitoring runs, ways of exporting data, proxies, and integrations can all add value to your Actor (on top of its own functionalities). Be sure to factor this into your tool's value proposition and communicate that to the potential user. ### Do research in Apify Store @@ -126,7 +126,7 @@ Learn more about what makes a good readme here: [How to create an Actor README]( ### Rental, pay-per-result (PPR), or pay-per-event (PPE) -Rental pricing is technically easier: you set the rental fee, and the user covers their CU usage. So all you have to define is how much you want to charge the users. With pay-per-result, you’ll need to include both CU usage and your margin. So you have to calculate how much the average run is going to cost for the user + define how much you want to charge them. +Rental pricing is technically easier: you set the rental fee, and the user covers their CU usage. All you have to define is how much you want to charge the users. With pay-per-result, you’ll need to include both CU usage and your margin. You have to calculate how much the average run is going to cost for the user + define how much you want to charge them. To figure out the average cost per run for users, just run a few test runs and look at the statistics in the Actor [**Analytics**](https://console.apify.com/actors?tab=analytics) tab. From 700fe942395b175fd8f1fde647cd2d3c357ae003 Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Wed, 24 Sep 2025 12:13:37 +0200 Subject: [PATCH 03/28] docs: Improve PPE examples, and add PPR vs PPE section --- .../publishing/monetize/pay_per_event.mdx | 179 +++++++++++++++--- .../publishing/monetize/pay_per_result.mdx | 85 +++++++-- 2 files changed, 227 insertions(+), 37 deletions(-) diff --git a/sources/platform/actors/publishing/monetize/pay_per_event.mdx b/sources/platform/actors/publishing/monetize/pay_per_event.mdx index fabacead53..d5985fde47 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_event.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_event.mdx @@ -191,6 +191,14 @@ If you want to use the synthetic start event, remove the existing start event fr Charge for things like URLs that appear valid but lead to errors (like 404s) since you had to open the page to discover the error. Return error items with proper error codes and messages instead of failing the entire Actor run. +:::info One call vs two calls + +The following code snippets show the single call option to both return error item and charge for the work done. + +If you prefer to return error item and charge for the work done in two calls, you can use the two calls option where you charge for the work done with `Actor.charge( ... )` and return the error item with `Actor.pushData( ... )`. + +::: + @@ -294,35 +302,158 @@ You can display a status message or push a record to the dataset to inform users If you're not using the Apify SDKs (JS/Python), you need to handle idempotency (ensuring the same operation produces the same result when called multiple times) manually to prevent charging the same event multiple times. -## Example of a PPE pricing model - -You make your Actor PPE and set the following pricing: +## Examples of a PPE pricing model + +### Example: simple PPE pricing + +- `scraped-product`: $0.01 per product - count every product record you return. +- `scraped-product-detail`: $0.05 per detail - count every enriched product detail you provide. + +#### Pricing breakdown by user + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
UserPlanEventsChargesTotalCost
1Paid plan +
1,000 × scraped-product
+
50 × scraped-product-detail
+
+
1,000 × $0.01 = $10.00
+
50 × $0.05 = $2.50
+
$12.50$3.20
2Paid plan +
500 × scraped-product
+
20 × scraped-product-detail
+
+
500 × $0.01 = $5.00
+
20 × $0.05 = $1.00
+
$6.00$1.50
3Free plan +
5 × scraped-product-detail
+
+
100 × $0.01 = $1.00
+
5 × $0.05 = $0.25
+
$1.25$0.40
+ +The platform usage costs are just examples, but you can see the actual costs in the [Computing your costs for PPE and PPR Actors](/platform/actors/publishing/monetize/pricing-and-costs#computing-your-costs-for-ppe-and-ppr-actors) section. + +#### Revenue breakdown + +- **Revenue (paid users only)**: $12.50 + $6.00 = **$18.50** +- **Underlying cost (paid users only)**: $3.20 + $1.50 = **$4.70** +- **Profit**: 0.8 × $18.50 − $4.70 = **$10.10** + +### Example: usage-indexed PPE pricing + + - `llm-token-cent`: $0.02 per $0.01 LLM spend - emit one event for each cent billed by your LLM provider. + +:::info Simplified example + +For the simplicity of the example, we show only the LLM-token-cent event. In reality, you can charge for any event you want. -- _`actor-start` event_: $0.10 per start -- _`scraped-product` event_: $0.01 per product -- _`scraped-product-detail` event_: $0.05 per detail -- _`ai-analysis` event_: $0.15 per analysis - -During the first month, three users use your Actor: - -- _User 1 (paid plan)_: Starts Actor 5 times, scrapes 1,000 products, makes 50 product details, runs 30 AI analyses - - Charges: 5 × $0.10 + 1,000 × $0.01 + 50 × $0.05 + 30 × $0.15 = $0.50 + $10.00 + $2.50 + $4.50 = $17.50 -- _User 2 (paid plan)_: Starts Actor 2 times, scrapes 500 products, makes 20 product details, runs 10 AI analyses - - Charges: 2 × $0.10 + 500 × $0.01 + 20 × $0.05 + 10 × $0.15 = $0.20 + $5.00 + $1.00 + $1.50 = $7.70 -- _User 3 (free plan)_: Starts Actor 1 time, scrapes 100 products, makes 5 product details, runs 3 AI analyses - - Charges: 1 × $0.10 + 100 × $0.01 + 5 × $0.05 + 3 × $0.15 = $0.10 + $1.00 + $0.25 + $0.45 = $1.80 - -Let's say the underlying platform usage for the first user is $3.20, for the second $1.50, and for the third $0.40. - -Your profit is computed only from the first two users, since they are on Apify paid plans. The revenue breakdown is: +::: -- _Total revenue_: $17.50 + $7.70 = $25.20 -- _Total underlying cost_: $3.20 + $1.50 = $4.70 -- _Your profit_: 80% of revenue minus costs = 0.8 × $25.20 - $4.70 = $15.46 +#### Pricing breakdown by user + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
UserPlanEventsChargesTotalCost
1Paid plan +
$25.40 LLM usage:
+
2,540 × llm-token-cent
+
+
2,540 × $0.02 = $50.80
+
$50.80$2.60
2Paid plan +
$12.10 LLM usage:
+
1,210 × llm-token-cent
+
+
1,210 × $0.02 = $24.20
+
$24.20$1.20
3Free plan +
$3.90 LLM usage:
+
390 × llm-token-cent
+
+
390 × $0.02 = $7.80
+
$7.80$0.35
+ +The platform usage costs are just examples, but you can see the actual costs in the [Computing your costs for PPE and PPR Actors](/platform/actors/publishing/monetize/pricing-and-costs#computing-your-costs-for-ppe-and-ppr-actors) section. + +#### Revenue breakdown + +- **Revenue (paid users only)**: $50.80 + $24.20 = **$75.00** +- **Underlying cost (paid users only)**: $2.60 + $1.20 = **$3.80** +- **Profit**: 0.8 × $75.00 − $3.80 = **$56.20** + +This example illustrates the key trade-off of PPE pricing: while it's harder for users to predict exact costs upfront, it provides developers with a safer and more scalable revenue model that grows with actual usage. ## Event names -To implement PPE pricing, you need to define specific events in your Actor code. You can retrieve the list of available pricing event names using the [Get Actor](https://apify.com/docs/api/v2/act-get) API endpoint. +If you need to know your event names, you can retrieve the list of available pricing event names using the [Get Actor](https://apify.com/docs/api/v2/act-get) API endpoint. ## Next steps diff --git a/sources/platform/actors/publishing/monetize/pay_per_result.mdx b/sources/platform/actors/publishing/monetize/pay_per_result.mdx index 09ceea1331..3dbe2efe5f 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_result.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_result.mdx @@ -35,6 +35,16 @@ where: Only revenue and cost for Apify customers on paid plans are taken into consideration when computing your profit. Users on free plans are not reflected there. +## PPR vs PPE + +PPR charges based on the number of results produced. PPE lets you define pricing for individual events, and help you to make your pricing more flexible. You can charge for specific events directly from your Actor by calling the PPE charging API. + +:::info Learn more about PPE + +If you want to learn more about PPE, please refer to the [Pay per event](/platform/actors/publishing/monetize/pay-per-event) section. + +::: + ## Best practices for PPR Actors To ensure profitability, check the following best practices. @@ -201,19 +211,68 @@ This ensures that every run generates at least one result, guaranteeing that use ## Example of PPR pricing model -You make your Actor PPR and set the price to be _$1/1,000 results_. During the first month, three users use your Actor: - -- _User 1 (paid plan)_: Gets 50,000 results, costing them $50 -- _User 2 (paid plan)_: Gets 20,000 results, costing them $20 -- _User 3 (free plan)_: Gets 5,000 results, costing them $0 - -Let's say the underlying platform usage for the first user is $5, for the second $2, and for the third $0.5. - -Your profit is computed only from the first two users, since they are on Apify paid plans. The revenue breakdown is: - -- _Total revenue_: $50 + $20 = $70 -- _Total underlying cost_: $5 + $2 = $7 -- _Your profit_: 80% of revenue minus costs = 0.8 × $70 - $7 = $49 +You make your Actor PPR and set the price to be _$1/1,000 results_. During the first month, three users use your Actor. + +#### Pricing breakdown by user + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
UserPlanResultsChargesTotalCost
1Paid plan +
50,000 results
+
+
50,000 ÷ 1,000 × $1.00 = $50.00
+
$50.00$5.00
2Paid plan +
20,000 results
+
+
20,000 ÷ 1,000 × $1.00 = $20.00
+
$20.00$2.00
3Free plan +
5,000 results
+
+
5,000 ÷ 1,000 × $1.00 = $5.00
+
$0.00$0.50
+ +The platform usage costs are just examples, but you can see the actual costs in the [Computing your costs for PPE and PPR Actors](/platform/actors/publishing/monetize/pricing-and-costs#computing-your-costs-for-ppe-and-ppr-actors) section. + +#### Revenue breakdown + +- **Revenue (paid users only)**: $50.00 + $20.00 = **$70.00** +- **Underlying cost (paid users only)**: $5.00 + $2.00 = **$7.00** +- **Profit**: 0.8 × $70.00 − $7.00 = **$49.00** ## Next steps From 37bc453a655b012b4e7e04462ca939f8a59fdeed Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Wed, 24 Sep 2025 14:31:09 +0200 Subject: [PATCH 04/28] docs: Improve synthetic start docs --- .../publishing/monetize/pay_per_event.mdx | 48 +++++++++++-------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/sources/platform/actors/publishing/monetize/pay_per_event.mdx b/sources/platform/actors/publishing/monetize/pay_per_event.mdx index d5985fde47..5125154720 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_event.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_event.mdx @@ -132,33 +132,21 @@ When using [Crawlee](https://crawlee.dev/), use `crawler.autoscaledPool.abort()` ## Best practices for PPE Actors -Use our SDKs ([JS](/sdk/js/) and, [Python](/sdk/python/) or use [`apify actor charge`](/cli/docs/next/reference#apify-actor-charge-eventname) when using our Apify CLI) to simplify PPE implementation into your Actor. This tool can handle pricing, usage tracking, idempotency keys, API errors, and, event charging via an API. +Use our SDKs ([JS](/sdk/js/) and, [Python](/sdk/python/) or use [`apify actor charge`](/cli/docs/next/reference#apify-actor-charge-eventname) when using our Apify CLI) to simplify PPE implementation into your Actor. SDKs help you handle pricing, usage tracking, idempotency keys, API errors, and, event charging via an API. You can also choose not to use it, but then you must handle API integration and possible edge cases manually. -You can also choose not to use it, but then you must handle API integration and possible edge cases manually. - -### Set memory limits - -Set memory limits using `minMemoryMbytes` and `maxMemoryMbytes` in your [`actor.json`](https://docs.apify.com/platform/actors/development/actor-definition/actor-json) file to control platform usage costs. - -```json -{ - "actorSpecification": 1, - "name": "name-of-my-scraper", - "version": "0.0", - "minMemoryMbytes": 512, - "maxMemoryMbytes": 1024, -} -``` +### Use synthetic start event `apify-actor-start` -:::note Memory requirements for browser-based scraping +:::info TL;DR: -When using browser automation tools like Puppeteer or Playwright for web scraping, increase the memory limits to accommodate the browser's memory usage. +We recommend using the synthetic Actor start event in PPE Actors. It benefits both you and your users. ::: -### Use synthetic start event `apify-actor-start` +Starting an Actor takes time, and creates additional cost for the Actor creator, because the profit equals revenue minus platform costs. -This event is automatically charged by the Apify platform when an Actor is started or resurrected. +One of the options to charge for the time spent on starting the Actor is to charge an “Actor start” event. Let’s say $1 for 1000 Actor starts. Unfortunately, this makes your Actor comparably expensive with other tools on the market (outside of [Apify Store](/platform/console/store)) that do not incur this startup cost. + +We want to make it easier for Apify Store creators to stay competitive. To do that, we have the Apify Actor synthetic start event `apify-actor-start`. Users of your Actor are charged one event for each GB of memory used by the Actor (at least one event per run). We _strongly_ suggest setting the price of this event to $0.0001 to remain competitive in the Store and attractive for your customers. If you define this event, you also save 5 seconds of Actor runtime from each Actor run, which won't be deducted from your payout profits. @@ -187,6 +175,26 @@ Your Actor might already have a start event defined, such as `actor-start` or an If you want to use the synthetic start event, remove the existing start event from your Actor and add the synthetic start event in Apify Console. +### Set memory limits + +Set memory limits using `minMemoryMbytes` and `maxMemoryMbytes` in your [`actor.json`](https://docs.apify.com/platform/actors/development/actor-definition/actor-json) file to control platform usage costs. + +```json +{ + "actorSpecification": 1, + "name": "name-of-my-scraper", + "version": "0.0", + "minMemoryMbytes": 512, + "maxMemoryMbytes": 1024, +} +``` + +:::note Memory requirements for browser-based scraping + +When using browser automation tools like Puppeteer or Playwright for web scraping, increase the memory limits to accommodate the browser's memory usage. + +::: + ### Charge for invalid input Charge for things like URLs that appear valid but lead to errors (like 404s) since you had to open the page to discover the error. Return error items with proper error codes and messages instead of failing the entire Actor run. From 217d341ce10f88da23bfe9531e5ce08303b0e784 Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Wed, 24 Sep 2025 14:56:13 +0200 Subject: [PATCH 05/28] docs: Remove PPR store visibility --- sources/platform/actors/publishing/monetize/index.mdx | 2 +- .../platform/actors/publishing/monetize/pay_per_result.mdx | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/sources/platform/actors/publishing/monetize/index.mdx b/sources/platform/actors/publishing/monetize/index.mdx index 5e0d8d9e1d..78a9c3ddfc 100644 --- a/sources/platform/actors/publishing/monetize/index.mdx +++ b/sources/platform/actors/publishing/monetize/index.mdx @@ -35,7 +35,7 @@ The following table compares the two main pricing models available for monetizin | AI/MCP compatibility | ❌ Not compatible | ✅ Fully compatible | ✅ Fully compatible | | User cost predictability| Unpredictable (rental + usage) | Predictable | Predictable | | Store discounts | ❌ Single price only | ✅ Store discounts available | ✅ Store discounts available | -| Marketing boost | Standard visibility | Priority store placement | Priority store placement | +| Marketing boost | Standard visibility | Standard visibility | Priority store placement | | Commission opportunities| Standard 20% | Standard 20% | Promotional 0% periods | | Custom event billing | Not available | Not available | ✅ Charge for any event | | Per-result billing | Not available | ✅ Charge per dataset item | Optional (via event) | diff --git a/sources/platform/actors/publishing/monetize/pay_per_result.mdx b/sources/platform/actors/publishing/monetize/pay_per_result.mdx index 3dbe2efe5f..0e4f3ed889 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_result.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_result.mdx @@ -16,12 +16,6 @@ In this model, you set a price per 1,000 results. Users are charged based on the The details on how your cost is computed can be found in [Example of a PPR pricing model](#example-of-a-ppr-pricing-model). -:::tip Additional benefits - -Actors that implement PPR pricing receive additional benefits, including increased visibility in Apify Store and enhanced discoverability for users looking for monetized solutions. - -::: - ## How is profit computed Your profit is calculated from the mentioned formula: From f493b6ac8bae36341443afaf9c6d8c060d4008ea Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Wed, 24 Sep 2025 15:27:50 +0200 Subject: [PATCH 06/28] docs: Synthetic start event improvements --- .../publishing/monetize/pay_per_event.mdx | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/sources/platform/actors/publishing/monetize/pay_per_event.mdx b/sources/platform/actors/publishing/monetize/pay_per_event.mdx index 5125154720..a1bb1913c6 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_event.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_event.mdx @@ -144,20 +144,22 @@ We recommend using the synthetic Actor start event in PPE Actors. It benefits bo Starting an Actor takes time, and creates additional cost for the Actor creator, because the profit equals revenue minus platform costs. -One of the options to charge for the time spent on starting the Actor is to charge an “Actor start” event. Let’s say $1 for 1000 Actor starts. Unfortunately, this makes your Actor comparably expensive with other tools on the market (outside of [Apify Store](/platform/console/store)) that do not incur this startup cost. +One of the options to charge for the time spent on starting the Actor is to charge an “Actor start” event. Let’s say $1 for 1000 Actor starts. Unfortunately, this makes your Actor comparably expensive with other tools on the market (outside of [Apify Store](/platform/console/store)) that do not incur this startup cost. -We want to make it easier for Apify Store creators to stay competitive. To do that, we have the Apify Actor synthetic start event `apify-actor-start`. +We want to make it easier for Actor creators to stay competitive, but also help them to be profitable. Therefore, we have the Apify Actor synthetic start event `apify-actor-start`. -Users of your Actor are charged one event for each GB of memory used by the Actor (at least one event per run). We _strongly_ suggest setting the price of this event to $0.0001 to remain competitive in the Store and attractive for your customers. If you define this event, you also save 5 seconds of Actor runtime from each Actor run, which won't be deducted from your payout profits. +#### How the synthetic start event works -:::note Automatic charging of synthetic start event - -You must _not_ manually charge for the synthetic start event (`apify-actor-start`) in your Actor code. - -If you attempt to charge this event yourself, the operation will fail. -This event is _always_ charged automatically by the Apify platform whenever your Actor starts or is resurrected. - -::: +- The Apify Actor start event is **automatically enabled** for all new PPE Actors. For existing Actors, you can enable it in Apify Console. +- Apify **automatically charges** the event. + - You must _not_ manually charge for the synthetic start event (`apify-actor-start`) in your Actor code. If you attempt to charge this event yourself, the operation will fail. +- The price of the event is **$0.00005**, which equals **$0.05 per 1,000 starts**. +- The number of events charged **depends on the memory** of the Actor run. Up to and including 1 GB of RAM, the event is charged once. Then it's charged once for each extra GB of memory. For example: + - 128 MB RAM: 1 event, $0.00005 + - 1 GB RAM: 1 event, $0.00005 + - 4 GB RAM: 4 events, $0.0002 +- You can increase the price of the event if you wish, but you **won't get more free compute**. +- You can delete the event if you wish, but if you do, you will **lose the free 5 seconds** of compute. #### Synthetic start event for new Actors @@ -167,13 +169,13 @@ For new Actors, this event is added automatically as you can see on the followin #### Synthetic start event for existing Actors -If you have existing Actors, you can add this event manually in Apify Console. +If you have existing Actors, you can add this event manually in Apify Console in the Publication tab. #### Synthetic start event for Actors with start event Your Actor might already have a start event defined, such as `actor-start` or another variant of the event name. In this case, you can choose whether to use the synthetic start event or keep the existing start event. -If you want to use the synthetic start event, remove the existing start event from your Actor and add the synthetic start event in Apify Console. +If you want to use the synthetic start event, remove the existing start event from your Actor and add the synthetic start event in Apify Console in the Publication tab. ### Set memory limits From ee82af0908b6d5522c8733c09bd7f1f09432861e Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Wed, 24 Sep 2025 15:39:18 +0200 Subject: [PATCH 07/28] docs: Fix lint errors --- .../actors/publishing/monetize/pay_per_event.mdx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sources/platform/actors/publishing/monetize/pay_per_event.mdx b/sources/platform/actors/publishing/monetize/pay_per_event.mdx index a1bb1913c6..7afe8d8536 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_event.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_event.mdx @@ -142,22 +142,22 @@ We recommend using the synthetic Actor start event in PPE Actors. It benefits bo ::: -Starting an Actor takes time, and creates additional cost for the Actor creator, because the profit equals revenue minus platform costs. +Starting an Actor takes time, and creates additional cost for the Actor creator, because the profit equals revenue minus platform costs. -One of the options to charge for the time spent on starting the Actor is to charge an “Actor start” event. Let’s say $1 for 1000 Actor starts. Unfortunately, this makes your Actor comparably expensive with other tools on the market (outside of [Apify Store](/platform/console/store)) that do not incur this startup cost. +One of the options to charge for the time spent on starting the Actor is to charge an “Actor start” event. Let’s say $1 for 1000 Actor starts. Unfortunately, this makes your Actor comparably expensive with other tools on the market (outside of [Apify Store](/platform/console/store)) that do not incur this startup cost. We want to make it easier for Actor creators to stay competitive, but also help them to be profitable. Therefore, we have the Apify Actor synthetic start event `apify-actor-start`. #### How the synthetic start event works - The Apify Actor start event is **automatically enabled** for all new PPE Actors. For existing Actors, you can enable it in Apify Console. -- Apify **automatically charges** the event. - - You must _not_ manually charge for the synthetic start event (`apify-actor-start`) in your Actor code. If you attempt to charge this event yourself, the operation will fail. +- Apify **automatically charges** the event. + - You must _not_ manually charge for the synthetic start event (`apify-actor-start`) in your Actor code. If you attempt to charge this event yourself, the operation will fail. - The price of the event is **$0.00005**, which equals **$0.05 per 1,000 starts**. - The number of events charged **depends on the memory** of the Actor run. Up to and including 1 GB of RAM, the event is charged once. Then it's charged once for each extra GB of memory. For example: - - 128 MB RAM: 1 event, $0.00005 - - 1 GB RAM: 1 event, $0.00005 - - 4 GB RAM: 4 events, $0.0002 + - 128 MB RAM: 1 event, $0.00005 + - 1 GB RAM: 1 event, $0.00005 + - 4 GB RAM: 4 events, $0.0002 - You can increase the price of the event if you wish, but you **won't get more free compute**. - You can delete the event if you wish, but if you do, you will **lose the free 5 seconds** of compute. @@ -413,7 +413,7 @@ For the simplicity of the example, we show only the LLM-token-cent event. In rea 1 Paid plan -
$25.40 LLM usage:
+
$25.40 LLM usage:
2,540 × llm-token-cent
From ba9a1585a6564d3ad3451f03b755c87e8a0a0403 Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Wed, 24 Sep 2025 15:43:47 +0200 Subject: [PATCH 08/28] docs: Fix lint errors --- sources/platform/actors/publishing/monetize/pay_per_event.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/platform/actors/publishing/monetize/pay_per_event.mdx b/sources/platform/actors/publishing/monetize/pay_per_event.mdx index 7afe8d8536..1d30362f97 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_event.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_event.mdx @@ -387,7 +387,7 @@ The platform usage costs are just examples, but you can see the actual costs in ### Example: usage-indexed PPE pricing - - `llm-token-cent`: $0.02 per $0.01 LLM spend - emit one event for each cent billed by your LLM provider. +- `llm-token-cent`: $0.02 per $0.01 LLM spend - emit one event for each cent billed by your LLM provider. :::info Simplified example From b0c5662cd131b77c578893879424542a98c20534 Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Wed, 24 Sep 2025 15:47:35 +0200 Subject: [PATCH 09/28] docs: Fix lint errors --- .../platform/actors/publishing/monetize/pay_per_result.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sources/platform/actors/publishing/monetize/pay_per_result.mdx b/sources/platform/actors/publishing/monetize/pay_per_result.mdx index 0e4f3ed889..79627d7650 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_result.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_result.mdx @@ -31,7 +31,7 @@ Only revenue and cost for Apify customers on paid plans are taken into considera ## PPR vs PPE -PPR charges based on the number of results produced. PPE lets you define pricing for individual events, and help you to make your pricing more flexible. You can charge for specific events directly from your Actor by calling the PPE charging API. +PPR charges based on the number of results produced. PPE lets you define pricing for individual events, and help you to make your pricing more flexible. You can charge for specific events directly from your Actor by calling the PPE charging API. :::info Learn more about PPE @@ -207,7 +207,7 @@ This ensures that every run generates at least one result, guaranteeing that use You make your Actor PPR and set the price to be _$1/1,000 results_. During the first month, three users use your Actor. -#### Pricing breakdown by user +### Pricing breakdown by user @@ -262,7 +262,7 @@ You make your Actor PPR and set the price to be _$1/1,000 results_. During the f The platform usage costs are just examples, but you can see the actual costs in the [Computing your costs for PPE and PPR Actors](/platform/actors/publishing/monetize/pricing-and-costs#computing-your-costs-for-ppe-and-ppr-actors) section. -#### Revenue breakdown +### Revenue breakdown - **Revenue (paid users only)**: $50.00 + $20.00 = **$70.00** - **Underlying cost (paid users only)**: $5.00 + $2.00 = **$7.00** From 91246aecddb5d82330805b7316d6e7026fc7842b Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Wed, 24 Sep 2025 16:01:14 +0200 Subject: [PATCH 10/28] docs: Remove unncessary sentence --- sources/platform/actors/publishing/monetize/pay_per_event.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/platform/actors/publishing/monetize/pay_per_event.mdx b/sources/platform/actors/publishing/monetize/pay_per_event.mdx index 1d30362f97..387f4a793c 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_event.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_event.mdx @@ -20,7 +20,7 @@ The details on how your cost is computed can be found in [Example of a PPE prici :::tip Additional benefits -Actors that implement PPE pricing receive additional benefits, including increased visibility in Apify Store and enhanced discoverability for users looking for monetized solutions. +Actors that implement PPE pricing receive additional benefits, including increased visibility in Apify Store and enhanced discoverability. ::: From db2abc1577bb420d793e3f6efeb6b857cc18445e Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Wed, 24 Sep 2025 16:11:38 +0200 Subject: [PATCH 11/28] docs: Improve sentece regarding to free compute --- .../platform/actors/publishing/monetize/pay_per_event.mdx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sources/platform/actors/publishing/monetize/pay_per_event.mdx b/sources/platform/actors/publishing/monetize/pay_per_event.mdx index 387f4a793c..3fd83d7ba0 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_event.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_event.mdx @@ -144,9 +144,11 @@ We recommend using the synthetic Actor start event in PPE Actors. It benefits bo Starting an Actor takes time, and creates additional cost for the Actor creator, because the profit equals revenue minus platform costs. -One of the options to charge for the time spent on starting the Actor is to charge an “Actor start” event. Let’s say $1 for 1000 Actor starts. Unfortunately, this makes your Actor comparably expensive with other tools on the market (outside of [Apify Store](/platform/console/store)) that do not incur this startup cost. +One of the options to charge for the time spent on starting the Actor is to charge an “Actor start” event. Unfortunately, this makes your Actor comparably expensive with other tools on the market (outside of [Apify Store](/platform/console/store)) that do not incur this startup cost. -We want to make it easier for Actor creators to stay competitive, but also help them to be profitable. Therefore, we have the Apify Actor synthetic start event `apify-actor-start`. +We want to make it easier for Actor creators to stay competitive, but also help them to be profitable. Therefore, we have the Apify Actor synthetic start event `apify-actor-start`. This event is enabled by default for all new PPE Actors, and when you use it Apify will cover the compute unit cost of the first 5 seconds of every Actor run. + +The default price of the event is set intentionally low. This pricing means that the free 5 seconds of compute we provide costs us more than the revenue generated from the event. We've made this investment to **support our creator community** by reducing your startup costs while keeping your Actors competitively priced for users. #### How the synthetic start event works From b0bef86073ce4acb1343b7edeb788d3a0bbec415 Mon Sep 17 00:00:00 2001 From: Patrik Braborec Date: Wed, 24 Sep 2025 16:56:02 +0200 Subject: [PATCH 12/28] Update apify-api/openapi/paths/actor-runs/actor-runs@{runId}@charge.yaml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Lukáš Křivka --- .../openapi/paths/actor-runs/actor-runs@{runId}@charge.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apify-api/openapi/paths/actor-runs/actor-runs@{runId}@charge.yaml b/apify-api/openapi/paths/actor-runs/actor-runs@{runId}@charge.yaml index 0d7b050428..73acee1f12 100644 --- a/apify-api/openapi/paths/actor-runs/actor-runs@{runId}@charge.yaml +++ b/apify-api/openapi/paths/actor-runs/actor-runs@{runId}@charge.yaml @@ -7,7 +7,7 @@ post: The event you are charging for must be one of the configured events in your Actor. If the Actor is not set up as pay per event, or if the event is not configured, the endpoint will return an error. The endpoint must be called from the Actor run itself, with the same API token that the run was started with. - For more details about PPE pricing, see our [PPE documentation](/platform/actors/publishing/monetize/pay-per-event). + For more details about pay-per-event (PPE) pricing, see our [PPE documentation](/platform/actors/publishing/monetize/pay-per-event). operationId: PostChargeRun parameters: From 27d5fd5a15ab739160f61e5ba1e66f0cd50b46eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludv=C3=ADk=20Prokopec?= <39367469+lewis-wow@users.noreply.github.com> Date: Thu, 25 Sep 2025 10:02:56 +0200 Subject: [PATCH 13/28] docs: update actor tagged builds manually (#1945) This PR updates the API documentation to reflect that tagged builds can now be modified manually via the public API. --- .../schemas/actors/UpdateActorRequest.yaml | 21 +++++++++++++++++++ .../actors/running/runs_and_builds.md | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/apify-api/openapi/components/schemas/actors/UpdateActorRequest.yaml b/apify-api/openapi/components/schemas/actors/UpdateActorRequest.yaml index 67fe295422..46a67727f2 100644 --- a/apify-api/openapi/components/schemas/actors/UpdateActorRequest.yaml +++ b/apify-api/openapi/components/schemas/actors/UpdateActorRequest.yaml @@ -50,3 +50,24 @@ properties: oneOf: - nullable: true - $ref: ./DefaultRunOptions.yaml + taggedBuilds: + type: object + description: | + Object containing the Actor's tagged builds, where the key is the tag name (e.g., _latest_) and the value is an object containing the build ID. + The object you provide will completely overwrite all existing tagged builds for the Actor. + + - To create or reassign a tag: Include it in the object with the desired `buildId`. + - To remove a specific tag: Submit the object without that tag's key. + - To remove all tags: Provide an empty object: `{}`. + - If this field is omitted or `null`, the existing tags will not be changed. + nullable: true + additionalProperties: + type: object + required: + - buildId + properties: + buildId: + type: string + example: + latest: + buildId: z2EryhbfhgSyqj6Hn diff --git a/sources/platform/actors/running/runs_and_builds.md b/sources/platform/actors/running/runs_and_builds.md index e6176b1197..9accc07dae 100644 --- a/sources/platform/actors/running/runs_and_builds.md +++ b/sources/platform/actors/running/runs_and_builds.md @@ -17,7 +17,7 @@ An Actor is a combination of source code and various settings in a Docker contai A Docker image is a lightweight, standalone, executable package of software that includes everything needed to run an application: code, runtime, system tools, system libraries, and settings. For more information visit Docker's [site](https://www.docker.com/resources/what-container/). ::: -With every new version of an Actor, a new build is created. Each Actor build has its number (for example, **1.2.34**), and some builds are tagged for easier use (for example, _latest_ or _beta_). When running an Actor, you can choose what build you want to run by selecting a tag or number in the run options. +With every new version of an Actor, a new build is created. Each Actor build has its number (for example, **1.2.34**), and some builds are tagged for easier use (for example, _latest_ or _beta_). When running an Actor, you can choose what build you want to run by selecting a tag or number in the run options. To change which build a tag refers to, you can reassign it using the [Actor update](/api/v2/act-put) API endpoint. ![Actor run options](./images/runs_and_builds/actor-run-options.png) From 96ec0ca7407c723487ac03f6752b5a6f82310284 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Sep 2025 10:44:33 +0200 Subject: [PATCH 14/28] fix: remove unused dependencies from `package.json` (#1953) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `globby` package was listed as a direct dependency in `devDependencies` but is not actually used anywhere in the codebase. This dependency is only needed as a transitive dependency through existing packages. ## Analysis A comprehensive search of the codebase revealed: - No direct imports or usage of `globby` in any source files - `globby` is available as a transitive dependency through: - `@docusaurus/core` → `@docusaurus/bundler` → `copy-webpack-plugin` → `globby@13.2.2` - `@docusaurus/utils` → `globby@11.1.0` ## Changes - Removed `"globby": "^14.0.0"` from `devDependencies` in `package.json` - Updated `package-lock.json` to reflect the removal of the extraneous package ## Testing All functionality remains intact after the removal: - ✅ ESLint and code linting work correctly - ✅ Markdown linting works correctly - ✅ API documentation build (`redoc:test`) succeeds - ✅ Docusaurus core functionality is unaffected - ✅ Transitive dependencies continue to provide needed functionality This change follows best practices by only listing packages as direct dependencies when they are actually imported or used directly in the project code. > [!WARNING] > >
> Firewall rules blocked me from connecting to one or more addresses (expand for details) > > #### I tried to connect to the following addresses, but was blocked by firewall rules: > > - `otel.cloud.redocly.com` > - Triggering command: `node /home/REDACTED/work/apify-docs/apify-docs/node_modules/.bin/redocly lint` (dns block) > - Triggering command: `node /home/REDACTED/work/apify-docs/apify-docs/node_modules/.bin/redocly bundle apify-api/openapi/openapi.yaml -o apify-api` (dns block) > > If you need me to access, download, or install something from one of these locations, you can either: > > - Configure [Actions setup steps](https://gh.io/copilot/actions-setup-steps) to set up my environment, which run before the firewall is enabled > - Add the appropriate URLs or hosts to the custom allowlist in this repository's [Copilot coding agent settings](https://github.com/apify/apify-docs/settings/copilot/coding_agent) (admins only) > >
Original prompt > remove dependency on globby from package.json, it is not used directly, only as part of our dependencies
--- 💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs. --- > [!NOTE] > Removes several unused dependencies/devDependencies from `package.json` and updates `package-lock.json` accordingly. > > - **Dependencies cleanup**: > - Remove unused `@docusaurus/utils`, `@mdx-js/react`, `ajv`, `form-data`, `proxy-from-env`, `search-insights`. > - **DevDependencies cleanup**: > - Remove unused `@rsbuild/plugin-styled-components`, `eslint-plugin-json`, `eslint-plugin-markdown`, `eslint-plugin-react-hooks`, `fs-extra`, `globby`. > - **Lockfile**: > - Prunes corresponding entries from `package-lock.json`. > > Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 68bd5777ede79a67c3c2d06c4b97922862b8f3e8. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot). --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: B4nan <615580+B4nan@users.noreply.github.com> Co-authored-by: Jindřich Bär --- package-lock.json | 345 ---------------------------------------------- package.json | 12 -- 2 files changed, 357 deletions(-) diff --git a/package-lock.json b/package-lock.json index 25349a36bf..5f2873b342 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,45 +21,33 @@ "@docusaurus/preset-classic": "^3.8.1", "@docusaurus/theme-common": "^3.8.1", "@docusaurus/theme-mermaid": "^3.8.1", - "@docusaurus/utils": "^3.8.1", "@giscus/react": "^3.0.0", - "@mdx-js/react": "^3.0.1", "@redocly/cli": "^1.27.1", "@signalwire/docusaurus-plugin-llms-txt": "^1.2.1", - "ajv": "^8.17.1", "clsx": "^2.0.0", "docusaurus-plugin-image-zoom": "^3.0.1", "docusaurus-plugin-openapi-docs": "^4.3.7", "docusaurus-theme-openapi-docs": "^4.3.7", - "form-data": "^4.0.0", "github-buttons": "^2.28.0", "postcss-preset-env": "^10.0.0", "prism-react-renderer": "^2.4.0", "prop-types": "^15.8.1", - "proxy-from-env": "^1.1.0", "raw-loader": "^4.0.2", "react": "^19.1.0", "react-dom": "^19.1.0", "react-github-btn": "^1.4.0", - "search-insights": "2.17.3", "styled-components": "6.1.19", "unist-util-visit": "^5.0.0" }, "devDependencies": { "@apify/eslint-config": "^1.0.0", "@apify/tsconfig": "^0.1.0", - "@rsbuild/plugin-styled-components": "^1.1.0", "@types/react": "^19.0.0", "babel-plugin-styled-components": "^2.1.4", "cross-env": "^7.0.3", "eslint": "^9.32.0", - "eslint-plugin-json": "^4.0.1", - "eslint-plugin-markdown": "^5.1.0", "eslint-plugin-react": "^7.37.5", - "eslint-plugin-react-hooks": "^5.2.0", - "fs-extra": "^11.1.1", "globals": "^16.0.0", - "globby": "^14.0.0", "markdownlint": "^0.38.0", "markdownlint-cli": "^0.45.0", "patch-package": "^8.0.0", @@ -6405,24 +6393,6 @@ } } }, - "node_modules/@rsbuild/plugin-styled-components": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@rsbuild/plugin-styled-components/-/plugin-styled-components-1.4.1.tgz", - "integrity": "sha512-M3RRoQdDDy8l8lv323TrCst2/bdB2nd0GtAApJ6iOIwkGsWKuIlLI2l2TBgIrf3kHch9i4WvYFaVEA/j65tGCA==", - "dev": true, - "dependencies": { - "@swc/plugin-styled-components": "^9.0.2", - "reduce-configs": "^1.1.0" - }, - "peerDependencies": { - "@rsbuild/core": "^1.4.0-beta.4 || ^1.4.0" - }, - "peerDependenciesMeta": { - "@rsbuild/core": { - "optional": true - } - } - }, "node_modules/@rspack/binding": { "version": "1.5.6", "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-1.5.6.tgz", @@ -6943,18 +6913,6 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, - "node_modules/@sindresorhus/merge-streams": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", - "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@slorber/remark-comment": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@slorber/remark-comment/-/remark-comment-1.0.0.tgz", @@ -7578,15 +7536,6 @@ "node": ">=10" } }, - "node_modules/@swc/plugin-styled-components": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/@swc/plugin-styled-components/-/plugin-styled-components-9.1.0.tgz", - "integrity": "sha512-c0eVq3KLZq614zMRu3HcJ9BR/2ZFEn4j42Oyo3zsKxiMP2w33CQOAO4IqQ+BhK8EKnpIptbpGEGfBsIF7H2U4w==", - "dev": true, - "dependencies": { - "@swc/counter": "^0.1.3" - } - }, "node_modules/@swc/types": { "version": "0.1.25", "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.25.tgz", @@ -9779,26 +9728,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/character-entities-legacy": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", - "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-reference-invalid": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", - "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/charset": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/charset/-/charset-1.0.1.tgz", @@ -12554,35 +12483,6 @@ "semver": "bin/semver.js" } }, - "node_modules/eslint-plugin-json": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-json/-/eslint-plugin-json-4.0.1.tgz", - "integrity": "sha512-3An5ISV5dq/kHfXdNyY5TUe2ONC3yXFSkLX2gu+W8xAhKhfvrRvkSAeKXCxZqZ0KJLX15ojBuLPyj+UikQMkOA==", - "dev": true, - "dependencies": { - "lodash": "^4.17.21", - "vscode-json-languageservice": "^4.1.6" - }, - "engines": { - "node": ">=18.0" - } - }, - "node_modules/eslint-plugin-markdown": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-markdown/-/eslint-plugin-markdown-5.1.0.tgz", - "integrity": "sha512-SJeyKko1K6GwI0AN6xeCDToXDkfKZfXcexA6B+O2Wr2btUS9GrC+YgwSyVli5DJnctUHjFXcQ2cqTaAmVoLi2A==", - "deprecated": "Please use @eslint/markdown instead", - "dev": true, - "dependencies": { - "mdast-util-from-markdown": "^0.8.5" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "peerDependencies": { - "eslint": ">=8" - } - }, "node_modules/eslint-plugin-react": { "version": "7.37.5", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", @@ -12615,18 +12515,6 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, - "node_modules/eslint-plugin-react-hooks": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", - "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" - } - }, "node_modules/eslint-plugin-react/node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -13904,47 +13792,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/globby": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", - "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", - "dev": true, - "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.3", - "ignore": "^7.0.3", - "path-type": "^6.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/globby/node_modules/path-type": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", - "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -15305,30 +15152,6 @@ "node": ">= 10" } }, - "node_modules/is-alphabetical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", - "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-alphanumerical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", - "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", - "dev": true, - "dependencies": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/is-array-buffer": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", @@ -15504,16 +15327,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-decimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", - "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -15596,16 +15409,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-hexadecimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", - "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/is-inside-container": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", @@ -17226,72 +17029,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mdast-util-from-markdown": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz", - "integrity": "sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-to-string": "^2.0.0", - "micromark": "~2.11.0", - "parse-entities": "^2.0.0", - "unist-util-stringify-position": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-from-markdown/node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", - "dev": true - }, - "node_modules/mdast-util-from-markdown/node_modules/mdast-util-to-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz", - "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-from-markdown/node_modules/micromark": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-2.11.4.tgz", - "integrity": "sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "debug": "^4.0.0", - "parse-entities": "^2.0.0" - } - }, - "node_modules/mdast-util-from-markdown/node_modules/unist-util-stringify-position": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", - "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/mdast-util-frontmatter": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mdast-util-frontmatter/-/mdast-util-frontmatter-2.0.1.tgz", @@ -22762,34 +22499,6 @@ "node": ">=6" } }, - "node_modules/parse-entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", - "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", - "dev": true, - "dependencies": { - "character-entities": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "character-reference-invalid": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-hexadecimal": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/parse-entities/node_modules/character-entities": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", - "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -26205,12 +25914,6 @@ "node": ">=8.0.0" } }, - "node_modules/reduce-configs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/reduce-configs/-/reduce-configs-1.1.1.tgz", - "integrity": "sha512-EYtsVGAQarE8daT54cnaY1PIknF2VB78ug6Zre2rs36EsJfC40EG6hmTU2A2P1ZuXnKAt2KI0fzOGHcX7wzdPw==", - "dev": true - }, "node_modules/redux": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", @@ -27538,11 +27241,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/search-insights": { - "version": "2.17.3", - "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz", - "integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==" - }, "node_modules/section-matter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", @@ -28115,18 +27813,6 @@ "node": ">=8" } }, - "node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/slugify": { "version": "1.6.6", "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", @@ -29409,18 +29095,6 @@ "node": ">=4" } }, - "node_modules/unicorn-magic": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", - "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/unified": { "version": "10.1.2", "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", @@ -30004,19 +29678,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/vscode-json-languageservice": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.2.1.tgz", - "integrity": "sha512-xGmv9QIWs2H8obGbWg+sIPI/3/pFgj/5OWBhNzs00BkYQ9UaB2F6JJaGB/2/YOZJ3BvLXQTC4Q7muqU25QgAhA==", - "dev": true, - "dependencies": { - "jsonc-parser": "^3.0.0", - "vscode-languageserver-textdocument": "^1.0.3", - "vscode-languageserver-types": "^3.16.0", - "vscode-nls": "^5.0.0", - "vscode-uri": "^3.0.3" - } - }, "node_modules/vscode-jsonrpc": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", @@ -30055,12 +29716,6 @@ "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" }, - "node_modules/vscode-nls": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.2.0.tgz", - "integrity": "sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==", - "dev": true - }, "node_modules/vscode-uri": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", diff --git a/package.json b/package.json index 64880109f7..a3fb0dcb69 100644 --- a/package.json +++ b/package.json @@ -46,18 +46,12 @@ "devDependencies": { "@apify/eslint-config": "^1.0.0", "@apify/tsconfig": "^0.1.0", - "@rsbuild/plugin-styled-components": "^1.1.0", "@types/react": "^19.0.0", "babel-plugin-styled-components": "^2.1.4", "cross-env": "^7.0.3", "eslint": "^9.32.0", - "eslint-plugin-json": "^4.0.1", - "eslint-plugin-markdown": "^5.1.0", "eslint-plugin-react": "^7.37.5", - "eslint-plugin-react-hooks": "^5.2.0", - "fs-extra": "^11.1.1", "globals": "^16.0.0", - "globby": "^14.0.0", "markdownlint": "^0.38.0", "markdownlint-cli": "^0.45.0", "patch-package": "^8.0.0", @@ -75,27 +69,21 @@ "@docusaurus/preset-classic": "^3.8.1", "@docusaurus/theme-common": "^3.8.1", "@docusaurus/theme-mermaid": "^3.8.1", - "@docusaurus/utils": "^3.8.1", "@giscus/react": "^3.0.0", - "@mdx-js/react": "^3.0.1", "@redocly/cli": "^1.27.1", "@signalwire/docusaurus-plugin-llms-txt": "^1.2.1", - "ajv": "^8.17.1", "clsx": "^2.0.0", "docusaurus-plugin-image-zoom": "^3.0.1", "docusaurus-plugin-openapi-docs": "^4.3.7", "docusaurus-theme-openapi-docs": "^4.3.7", - "form-data": "^4.0.0", "github-buttons": "^2.28.0", "postcss-preset-env": "^10.0.0", "prism-react-renderer": "^2.4.0", "prop-types": "^15.8.1", - "proxy-from-env": "^1.1.0", "raw-loader": "^4.0.2", "react": "^19.1.0", "react-dom": "^19.1.0", "react-github-btn": "^1.4.0", - "search-insights": "2.17.3", "styled-components": "6.1.19", "unist-util-visit": "^5.0.0" }, From 2accfa76d7e3c5456a467dfb6074a57bc8da8fd6 Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Mon, 29 Sep 2025 13:59:04 +0200 Subject: [PATCH 15/28] docs: improve text for arge charge for invalid input --- .../platform/actors/publishing/monetize/pay_per_event.mdx | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sources/platform/actors/publishing/monetize/pay_per_event.mdx b/sources/platform/actors/publishing/monetize/pay_per_event.mdx index 3fd83d7ba0..9433ce24c5 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_event.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_event.mdx @@ -203,13 +203,7 @@ When using browser automation tools like Puppeteer or Playwright for web scrapin Charge for things like URLs that appear valid but lead to errors (like 404s) since you had to open the page to discover the error. Return error items with proper error codes and messages instead of failing the entire Actor run. -:::info One call vs two calls - -The following code snippets show the single call option to both return error item and charge for the work done. - -If you prefer to return error item and charge for the work done in two calls, you can use the two calls option where you charge for the work done with `Actor.charge( ... )` and return the error item with `Actor.pushData( ... )`. - -::: +The snippet below shows how you can charge for invalid inputs using `Actor.pushData` when a dataset item is created and the `scraped-result` event is charged. From ca3a6116207b2a7fc5bc03919af09fab1bc818a3 Mon Sep 17 00:00:00 2001 From: Patrik Braborec Date: Mon, 29 Sep 2025 14:01:12 +0200 Subject: [PATCH 16/28] Update sources/platform/actors/publishing/monetize/pay_per_event.mdx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jiří Spilka --- sources/platform/actors/publishing/monetize/pay_per_event.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/sources/platform/actors/publishing/monetize/pay_per_event.mdx b/sources/platform/actors/publishing/monetize/pay_per_event.mdx index 9433ce24c5..2288d1c0a7 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_event.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_event.mdx @@ -361,6 +361,7 @@ If you're not using the Apify SDKs (JS/Python), you need to handle idempotency (
3 Free plan +
100 × scraped-product
5 × scraped-product-detail
From ee8dd3b4274baaf4cc69b46b535a20102eecd13f Mon Sep 17 00:00:00 2001 From: Patrik Braborec Date: Mon, 29 Sep 2025 14:02:50 +0200 Subject: [PATCH 17/28] Update sources/platform/actors/publishing/monetize/pay_per_event.mdx Co-authored-by: Ondra Urban <23726914+mnmkng@users.noreply.github.com> --- sources/platform/actors/publishing/monetize/pay_per_event.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/platform/actors/publishing/monetize/pay_per_event.mdx b/sources/platform/actors/publishing/monetize/pay_per_event.mdx index 2288d1c0a7..65523af8a0 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_event.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_event.mdx @@ -155,7 +155,7 @@ The default price of the event is set intentionally low. This pricing means that - The Apify Actor start event is **automatically enabled** for all new PPE Actors. For existing Actors, you can enable it in Apify Console. - Apify **automatically charges** the event. - You must _not_ manually charge for the synthetic start event (`apify-actor-start`) in your Actor code. If you attempt to charge this event yourself, the operation will fail. -- The price of the event is **$0.00005**, which equals **$0.05 per 1,000 starts**. +- The default price of the event is **$0.00005**, which equals **$0.05 per 1,000 starts**. We recommend keeping the default price to keep your Actors competitive. - The number of events charged **depends on the memory** of the Actor run. Up to and including 1 GB of RAM, the event is charged once. Then it's charged once for each extra GB of memory. For example: - 128 MB RAM: 1 event, $0.00005 - 1 GB RAM: 1 event, $0.00005 From 4f8fda377c4d1cfe3d783f6f117a5c969166f631 Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Mon, 29 Sep 2025 16:16:16 +0200 Subject: [PATCH 18/28] docs: Improve docs based on feedback --- .../publishing/monetize/pay_per_event.mdx | 90 +++++++++++-------- .../publishing/monetize/pay_per_result.mdx | 16 ++-- 2 files changed, 64 insertions(+), 42 deletions(-) diff --git a/sources/platform/actors/publishing/monetize/pay_per_event.mdx b/sources/platform/actors/publishing/monetize/pay_per_event.mdx index 65523af8a0..cb6e3c4892 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_event.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_event.mdx @@ -16,7 +16,7 @@ The PPE pricing model offers a flexible monetization option for Actors on Apify PPE lets you define pricing for individual events. You can charge for specific events directly from your Actor using the [JS](/sdk/js/reference/class/Actor#charge)/[Python](/sdk/python/reference/class/Actor#charge) SDK, or by calling the [PPE charging API](/api/v2/post-charge-run) directly. Common events include Actor start, dataset item creation, and external API calls. -The details on how your cost is computed can be found in [Example of a PPE pricing model](#example-of-a-ppe-pricing-model). +The details on how your cost is computed can be found in [Examples of a PPE pricing](#examples-of-a-ppe-pricing). :::tip Additional benefits @@ -293,9 +293,9 @@ However, we acknowledge that some events don't produce tangible results (such as Examples: -- _`scraped-product` event_: Each charge adds one product record to the dataset -- _`processed-image` event_: Each charge adds one processed image to the dataset -- _`extracted-review` event_: Each charge adds one review to the dataset +- _`post` event_: Each charge adds one social media post to the dataset +- _`profile` event_: Each charge adds one user profile to the dataset +- _`processed-image` event_: Each charge adds one processed image to the dataset - _`ai-analysis` event_: Each charge processes one document through an AI workflow (no tangible output, but valuable processing) :::note Additional context @@ -308,24 +308,36 @@ You can display a status message or push a record to the dataset to inform users If you're not using the Apify SDKs (JS/Python), you need to handle idempotency (ensuring the same operation produces the same result when called multiple times) manually to prevent charging the same event multiple times. -## Examples of a PPE pricing model +## Example of a PPE pricing -### Example: simple PPE pricing +You create a social media monitoring Actor with the following pricing: -- `scraped-product`: $0.01 per product - count every product record you return. -- `scraped-product-detail`: $0.05 per detail - count every enriched product detail you provide. +- `post`: $0.002 per post - count every social media post you extract. +- `profile`: $0.001 per profile - count every user profile you extract. +- `sentiment-analysis`: $0.005 per post - count every post analyzed for sentiment, engagement metrics, and content classification using external LLM APIs. -#### Pricing breakdown by user +:::info Fixed pricing vs. usage-based pricing + +You have two main strategies for charging AI-related operations: + +1. **Fixed event pricing** (like `sentiment-analysis` above): Charge a fixed amount per operation, regardless of actual LLM costs +2. **Usage-based pricing**: Use events like `llm-token` that charge based on actual LLM usage costs + +Fixed pricing is simpler for users to predict, while usage-based pricing more accurately reflects your actual costs. + +::: + +### Pricing breakdown by user - + - + @@ -333,56 +345,64 @@ If you're not using the Apify SDKs (JS/Python), you need to handle idempotency ( - - + + - + - +
User PlanEventsEvents Charges TotalCostPlatform cost
1 Paid plan -
1,000 × scraped-product
-
50 × scraped-product-detail
+
5,000 × post
+
50 × profile
+
2,000 × sentiment-analysis
-
1,000 × $0.01 = $10.00
-
50 × $0.05 = $2.50
+
5,000 × $0.002
+
50 × $0.001
+
2,000 × $0.005
$12.50$3.20$20.05$2.50
2 Paid plan -
500 × scraped-product
-
20 × scraped-product-detail
+
3,000 × post
+
20 × profile
+
1,000 × sentiment-analysis
-
500 × $0.01 = $5.00
-
20 × $0.05 = $1.00
+
3,000 × $0.002
+
20 × $0.001
+
1,000 × $0.005
$6.00$11.02 $1.50
3 Free plan -
100 × scraped-product
-
5 × scraped-product-detail
+
1,000 × post
+
5 × profile
+
200 × sentiment-analysis
-
100 × $0.01 = $1.00
-
5 × $0.05 = $0.25
+
1,000 × $0.002
+
5 × $0.001
+
200 × $0.005
$1.25$3.01 $0.40
+Your profit and costs are computed **only from the first two users** since they are on Apify paid plans. + The platform usage costs are just examples, but you can see the actual costs in the [Computing your costs for PPE and PPR Actors](/platform/actors/publishing/monetize/pricing-and-costs#computing-your-costs-for-ppe-and-ppr-actors) section. -#### Revenue breakdown +### Revenue breakdown -- **Revenue (paid users only)**: $12.50 + $6.00 = **$18.50** -- **Underlying cost (paid users only)**: $3.20 + $1.50 = **$4.70** -- **Profit**: 0.8 × $18.50 − $4.70 = **$10.10** +- **Revenue (paid users only)**: $20.05 + $11.02 = **$31.07** +- **Platform cost (paid users only)**: $2.50 + $1.50 = **$4.00** +- **Profit**: 0.8 × $31.07 − $4.00 = **$20.86** -### Example: usage-indexed PPE pricing +{/* ### Example: usage-indexed PPE pricing - `llm-token-cent`: $0.02 per $0.01 LLM spend - emit one event for each cent billed by your LLM provider. @@ -390,9 +410,9 @@ The platform usage costs are just examples, but you can see the actual costs in For the simplicity of the example, we show only the LLM-token-cent event. In reality, you can charge for any event you want. -::: +::: */} -#### Pricing breakdown by user +{/* #### Pricing breakdown by user @@ -456,7 +476,7 @@ The platform usage costs are just examples, but you can see the actual costs in - **Underlying cost (paid users only)**: $2.60 + $1.20 = **$3.80** - **Profit**: 0.8 × $75.00 − $3.80 = **$56.20** -This example illustrates the key trade-off of PPE pricing: while it's harder for users to predict exact costs upfront, it provides developers with a safer and more scalable revenue model that grows with actual usage. +This example illustrates the key trade-off of PPE pricing: while it's harder for users to predict exact costs upfront, it provides developers with a safer and more scalable revenue model that grows with actual usage. */} ## Event names diff --git a/sources/platform/actors/publishing/monetize/pay_per_result.mdx b/sources/platform/actors/publishing/monetize/pay_per_result.mdx index 79627d7650..e987a2f6ce 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_result.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_result.mdx @@ -203,7 +203,7 @@ Example scenarios: This ensures that every run generates at least one result, guaranteeing that users are charged appropriately for using your Actor. -## Example of PPR pricing model +## Example of PPR pricing You make your Actor PPR and set the price to be _$1/1,000 results_. During the first month, three users use your Actor. @@ -217,7 +217,7 @@ You make your Actor PPR and set the price to be _$1/1,000 results_. During the f - + @@ -228,7 +228,7 @@ You make your Actor PPR and set the price to be _$1/1,000 results_. During the f
50,000 results
@@ -240,7 +240,7 @@ You make your Actor PPR and set the price to be _$1/1,000 results_. During the f
20,000 results
@@ -252,20 +252,22 @@ You make your Actor PPR and set the price to be _$1/1,000 results_. During the f
5,000 results
- +
Results Charges TotalCostPlatform cost
-
50,000 ÷ 1,000 × $1.00 = $50.00
+
50,000 ÷ 1,000 × $1.00
$50.00 $5.00 -
20,000 ÷ 1,000 × $1.00 = $20.00
+
20,000 ÷ 1,000 × $1.00
$20.00 $2.00 -
5,000 ÷ 1,000 × $1.00 = $5.00
+
5,000 ÷ 1,000 × $1.00
$0.00$5.00 $0.50
+Your profit and costs are computed **only from the first two users** since they are on Apify paid plans. + The platform usage costs are just examples, but you can see the actual costs in the [Computing your costs for PPE and PPR Actors](/platform/actors/publishing/monetize/pricing-and-costs#computing-your-costs-for-ppe-and-ppr-actors) section. ### Revenue breakdown - **Revenue (paid users only)**: $50.00 + $20.00 = **$70.00** -- **Underlying cost (paid users only)**: $5.00 + $2.00 = **$7.00** +- **Platform cost (paid users only)**: $5.00 + $2.00 = **$7.00** - **Profit**: 0.8 × $70.00 − $7.00 = **$49.00** ## Next steps From 9649ded62d7338acba1b0dfbd03309f3d8d468df Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Mon, 29 Sep 2025 16:17:28 +0200 Subject: [PATCH 19/28] docs: remove unused example --- .../publishing/monetize/pay_per_event.mdx | 76 ------------------- 1 file changed, 76 deletions(-) diff --git a/sources/platform/actors/publishing/monetize/pay_per_event.mdx b/sources/platform/actors/publishing/monetize/pay_per_event.mdx index cb6e3c4892..9d8a826b73 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_event.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_event.mdx @@ -402,82 +402,6 @@ The platform usage costs are just examples, but you can see the actual costs in - **Platform cost (paid users only)**: $2.50 + $1.50 = **$4.00** - **Profit**: 0.8 × $31.07 − $4.00 = **$20.86** -{/* ### Example: usage-indexed PPE pricing - -- `llm-token-cent`: $0.02 per $0.01 LLM spend - emit one event for each cent billed by your LLM provider. - -:::info Simplified example - -For the simplicity of the example, we show only the LLM-token-cent event. In reality, you can charge for any event you want. - -::: */} - -{/* #### Pricing breakdown by user - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
UserPlanEventsChargesTotalCost
1Paid plan -
$25.40 LLM usage:
-
2,540 × llm-token-cent
-
-
2,540 × $0.02 = $50.80
-
$50.80$2.60
2Paid plan -
$12.10 LLM usage:
-
1,210 × llm-token-cent
-
-
1,210 × $0.02 = $24.20
-
$24.20$1.20
3Free plan -
$3.90 LLM usage:
-
390 × llm-token-cent
-
-
390 × $0.02 = $7.80
-
$7.80$0.35
- -The platform usage costs are just examples, but you can see the actual costs in the [Computing your costs for PPE and PPR Actors](/platform/actors/publishing/monetize/pricing-and-costs#computing-your-costs-for-ppe-and-ppr-actors) section. - -#### Revenue breakdown - -- **Revenue (paid users only)**: $50.80 + $24.20 = **$75.00** -- **Underlying cost (paid users only)**: $2.60 + $1.20 = **$3.80** -- **Profit**: 0.8 × $75.00 − $3.80 = **$56.20** - -This example illustrates the key trade-off of PPE pricing: while it's harder for users to predict exact costs upfront, it provides developers with a safer and more scalable revenue model that grows with actual usage. */} - ## Event names If you need to know your event names, you can retrieve the list of available pricing event names using the [Get Actor](https://apify.com/docs/api/v2/act-get) API endpoint. From 82b0ffbdbb78f0cd55855ee089aef51db6849a47 Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Mon, 29 Sep 2025 16:42:29 +0200 Subject: [PATCH 20/28] docs: Fix broken link --- sources/platform/actors/publishing/monetize/pay_per_event.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/platform/actors/publishing/monetize/pay_per_event.mdx b/sources/platform/actors/publishing/monetize/pay_per_event.mdx index 9d8a826b73..3972f71b7c 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_event.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_event.mdx @@ -16,7 +16,7 @@ The PPE pricing model offers a flexible monetization option for Actors on Apify PPE lets you define pricing for individual events. You can charge for specific events directly from your Actor using the [JS](/sdk/js/reference/class/Actor#charge)/[Python](/sdk/python/reference/class/Actor#charge) SDK, or by calling the [PPE charging API](/api/v2/post-charge-run) directly. Common events include Actor start, dataset item creation, and external API calls. -The details on how your cost is computed can be found in [Examples of a PPE pricing](#examples-of-a-ppe-pricing). +The details on how your cost is computed can be found in [Example of a PPE pricing](#example-of-a-ppe-pricing). :::tip Additional benefits From a87138bb7f2236231be2323b2e796a284180560f Mon Sep 17 00:00:00 2001 From: Patrik Braborec Date: Tue, 30 Sep 2025 16:17:58 +0200 Subject: [PATCH 21/28] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michał Olender <92638966+TC-MO@users.noreply.github.com> --- .../actor-runs/actor-runs@{runId}@charge.yaml | 2 +- sources/academy/ai/ai-agents.mdx | 2 +- .../how_actor_monetization_works.md | 6 +++--- .../publishing/monetize/pay_per_event.mdx | 18 +++++++++--------- .../publishing/monetize/pay_per_result.mdx | 10 +++++----- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/apify-api/openapi/paths/actor-runs/actor-runs@{runId}@charge.yaml b/apify-api/openapi/paths/actor-runs/actor-runs@{runId}@charge.yaml index 73acee1f12..37cd655775 100644 --- a/apify-api/openapi/paths/actor-runs/actor-runs@{runId}@charge.yaml +++ b/apify-api/openapi/paths/actor-runs/actor-runs@{runId}@charge.yaml @@ -7,7 +7,7 @@ post: The event you are charging for must be one of the configured events in your Actor. If the Actor is not set up as pay per event, or if the event is not configured, the endpoint will return an error. The endpoint must be called from the Actor run itself, with the same API token that the run was started with. - For more details about pay-per-event (PPE) pricing, see our [PPE documentation](/platform/actors/publishing/monetize/pay-per-event). + For more details about pay-per-event (PPE) pricing, refer to our [PPE documentation](/platform/actors/publishing/monetize/pay-per-event). operationId: PostChargeRun parameters: diff --git a/sources/academy/ai/ai-agents.mdx b/sources/academy/ai/ai-agents.mdx index 157bf7ac66..8ccea0a205 100644 --- a/sources/academy/ai/ai-agents.mdx +++ b/sources/academy/ai/ai-agents.mdx @@ -253,7 +253,7 @@ Apify's pay-per-event (PPE) pricing model allows charging users based on specifi :::info How pay-per-event pricing works -If you want more details about PPE pricing, please refer to our [PPE documentation](/platform/actors/publishing/monetize/pay-per-event). +If you want more details about PPE pricing, refer to our [PPE documentation](/platform/actors/publishing/monetize/pay-per-event). ::: diff --git a/sources/academy/platform/get_most_of_actors/store_basics/how_actor_monetization_works.md b/sources/academy/platform/get_most_of_actors/store_basics/how_actor_monetization_works.md index b212ee9611..f580904881 100644 --- a/sources/academy/platform/get_most_of_actors/store_basics/how_actor_monetization_works.md +++ b/sources/academy/platform/get_most_of_actors/store_basics/how_actor_monetization_works.md @@ -35,7 +35,7 @@ Monetizing your Actor on the Apify platform involves several key steps: :::info Rental pricing details -If you want more details about rental pricing, please refer to our [rental pricing documentation](/platform/actors/publishing/monetize/rental). +If you want more details about rental pricing, refer to our [rental pricing documentation](/platform/actors/publishing/monetize/rental). ::: @@ -55,7 +55,7 @@ If you want more details about rental pricing, please refer to our [rental prici :::info Pay-per-result details -If you want more details about PPR pricing, please refer to our [PPR documentation](/platform/actors/publishing/monetize/pay-per-result). +If you want more details about PPR pricing, refer to our [PPR documentation](/platform/actors/publishing/monetize/pay-per-result). ::: @@ -87,7 +87,7 @@ If you want more details about PPR pricing, please refer to our [PPR documentati :::info Pay-per-event details -If you want more details about PPE pricing, please refer to our [PPE documentation](/platform/actors/publishing/monetize/pay-per-event). +If you want more details about PPE pricing, refer to our [PPE documentation](/platform/actors/publishing/monetize/pay-per-event). ::: diff --git a/sources/platform/actors/publishing/monetize/pay_per_event.mdx b/sources/platform/actors/publishing/monetize/pay_per_event.mdx index 3972f71b7c..c4b5b30af4 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_event.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_event.mdx @@ -148,7 +148,7 @@ One of the options to charge for the time spent on starting the Actor is to char We want to make it easier for Actor creators to stay competitive, but also help them to be profitable. Therefore, we have the Apify Actor synthetic start event `apify-actor-start`. This event is enabled by default for all new PPE Actors, and when you use it Apify will cover the compute unit cost of the first 5 seconds of every Actor run. -The default price of the event is set intentionally low. This pricing means that the free 5 seconds of compute we provide costs us more than the revenue generated from the event. We've made this investment to **support our creator community** by reducing your startup costs while keeping your Actors competitively priced for users. +The default price of the event is set intentionally low. This pricing means that the free 5 seconds of compute we provide costs us more than the revenue generated from the event. We've made this investment to _support our creator community_ by reducing your startup costs while keeping your Actors competitively priced for users. #### How the synthetic start event works @@ -171,13 +171,13 @@ For new Actors, this event is added automatically as you can see on the followin #### Synthetic start event for existing Actors -If you have existing Actors, you can add this event manually in Apify Console in the Publication tab. +If you have existing Actors, you can add this event manually in Apify Console in the **Publication** tab. #### Synthetic start event for Actors with start event Your Actor might already have a start event defined, such as `actor-start` or another variant of the event name. In this case, you can choose whether to use the synthetic start event or keep the existing start event. -If you want to use the synthetic start event, remove the existing start event from your Actor and add the synthetic start event in Apify Console in the Publication tab. +If you want to use the synthetic start event, remove the existing start event from your Actor and add the synthetic start event in Apify Console in the **Publication** tab. ### Set memory limits @@ -320,8 +320,8 @@ You create a social media monitoring Actor with the following pricing: You have two main strategies for charging AI-related operations: -1. **Fixed event pricing** (like `sentiment-analysis` above): Charge a fixed amount per operation, regardless of actual LLM costs -2. **Usage-based pricing**: Use events like `llm-token` that charge based on actual LLM usage costs +1. _Fixed event pricing_ (like `sentiment-analysis` above): Charge a fixed amount per operation, regardless of actual LLM costs +2. _Usage-based pricing_: Use events like `llm-token` that charge based on actual LLM usage costs Fixed pricing is simpler for users to predict, while usage-based pricing more accurately reflects your actual costs. @@ -392,15 +392,15 @@ Fixed pricing is simpler for users to predict, while usage-based pricing more ac
-Your profit and costs are computed **only from the first two users** since they are on Apify paid plans. +Your profit and costs are computed _only from the first two users_ since they are on Apify paid plans. The platform usage costs are just examples, but you can see the actual costs in the [Computing your costs for PPE and PPR Actors](/platform/actors/publishing/monetize/pricing-and-costs#computing-your-costs-for-ppe-and-ppr-actors) section. ### Revenue breakdown -- **Revenue (paid users only)**: $20.05 + $11.02 = **$31.07** -- **Platform cost (paid users only)**: $2.50 + $1.50 = **$4.00** -- **Profit**: 0.8 × $31.07 − $4.00 = **$20.86** +- _Revenue (paid users only): $20.05 + $11.02 = $31.07_ +- _Platform cost (paid users only): $2.50 + $1.50 = $4.00_ +- _Profit: 0.8 × $31.07 − $4.00 = $20.86_ ## Event names diff --git a/sources/platform/actors/publishing/monetize/pay_per_result.mdx b/sources/platform/actors/publishing/monetize/pay_per_result.mdx index e987a2f6ce..6ab39b0420 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_result.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_result.mdx @@ -35,7 +35,7 @@ PPR charges based on the number of results produced. PPE lets you define pricing :::info Learn more about PPE -If you want to learn more about PPE, please refer to the [Pay per event](/platform/actors/publishing/monetize/pay-per-event) section. +If you want to learn more about PPE, refer to the [Pay per event](/platform/actors/publishing/monetize/pay-per-event) section. ::: @@ -260,15 +260,15 @@ You make your Actor PPR and set the price to be _$1/1,000 results_. During the f -Your profit and costs are computed **only from the first two users** since they are on Apify paid plans. +Your profit and costs are computed _only from the first two users_ since they are on Apify paid plans. The platform usage costs are just examples, but you can see the actual costs in the [Computing your costs for PPE and PPR Actors](/platform/actors/publishing/monetize/pricing-and-costs#computing-your-costs-for-ppe-and-ppr-actors) section. ### Revenue breakdown -- **Revenue (paid users only)**: $50.00 + $20.00 = **$70.00** -- **Platform cost (paid users only)**: $5.00 + $2.00 = **$7.00** -- **Profit**: 0.8 × $70.00 − $7.00 = **$49.00** +- _Revenue (paid users only): $50.00 + $20.00 = $70.00_ +- _Platform cost (paid users only): $5.00 + $2.00 = $7.00_ +- _Profit: 0.8 × $70.00 − $7.00 = $49.00_ ## Next steps From 0aac4f1dd878b86df5fbf7971fb91bec9415db91 Mon Sep 17 00:00:00 2001 From: Patrik Braborec Date: Tue, 30 Sep 2025 16:19:28 +0200 Subject: [PATCH 22/28] Update sources/platform/actors/publishing/monetize/pay_per_event.mdx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michał Olender <92638966+TC-MO@users.noreply.github.com> --- sources/platform/actors/publishing/monetize/pay_per_event.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/platform/actors/publishing/monetize/pay_per_event.mdx b/sources/platform/actors/publishing/monetize/pay_per_event.mdx index c4b5b30af4..09acd2bfae 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_event.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_event.mdx @@ -136,7 +136,7 @@ Use our SDKs ([JS](/sdk/js/) and, [Python](/sdk/python/) or use [`apify actor ch ### Use synthetic start event `apify-actor-start` -:::info TL;DR: +:::info Synthetic Actor recommended We recommend using the synthetic Actor start event in PPE Actors. It benefits both you and your users. From 8e25c8f7e1b1d45dc60e4725b82b4f3d2332ecd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20Proch=C3=A1zka?= Date: Mon, 29 Sep 2025 15:47:28 +0200 Subject: [PATCH 23/28] docs: Add signature query parameter to docs of relevant endpoints (#1955) ### Description: Update docs with signature query parameter for the following endpoints: - /key-value-store-record-get - /key-value-store-keys-get - /dataset-items-get ### Issues: Closed: #1954 --- .../paths/datasets/datasets@{datasetId}@items.yaml | 8 ++++++++ .../key-value-stores/key-value-stores@{storeId}@keys.yaml | 8 ++++++++ .../key-value-stores@{storeId}@records@{recordKey}.yaml | 8 ++++++++ 3 files changed, 24 insertions(+) diff --git a/apify-api/openapi/paths/datasets/datasets@{datasetId}@items.yaml b/apify-api/openapi/paths/datasets/datasets@{datasetId}@items.yaml index f2dda00bcc..bde66cf2c9 100644 --- a/apify-api/openapi/paths/datasets/datasets@{datasetId}@items.yaml +++ b/apify-api/openapi/paths/datasets/datasets@{datasetId}@items.yaml @@ -367,6 +367,14 @@ get: schema: type: boolean example: false + - name: signature + in: query + description: Signature used to access the items. + required: false + style: simple + schema: + type: string + example: 2wTI46Bg8qWQrV7tavlPI responses: '200': description: '' diff --git a/apify-api/openapi/paths/key-value-stores/key-value-stores@{storeId}@keys.yaml b/apify-api/openapi/paths/key-value-stores/key-value-stores@{storeId}@keys.yaml index 6dde0abd91..6c0335a230 100644 --- a/apify-api/openapi/paths/key-value-stores/key-value-stores@{storeId}@keys.yaml +++ b/apify-api/openapi/paths/key-value-stores/key-value-stores@{storeId}@keys.yaml @@ -48,6 +48,14 @@ get: schema: type: string example: post-images- + - name: signature + in: query + description: Signature used to access the keys. + required: false + style: simple + schema: + type: string + example: 2wTI46Bg8qWQrV7tavlPI responses: '200': description: '' diff --git a/apify-api/openapi/paths/key-value-stores/key-value-stores@{storeId}@records@{recordKey}.yaml b/apify-api/openapi/paths/key-value-stores/key-value-stores@{storeId}@records@{recordKey}.yaml index 38feffc9b1..85a414ad69 100644 --- a/apify-api/openapi/paths/key-value-stores/key-value-stores@{storeId}@records@{recordKey}.yaml +++ b/apify-api/openapi/paths/key-value-stores/key-value-stores@{storeId}@records@{recordKey}.yaml @@ -32,6 +32,14 @@ get: schema: type: string example: someKey + - name: signature + in: query + description: Signature used to access the record. + required: false + style: simple + schema: + type: string + example: 2wTI46Bg8qWQrV7tavlPI responses: '200': description: '' From 39be029ba0983ffeca63c02bb235b9396c46b683 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 1 Oct 2025 04:34:00 +0000 Subject: [PATCH 24/28] chore(deps): update dependency typescript to v5.9.3 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5f2873b342..e30fd52563 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,7 +53,7 @@ "patch-package": "^8.0.0", "path-browserify": "^1.0.1", "rimraf": "^6.0.0", - "typescript": "5.9.2", + "typescript": "5.9.3", "typescript-eslint": "^8.38.0" }, "engines": { @@ -28962,9 +28962,9 @@ } }, "node_modules/typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "bin": { "tsc": "bin/tsc", diff --git a/package.json b/package.json index a3fb0dcb69..cc1e3311de 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "patch-package": "^8.0.0", "path-browserify": "^1.0.1", "rimraf": "^6.0.0", - "typescript": "5.9.2", + "typescript": "5.9.3", "typescript-eslint": "^8.38.0" }, "dependencies": { From 148ca1ae772af226490825d1ccde0cfe6a579076 Mon Sep 17 00:00:00 2001 From: Patrik Braborec Date: Wed, 1 Oct 2025 10:21:24 +0200 Subject: [PATCH 25/28] docs: Improve Academy text regarding to Rental, PPR and PPE (#1947) --- .../store_basics/how_actor_monetization_works.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/sources/academy/platform/get_most_of_actors/store_basics/how_actor_monetization_works.md b/sources/academy/platform/get_most_of_actors/store_basics/how_actor_monetization_works.md index f580904881..d5a0266938 100644 --- a/sources/academy/platform/get_most_of_actors/store_basics/how_actor_monetization_works.md +++ b/sources/academy/platform/get_most_of_actors/store_basics/how_actor_monetization_works.md @@ -126,13 +126,19 @@ Learn more about what makes a good readme here: [How to create an Actor README]( ### Rental, pay-per-result (PPR), or pay-per-event (PPE) -Rental pricing is technically easier: you set the rental fee, and the user covers their CU usage. All you have to define is how much you want to charge the users. With pay-per-result, you’ll need to include both CU usage and your margin. You have to calculate how much the average run is going to cost for the user + define how much you want to charge them. +Rental pricing allows you to charge a monthly fee for your Actor and users cover their own compute usage. -To figure out the average cost per run for users, just run a few test runs and look at the statistics in the Actor [**Analytics**](https://console.apify.com/actors?tab=analytics) tab. +Pay-per-result (PPR) charges users based on the number of items your Actor adds to the dataset. This model works best when each dataset item represents clear value to the user - like scraped product listings, extracted contact information, or processed documents. -From an average user's perspective, pay-per-result is often easier to grasp — $25 for a thousand pages, $5 for a thousand videos, $1 for a thousand images, etc. It gives users a clearer idea of what they’re paying for and allows them to estimate faster. But rental pricing has its fans, too — if your tool provides high value, users will come. +Pay-per-event (PPE) gives you the most flexibility and growth potential. You can charge for any meaningful event your Actor performs (for example, page scraped, browser page opened, or an external API call). This makes costs predictable for users, lets you model value precisely, and is fully compatible with AI and MCP-based integrations. -Pay-per-event (PPE) lets you define pricing for individual events. You can charge for specific events directly from your Actor by calling our PPE charging API. The most common events will most likely be Actor start, dataset item, external API calls, etc. PPE is great for users who want to optimize their costs and value transparency. PPE is also a fairer pricing model for integration and AI-driven use cases, where dataset-based pricing doesn’t make sense. +:::tip Additional benefits + +Actors that implement PPE receive additional benefits, including increased visibility in Apify Store and enhanced discoverability. + +::: + +To estimate pricing, run a few test runs and review the statistics in the Actor [**Analytics**](https://console.apify.com/actors?tab=analytics) tab. ### Adapt when needed From 6cf2de2bba0a45d3b3068260e3a0f79b3b308626 Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Wed, 1 Oct 2025 14:50:05 +0200 Subject: [PATCH 26/28] docs: Rebase and PR comments --- .../publishing/monetize/pay_per_event.mdx | 48 ++++++++----------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/sources/platform/actors/publishing/monetize/pay_per_event.mdx b/sources/platform/actors/publishing/monetize/pay_per_event.mdx index 09acd2bfae..a734fc0b98 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_event.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_event.mdx @@ -132,7 +132,7 @@ When using [Crawlee](https://crawlee.dev/), use `crawler.autoscaledPool.abort()` ## Best practices for PPE Actors -Use our SDKs ([JS](/sdk/js/) and, [Python](/sdk/python/) or use [`apify actor charge`](/cli/docs/next/reference#apify-actor-charge-eventname) when using our Apify CLI) to simplify PPE implementation into your Actor. SDKs help you handle pricing, usage tracking, idempotency keys, API errors, and, event charging via an API. You can also choose not to use it, but then you must handle API integration and possible edge cases manually. +Use our [SDKs](/sdk) (JS and, Python or use [`apify actor charge`](/cli/docs/next/reference#apify-actor-charge-eventname) when using our Apify CLI) to simplify PPE implementation into your Actor. SDKs help you handle pricing, usage tracking, idempotency keys, API errors, and, event charging via an API. You can also choose not to use it, but then you must handle API integration and possible edge cases manually. ### Use synthetic start event `apify-actor-start` @@ -152,16 +152,16 @@ The default price of the event is set intentionally low. This pricing means that #### How the synthetic start event works -- The Apify Actor start event is **automatically enabled** for all new PPE Actors. For existing Actors, you can enable it in Apify Console. -- Apify **automatically charges** the event. +- The Apify Actor start event is _automatically enabled_ for all new PPE Actors. For existing Actors, you can enable it in Apify Console. +- Apify _automatically charges_ the event. - You must _not_ manually charge for the synthetic start event (`apify-actor-start`) in your Actor code. If you attempt to charge this event yourself, the operation will fail. -- The default price of the event is **$0.00005**, which equals **$0.05 per 1,000 starts**. We recommend keeping the default price to keep your Actors competitive. -- The number of events charged **depends on the memory** of the Actor run. Up to and including 1 GB of RAM, the event is charged once. Then it's charged once for each extra GB of memory. For example: +- The default price of the event is _$0.00005_, which equals _$0.05 per 1,000 starts_. We recommend keeping the default price to keep your Actors competitive. +- The number of events charged _depends on the memory_ of the Actor run. Up to and including 1 GB of RAM, the event is charged once. Then it's charged once for each extra GB of memory. For example: - 128 MB RAM: 1 event, $0.00005 - 1 GB RAM: 1 event, $0.00005 - 4 GB RAM: 4 events, $0.0002 -- You can increase the price of the event if you wish, but you **won't get more free compute**. -- You can delete the event if you wish, but if you do, you will **lose the free 5 seconds** of compute. +- You can increase the price of the event if you wish, but you _won't get more free compute_. +- You can delete the event if you wish, but if you do, you will _lose the free 5 seconds_ of compute. #### Synthetic start event for new Actors @@ -313,8 +313,8 @@ If you're not using the Apify SDKs (JS/Python), you need to handle idempotency ( You create a social media monitoring Actor with the following pricing: - `post`: $0.002 per post - count every social media post you extract. -- `profile`: $0.001 per profile - count every user profile you extract. -- `sentiment-analysis`: $0.005 per post - count every post analyzed for sentiment, engagement metrics, and content classification using external LLM APIs. +- `profile`: $0.005 per profile - count every user profile you extract. +- `sentiment-analysis`: $0.01 per post - count every post analyzed for sentiment, engagement metrics, and content classification using external LLM APIs. :::info Fixed pricing vs. usage-based pricing @@ -346,15 +346,13 @@ Fixed pricing is simpler for users to predict, while usage-based pricing more ac Paid plan
5,000 × post
-
50 × profile
-
2,000 × sentiment-analysis
+
1,000 × sentiment-analysis
5,000 × $0.002
-
50 × $0.001
-
2,000 × $0.005
+
1,000 × $0.01
- $20.05 + $20 $2.50 @@ -362,15 +360,13 @@ Fixed pricing is simpler for users to predict, while usage-based pricing more ac Paid plan
3,000 × post
-
20 × profile
-
1,000 × sentiment-analysis
+
500 × sentiment-analysis
3,000 × $0.002
-
20 × $0.001
-
1,000 × $0.005
+
500 × $0.01
- $11.02 + $11 $1.50 @@ -378,15 +374,13 @@ Fixed pricing is simpler for users to predict, while usage-based pricing more ac Free plan
1,000 × post
-
5 × profile
-
200 × sentiment-analysis
+
100 × sentiment-analysis
1,000 × $0.002
-
5 × $0.001
-
200 × $0.005
+
100 × $0.01
- $3.01 + $3 $0.40 @@ -398,9 +392,9 @@ The platform usage costs are just examples, but you can see the actual costs in ### Revenue breakdown -- _Revenue (paid users only): $20.05 + $11.02 = $31.07_ -- _Platform cost (paid users only): $2.50 + $1.50 = $4.00_ -- _Profit: 0.8 × $31.07 − $4.00 = $20.86_ +- **Revenue (paid users only)**: $20 + $11 = **$31** +- **Platform cost (paid users only)**: $2.50 + $1.50 = **$4** +- **Profit**: 0.8 × $31 − $4 = **$20.80** ## Event names From 8c5b826b517ca69739b01c6ba5363299bf54e52f Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Wed, 1 Oct 2025 14:59:14 +0200 Subject: [PATCH 27/28] docs: Make example italic --- .../platform/actors/publishing/monetize/pay_per_event.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sources/platform/actors/publishing/monetize/pay_per_event.mdx b/sources/platform/actors/publishing/monetize/pay_per_event.mdx index a734fc0b98..5d0bc1be76 100644 --- a/sources/platform/actors/publishing/monetize/pay_per_event.mdx +++ b/sources/platform/actors/publishing/monetize/pay_per_event.mdx @@ -392,9 +392,9 @@ The platform usage costs are just examples, but you can see the actual costs in ### Revenue breakdown -- **Revenue (paid users only)**: $20 + $11 = **$31** -- **Platform cost (paid users only)**: $2.50 + $1.50 = **$4** -- **Profit**: 0.8 × $31 − $4 = **$20.80** +- _Revenue (paid users only)_: $20 + $11 = _\$31_ +- _Platform cost (paid users only)_: $2.50 + $1.50 = _\$4_ +- _Profit_: 0.8 × $31 − $4 = _\$20.80_ ## Event names From f287cf889acf12d0b254e5ec424c888173545477 Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Wed, 1 Oct 2025 15:19:55 +0200 Subject: [PATCH 28/28] docs: Improve API docs --- .../openapi/paths/actor-runs/actor-runs@{runId}@charge.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apify-api/openapi/paths/actor-runs/actor-runs@{runId}@charge.yaml b/apify-api/openapi/paths/actor-runs/actor-runs@{runId}@charge.yaml index 37cd655775..3f54eaaa80 100644 --- a/apify-api/openapi/paths/actor-runs/actor-runs@{runId}@charge.yaml +++ b/apify-api/openapi/paths/actor-runs/actor-runs@{runId}@charge.yaml @@ -7,8 +7,12 @@ post: The event you are charging for must be one of the configured events in your Actor. If the Actor is not set up as pay per event, or if the event is not configured, the endpoint will return an error. The endpoint must be called from the Actor run itself, with the same API token that the run was started with. + :::info Learn more about pay-per-event pricing + For more details about pay-per-event (PPE) pricing, refer to our [PPE documentation](/platform/actors/publishing/monetize/pay-per-event). + ::: + operationId: PostChargeRun parameters: - name: runId