# Creative Scotland Opportunities Scraper (`memo23/creativescotland-scraper`) Actor

Scrape opportunities.creativescotland.com — Scotland's creative hub for jobs, workshops, festivals, training. Cloudflare WAF bypassed via residential proxy rotation. RSS feed gives every live opportunity with contact email auto-extracted. JSON or CSV out.

- **URL**: https://apify.com/memo23/creativescotland-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Jobs, AI, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.99 / 1,000 results

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Creative Scotland Opportunities Scraper

**Scrape opportunities.creativescotland.com — Scotland's creative-sector hub for paid jobs, workshops, training, festivals, and exhibitions.** The site sits behind Cloudflare's "Sorry, you have been blocked" WAF rule that hits ~90% of HTTP requests even from residential proxies. This actor solves that by **rotating residential proxy exits until one gets through**, then fetching the public `/api/rss/` endpoint which returns every live opportunity in a single XML feed. JSON or CSV out, no compute charge per run, just per result.

#### How it works

![How Creative Scotland Opportunities Scraper works](https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-creativescotland.png)

#### ✨ Why use this scraper?

Tracking Scotland's creative sector is *hard* — Creative Scotland's Opportunities tool is the central hub but Cloudflare's WAF makes direct scraping nearly impossible. This actor solves the proxy-rotation problem so you can focus on the data.

- 🛡️ **Cloudflare WAF bypassed.** No browser automation, no Camoufox, no `cf_clearance` cookie capture — just residential-proxy rotation. With 30 attempts (default), there's a **~96% chance** one Evomi/Apify-residential exit gets through.
- ⚡ **One successful fetch → 25+ opportunities.** Once we crack CF, `/api/rss/` returns the whole live list inline (title, link, contact email, description teaser, modified date).
- 🎨 **Jobs + workshops + festivals + training in one feed.** The actor auto-categorises each row by title (`type: "job"` vs `type: "opportunity"`), and tags `categories: ["job"|"workshop"|"event"|"training"|"opportunity"]` for downstream filtering.
- 📧 **Contact email captured.** Creative Scotland's RSS puts the organiser's contact email in `<guid>` for most items — extracted as `applyEmail` automatically.
- 🇬🇧 **Scotland-wide.** Edinburgh galleries, Highland community workshops, Glasgow theatres, rural craft schools, festival organisers.
- 📤 **Clean exports.** One row per opportunity. JSON + CSV exported automatically.

#### 🎯 Use cases

| Team | What they build |
|------|-----------------|
| **Creative-sector recruiters** | Daily new-vacancy feeds across Scottish arts orgs |
| **Festival / event aggregators** | Auto-populate Scotland-wide creative events calendars |
| **Craft schools / workshop platforms** | Discover competitor workshop offerings |
| **Funders & cultural strategists** | Track who's hiring + what training is being offered in Scottish creative sector |
| **Researchers** | Scottish creative labour-market datasets |

#### 📥 Supported inputs

| URL pattern | Behaviour |
|---|---|
| `https://opportunities.creativescotland.com/api/rss/` | **RSS feed** (default) — every live opportunity |
| `https://opportunities.creativescotland.com/opportunity/index/<uuid>` | **Single opportunity** — synthetic stub + optional detail fetch |
| (anything else on the domain) | Routed to the RSS feed |

Leave `startUrls` empty for the RSS feed.

#### ⚠️ Proxy requirement (mandatory)

Cloudflare blocks direct + datacenter requests instantly. **A residential proxy pool is REQUIRED.** Defaults to Apify Residential — you can also bring your own (Evomi, BrightData, Smartproxy, etc.) via the `proxy` input.

The actor rotates exits each retry (`Actor.createProxyConfiguration().newProxyInfo()` returns a fresh URL). With Apify Residential's pool size, you typically need 5–15 attempts to get through; we default `cfMaxAttempts` to 30 for ~96% success rate.

#### 🔄 How it works

1. **Resolve start URLs** — default is the RSS endpoint.
2. **For each URL**, attempt up to `cfMaxAttempts` times via the proxy pool:
   - Instantiate a fresh `impit` with a new proxy URL
   - GET with Firefox-144 UA + realistic accept headers
   - If `200 OK` AND body doesn't contain "Sorry, you have been blocked" → success
   - Otherwise, rotate and retry
