{
  "openapi": "3.0.1",
  "info": {
    "title": "Planity Scraper - Beauty Salons, Contacts & Reviews",
    "description": "Scrape Planity (planity.com) beauty salons across France, including hairdressers, barbers, nail salons and spas. Extract business names, addresses, phone numbers, opening hours, ratings, customer reviews, photos and booking availability signals for lead generation and market research.",
    "version": "0.1",
    "x-build-id": "cse0kaiya4GYTJGuS"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/abotapi~planity-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-abotapi-planity-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/abotapi~planity-scraper/runs": {
      "post": {
        "operationId": "runs-sync-abotapi-planity-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/abotapi~planity-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-abotapi-planity-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",
        "required": [
          "mode"
        ],
        "properties": {
          "mode": {
            "title": "What do you want to scrape?",
            "enum": [
              "search",
              "url"
            ],
            "type": "string",
            "description": "Search by location and category, or paste Planity listing and salon links. Fields of the other mode are ignored.",
            "default": "search"
          },
          "locations": {
            "title": "Locations",
            "type": "array",
            "description": "Plain names, no ids needed: a city (Paris, Lyon), an arrondissement (Paris 15, Lyon 6eme) or a postal code (33000). One search per entry. An entry that matches no Planity place exactly is skipped with a warning, never guessed.",
            "items": {
              "type": "string"
            }
          },
          "category": {
            "title": "Category",
            "enum": [
              "coiffeur",
              "barbier",
              "manucure-et-pedicure",
              "institut-de-beaute",
              "spa",
              "reflexologue",
              "massotherapeute",
              "sophrologue",
              "hypnotherapeute",
              "naturopathe",
              "coach-de-vie",
              "tatoueur",
              "fitness",
              "bien-etre"
            ],
            "type": "string",
            "description": "Type of establishment to list.",
            "default": "coiffeur"
          },
          "searchText": {
            "title": "Name filter",
            "type": "string",
            "description": "Optional text to match against salon names and descriptions."
          },
          "minRating": {
            "title": "Minimum rating",
            "minimum": 0,
            "maximum": 5,
            "type": "number",
            "description": "Only keep salons rated at least this value (0 to 5). Leave empty for no filter."
          },
          "sortBy": {
            "title": "Sort by",
            "enum": [
              "relevance",
              "rating",
              "price-asc",
              "price-desc"
            ],
            "type": "string",
            "description": "Order of the results. Relevance ranks by distance to the place centre; the other options order the whole place (best rated, or by price level).",
            "default": "relevance"
          },
          "urls": {
            "title": "Planity links",
            "type": "array",
            "description": "Planity links, one per line. Accepted: a listing (planity.com/coiffeur/paris-75), a listing page (…/page-2), a district listing (…/coiffeur/paris-75/75011-paris-11eme), a service page (…/coiffeur/coupe-femme/paris-75, lists the whole category for that place) or a single salon link. Query strings and a /fr-FR/ prefix are ignored; home pages and category pages without a place are skipped with a warning. Filter fields are ignored in this mode.",
            "default": [
              "https://www.planity.com/coiffeur/paris-75",
              "https://www.planity.com/coiffeur/paris-75/page-2",
              "https://www.planity.com/coiffeur/paris-75/75011-paris-11eme",
              "https://www.planity.com/coiffeur/coupe-femme/paris-75",
              "https://www.planity.com/barbier/lyon-69",
              "https://www.planity.com/y-coiffure-75004-paris"
            ],
            "items": {
              "type": "string"
            }
          },
          "fetchDetails": {
            "title": "Add salon details",
            "type": "boolean",
            "description": "Adds the salon page data: services with prices and durations, team, photos, about text, opening hours by day, sub-ratings, access info, SIRET and review excerpts. Billed as one detail-enrichment unit per enriched result, plus one more unit per started block of 10 delivered reviews (Max reviews per salon).",
            "default": true
          },
          "maxReviews": {
            "title": "Max reviews per salon",
            "minimum": 0,
            "maximum": 1000,
            "type": "integer",
            "description": "How many review excerpts to keep on each salon row (0 skips them). Applies when Add salon details is on. Every started block of 10 delivered reviews adds one detail-enrichment unit.",
            "default": 20
          },
          "maxPages": {
            "title": "Max pages per search",
            "minimum": 0,
            "type": "integer",
            "description": "Does not cap the run: it has no default and defers to Max items, which is the only default cap. Leave empty or 0 to walk every result page (20 results per page); set it only to stop a search earlier."
          },
          "maxItems": {
            "title": "Max items",
            "minimum": 0,
            "type": "integer",
            "description": "The one default cap on the run (20). Maximum results to return across all searches. 0 means unlimited.",
            "default": 20
          },
          "proxy": {
            "title": "Proxy",
            "type": "object",
            "description": "Proxy settings. Residential is the default and recommended for the most reliable results; it is billed by traffic on your account. If the selected connection is refused, the run switches to a backup connection on its own.",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": [
                "RESIDENTIAL"
              ]
            }
          },
          "resumeFromRunId": {
            "title": "Resume from run ID",
            "type": "string",
            "description": "Run ID (or dataset ID) of a previous run of this Actor. Salons already collected there are skipped, so this run returns only the delta. Leave empty for a normal run. For recurring monitoring of the same search, use Incremental mode instead."
          },
          "incrementalMode": {
            "title": "Incremental changes for scheduled runs",
            "type": "boolean",
            "description": "For recurring monitoring. A salon is returned as NEW the first time, and as UPDATED when a tracked field changes (name, description, phone, address, opening hours, categories, photos, services and prices, team, booking settings). Unchanged salons are not returned or billed. Rating and review counters are not compared. State is kept per search setup, or per State key when you set one.",
            "default": false
          },
          "stateKey": {
            "title": "State key",
            "type": "string",
            "description": "Optional name for a monitoring campaign. Runs sharing a key share their incremental state. Leave empty to scope it automatically to the search."
          },
          "ignoreFieldsForChanges": {
            "title": "Ignore fields when detecting changes (incremental mode only)",
            "type": "array",
            "description": "Extra field names that must not mark a venue as UPDATED in incremental mode. Rating, review and booking counters are already ignored.",
            "items": {
              "type": "string"
            }
          },
          "mcpConnectors": {
            "title": "Pipe results into your apps (optional)",
            "type": "array",
            "description": "Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify Settings, Integrations, then select it here. The connector receives a condensed summary per item; the full record stays in the dataset. Leave empty to skip."
          },
          "notionParentPageUrl": {
            "title": "Notion parent page (Notion connector only)",
            "type": "string",
            "description": "URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors."
          },
          "maxNotifyListings": {
            "title": "Max items to export per connector",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap on items written to each connector per run. Does not affect the dataset.",
            "default": 50
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}