{
  "openapi": "3.0.1",
  "info": {
    "title": "France Travail Jobs Scraper — 777K FR Offers + Employer Phone",
    "description": "Scrape France Travail (candidat.francetravail.fr), the French state job board: 777,220 live offers, 2026-09-06. Filter by keyword, departement, contract, salary, posting age. Offer pages add pay, NAF sector, full text and the recruiter's phone: 37.8% on France Travail's own offers, 0% on syndicated.",
    "version": "0.1",
    "x-build-id": "aaLhJJtgrZwFYkHM3"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/scrapersdelight~france-travail-jobs-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-scrapersdelight-france-travail-jobs-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/scrapersdelight~france-travail-jobs-scraper/runs": {
      "post": {
        "operationId": "runs-sync-scrapersdelight-france-travail-jobs-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/scrapersdelight~france-travail-jobs-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-scrapersdelight-france-travail-jobs-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": {
          "searchTerms": {
            "title": "Search terms (mots-clés)",
            "type": "array",
            "description": "Free-text keywords, one crawl per term — sent to France Travail as `motsCles`. Accents and spaces work (\"agent de sécurité\" resolves fine). MAY BE LEFT EMPTY: with a location alone you get the whole geographic slice, which is the sweep a staffing agency actually wants — measured 30,291 live offers for Paris (75) with no keyword at all (2026-09-06).",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "location": {
            "title": "Locations (departement, region or commune)",
            "type": "array",
            "description": "Maps to `lieux`. Three verified forms: `75D` departement (all 106 codes shipped, incl. `2AD`, `2BD`, `971D`…`988D`), `11R` INSEE region, or a 5-digit commune INSEE code (`69123` = Lyon). Region supply measured 2026-09-06: 11 Île-de-France 122,040 · 84 Auvergne-Rhône-Alpes 115,549 · 75 Nouvelle-Aquitaine 73,189 · 76 Occitanie 63,014 · 52 Pays de la Loire 62,501 · 44 Grand Est 62,178 · 93 PACA 59,444 · 53 Bretagne 55,906 · 32 Hauts-de-France 47,847 · 28 Normandie 38,778 · 27 Bourgogne-Franche-Comté 33,025 · 24 Centre-Val de Loire 31,885 · 04 La Réunion 4,959 · 94 Corse 2,214 · 02 Martinique 1,563 · 01 Guadeloupe 1,345 · 03 Guyane 1,239 · 06 Mayotte 544. France Travail IGNORES a repeated `lieux`, so each entry here is crawled as its own query and the results merged.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "startUrls": {
            "title": "France Travail URLs",
            "type": "array",
            "description": "Paste France Travail result URLs. BOTH shapes are accepted and both paginate: the raw search `https://candidat.francetravail.fr/offres/recherche?motsCles=comptable&lieux=59D` and the canonical SEO path `https://candidat.francetravail.fr/offres/emploi/comptable/nord/s12m1d59`. (Through the API this field takes objects, `[{\"url\": \"https://…\"}]`, not bare strings.) Canonical paths are enumerable from France Travail's own sitemaps — 27,454 métier × departement and 38,850 métier × ville `<loc>` entries counted 2026-09-06 — which is what the métier slicing modes below use. A `/rechercheoffre/emploi/...` URL is a link hub with no result list and is skipped; if every URL you give is skipped the run stops and says which ones and why, rather than crawling something else.",
            "default": [],
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "contractTypes": {
            "title": "Contract types",
            "type": "array",
            "description": "Maps to `typeContrat`. Measured on commercial/Paris 2026-09-06: CDI 1,770 · CDD 312 · MIS (intérim) 61 · SAI (saisonnier) 0 (\"Aucune offre\"). France Travail takes only the FIRST `typeContrat` when it is repeated, so several selections are crawled as separate queries and merged.",
            "items": {
              "type": "string",
              "enum": [
                "CDI",
                "CDD",
                "MIS",
                "SAI"
              ],
              "enumTitles": [
                "CDI — permanent",
                "CDD — fixed term",
                "MIS — intérim / temp",
                "SAI — saisonnier / seasonal"
              ]
            },
            "default": []
          },
          "postedWithinDays": {
            "title": "Posted within (days)",
            "enum": [
              "0",
              "1",
              "3",
              "7",
              "14",
              "31"
            ],
            "type": "string",
            "description": "Maps to `emission` — the hiring-TRIGGER lever. Measured on commercial/Paris 2026-09-06: 1 day 102 · 7 days 612 · 31 days 1,513 of 2,201 total. Set this to 1 or 3 and schedule the run to get a clean \"new roles since yesterday\" feed. 0 = no age filter.",
            "default": "0"
          },
          "radiusKm": {
            "title": "Radius around a commune (km)",
            "enum": [
              "0",
              "10",
              "20",
              "30",
              "50"
            ],
            "type": "string",
            "description": "Maps to `rayon`, and it WORKS ONLY with a 5-digit commune INSEE code in \"Locations\". Measured on commercial + Lyon 69123, 2026-09-06: 503 offers at 0 km, 1,554 at 10 km, 1,877 at 20 km, 2,164 at 30 km, 2,769 at 50 km. Note that France Travail's own default when no `rayon` is sent is 10 km (1,554, identical to an explicit rayon=10), so this actor always sends the value — including `rayon=0` — for a commune search, otherwise \"0 km\" would silently return the 10 km result (runs QSayG4Wc47wdR56De at 0 km and ymql3VTaHUJcdqz85 at 10 km). It is INERT at departement (`75D`) and region (`11R`) level (comptable+59D answers 1,097 with and without it), so it is not sent for those.",
            "default": "0"
          },
          "salaryMin": {
            "title": "Minimum salary (EUR)",
            "minimum": 0,
            "type": "integer",
            "description": "Maps to `salaireMin`, always paired with the period below. Measured on commercial/Paris 2026-09-06: 30,000 annual → 1,218 offers; 2,000 monthly → 2,158. 0 = off.",
            "default": 0
          },
          "salaryPeriod": {
            "title": "Salary period",
            "enum": [
              "A",
              "M"
            ],
            "type": "string",
            "description": "The period the minimum salary above is expressed in — maps to `periodeSalaire`.",
            "default": "A"
          },
          "weeklyHours": {
            "title": "Full time / part time",
            "enum": [
              "0",
              "1",
              "2"
            ],
            "type": "string",
            "description": "Maps to `dureeHebdo`. Measured on commercial/Paris 2026-09-06: full time 231 · part time 9 (the site only sets this flag on a minority of offers, so it is a narrowing filter, not a split of the whole list).",
            "default": "0"
          },
          "qualificationLevel": {
            "title": "Qualification level (0–9)",
            "type": "string",
            "description": "Maps to `qualification`, France Travail's own qualification ladder from 0 (manœuvre) to 9 (cadre). Measured on commercial/Paris 2026-09-06: 0 → 765 offers, 9 → 630. Leave empty for any level.",
            "default": ""
          },
          "professionalDomain": {
            "title": "Professional domain code",
            "type": "string",
            "description": "Maps to `domaine`, e.g. `M17` (commerce/vente). Measured 439 offers on commercial/Paris 2026-09-06. NOTE — France Travail DROPS this parameter when there is no keyword, and you then get the whole board back, so it is only sent alongside a search term.",
            "default": ""
          },
          "includePartnerOffers": {
            "title": "Include partner-board offers",
            "type": "boolean",
            "description": "Maps to `offresPartenaires`. France Travail republishes offers syndicated from HelloWork, APEC, Meteojob, Cadremploi, TalentPlug, DirectEmploi and ~30 other boards. High impact and measured: commercial/Paris returns 2,201 with partners and 155 without (2026-09-06). Every row is stamped with `offerOrigin` and `isPartnerOffer` either way, so you can tell them apart downstream.",
            "default": true
          },
          "onlyDirectEmployerOffers": {
            "title": "Only France-Travail-original offers",
            "type": "boolean",
            "description": "Keep only rows whose origin is France Travail itself — filed with the state service directly, not syndicated from a commercial job board. Applied on our side over the rows, so nothing you drop is billed. The site lists its OWN offers first: on a full 1,000-row comptable/Nord sweep (run dEcliLfEWocFWlpN4, 2026-09-06) the first 60 rows were 60/60 direct and the sweep as a whole was 78 direct to 922 syndicated, across 34 origin boards. THIS IS THE COHORT SELECTOR FOR EVERY RICH FIELD. Measured 2026-09-06 on run e82xg4ftZkb8KqWOR (497 enriched): direct offers carry a recruiter phone 37.8% of the time against 0.0% for syndicated ones, a named contact 39.2% against 0.0%, skills 97.3% against 0.0% and an employer page URL 62.2% against 0.7%. Because this filter runs on the RESULT LIST, syndicated offers are dropped before their pages are ever fetched: run DaPhQaiDHjc6zJwvd made 23 offer-page requests where run n5kXSn6PLfM1hj2tN, the same recipe without it, made 1,000.",
            "default": false
          },
          "excludeKeywords": {
            "title": "Exclude keywords",
            "type": "array",
            "description": "Drop offers whose title, teaser or employer name contains any of these (case-insensitive). France Travail has no server-side NOT, so this runs on our side — excluded rows are never billed.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "fetchOfferDetails": {
            "title": "Fetch offer details",
            "type": "boolean",
            "description": "One extra request per offer that unlocks the fields the result list does not carry. FILL DEPENDS ON WHO PUBLISHED THE OFFER, and the gap is not small. Measured 2026-09-06, run e82xg4ftZkb8KqWOR (comptable/Nord 59D crawled 25 pages deep: 500 delivered, 497 enriched, 506 detail calls, 3 failures) — France Travail's OWN offers (n=74) / SYNDICATED partner offers (n=423) / the blend over all 497: recruiter PHONE 37.8% / 0.0% / 5.6% · named contact 39.2% / 0.0% / 5.8% · skills 97.3% / 0.0% / 14.5% · employer page URL 62.2% / 0.7% / 9.9% · headcount band 68.9% / 27.0% / 33.2% · NAF sector 100% / 71.6% / 75.9% · pay figures 75.7% / 70.0% / 70.8% · experience, qualification level, métier code, dates and the full offer text 100% on both. A full-depth 1,000-row sweep of that query (run OMOJ5VkckkbcB5PLV) is 92.3% syndicated, so a deep crawl lands near the blended column and a shallow one near the direct column. Use \"Only direct-employer offers\" to select the rich cohort. Bills the separate `job-detail-enriched` event, only for rows that really came back enriched.",
            "default": false
          },
          "onlyWithPhone": {
            "title": "Only offers with a recruiter phone",
            "type": "boolean",
            "description": "Keep only rows that carry `employerPhone` — the direct line of the person recruiting. THE PHONE IS ON DIRECT OFFERS ONLY: measured 2026-09-06 on run e82xg4ftZkb8KqWOR (497 enriched offers), France Travail's own offers carry one 37.8% of the time (28 of 74) and syndicated partner offers 0.0% of the time (0 of 423); the blend over all 497 was 5.6%, because a full-depth slice is ~92% syndicated (923 of 1,000, run OMOJ5VkckkbcB5PLV). So turn \"Only direct-employer offers\" ON with this: it drops the syndicated offers BEFORE their pages are fetched. Measured on the same recipe with and without that flag — run DaPhQaiDHjc6zJwvd made 23 offer-page requests in 3 min 07 s and delivered 9 rows; run n5kXSn6PLfM1hj2tN made 1,000 requests in 9 min 48 s and delivered 6. Turns \"Fetch offer details\" on automatically, because the phone only exists on the offer page. Dropped rows are never billed.",
            "default": false
          },
          "onlyWithSalary": {
            "title": "Only offers with a published salary",
            "type": "boolean",
            "description": "Keep only rows with a numeric `salaryMin`. Measured 2026-09-06 on run e82xg4ftZkb8KqWOR (497 enriched offers): 70.8% overall, 75.7% on France Travail's own offers and 70.0% on syndicated ones — the one enriched field that barely differs between the two. Verified on run QYDNpVtamg1eRM4Y4 (100 delivered of 140 candidates, 28 dropped): 0 of 100 delivered rows had a null `salaryMin`, including the one row whose offer-page fetch failed — a failed fetch can no longer satisfy this filter. Turns \"Fetch offer details\" on automatically, because the figures only exist on the offer page. Dropped rows are never billed.",
            "default": false
          },
          "sliceBy": {
            "title": "Slice the corpus (beats the 1,000-row cap)",
            "enum": [
              "none",
              "departement",
              "region",
              "contractType",
              "postedWindow",
              "metierDepartement",
              "metierVille"
            ],
            "type": "string",
            "description": "France Travail hard-caps EVERY query at 1,000 rows — 50 pages of 20, verified by asking for 160 pages and receiving exactly 50. Coverage past that needs partitioning, which is what this does. `departement` and `region` re-run your search once per French place code; `contractType` once per CDI/CDD/MIS/SAI; `postedWindow` once per 1/3/7/14/31-day bucket; `metierDepartement` and `metierVille` pull France Travail's own sitemaps (27,454 and 38,850 canonical métier × place pages, counted 2026-09-06) and crawl the ones matching \"Métier filter\" and \"Locations\". Every slice is deduplicated on the offer number before anything is billed, so overlapping sweeps never double-charge.",
            "default": "none"
          },
          "sliceMetiers": {
            "title": "Métier filter (for the métier slicing modes)",
            "type": "array",
            "description": "Substrings matched against the métier slug of France Travail's canonical URLs — e.g. `infirmier`, `chauffeur`, `comptable`, `electricien`. Accent- and case-insensitive. Leave empty and the \"Search terms\" above are used instead. Only read by the `metierDepartement` / `metierVille` slicing modes.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "maxSlices": {
            "title": "Max slices per run",
            "minimum": 1,
            "maximum": 5000,
            "type": "integer",
            "description": "Upper bound on how many QUERIES a sweep expands into — places × keywords × contract types, not places alone — so a métier × ville run cannot quietly become 38,850 crawls. Run xa0KdP4wf4qSmmZPM: 2 keywords × departement at maxSlices 6 expanded to exactly 6 queries / 120 rows, and the log says so when it caps. Each slice is up to 1,000 rows.",
            "default": 25
          },
          "maxResults": {
            "title": "Max offers (whole run)",
            "minimum": 0,
            "type": "integer",
            "description": "Hard stop across every query and slice, counted in rows DELIVERED. 0 = no limit. Note the site's own ceiling: any single query tops out at 1,000 rows, so going past that needs a slicing mode above.",
            "default": 100
          },
          "maxResultsPerQuery": {
            "title": "Max offers per query",
            "minimum": 0,
            "maximum": 1000,
            "type": "integer",
            "description": "Per-query stop, counted in rows DELIVERED by that query (not rows read), useful when you sweep many slices and want an even sample from each. It is enforced inside the page, so a cap of 50 delivers exactly 50, not the whole 60-row page that contains the 50th — run iJ051hyiCALkCOMbn saw 120 candidates across 2 queries and delivered exactly 100. 0 = the site's own ceiling of 1,000.",
            "default": 0
          },
          "maxPagesPerQuery": {
            "title": "Max pages per query (20 offers each)",
            "minimum": 1,
            "maximum": 50,
            "type": "integer",
            "description": "Cheap early exit for buyers who only want the freshest page or two. The site itself stops at 50 pages; higher values are clamped to 50.",
            "default": 50
          },
          "deduplicateBy": {
            "title": "Deduplicate by",
            "enum": [
              "offerId",
              "none"
            ],
            "type": "string",
            "description": "The 7-character France Travail offer number (e.g. `213KBGC`) is the national identifier the vacancy is published under, and it is the dedupe key. Verified 1,000 unique offer numbers across a contiguous 1,000-row / 50-page crawl (run dEcliLfEWocFWlpN4, 2026-09-06); the real collision risk is BETWEEN slices — a 5-window postedWindow sweep saw 260 candidates and dropped 153 as duplicates (run QH9XE2ffhxyVhK59H) — which is why deduplication is global to the run and applied before anything is billed.",
            "default": "offerId"
          },
          "outputFormat": {
            "title": "Output shape",
            "enum": [
              "flat",
              "nested"
            ],
            "type": "string",
            "description": "`flat` gives one level of plain columns, which is what a CRM / Clay / Sheets import wants, and it is the shape the dataset's field types and table views describe. `nested` groups the same values under employer / location / contract / salary / profile / dates objects for API consumers — the Console's table views do not apply to that shape.",
            "default": "flat"
          },
          "includeRawHtml": {
            "title": "Include the raw offer-page HTML",
            "type": "boolean",
            "description": "Debug lever — attaches the offer page's raw HTML to each enriched row. Makes the dataset very large; off by default.",
            "default": false
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Apify DATACENTER is the tested default and it is enough. Measured 2026-09-06: a bare home IP answers HTTP 200 with a 143,571-byte result page, the default datacenter pool delivered 40 rows in 5 s (run VcVf9ITvpfYIAeA58) and RESIDENTIAL-FR delivered 20 rows in 21 s (run ZpO0tPNcEAaWeHPPf) — same rows, no geo-block on any rung. A rival actor's claim that this site \"requires residential proxies to bypass geo-restrictions\" is measurably false — do not pay for residential here.",
            "default": {
              "useApifyProxy": true
            }
          },
          "proxyCountry": {
            "title": "Proxy country (optional)",
            "type": "string",
            "description": "Two-letter country for the Apify proxy, e.g. `FR`. Left EMPTY on purpose — no geo-block was measured from any exit IP on 2026-09-06, so pinning a country only narrows the pool. Note that Apify's shared DATACENTER group has no country selection (it answers 407), so setting this switches the run to RESIDENTIAL proxies, which cost more. Both returned rows the same minute (runs VcVf9ITvpfYIAeA58 datacenter, ZpO0tPNcEAaWeHPPf RESIDENTIAL-FR).",
            "default": ""
          },
          "maxConcurrency": {
            "title": "Max concurrency",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "Parallel offer-page fetches. Offer-page latency is the site's and it varies by slice and by hour, so more parallelism does not reliably buy speed: a same-moment A/B on infirmier/Rhône for 30 enriched offers took 4 min 37 s at 10 (run Dhj55MdPvDdWEQrnl) against 4 min 52 s at 5 (run IJz32jZThTIWRGfEM), while a 500-offer deep run at 5 finished in 9 min 11 s (run e82xg4ftZkb8KqWOR, 497/500 enriched, 506 detail calls, 3 failures) — all 2026-09-06. 5 is the default, 10 the cap. The result-list crawl is always sequential — its pagination is server-side session state that concurrency would break.",
            "default": 5
          },
          "maxRequestRetries": {
            "title": "Max request retries",
            "minimum": 0,
            "maximum": 5,
            "type": "integer",
            "description": "Across 2026-09-06's 41 platform runs — 71 queries, 303 result-list pages and 1,179 offer-page fetches — exactly one fetch failed after both of its attempts (0.07%), and it was a socket-level status 0. Never a 403, never a challenge, never a rate limit. A retry on a FRESH proxy exit is what clears them; 2 is the default.",
            "default": 2
          },
          "requestTimeoutSecs": {
            "title": "Request timeout (seconds)",
            "minimum": 15,
            "maximum": 180,
            "type": "integer",
            "description": "Per-request timeout. 60 s is comfortable for the biggest result pages — the comptable/Nord page 0 measured 143,571 bytes on 2026-09-06.",
            "default": 60
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}