3. **Parse the RSS** — extract title, link, opportunityId (UUID from link), guid (often contact email), description, modified date.
4. **Auto-categorise** each row by title keywords (officer/manager → `job`; workshop/class → `workshop`; festival/exhibition → `event`; course/school → `training`; else `opportunity`).
5. **Push one normalised row per opportunity.**
6. **Optional**: when `enrichDetail: true`, fetch each detail page via the same CF rotation (expensive — each detail call needs its own 5–30 attempts).

#### ⚙️ Input parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `startUrls` | array | `["https://opportunities.creativescotland.com/api/rss/"]` | RSS URL, opportunity URLs, or anything on the domain. |
| `enrichDetail` | boolean | `false` | When `true`, fetches each detail page for fuller body + structured organiser/location/deadline/fee. EXPENSIVE — each detail call needs its own CF rotation. |
| `cfMaxAttempts` | integer | `30` | Max proxy attempts per URL. Higher = more cost + slower; lower = risks giving up on CF too early. |
| `postedWithinHours` | integer | (none) | Only return rows posted in the last N hours (24 = last day, 72 = last 3 days). Empty/0 = all. Ideal for daily monitoring runs that only want fresh postings. |
| `maxItems` | integer | `1000` | Hard cap on rows pushed (~25 live opportunities). |
| `maxConcurrency` | integer | `3` | Parallel detail-page fetch limit (matters only with `enrichDetail: true`). |
| `maxRequestRetries` | integer | `5` | Reserved — superseded by `cfMaxAttempts` for this actor. |
| `proxy` | object | Apify Residential | **REQUIRED**. Default Apify Residential; bring-your-own Evomi/BrightData/Smartproxy also works. |

#### 📊 Output overview

Each scraped opportunity is one **single dataset row**. Jobs get `type: "job"`; everything else gets `type: "opportunity"`. The `cpt`-style discriminator is in `categories[0]` (`job` / `workshop` / `event` / `training` / `opportunity`).

#### 📦 Output sample

