{
  "openapi": "3.0.1",
  "info": {
    "title": "PureStream — Turn Messy Data into Trusted Insights with Clarity",
    "description": "Consistently clean, validate, and reshape an Apify Dataset. You can join, stack, or summarize datasets. Parse numbers and dates, validate email fields, and flatten nested JSON. Accepted rows will be moved to a new dataset, while rejected rows will go to quarantine with the reason for rejection noted",
    "version": "0.3",
    "x-build-id": "5vhy3M5ccSEXZIA5J"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/ahmedmohamed~purestream/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-ahmedmohamed-purestream",
        "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/ahmedmohamed~purestream/runs": {
      "post": {
        "operationId": "runs-sync-ahmedmohamed-purestream",
        "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/ahmedmohamed~purestream/run-sync": {
      "post": {
        "operationId": "run-sync-ahmedmohamed-purestream",
        "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": {
          "sourceDatasetId": {
            "title": "Source dataset",
            "type": "string",
            "description": "The dataset to clean. Picking it here is what grants this run read access, so a dataset named only inside a config file cannot be read. Leave empty to run a tiny built-in sample (what Apify Daily uses). A config file still needs this field, matching the file's source.dataset_id. Read-only: the Actor never writes to your source."
          },
          "job": {
            "title": "Job",
            "enum": [
              "dedupe",
              "append",
              "join",
              "filter",
              "columns",
              "summarise"
            ],
            "type": "string",
            "description": "One job for this run. Leave empty to pass the dataset through. A config file below ignores this."
          },
          "additionalDatasetIds": {
            "title": "Additional datasets",
            "type": "array",
            "description": "Used when Job is Append datasets (every picked dataset) or Join on keys (exactly one), and by a config file's inputs. Picking them here is what grants this run read access — a dataset named only inside a config file cannot be read."
          },
          "pipeline": {
            "title": "Config file",
            "type": "object",
            "description": "A config file for the whole cleaning, pasted as JSON. When set, Job is ignored, but Source dataset is still required, and the file's source.dataset_id must name that same dataset. See the operation reference for the format, or paste the prompt from the README into an LLM and describe your data. Use this or Config file URL, not both."
          },
          "pipelineUrl": {
            "title": "Config file URL",
            "type": "string",
            "description": "An https:// URL of the same config file. Use this or Config file, not both."
          },
          "jobColumns": {
            "title": "Saved-task columns",
            "type": "array",
            "description": "Accepted from a saved task or the API. The form shows a Columns field inside each job instead, and that field is the one a new run reads.",
            "items": {
              "type": "string"
            }
          },
          "dedupeColumns": {
            "title": "Columns that mark a copy",
            "type": "array",
            "description": "The columns that decide whether two rows are copies.",
            "items": {
              "type": "string"
            }
          },
          "dedupeKeep": {
            "title": "Copy to keep",
            "enum": [
              "first",
              "last"
            ],
            "type": "string",
            "description": "Used when Job is Dedupe by fields. Which copy to keep.",
            "default": "first"
          },
          "keepDropColumns": {
            "title": "Columns to keep or drop",
            "type": "array",
            "description": "The columns to keep, or to drop, as chosen below.",
            "items": {
              "type": "string"
            }
          },
          "columnsMode": {
            "title": "Keep or drop",
            "enum": [
              "keep",
              "drop"
            ],
            "type": "string",
            "description": "Used when Job is Keep or drop columns.",
            "default": "keep"
          },
          "filterColumns": {
            "title": "Column to test",
            "type": "array",
            "description": "The one column to compare. This job takes exactly one name.",
            "items": {
              "type": "string"
            }
          },
          "filterOp": {
            "title": "Comparison",
            "enum": [
              "eq",
              "ne",
              "gt",
              "ge",
              "lt",
              "le"
            ],
            "type": "string",
            "description": "Used when Job is Filter rows. A text column compares as text, letter by letter: \"10\" sorts before \"9\", and letters after digits.",
            "default": "eq"
          },
          "filterValue": {
            "title": "Value to compare with",
            "type": "string",
            "description": "Used when Job is Filter rows, and required then: a blank value is refused before anything is read. A number column takes a plain number, with no separators. A true or false column takes true or false. A date column is not filtered from here."
          },
          "summariseColumns": {
            "title": "Columns that set the group",
            "type": "array",
            "description": "The columns that define a group. Leave empty for one row covering the whole dataset.",
            "items": {
              "type": "string"
            }
          },
          "aggregate": {
            "title": "Calculation",
            "enum": [
              "count",
              "n_unique",
              "sum",
              "mean",
              "median",
              "std",
              "var",
              "min",
              "max",
              "first",
              "last",
              "list"
            ],
            "type": "string",
            "description": "Used when Job is Summarise.",
            "default": "count"
          },
          "aggregateColumn": {
            "title": "Column to calculate on",
            "type": "string",
            "description": "Used when Job is Summarise and the calculation is not count of rows. The column the calculation reads."
          },
          "aggregateInto": {
            "title": "Result column",
            "type": "string",
            "description": "Used when Job is Summarise. Name of the column the calculation is written to.",
            "default": "count"
          },
          "joinColumns": {
            "title": "Key columns",
            "type": "array",
            "description": "The key names shared by both datasets.",
            "items": {
              "type": "string"
            }
          },
          "joinHow": {
            "title": "Join kind",
            "enum": [
              "left",
              "inner",
              "semi",
              "anti"
            ],
            "type": "string",
            "description": "Used when Job is Join on keys.",
            "default": "left"
          },
          "joinCardinality": {
            "title": "Can a key repeat?",
            "enum": [
              "one_to_one",
              "many_to_one",
              "many_to_many"
            ],
            "type": "string",
            "description": "Used when Job is Join on keys. Required for that job. The run refuses a join that omits it. The run checks what you choose, except Both sides may repeat a key, which is taken as stated."
          },
          "joinSuffix": {
            "title": "Suffix for a column both datasets hold",
            "type": "string",
            "description": "Used when Job is Join on keys. When both datasets hold a column besides the keys, the second dataset's copy is renamed with this suffix: url beside url_right.",
            "default": "_right"
          },
          "joinKeysAsText": {
            "title": "Compare keys as text",
            "type": "boolean",
            "description": "Used when Job is Join on keys. On, both datasets' keys are compared as text, so a key held as a number in one (5) matches the same digits held as text in the other (\"5\"), and the key is written as text. Off, a key must hold the same type in both.",
            "default": false
          },
          "dryRun": {
            "title": "Dry run",
            "type": "boolean",
            "description": "Check without writing. It reports the cleaning that would run, the columns you would get, and every configuration error at once. It writes nothing, but it does read every input the run would read, not just Source dataset: Append datasets and Join on keys name more datasets under Additional datasets, and a config file names its own inputs. Those are read in full, the same way the real run does, so the cost grows with how many inputs the config file declares. It reports what the real run would be charged and what the size check would decide, and refuses on neither: the real run checks the charge against your spending limit before it reads anything, and the size once its input is downloaded.",
            "default": false
          },
          "previewRows": {
            "title": "Preview rows",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Try the cleaning on a sample. It reads at most this many items, runs the real operations over them, writes nothing, and returns the first rows it would accept and the first it would reject. This is a sample, not a dry run. The columns of a sample can differ from the columns of the whole dataset, because a name or a value that only appears later cannot be seen here. Leave empty for a normal run."
          },
          "quarantineDatasetName": {
            "title": "Quarantine dataset",
            "type": "string",
            "description": "The six jobs do not reject rows, so a job run does not create this dataset. A config file names its quarantine inside the file.",
            "default": "purestream-quarantine"
          },
          "engine": {
            "title": "Engine",
            "enum": [
              "streaming",
              "in-memory"
            ],
            "type": "string",
            "description": "How the run executes. Streaming keeps memory bounded and is the default. In-memory is faster but holds the whole dataset at once. Some operations cannot stream, and with a memory ceiling set those are refused by name before the run starts rather than left to run out of memory.",
            "default": "streaming"
          },
          "redactValues": {
            "title": "Redact values in error messages",
            "type": "boolean",
            "description": "On by default. A rejection names the field, never the value, so a run's logs never carry your data.",
            "default": true
          },
          "releaseLeafInputs": {
            "title": "Release inputs after their last reader (diagnostic)",
            "type": "boolean",
            "description": "A diagnostic switch for memory measurement, not an ordinary run option — leave it on. On (default), a combined dataset's memory is freed as soon as the last operation that reads it finishes; off holds every input live for the whole run, which is only useful for comparing peak memory between the two.",
            "default": true
          },
          "refuseOversized": {
            "title": "Refuse a dataset too large for the container (diagnostic)",
            "type": "boolean",
            "description": "A diagnostic switch for memory measurement, not an ordinary run option — leave it on. On (default), a run too large for the container is refused: before any item is read when the datasets' stored sizes alone show it cannot fit, and otherwise once its input has been downloaded and measured, before it is loaded into memory. Off lets it run anyway, which is only useful for measuring where the limit really is.",
            "default": true
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}