{
  "openapi": "3.0.1",
  "info": {
    "title": "NASA Earthdata Search: Satellite Datasets and Data Files",
    "description": "Search NASA's Earth-science metadata catalog without a key: datasets by keyword, mission, instrument, data center, processing level, bounding box and time range, or the single data files of a dataset with size, day/night flag, footprint and download, S3 and OPeNDAP links.",
    "version": "0.1",
    "x-build-id": "a4IVX7QySfyJqIOVU"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/yadroo~nasa-earthdata-search/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-yadroo-nasa-earthdata-search",
        "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/yadroo~nasa-earthdata-search/runs": {
      "post": {
        "operationId": "runs-sync-yadroo-nasa-earthdata-search",
        "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/yadroo~nasa-earthdata-search/run-sync": {
      "post": {
        "operationId": "run-sync-yadroo-nasa-earthdata-search",
        "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": {
          "mode": {
            "title": "What one row stands for",
            "enum": [
              "collections",
              "granules"
            ],
            "type": "string",
            "description": "What one row stands for, one question per run. `collections`: one row per dataset - id, mission, data center, processing level, time span, footprint and how many files it holds. `granules`: one row per data file - acquisition window, size in megabytes, footprint and the download, S3, OPeNDAP and browse links. The source has no free-text search over files, so a `granules` run needs at least one `shortNames` or `conceptIds` value; with neither it stops and names both fields.",
            "default": "collections"
          },
          "query": {
            "title": "Search words",
            "type": "string",
            "description": "Free-text search over dataset title, summary, science keywords, mission and instrument names: `wildfire`, `sea surface temperature`, `nighttime lights`. Several words are one phrase ranked by the source, not three filters. Leave empty and use the filters below to list a whole mission or data center instead of searching. `collections` mode only: the source indexes no free text per file, so a `granules` run ignores this and narrows files by dataset (`shortNames`, `conceptIds`), place and time."
          },
          "shortNames": {
            "title": "Dataset short names",
            "maxItems": 20,
            "type": "array",
            "description": "The source's own short name of a dataset, the identifier printed in papers and user guides: `MOD11A1`, `VNP46A2`, `MUR-JPL-L4-GLOB-v4.1`. Several values are OR-combined; case and surrounding spaces do not matter. Every value is checked against the catalog first, and a name it does not know is never sent as a filter - it gets its own row with `found: false` and what to do instead. In `granules` mode this is how you name the dataset whose files you want.",
            "items": {
              "type": "string"
            }
          },
          "conceptIds": {
            "title": "Dataset concept ids",
            "maxItems": 20,
            "type": "array",
            "description": "The catalog's permanent dataset id, shaped `C<digits>-<DATACENTER>`: `C1748058432-LPCLOUD`, `C1996881146-POCLOUD`. Several values are combined with OR. Unlike a short name it never changes and never collides, so it is the id an agent or a pipeline should store. In `collections` mode each id returns its own dataset row; in `granules` mode each id returns that dataset's files. An id the catalog does not know gets a row with `found: false` instead of a wider search.",
            "items": {
              "type": "string"
            }
          },
          "platforms": {
            "title": "Satellite or platform",
            "maxItems": 10,
            "type": "array",
            "description": "Mission or platform names as the catalog writes them: `Terra`, `Aqua`, `Sentinel-3A`, `NOAA-20`, `Landsat-8`, `ICESat-2`, `SMAP`, `Suomi-NPP`, `BUOYS`. Several values are OR-combined. Case, spaces and the README's aliases are accepted (`terra`, `SENTINEL 3A`, `snpp`); a name outside the actor's list is checked against the catalog and refused with the closest names when nothing uses it. One dataset often lists many platforms, so this finds every dataset that used it.",
            "items": {
              "type": "string"
            }
          },
          "instruments": {
            "title": "Instrument",
            "maxItems": 10,
            "type": "array",
            "description": "Sensor names as the catalog writes them: `MODIS`, `VIIRS`, `SLSTR`, `OLI`, `ATLAS`, `AVHRR`, `AMSR2`, `GMI`, `ECOSTRESS`. Several values are OR-combined, and the filter pairs with `platforms` to separate one sensor on two satellites (`MODIS` on `Terra` versus on `Aqua`). Case and spaces do not matter; a name outside the actor's list is checked against the catalog and refused with the closest names when no dataset uses it. Dataset rows carry `platforms`, not instruments.",
            "items": {
              "type": "string"
            }
          },
          "providers": {
            "title": "Data center",
            "maxItems": 10,
            "type": "array",
            "description": "The archive that publishes the dataset, by its catalog id: `LPCLOUD` and `LAADS` (land and atmosphere), `POCLOUD` (ocean), `NSIDC_ECS` (snow and ice), `GES_DISC` (water cycle), `ORNL_CLOUD`, `ASF` (radar), `OB_DAAC`. Several values are OR-combined. This is the value every row carries in its `dataCenter` column, so filter and column use the same words. Case and spaces do not matter and spoken names such as `PO.DAAC` are read as their id; any other unknown id is refused with the closest ones.",
            "items": {
              "type": "string"
            }
          },
          "processingLevels": {
            "title": "Processing level",
            "type": "array",
            "description": "How far the data has been processed, OR-combined; empty means every level. `0` and `1*` are instrument radiances and brightness values, `2*` are geophysical values along the satellite track, `3` is gridded and averaged, `4` a model or analysis product, `NA` no level given. A map usually wants `3` or `4`. The platform refuses an off-list value before the run. `collections` mode only: the file endpoint knows no levels, so a `granules` run leaves this out and says so.",
            "items": {
              "type": "string",
              "enum": [
                "0",
                "1",
                "1A",
                "1B",
                "1C",
                "1T",
                "2",
                "2G",
                "2P",
                "3",
                "4",
                "NA"
              ],
              "enumTitles": [
                "0 - raw instrument data, unprocessed",
                "1 - instrument measurements, radiances and brightness values",
                "1A - instrument measurements with calibration data added",
                "1B - calibrated radiances",
                "1C - calibrated radiances, resampled",
                "1T - instrument measurements, terrain corrected",
                "2 - geophysical values along the satellite track",
                "2G - geophysical values gridded per orbit",
                "2P - geophysical values along the track, swath product",
                "3 - gridded and averaged, the usual choice for a map",
                "4 - model or analysis product blending several sources",
                "NA - no level given by the publisher"
              ]
            }
          },
          "boundingBox": {
            "title": "Bounding box (west, south, east, north)",
            "pattern": "^\\s*-?\\d+(\\.\\d+)?\\s*,\\s*-?\\d+(\\.\\d+)?\\s*,\\s*-?\\d+(\\.\\d+)?\\s*,\\s*-?\\d+(\\.\\d+)?\\s*$",
            "type": "string",
            "description": "Four numbers in degrees, in this order: westernmost longitude, southernmost latitude, easternmost longitude, northernmost latitude. `46,40,88,56` is Kazakhstan and its neighbours. Longitude runs -180 to 180, latitude -90 to 90. A dataset or a file matches when its own footprint overlaps the box at all, not when it lies inside it, so a global dataset matches every box. The order is the one the source uses; a value in the wrong shape is refused by the platform before the run starts."
          },
          "point": {
            "title": "Single point (longitude, latitude)",
            "pattern": "^\\s*-?\\d+(\\.\\d+)?\\s*,\\s*-?\\d+(\\.\\d+)?\\s*$",
            "type": "string",
            "description": "Longitude first, then latitude - `76.889,43.238` is Almaty, `-74.006,40.713` New York, `2.352,48.857` Paris. Keeps only datasets or files whose footprint covers that spot. Useful for the question people actually ask: \"what does NASA have over this city\". Longitude before latitude is the source's order and the opposite of what a map app shows, so check the numbers. Set either this or `boundingBox`, not both; if both are given the box wins and the run says so in its status message."
          },
          "temporalFrom": {
            "title": "Covers data from",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2})?Z?)?$",
            "type": "string",
            "description": "Start of the period you care about, as `2026-09-01` or `2026-09-01T00:00:00Z`, read as UTC. A dataset matches when its own time span overlaps the period; a file matches when its acquisition window does. Leave empty for no lower bound. Together with `temporalTo` this is the cheapest filter in `granules` mode, because the source applies it and the run then pays only for files inside the window - a dataset such as MOD11A1 holds over three million files, so always set a window or a small `maxItems`."
          },
          "temporalTo": {
            "title": "Covers data until",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2})?Z?)?$",
            "type": "string",
            "description": "End of the period, same format, inclusive, UTC. Leave empty for no upper bound - with only `temporalFrom` set you get everything from that date onwards, which is what a scheduled run wants. A dataset that is still being produced has no end date at all: its `timeEnd` is empty and its `ongoing` column is true, and it matches every period that starts after its `timeStart`."
          },
          "cloudHostedOnly": {
            "title": "Only datasets held in the cloud",
            "type": "boolean",
            "description": "Keep only datasets the archive has moved into cloud storage. Those are the ones whose files carry an `s3://` link, so a pipeline running in the same AWS region can read them directly instead of downloading them. Switch it on when the answer has to be usable from a cloud job; leave it off for a complete search, because many long archives are still only available over HTTPS. `collections` mode only: the file endpoint does not know this flag, so a `granules` run leaves it out and says so.",
            "default": false
          },
          "downloadableOnly": {
            "title": "Only datasets with downloadable files",
            "type": "boolean",
            "description": "Keep only datasets the catalog marks as having online access to its data. Filters out catalog entries that describe data obtainable by order, on tape, or on request only - a common surprise with older campaigns and field surveys.",
            "default": false
          },
          "withGranulesOnly": {
            "title": "Only datasets that already hold files",
            "type": "boolean",
            "description": "Keep only datasets with at least one file in the archive. The catalog also holds registered datasets whose files live elsewhere or have not been ingested yet; they are real entries but a `granules` run on them returns nothing. Switch this on before you collect ids for a `granules` run. `collections` mode only.",
            "default": false
          },
          "sort": {
            "title": "Order of the results",
            "enum": [
              "relevance",
              "newestData",
              "oldestData",
              "mostUsed",
              "title"
            ],
            "type": "string",
            "description": "Which rows you get first when `maxItems` cuts the answer, so it decides what you pay for. `relevance` only means something together with `query`; with the filters alone the source falls back to its own internal order. `newestData` is the one for monitoring - the newest files of a dataset come first. `mostUsed` exists for datasets only; in `granules` mode the run uses newest-first instead and says so in its status message.",
            "default": "relevance"
          },
          "onlyNew": {
            "title": "Skip rows seen in earlier runs",
            "type": "boolean",
            "description": "Remember the concept ids this run writes in the actor's key-value store and, on the next run of the same actor or task, write only ids that were not written before. This is the watch mode: a task in `granules` mode with one `shortNames` value, `sort` on newest first and a small `maxItems`, scheduled daily, then holds exactly the files that appeared since the last run - and pays for nothing else. The memory is kept per actor or task, so two tasks watching two datasets do not interfere.",
            "default": false
          },
          "maxItems": {
            "title": "Maximum rows",
            "minimum": 1,
            "maximum": 2000,
            "type": "integer",
            "description": "Hard cap on the rows this run writes, and therefore on what it costs. Paging stops as soon as the cap is reached. For scale: a keyword search over the datasets usually has tens to a few thousand matches, while a single long-running dataset can hold millions of files - which is why a `granules` run should always carry a time window, a place, or a small cap here.",
            "default": 25
          },
          "includeGranuleCounts": {
            "title": "Add the number of files per dataset",
            "type": "boolean",
            "description": "Fill the `granuleCount` column of a dataset row with how many files the archive holds for it. It is the fastest way to tell a continuously produced dataset from a one-off publication, and it tells you in advance how big a `granules` run on that dataset would be. Costs no extra request. `collections` mode only; a dataset the catalog keeps no count for keeps the column empty.",
            "default": true
          },
          "maxSummaryChars": {
            "title": "Length of the dataset summary",
            "minimum": 0,
            "maximum": 20000,
            "type": "integer",
            "description": "Dataset summaries run from one line to several pages. The `summary` column is cut to this many characters at a word boundary. `0` leaves the column out of the row altogether - the right setting for a wide export or for an agent with a small context window. `collections` mode only.",
            "default": 1200
          },
          "fields": {
            "title": "Only these columns",
            "type": "array",
            "description": "Keep only the named columns, in the order given - for example `title, shortName, dataCenter, granuleCount`. Empty = every column. `rowType`, `conceptId`, `title`, `url` and `fetchedAt` are always present; name one of them here and it moves to the position you gave it. Letter case does not matter and unknown names are reported in the status message instead of being dropped in silence; a list with no real column at all is refused.",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}