```json
{
  "type": "job",
  "source": "opportunities.creativescotland.com",
  "opportunityId": "86a158c5-89c5-4d2c-9a74-0a6fd30c9713",
  "jobId": "86a158c5-89c5-4d2c-9a74-0a6fd30c9713",
  "slug": "86a158c5-89c5-4d2c-9a74-0a6fd30c9713",
  "jobUrl": "https://opportunities.creativescotland.com/opportunity/index/86a158c5-89c5-4d2c-9a74-0a6fd30c9713",
  "opportunityUrl": "https://opportunities.creativescotland.com/opportunity/index/86a158c5-89c5-4d2c-9a74-0a6fd30c9713",
  "title": "Native Woodland Partnership Officer",
  "description": null,
  "descriptionText": "In this role you will lead the Trusts outreach for native woodland restoration across Scotland, developing several large scale projects.",
  "descriptionTeaser": "In this role you will lead the Trusts outreach for native woodland restoration across Scotland, developing several large scale projects.",
  "companyName": null,
  "companyWebsite": null,
  "companyDomain": "nts.org.uk",
  "location": null,
  "remote": false,
  "salary": null,
  "salaryRaw": null,
  "fee": null,
  "categories": ["job"],
  "employmentTypes": [],
  "contractType": null,
  "status": "publish",
  "postedDate": null,
  "closingDate": null,
  "modifiedDate": "2026-05-22T09:30:00.000Z",
  "applyType": "email",
  "applyUrl": "https://opportunities.creativescotland.com/opportunity/index/86a158c5-89c5-4d2c-9a74-0a6fd30c9713",
  "applyEmail": "workforus@nts.org.uk",
  "externalApplyUrl": null,
  "scrapedAt": "2026-05-22T20:01:00.000Z"
}
````

#### 🗂 Key output fields

| Group | Fields |
|---|---|
| **Identifiers** | `type` (`job` or `opportunity`), `source`, `opportunityId` (UUID), `jobId` (= opportunityId), `slug`, `jobUrl`, `opportunityUrl`, `scrapedAt` |
| **Content** | `title`, `description` (HTML, only when `enrichDetail: true`), `descriptionText` (plain), `descriptionTeaser` (from RSS) |
| **Dates** | `modifiedDate` (ISO from RSS `<a10:updated>`), `closingDate` (only with `enrichDetail`) |
| **Employer / organiser** | `companyName` (with `enrichDetail`), `companyDomain` (derived from contact email) |
| **Categorisation** | `categories[]` (auto-detected: `job` / `workshop` / `event` / `training` / `opportunity`) |
| **Apply flow** | `applyType` (`email` if contact email present, else `internal`), `applyUrl` (the opportunity page), `applyEmail` (from RSS `<guid>`) |
| **Optional (with `enrichDetail`)** | `location`, `fee`, full HTML description |

#### ❓ FAQ

**Why does the actor sometimes take 30+ retries to fetch one URL?**
Cloudflare's WAF blocks roughly 90% of residential proxy exits. The actor rotates exits each retry. With 30 attempts the probability of zero successes is `0.9^30 ≈ 4%`. If you see "CF rotation exhausted", bump `cfMaxAttempts` higher (up to 100) or use a larger residential pool.

**Why is `enrichDetail` off by default?**
Each detail-page fetch needs its own CF rotation (another 5-30 proxy attempts). For 25 items that's potentially 750 proxy hits. The RSS already includes title, link, contact email, description teaser, and modified date — enough for most use cases. Enable detail fetch only when you need the full HTML body / location / deadline / fee.

**Why does `type` sometimes say `opportunity` when it's clearly a workshop?**
`type` is a binary classifier (job vs not-job). The `categories[]` array carries the finer-grained label (`workshop` / `event` / `training` / `opportunity`). Filter on `categories[0]` for the specific shape.

**Can I scrape private pages or authenticated content?**
No. Only the public `/api/rss/` endpoint and public `/opportunity/index/<uuid>` pages.

**How do I limit results?**
Set `maxItems`. With ~25 live opportunities, `maxItems: 100` covers everything.

#### 💬 Support

- For issues or feature requests, please use the **Issues** tab on the actor's Apify Console page.
- Author's website: <https://muhamed-didovic.github.io/>
- Email: <muhamed.didovic@gmail.com>

#### 🛠 Additional services

- Custom output shape, additional fields, or one-off datasets: <muhamed.didovic@gmail.com>
- Cloudflare-WAF-bypass scrapers for other CF-protected sites in your portfolio (same residential-rotation pattern works on many): drop an email.
- For API access (no Apify fee, just usage): <muhamed.didovic@gmail.com>

#### 🔎 Explore more scrapers

See other scrapers at [memo23's Apify profile](https://apify.com/memo23) — covering job boards, real estate, social media, and more.

***

### ⚠️ Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Creative Scotland, Alba Chruthachail, or any of their subsidiaries or affiliates. All trademarks mentioned are the property of their respective owners.

The scraper accesses only the publicly available RSS feed and public opportunity pages on opportunities.creativescotland.com — no authenticated endpoints, recruiter-only features, or content behind a login. Cloudflare WAF rotation is used solely to overcome unintentional IP-reputation false positives that block legitimate scraping; we do not bypass JS challenges, CAPTCHAs, or any security mechanism that requires interactive verification. Users are responsible for ensuring their use complies with opportunities.creativescotland.com's Terms of Service, applicable data-protection law (GDPR, CCPA, etc.), and any contractual obligations of their own organisation.

***

### SEO Keywords

creative scotland scraper, scrape opportunities.creativescotland.com, creative scotland opportunities api, scottish creative sector jobs scraper, scottish arts jobs api, scotland workshops scraper, scottish festivals data, scottish creative jobs scraper, Apify creative scotland, cloudflare waf bypass scraper, residential proxy rotation scraper, scotland cultural sector jobs api, scottish gallery jobs scraper, scottish theatre jobs scraper, edinburgh creative jobs scraper, glasgow arts jobs scraper, asva alternative scraper, highlandjobs alternative scraper, s1jobs alternative scraper, scotland creative recruitment data

# Actor input Schema

## `startUrls` (type: `array`):

Supported shapes: `https://opportunities.creativescotland.com/api/rss/`, `https://opportunities.creativescotland.com/opportunity/index/<uuid>`. Leave empty for the RSS feed.

## `enrichDetail` (type: `boolean`):

When enabled, each opportunity triggers its own Cloudflare-rotation fetch (up to `cfMaxAttempts` proxies). With ~10% pass rate per proxy, expect ~10× proxy usage per item. DEFAULT: off — the RSS already includes title, link, contact email, description teaser, modified date for every opportunity.

## `cfMaxAttempts` (type: `integer`):

Cloudflare blocks ~90% of residential proxy exits. With 30 attempts you have a ~96% chance at least one gets through. Higher = more cost + slower; lower = risks giving up.

## `postedWithinHours` (type: `integer`):

