{
  "openapi": "3.0.1",
  "info": {
    "title": "FINN Jobs Scraper: Norway Job Ads, Employers",
    "description": "FINN jobb ads across Norway with the full ad page, by keyword, place, FINN's job filters, employer or link, read past FINN's 2,500 ad cap, no login. Rows: job title, employer, org number, søknadsfrist, sector, skills, apply system, salary benchmark add-on. Monitor alerts, pay per job, Excel, API.",
    "version": "0.1",
    "x-build-id": "zxsY81xrVJFkR0Ztk"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/automation_craft~finn-jobs-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-automation_craft-finn-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/automation_craft~finn-jobs-scraper/runs": {
      "post": {
        "operationId": "runs-sync-automation_craft-finn-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/automation_craft~finn-jobs-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-automation_craft-finn-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": {
          "keywords": {
            "title": "Keywords",
            "type": "array",
            "description": "Search words, each one its own search (\"sykepleier\", \"utvikler\", \"lærer\", \"elektriker\"). Left empty, every FINN job is searched (newest first). FINN matches words in the title and the ad text.",
            "items": {
              "type": "string"
            }
          },
          "jobTypes": {
            "title": "Job searches",
            "type": "array",
            "description": "Which FINN job searches to read: all FINN jobs (the default), part time, management, or the NAV job ads FINN shows beside its own.",
            "items": {
              "type": "string",
              "enum": [
                "all",
                "parttime",
                "management",
                "nav"
              ],
              "enumTitles": [
                "All FINN jobs (full and part time)",
                "Part time jobs",
                "Management jobs",
                "NAV job ads shown on FINN"
              ]
            }
          },
          "employerIds": {
            "title": "Employer account ids",
            "type": "array",
            "description": "Every job ad of one employer: FINN employer account ids (the companyId of a job row, such as \"3761115\"), each its own search. FINN's account filter also covers the account's sister accounts (one staffing group posting under several names).",
            "items": {
              "type": "string"
            }
          },
          "searchUrls": {
            "title": "Job search links",
            "type": "array",
            "description": "Job search pages copied from FINN.no (https://www.finn.no/job/search?...), read with all their filters. FINN's sort order in a link is not sent (FINN asks robots not to); the link is read in FINN's default order.",
            "items": {
              "type": "string"
            }
          },
          "adUrls": {
            "title": "Job ad links or FINN codes",
            "type": "array",
            "description": "Job ad links (https://www.finn.no/job/ad/<FINN code>) or FINN codes (finnkode): each read with its full ad page and billed as one Job. An expired, removed or unknown ad is a free status row.",
            "items": {
              "type": "string"
            }
          },
          "locations": {
            "title": "Places",
            "type": "array",
            "description": "Counties, municipalities or districts by FINN's Norwegian name (\"Oslo\", \"Bergen\", \"Trøndelag\", \"Utlandet\" for abroad) or FINN's value (\"0.20061\"). Several places are one search (any of them).",
            "items": {
              "type": "string",
              "enumSuggestedValues": [
                "Agder",
                "Akershus",
                "Buskerud",
                "Finnmark",
                "Innlandet",
                "Møre og Romsdal",
                "Nordland",
                "Oslo",
                "Rogaland",
                "Telemark",
                "Troms",
                "Trøndelag",
                "Vestfold",
                "Vestland",
                "Østfold",
                "Utlandet"
              ]
            }
          },
          "latitude": {
            "title": "Latitude",
            "minimum": 57,
            "maximum": 81,
            "type": "number",
            "description": "With longitude and radiusKm: jobs around a point in Norway (FINN's own map radius)."
          },
          "longitude": {
            "title": "Longitude",
            "minimum": 4,
            "maximum": 32,
            "type": "number",
            "description": "With latitude and radiusKm."
          },
          "radiusKm": {
            "title": "Radius (km)",
            "minimum": 1,
            "maximum": 500,
            "type": "integer",
            "description": "With latitude and longitude: the distance in kilometres."
          },
          "occupations": {
            "title": "Occupations",
            "type": "array",
            "description": "Occupation fields by FINN's name (\"Analyse\", \"Helse\", \"IT utvikling\", \"Annet\"). Not together with industries: FINN asks robots not to combine them.",
            "items": {
              "type": "string"
            }
          },
          "industries": {
            "title": "Industries",
            "type": "array",
            "description": "Industries by FINN's name (\"Bank, finans og forsikring\", \"Helse og omsorg\", \"IT\"). Not together with occupations.",
            "items": {
              "type": "string"
            }
          },
          "extents": {
            "title": "Full or part time",
            "type": "array",
            "description": "\"Heltid\" (full time) or \"Deltid\" (part time).",
            "items": {
              "type": "string"
            }
          },
          "employmentTypes": {
            "title": "Employment type",
            "type": "array",
            "description": "\"Fast\" (permanent), \"Vikariat\" (temporary), \"Engasjement\" (fixed term), \"Prosjekt\", \"Sesong\", \"Lærling\" (apprentice), \"Bemanningsbyrå\" (staffing agency) and the other types FINN lists.",
            "items": {
              "type": "string"
            }
          },
          "sectors": {
            "title": "Sector",
            "type": "array",
            "description": "\"Privat\", \"Offentlig\", \"Organisasjoner\", \"Samvirke\", \"Franchise/Selvstendig næringsdrivende\".",
            "items": {
              "type": "string"
            }
          },
          "remoteOptions": {
            "title": "Home office",
            "type": "array",
            "description": "\"Kun hjemmekontor\" (fully remote), \"Delvis hjemmekontor\" (hybrid), \"Ingen hjemmekontor\".",
            "items": {
              "type": "string"
            }
          },
          "educationLevels": {
            "title": "Education",
            "type": "array",
            "description": "\"Videregående\", \"Fagbrev\", \"Fagskole\", \"Høyskole/universitet, lavere nivå\", \"Høyskole/universitet, høyere nivå\", \"Doktorgrad\" and the other levels FINN lists.",
            "items": {
              "type": "string"
            }
          },
          "experienceLevels": {
            "title": "Work experience",
            "type": "array",
            "description": "\"Ingen erfaring\" (none), \"Junior\", \"Erfaren\" (experienced), \"Leder\" (manager).",
            "items": {
              "type": "string"
            }
          },
          "workingLanguages": {
            "title": "Working language",
            "type": "array",
            "description": "\"Norsk\" or \"Engelsk\".",
            "items": {
              "type": "string"
            }
          },
          "managerRoles": {
            "title": "Manager role",
            "type": "array",
            "description": "\"Leder\", \"Fagleder\", \"Direktør\".",
            "items": {
              "type": "string"
            }
          },
          "deadlineWithin": {
            "title": "Application deadline within",
            "enum": [
              "oneDay",
              "threeDays",
              "oneWeek"
            ],
            "type": "string",
            "description": "Only jobs whose application deadline falls within this window (FINN's own deadline filter). Jobs whose deadline is \"Snarest\" (as soon as possible) have no date and are left out by it."
          },
          "postedToday": {
            "title": "New today",
            "type": "boolean",
            "description": "Only jobs FINN marks as new today (\"Nye i dag\").",
            "default": false
          },
          "includeNavAds": {
            "title": "Include NAV job ads",
            "type": "boolean",
            "description": "FINN also shows job ads copied from NAV (Arbeidsplassen): they are left out unless this is on (or the NAV job search is chosen). Rows say jobSource FINN or NAV.",
            "default": false
          },
          "attributeFilters": {
            "title": "Any other FINN job filter",
            "type": "object",
            "description": "Any other filter of FINN's job search by FINN's name or Norwegian label, with values by label or value. For example {\"education\": [\"Fagbrev\"], \"home_office\": [\"Delvis hjemmekontor\"]}."
          },
          "postedAfter": {
            "title": "Posted on or after",
            "type": "string",
            "description": "Only jobs published on or after this day in Norway (YYYY-MM-DD), checked on every row."
          },
          "postedWithinHours": {
            "title": "Posted within (hours)",
            "minimum": 1,
            "maximum": 8760,
            "type": "integer",
            "description": "Only jobs published within this many hours of the run's start, checked on every row."
          },
          "includeKeywords": {
            "title": "Must contain",
            "type": "array",
            "description": "Words a job must contain (its title and full description). Any one of them, or all with requireAllKeywords.",
            "items": {
              "type": "string"
            }
          },
          "requireAllKeywords": {
            "title": "Require all words",
            "type": "boolean",
            "description": "With includeKeywords: every word must be in the job.",
            "default": false
          },
          "excludeKeywords": {
            "title": "Must not contain",
            "type": "array",
            "description": "Jobs holding any of these words are left out, free.",
            "items": {
              "type": "string"
            }
          },
          "titleOnly": {
            "title": "Look in titles only",
            "type": "boolean",
            "description": "includeKeywords and excludeKeywords look at the job title only.",
            "default": false
          },
          "excludeAdIds": {
            "title": "Exclude FINN codes",
            "type": "array",
            "description": "FINN codes (finnkode) or job ad links never to deliver.",
            "items": {
              "type": "string"
            }
          },
          "maxItems": {
            "title": "Maximum jobs",
            "minimum": 1,
            "maximum": 200000,
            "type": "integer",
            "description": "The most paid rows the run delivers (jobs, change rows, removed rows), across all searches and links.",
            "default": 100
          },
          "maxItemsPerSearch": {
            "title": "Maximum jobs per search",
            "minimum": 1,
            "maximum": 200000,
            "type": "integer",
            "description": "The most paid rows from one search or search link."
          },
          "maxPagesPerSearch": {
            "title": "Maximum pages per search",
            "minimum": 1,
            "maximum": 20000,
            "type": "integer",
            "description": "The most result pages read for one search (50 jobs a page)."
          },
          "maxRowsPerSearch": {
            "title": "Rows read per search (window)",
            "minimum": 1,
            "maximum": 200000,
            "type": "integer",
            "description": "How many rows of each search are read at most; a monitor reads this window of every search every run (100 by default)."
          },
          "includeSalaryBenchmark": {
            "title": "Add FINN's salary benchmark (add-on)",
            "type": "boolean",
            "description": "Add FINN's salary figures for the job's title (median, average, lower and upper quartile, number of salaries, data quality, from finn.no/job/salary) to each job whose normalised title FINN's salary pages list. Billed as one Salary benchmark per distinct title per run, on the first job that carries it; jobs with the same title in the same run get it free.",
            "default": false
          },
          "resolveApplyTarget": {
            "title": "Resolve the apply link",
            "type": "boolean",
            "description": "Name the employer's own application page and system (Webcruiter, Recman, Teamtailor, Jobbnorge, ReachMee and others) behind FINN's apply button: one extra read of FINN's apply redirect per FINN job that has one (FINN may count it as a click on its apply button; the target itself is never opened). Included in the Job price.",
            "default": false
          },
          "markPaidPlacements": {
            "title": "Mark paid placements",
            "type": "boolean",
            "description": "Read FINN's paid placement slot (\"Betalt plassering\") of each search once and mark a job row that FINN also sells there (paidPlacement). FINN rotates the slot, so a run sees one paid ad per search.",
            "default": false
          },
          "includePersonalData": {
            "title": "Include personal data",
            "type": "boolean",
            "description": "Deliver the job's contact persons (names, titles, phone and mobile numbers, e-mail addresses) and the contacts written in the job text (with extractContacts). Off: those fields are empty; the employer's name, organisation number, website, address and logo are business data and always delivered. You are responsible for a lawful use, GDPR included.",
            "default": false
          },
          "includeRawData": {
            "title": "Include raw search row",
            "type": "boolean",
            "description": "Add FINN's search row as served.",
            "default": false
          },
          "descriptionFormat": {
            "title": "Description format",
            "enum": [
              "asServed",
              "text",
              "markdown"
            ],
            "type": "string",
            "description": "How the job description is delivered.",
            "default": "asServed"
          },
          "descriptionMaxLength": {
            "title": "Description maximum length",
            "minimum": 20,
            "maximum": 100000,
            "type": "integer",
            "description": "Cut descriptions to this many characters (descriptionCut marks the row)."
          },
          "compactOutput": {
            "title": "Compact rows",
            "type": "boolean",
            "description": "Deliver only the most used fields (handy for AI agents).",
            "default": false
          },
          "excludeEmptyFields": {
            "title": "Leave out empty fields",
            "type": "boolean",
            "description": "Drop fields that are empty on a row.",
            "default": false
          },
          "extractContacts": {
            "title": "Extract contacts from texts",
            "type": "boolean",
            "description": "Add the e-mail addresses, phone numbers, websites and social profiles written in the job title and description (with includePersonalData on: job texts name people).",
            "default": false
          },
          "phoneExtractionMode": {
            "title": "Phone extraction",
            "enum": [
              "strict",
              "lenient"
            ],
            "type": "string",
            "description": "With extractContacts."
          },
          "monitorName": {
            "title": "Monitor name",
            "type": "string",
            "description": "Name a monitor to deliver only jobs new to it on every scheduled run (each job billed once; each search page a monitor run reads is a Results page, also on a day with nothing new). The memory belongs to this Actor; up to 60 characters."
          },
          "resetMonitor": {
            "title": "Reset the monitor",
            "type": "boolean",
            "description": "Forget what the monitor delivered and start again (a run that restarts never resets).",
            "default": false
          },
          "trackChanges": {
            "title": "Track changes",
            "type": "boolean",
            "description": "With a monitor: deliver a known job again when its title, job title, place or status changed (updated), and report a job the monitor delivered once it is gone from its complete searches and its page shows it removed or expired (removed). Each such row is billed as a Job.",
            "default": false
          },
          "emitUnchanged": {
            "title": "Deliver unchanged jobs too",
            "type": "boolean",
            "description": "With a monitor: deliver known jobs again as unchanged (billed as a Job).",
            "default": false
          },
          "markReposts": {
            "title": "Mark reposts",
            "type": "boolean",
            "description": "With a monitor: mark a new job whose title and employer match one the monitor delivered (possibleRepostOf).",
            "default": false
          },
          "skipReposts": {
            "title": "Skip reposts",
            "type": "boolean",
            "description": "With markReposts: leave reposts out, free.",
            "default": false
          },
          "telegramBotToken": {
            "title": "Telegram bot token",
            "type": "string",
            "description": "Send the jobs of the run to Telegram through your own bot (the token BotFather gave you)."
          },
          "telegramChatId": {
            "title": "Telegram chat id",
            "type": "string",
            "description": "Your chat id, or a channel name starting with @."
          },
          "slackWebhookUrl": {
            "title": "Slack webhook link",
            "type": "string",
            "description": "A Slack incoming webhook link (https://hooks.slack.com/...)."
          },
          "discordWebhookUrl": {
            "title": "Discord webhook link",
            "type": "string",
            "description": "A Discord webhook link (https://discord.com/api/webhooks/...)."
          },
          "whatsappAccessToken": {
            "title": "WhatsApp access token",
            "type": "string",
            "description": "Your WhatsApp Cloud API token."
          },
          "whatsappPhoneNumberId": {
            "title": "WhatsApp phone number id",
            "type": "string",
            "description": "Your WhatsApp Cloud API phone number id (digits)."
          },
          "whatsappTo": {
            "title": "WhatsApp recipient",
            "type": "string",
            "description": "The number to send to, in international form without +, such as 4791234567."
          },
          "webhookUrl": {
            "title": "Webhook link",
            "type": "string",
            "description": "Your own https endpoint: the rows are POSTed to it as JSON in batches of 100."
          },
          "webhookSecret": {
            "title": "Webhook secret",
            "type": "string",
            "description": "Signs each webhook call (header X-Signature-Sha256, HMAC SHA-256 of the body); 16 to 200 characters."
          },
          "webhookHeaders": {
            "title": "Webhook headers",
            "type": "object",
            "description": "Extra headers for the webhook (at most 10)."
          },
          "notificationLimit": {
            "title": "Jobs per notification",
            "minimum": 1,
            "maximum": 30,
            "type": "integer",
            "description": "How many jobs a message lists (10 by default)."
          },
          "notifyOnlyChanges": {
            "title": "Notify changes only",
            "type": "boolean",
            "description": "With trackChanges: notify changed and removed jobs, not new ones.",
            "default": false
          },
          "failIfIncomplete": {
            "title": "Fail if incomplete",
            "type": "boolean",
            "description": "End the run as failed when a search or link could not be read in full (the rows delivered stay).",
            "default": false
          },
          "maxFailedRequestsPercent": {
            "title": "Fail above this share of failed reads (%)",
            "minimum": 1,
            "maximum": 100,
            "type": "integer",
            "description": "End the run as failed when more of its reads failed."
          },
          "proxyConfiguration": {
            "title": "Proxy",
            "type": "object",
            "description": "Leave as is: FINN is read through Apify's datacenter proxy, which every FINN job door answers. Your own proxy links replace it."
          },
          "requestsPerSecond": {
            "title": "Requests per second",
            "minimum": 0.2,
            "maximum": 2,
            "type": "number",
            "description": "The pace of the run's one exit (0.2 to 2).",
            "default": 1
          },
          "maxConcurrency": {
            "title": "Requests in flight",
            "minimum": 1,
            "maximum": 4,
            "type": "integer",
            "description": "At most this many requests in flight, inside the pace (FINN is never asked more than requestsPerSecond requests a second): job ad pages are read on this many lanes.",
            "default": 4
          },
          "maxRequestRetries": {
            "title": "Retries",
            "minimum": 0,
            "maximum": 5,
            "type": "integer",
            "description": "Tries of a failed read after the first.",
            "default": 2
          }
        }
      },
      "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}