{
  "openapi": "3.0.1",
  "info": {
    "title": "Join Datasets: VLOOKUP & Merge Two Datasets or CSV Files",
    "description": "Join two Apify datasets or CSV, JSON or Excel files by a key, like VLOOKUP or a SQL join: add the fields of the matching lookup row to each row. Match on text, exact values or website domains; left, inner or anti join. Enrich scraper results with other actors' data. Pay per row.",
    "version": "0.1",
    "x-build-id": "HwYVOYd3YYpMgybhq"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/humble-echidna~dataset-join/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-humble-echidna-dataset-join",
        "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/humble-echidna~dataset-join/runs": {
      "post": {
        "operationId": "runs-sync-humble-echidna-dataset-join",
        "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/humble-echidna~dataset-join/run-sync": {
      "post": {
        "operationId": "run-sync-humble-echidna-dataset-join",
        "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",
        "required": [
          "joinOn"
        ],
        "properties": {
          "datasetId": {
            "title": "Main data: Apify dataset",
            "type": "string",
            "description": "The rows to add fields to (every output row is one of these): the id or name of one of your own Apify datasets, e.g. a Google Maps or product scraper's results (or pick one in the form). To run this actor after a scraper in an integration, `{{resource.defaultDatasetId}}`. Read-only, with your own account's access. When it's set, fileUrl is ignored."
          },
          "fileUrl": {
            "title": "Or: main data file URL (CSV, JSON, JSONL or Excel)",
            "type": "string",
            "description": "Used only when datasetId is empty: a direct link to a CSV/TSV, JSON (a list of objects), JSON Lines or Excel (.xlsx, first sheet) file on a public web address (http/https, ports 80 and 443), up to 200 MB. The default is the US Treasury's official exchange rates for 2025-12-31, the example's main data.",
            "default": "https://api.fiscaldata.treasury.gov/services/api/fiscal_service/v1/accounting/od/rates_of_exchange?format=csv&filter=record_date:eq:2025-12-31&page[size]=300"
          },
          "lookupDatasetId": {
            "title": "Lookup data: Apify dataset",
            "type": "string",
            "description": "The rows with the fields to add (like the second table of a VLOOKUP): one of your own Apify datasets, e.g. Tech Stack Detector's or a contact scraper's results. Read-only. When it's set, lookupFileUrl is ignored."
          },
          "lookupFileUrl": {
            "title": "Or: lookup data file URL",
            "type": "string",
            "description": "Used only when lookupDatasetId is empty: a direct link to the lookup CSV, JSON, JSONL or Excel file. The default is the same Treasury table a year earlier (2024-12-31), the example's lookup data; it's only used together with the example's main data, never with your own.",
            "default": "https://api.fiscaldata.treasury.gov/services/api/fiscal_service/v1/accounting/od/rates_of_exchange?format=csv&filter=record_date:eq:2024-12-31&page[size]=300"
          },
          "joinOn": {
            "title": "Join on (the field that links them)",
            "type": "array",
            "description": "The field that links a main row to its lookup row(s), one pair per line: `field` when both sides call it the same (e.g. `url`), or `main field = lookup field` when they don't (e.g. `website = domain`). Several lines join on all of them together (`name` and `city`). Dots reach nested fields (`address.postalCode`). The default is the example's key.",
            "default": [
              "country_currency_desc"
            ],
            "items": {
              "type": "string"
            }
          },
          "matchAs": {
            "title": "Match values as",
            "enum": [
              "text",
              "exact",
              "domain"
            ],
            "type": "string",
            "description": "How key values are compared. `text` (the default): upper/lower case, spaces at either end or repeated, and how accents are encoded are ignored; 12 and \"12\" match. `exact`: only number formatting is ignored. `domain`: the website's domain, so https://www.acme.com/about, acme.com and info@acme.com all match acme.com (for joining leads on websites).",
            "default": "text"
          },
          "joinType": {
            "title": "Which rows to keep",
            "enum": [
              "left",
              "inner",
              "anti"
            ],
            "type": "string",
            "description": "`left` (the default): every main row, with the lookup fields filled in when it matched and null when it didn't. `inner`: only main rows that matched. `anti`: only main rows that didn't match, with no lookup fields (e.g. leads not in your CRM yet).",
            "default": "left"
          },
          "multipleMatches": {
            "title": "When a key matches several lookup rows",
            "enum": [
              "first",
              "all"
            ],
            "type": "string",
            "description": "`first` (the default): like VLOOKUP, the first lookup row with the key wins, so each main row gives exactly one output row. `all`: one output row per matching lookup row, like a SQL join (e.g. a company with three contacts gives three rows).",
            "default": "first"
          },
          "lookupFields": {
            "title": "Lookup fields to add (and rename)",
            "type": "array",
            "description": "The lookup fields to add to each main row, one per line: `field`, or `field -> new name` to rename it (e.g. `technologies -> stack`). Leave empty (the default) to add every lookup field. A field the main row already has is added as `lookup_<name>`, so the main row's values are never overwritten.",
            "items": {
              "type": "string"
            }
          },
          "lookupPrefix": {
            "title": "Prefix for the added fields",
            "type": "string",
            "description": "Optional text put in front of every added field's name, e.g. `crm_` gives `crm_owner`, `crm_stage`. Default: none."
          },
          "addMatchedField": {
            "title": "Add a matched true/false field",
            "type": "boolean",
            "description": "Default true: add `joinMatched` (true when the row found a lookup row) to every output row, to filter or count matches later.",
            "default": true
          },
          "maxResults": {
            "title": "Max rows per run",
            "minimum": 1,
            "type": "integer",
            "description": "Stop after writing this many rows, e.g. 100. Minimum 1; leave empty (the default) for no limit. The run also stops cleanly at the maximum cost per run you set in the run options, whichever comes first."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}