Filters on each row's posted date. Set 24 for the last day, 72 for the last 3 days, etc. Leave empty (or 0) to return everything regardless of age. Rows whose source has no posted date are always kept.

## `maxItems` (type: `integer`):

Hard cap on rows pushed (~25 live at any time).

## `maxConcurrency` (type: `integer`):

Parallel detail-page fetches (only matters with `enrichDetail: true`).

## `minConcurrency` (type: `integer`):

Reserved.

## `maxRequestRetries` (type: `integer`):

Reserved — superseded by `cfMaxAttempts` for this actor.

## `proxy` (type: `object`):

Leave empty — the actor already routes all traffic through its own built-in residential proxy at no extra cost to you. Only set this if you want to use your own proxies.

## Actor input object example

```json
{
  "startUrls": [
    "https://opportunities.creativescotland.com/api/rss/"
  ],
  "enrichDetail": false,
  "cfMaxAttempts": 30,
  "postedWithinHours": 24,
  "maxItems": 1000,
  "maxConcurrency": 3,
  "minConcurrency": 1,
  "maxRequestRetries": 5
}
```

# 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 = {
    "startUrls": [
        "https://opportunities.creativescotland.com/api/rss/"
    ],
    "postedWithinHours": 24
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/creativescotland-scraper").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 = {
    "startUrls": ["https://opportunities.creativescotland.com/api/rss/"],
    "postedWithinHours": 24,
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/creativescotland-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "startUrls": [
    "https://opportunities.creativescotland.com/api/rss/"
  ],
  "postedWithinHours": 24
}' |
apify call memo23/creativescotland-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=memo23/creativescotland-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Creative Scotland Opportunities Scraper",
        "description": "Scrape opportunities.creativescotland.com — Scotland's creative hub for jobs, workshops, festivals, training. Cloudflare WAF bypassed via residential proxy rotation. RSS feed gives every live opportunity with contact email auto-extracted. JSON or CSV out.",
        "version": "0.0",
        "x-build-id": "l5qc4EMzcgPBolO0r"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/memo23~creativescotland-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-memo23-creativescotland-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/memo23~creativescotland-scraper/runs": {
            "post": {
                "operationId": "runs-sync-memo23-creativescotland-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/memo23~creativescotland-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-memo23-creativescotland-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "startUrls": {
                        "title": "opportunities.creativescotland.com URLs",
                        "type": "array",
                        "description": "Supported shapes: `https://opportunities.creativescotland.com/api/rss/`, `https://opportunities.creativescotland.com/opportunity/index/<uuid>`. Leave empty for the RSS feed.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "enrichDetail": {
                        "title": "Fetch each detail page (EXPENSIVE — each retries through Cloudflare rotation)",
                        "type": "boolean",
                        "description": "When enabled, each opportunity triggers its own Cloudflare-rotation fetch (up to `cfMaxAttempts` proxies). With ~10% pass rate per proxy, expect ~10× proxy usage per item. DEFAULT: off — the RSS already includes title, link, contact email, description teaser, modified date for every opportunity.",
                        "default": false
                    },
                    "cfMaxAttempts": {
                        "title": "Max proxy attempts per URL before giving up",
                        "minimum": 5,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Cloudflare blocks ~90% of residential proxy exits. With 30 attempts you have a ~96% chance at least one gets through. Higher = more cost + slower; lower = risks giving up.",
                        "default": 30
                    },
                    "postedWithinHours": {
                        "title": "Only rows posted in the last N hours",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Filters on each row's posted date. Set 24 for the last day, 72 for the last 3 days, etc. Leave empty (or 0) to return everything regardless of age. Rows whose source has no posted date are always kept."
                    },
                    "maxItems": {
                        "title": "Maximum opportunities to scrape",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Hard cap on rows pushed (~25 live at any time).",
                        "default": 1000
                    },
                    "maxConcurrency": {
                        "title": "Max concurrency",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Parallel detail-page fetches (only matters with `enrichDetail: true`).",
                        "default": 3
                    },
                    "minConcurrency": {
                        "title": "Min concurrency",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Reserved.",
                        "default": 1
                    },
                    "maxRequestRetries": {
                        "title": "Max request retries",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Reserved — superseded by `cfMaxAttempts` for this actor.",
                        "default": 5
                    },
                    "proxy": {
                        "title": "Proxy configuration (optional override)",
                        "type": "object",
                        "description": "Leave empty — the actor already routes all traffic through its own built-in residential proxy at no extra cost to you. Only set this if you want to use your own proxies."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
