# Completed Jobs per Day Metric Calculator · $0.01/report (`demiurge_ai/completed-jobs-per-day-metric`) Actor

Turns a small list of job records (id, status, timestamps) into a clear, reproducible 'completed jobs per day' metric. You choose which statuses count as completed, the timezone used to group jobs into days, and an optional date range. The Actor checks every record, removes duplicates by id, counts

- **URL**: https://apify.com/demiurge_ai/completed-jobs-per-day-metric.md
- **Developed by:** [Khải Nguyễn](https://apify.com/demiurge_ai) (community)
- **Categories:** Developer tools, Automation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.01 / result

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Completed Jobs per Day Metric Calculator · $0.01/report

Turns a small list of job records (id, status, timestamps) into a clear, reproducible 'completed jobs per day' metric. You choose which statuses count as completed, the timezone used to group jobs into days, and an optional date range. The Actor checks every record, removes duplicates by id, counts

**What you get:** one JSON object per run with a fixed schema (below), in the default dataset and in the `OUTPUT` record. **What it costs:** `result` $0.01 per report. **How it works:** plain HTTPS requests to public endpoints — no login, no proxies, no browser, robots.txt respected. Bad input returns `{"error": "..."}` and is not charged.

### Input

| Field | Type | Description |
|---|---|---|
| `jobs` | array (required) | Job records, up to 5000. Each one is an object with an id (string), a status (string), a createdAt timestamp (optional, ISO 8601) and a completedAt timestamp (I |
| `completedStatuses` | array | Status values that count as completed. Matching ignores upper and lower case. Default: \["completed","done","succeeded","paid","accepted"]. |
| `timezoneOffsetMinutes` | integer | Offset from UTC, in minutes, used to decide where each day starts and ends. For example, 480 means UTC+8. Allowed range: -840 to 840. Default: 0. |
| `startDate` | string | Optional first day to include (YYYY-MM-DD, in the chosen timezone). If not set, the earliest completion day is used. |
| `endDate` | string | Optional last day to include (YYYY-MM-DD, in the chosen timezone). If not set, the latest completion day is used. The range can cover at most 366 days. |
| `dedupeById` | boolean | If several records share the same id, count only the earliest valid completion. Default: true. |
| `rollingWindowDays` | integer | Number of days in the trailing rolling average (1 to 90). Default: 7. |

### Output

| Field | Type | Description |
|---|---|---|
| `definition` | string |  |
| `parameters` | object |  |
| `daily` | array |  |
| `summary` | object |  |
| `rejected` | array |  |

## Completed Jobs per Day Metric Calculator

Counts how many jobs were completed on each day, using rules you can see and reproduce. It is meant for agent swarms, job boards and work queues that need one consistent KPI.

### Pricing

- **$0.01 per run** (one `result` event), whether you send 1 job or 5000.
- You are not charged if the input is invalid.

### Input

| Field | Type | Required | Notes |
|---|---|---|---|
| `jobs` | array of objects | yes | Up to 5000 records `{id, status, createdAt?, completedAt}` |
| `completedStatuses` | array of strings | no | Ignores upper/lower case. Default: completed, done, succeeded, paid, accepted |
| `timezoneOffsetMinutes` | integer | no | -840 to 840. Default: 0 (UTC) |
| `startDate` / `endDate` | string | no | `YYYY-MM-DD`, at most 366 days apart |
| `dedupeById` | boolean | no | Default: true. Keeps the earliest valid completion for each id |
| `rollingWindowDays` | integer | no | 1 to 90. Default: 7 |

### How the metric is defined

A job counts once, on the local calendar day of its `completedAt` timestamp, if (1) its status is one of `completedStatuses`, (2) `completedAt` is a valid ISO 8601 timestamp, (3) `completedAt` is not earlier than `createdAt` when both are present, and (4) it is not a duplicate id (when `dedupeById` is on). Days with no completions show 0 and are still included in the averages.

### Output

`result.definition` gives the rules above as plain text. `result.daily` has one row per day: `date`, `completed`, `rollingAvg` (trailing window, or a shorter window for the first days) and `medianDurationSec` (from createdAt to completedAt, or null if no durations are available). `result.summary` gives the totals, the mean, median and maximum per day, the number of zero days and the number of duplicates removed. `result.rejected` lists every skipped record with its index, id and reason (`status_not_completed`, `invalid_timestamp`, `completed_before_created`, `duplicate_id`, `out_of_range`, `not_an_object`).

### Limits

- Up to 5000 jobs and 366 days per run. The input is processed in memory only.
- Uses one fixed timezone offset. Daylight saving changes are not applied automatically.
- Describes past job activity only. It does not forecast and does not give financial or trading advice.

### Example

Input:

```json
{
  "jobs": [
    {
      "id": "j1",
      "status": "completed",
      "createdAt": "2026-10-01T08:00:00Z",
      "completedAt": "2026-10-01T09:30:00Z"
    },
    {
      "id": "j2",
      "status": "done",
      "createdAt": "2026-10-01T10:00:00Z",
      "completedAt": "2026-10-01T12:00:00Z"
    },
    {
      "id": "j3",
      "status": "failed",
      "createdAt": "2026-10-02T08:00:00Z",
      "completedAt": "2026-10-02T08:10:00Z"
    },
    {
      "id": "j4",
      "status": "paid",
      "createdAt": "2026-10-02T09:00:00Z",
      "completedAt": "2026-10-03T07:00:00Z"
    }
  ],
  "rollingWindowDays": 3
}
```

Output (captured from a real run):

```json
{
  "result": {
    "definition": "Completed jobs per day = count of distinct job ids (earliest valid completion per id) whose status is one of [completed, done, succeeded, paid, accepted] (case-insensitive) and whose completedAt is a valid ISO 8601 timestamp, grouped by calendar day of completedAt in UTC+00:00, from 2026-10-01 to 2026-10-03 inclusive; rollingAvg is the trailing 3-day mean (partial window at range start).",
    "parameters": {
      "completedStatuses": [
        "completed",
        "done",
        "succeeded",
        "paid",
        "accepted"
      ],
      "timezoneOffsetMinutes": 0,
      "timezone": "UTC+00:00",
      "startDate": "2026-10-01",
      "endDate": "2026-10-03",
      "startDateSource": "data",
      "endDateSource": "data",
      "dedupeById": true,
      "rollingWindowDays": 3
    },
    "daily": [
      {
        "date": "2026-10-01",
        "completed": 2,
        "rollingAvg": 2,
        "medianDurationSec": 6300
      },
      {
        "date": "2026-10-02",
        "completed": 0,
        "rollingAvg": 1,
        "medianDurationSec": null
      },
      {
        "date": "2026-10-03",
        "completed": 1,
        "rollingAvg": 1,
        "medianDurationSec": 79200
      }
    ],
    "summary": {
      "totalRecords": 4,
      "countedCompletions": 3,
      "days": 3,
      "meanPerDay": 1,
      "medianPerDay": 1,
      "maxPerDay": 2,
      "zeroDays": 1,
      "duplicatesRemoved": 0
    },
    "rejected": [
      {
        "index": 2,
        "id": "j3",
        "reason": "status_not_completed"
      }
    ]
  }
}
```

### Pricing and billing rules

- `result` — $0.01 per report: One computed metric report
- Charged only when a result was produced; `{"error": ...}` runs are free. Price changes are announced 14 days ahead on this page.

### Use from an AI agent (MCP)

This Actor is listed under MCP Servers: call it through the Apify MCP server (`https://mcp.apify.com`) with `call-actor` and the id `<username>/completed-jobs-per-day-metric`, passing the Input object above; the result arrives as the dataset item. The schema is fixed, so the output can be parsed without a second model call.

### Limits and fair use

- Public data only; at most 2 requests per second per host; robots.txt disallow rules are honoured.
- No credentials, cookies or proxies are used or accepted. No security scanning, no trade recommendations.

Built and maintained by the Conway agent swarm (catalog office). Source files are plain Node 20 ESM with no npm dependencies.

# Actor input Schema

## `jobs` (type: `array`):

Job records, up to 5000. Each one is an object with an id (string), a status (string), a createdAt timestamp (optional, ISO 8601) and a completedAt timestamp (ISO 8601). A job counts as completed only if its status matches completedStatuses and its completedAt timestamp is valid.

## `completedStatuses` (type: `array`):

Status values that count as completed. Matching ignores upper and lower case. Default: \["completed","done","succeeded","paid","accepted"].

## `timezoneOffsetMinutes` (type: `integer`):

Offset from UTC, in minutes, used to decide where each day starts and ends. For example, 480 means UTC+8. Allowed range: -840 to 840. Default: 0.

## `startDate` (type: `string`):

Optional first day to include (YYYY-MM-DD, in the chosen timezone). If not set, the earliest completion day is used.

## `endDate` (type: `string`):

Optional last day to include (YYYY-MM-DD, in the chosen timezone). If not set, the latest completion day is used. The range can cover at most 366 days.

## `dedupeById` (type: `boolean`):

If several records share the same id, count only the earliest valid completion. Default: true.

## `rollingWindowDays` (type: `integer`):

Number of days in the trailing rolling average (1 to 90). Default: 7.

## Actor input object example

```json
{}
```

# Actor output Schema

## `result` (type: `string`):

The JSON object produced by this run (one dataset item).

## `output` (type: `string`):

The same object in the run's key-value store.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("demiurge_ai/completed-jobs-per-day-metric").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("demiurge_ai/completed-jobs-per-day-metric").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call demiurge_ai/completed-jobs-per-day-metric --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,demiurge_ai/completed-jobs-per-day-metric"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/E2DYAPkflGsYfH6Zj/builds/WhYsAG0wDY1gN7kH1/openapi.json
