{
  "openapi": "3.0.1",
  "info": {
    "title": "Dataset to REST API (Sync Rows to Any API)",
    "description": "Sends every row of an Apify dataset, file or Google Sheet URL, or JSON array to any REST API as its own request. Templated URL, body and headers with {{field}} placeholders, auth presets, rate limits, retries. One result row per request. Charged per answered request. Agent-ready via x402 and MCP.",
    "version": "0.1",
    "x-build-id": "P0vYKAJ1zAICv7Rhz"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/nerolabs~dataset-to-rest-api/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-nerolabs-dataset-to-rest-api",
        "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/nerolabs~dataset-to-rest-api/runs": {
      "post": {
        "operationId": "runs-sync-nerolabs-dataset-to-rest-api",
        "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/nerolabs~dataset-to-rest-api/run-sync": {
      "post": {
        "operationId": "run-sync-nerolabs-dataset-to-rest-api",
        "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": [
          "url"
        ],
        "properties": {
          "datasetId": {
            "title": "Dataset to send",
            "type": "string",
            "description": "Pick an existing Apify dataset (for example the output of any scraper run). Use this OR 'File URL' OR 'Data (inline)' below. Declaring it this way is what lets this Actor run with limited permissions: it may read the dataset you point at, and nothing else on your account."
          },
          "fileUrl": {
            "title": "File URL (CSV, Excel, JSON or Google Sheet)",
            "type": "string",
            "description": "Instead of a dataset, download the rows from a public link: a CSV or TSV file, an Excel .xlsx file (first sheet, header row), a JSON array or JSON Lines file, or a Google Sheet (paste the normal sheet link, sharing set to 'Anyone with the link can view'). The format is detected automatically. Up to 100 MB per run. The download is never charged; only requests that get a reply are."
          },
          "data": {
            "title": "Data (inline)",
            "type": "array",
            "description": "A JSON array of records to send, for ad-hoc data instead of a dataset ID or file URL."
          },
          "fileFormat": {
            "title": "File format",
            "enum": [
              "auto",
              "csv",
              "tsv",
              "json",
              "jsonl",
              "xlsx"
            ],
            "type": "string",
            "description": "Only needed if automatic detection gets the file URL's format wrong.",
            "default": "auto"
          },
          "url": {
            "title": "Endpoint URL",
            "type": "string",
            "description": "The endpoint each row is sent to, for example https://api.example.com/contacts. Put a placeholder in the path to hit a per-row URL: https://api.example.com/contacts/{{id}}. Values in the URL are URL-encoded automatically."
          },
          "method": {
            "title": "HTTP method",
            "enum": [
              "POST",
              "PUT",
              "PATCH",
              "GET",
              "DELETE"
            ],
            "type": "string",
            "description": "POST to create, PUT or PATCH to update, GET or DELETE for requests with no body.",
            "default": "POST"
          },
          "bodyMode": {
            "title": "Request body",
            "enum": [
              "row",
              "template",
              "none"
            ],
            "type": "string",
            "description": "'Send the whole row' posts the row exactly as it is, which is what most APIs that accept JSON want. 'Use a body template' sends only the shape you define below, so you can rename and nest fields to match the API. 'No body' sends nothing (automatic for GET and DELETE).",
            "default": "row"
          },
          "bodyTemplate": {
            "title": "Body template (JSON)",
            "type": "object",
            "description": "Used when 'Request body' is set to the template option. Any JSON shape, with {{field}} placeholders. A value that is exactly one placeholder keeps the row's real type, so {\"mrr\": \"{{mrr}}\"} sends the number 49, not the text \"49\". Nesting and arrays are supported."
          },
          "queryParams": {
            "title": "Query parameters (JSON)",
            "type": "object",
            "description": "Optional. Added to the URL as ?key=value, with {{field}} placeholders supported and values URL-encoded for you. Anything already in the URL is kept."
          },
          "headers": {
            "title": "Headers (JSON)",
            "type": "object",
            "description": "Optional extra headers, for example {\"X-Source\": \"apify\"}. Content-Type is set to application/json automatically when a body is sent. {{field}} placeholders work here too. Use the Authentication section below for tokens rather than writing an Authorization header by hand, so the secret is stored encrypted."
          },
          "authType": {
            "title": "Authentication",
            "enum": [
              "none",
              "bearer",
              "basic",
              "apiKeyHeader",
              "apiKeyQuery"
            ],
            "type": "string",
            "description": "'Bearer token' sends Authorization: Bearer <secret>, which covers most modern APIs (Airtable, Notion, HubSpot, Stripe). 'Basic' sends a base64 user:password. 'API key header' sends the secret in a header you name. 'API key in query' puts it in the query string instead.",
            "default": "none"
          },
          "authSecret": {
            "title": "Token, key or password (kept secret)",
            "type": "string",
            "description": "The bearer token, API key, or the password for Basic auth. Stored encrypted by Apify."
          },
          "authUsername": {
            "title": "Username (Basic auth only)",
            "type": "string",
            "description": "Only used when Authentication is set to Basic."
          },
          "authName": {
            "title": "Header or parameter name (API key only)",
            "type": "string",
            "description": "The name the API expects for the key, for example X-API-Key, apikey or api_key. Defaults to X-API-Key for a header and api_key for the query string."
          },
          "batchSize": {
            "title": "Rows per request",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "1 sends one request per row, which is what most APIs expect. A higher number packs that many rows into one request as a JSON array, for endpoints that accept bulk writes. You are charged per request, so batching is also how you cut the cost of a large sync.",
            "default": 1
          },
          "batchWrapperField": {
            "title": "Batch wrapper field",
            "type": "string",
            "description": "Only used when 'Rows per request' is above 1. Leave empty to send a bare JSON array. Set it to wrap the array in a field the API expects, for example 'records' produces {\"records\": [...]}."
          },
          "rateLimitPerSecond": {
            "title": "Requests per second",
            "minimum": 0,
            "maximum": 50,
            "type": "integer",
            "description": "Requests are spaced out so the endpoint is never hit faster than this. Lower it if the API rate limits you (many allow 2 to 10 per second). 0 removes the spacing entirely.",
            "default": 5
          },
          "retries": {
            "title": "Retries per request",
            "minimum": 0,
            "maximum": 10,
            "type": "integer",
            "description": "Extra attempts after the first one, for HTTP 429, 408, 5xx and connection failures only. A 4xx answer such as 400 or 401 is a real answer from the API and is never retried. Backoff doubles each time, and a Retry-After header from the API is obeyed.",
            "default": 3
          },
          "timeoutSecs": {
            "title": "Timeout per request (seconds)",
            "minimum": 1,
            "maximum": 600,
            "type": "integer",
            "description": "How long to wait for each response before giving up on that attempt.",
            "default": 60
          },
          "stopOnFirstError": {
            "title": "Stop on first error",
            "type": "boolean",
            "description": "On: the run stops as soon as one request fails, and the remaining rows are reported as skipped. Useful for a first careful run against a live API. Off: every row is attempted and the failures are listed in the output.",
            "default": false
          },
          "skipRowsMissingFields": {
            "title": "Skip rows missing a placeholder value",
            "type": "boolean",
            "description": "On: a row with an empty value for any {{field}} used in the URL, query, headers or body template is not sent, and is reported as skipped with the field named. Off: it is sent with that placeholder left blank.",
            "default": false
          },
          "includeFields": {
            "title": "Row fields to copy into the results",
            "type": "array",
            "description": "Field names copied from each source row into its result row, so results can be joined back to the data you sent (for example 'email' or 'id'). If a name clashes with an output field such as 'url' or 'status', the output field wins.",
            "items": {
              "type": "string"
            }
          },
          "responseSnippetChars": {
            "title": "Response characters to keep",
            "minimum": 0,
            "maximum": 10000,
            "type": "integer",
            "description": "How much of each response body to store in the result row. 0 stores none, which is the right setting when responses contain personal data you do not want copied into a dataset. JSON responses within this budget are also parsed into a 'responseJson' field.",
            "default": 500
          },
          "dryRun": {
            "title": "Dry run (plan only, send nothing)",
            "type": "boolean",
            "description": "On: nothing is sent and nothing is charged. The output shows the first three requests exactly as they would go out, including the resolved URL and body, with header names only so a secret is never echoed back. Turn off to actually send.",
            "default": false
          },
          "maxItems": {
            "title": "Maximum input rows",
            "minimum": 1,
            "type": "integer",
            "description": "Stop loading after this many rows, a cost guard for large inputs. There is a hard safety ceiling of 100,000 rows per run regardless."
          },
          "webhookUrl": {
            "title": "Webhook URL (optional)",
            "type": "string",
            "description": "Optional. If set, the run summary (how many requests were sent, how many succeeded, the status codes; never the rows or the response bodies) is POSTed here as JSON the moment the sync finishes, so a scheduled job can tell Slack, Zapier, Make, n8n or your own API that the sync ran. Only charged when the endpoint confirms receipt (HTTP 2xx); a failed delivery is reported as a warning and costs nothing."
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}