{"openapi":"3.1.0","info":{"title":"Scout","version":"1.0.0"},"paths":{"/account":{"get":{"tags":["Account"],"summary":"Get account info","description":"Get current user's profile.","operationId":"get_account","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountResponse"}}}}},"security":[{"HTTPBearer":[]}]},"put":{"tags":["Account"],"summary":"Update account info","description":"Update the account name. Returns the account.","operationId":"update_account","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAccountRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/account/api-keys":{"get":{"tags":["Account"],"summary":"List API keys","description":"List all active API keys for the current user.","operationId":"list_api_keys","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/APIKeyResponse"},"type":"array","title":"Response List Api Keys"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["Account"],"summary":"Create API key","description":"Create a new API key. Plaintext is shown once in the response.","operationId":"create_api_key","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAPIKeyRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAPIKeyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/account/api-keys/{key_id}":{"delete":{"tags":["Account"],"summary":"Revoke API key","description":"Deactivate an API key by its id.","operationId":"revoke_api_key","security":[{"HTTPBearer":[]}],"parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","title":"Key Id"}}],"responses":{"204":{"description":"Successful Response"},"404":{"description":"Not the user's key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/customers/{customer_id}/billing/balance":{"get":{"tags":["Billing"],"summary":"Get prepaid balance","description":"The customer's prepaid EUR balance. Read-only.","operationId":"get_balance","security":[{"HTTPBearer":[]}],"parameters":[{"name":"customer_id","in":"path","required":true,"schema":{"type":"string","title":"Customer Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BalanceResponse"}}}},"403":{"description":"Not a member, insufficient role, or managed customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Billing is not available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/customers/{customer_id}/billing/usage":{"get":{"tags":["Billing"],"summary":"List job charges of a month","description":"The job charges of one month (YYYY-MM, Europe/Prague), newest first.\nWithout `month`, the current month. Read-only.","operationId":"get_usage","security":[{"HTTPBearer":[]}],"parameters":[{"name":"customer_id","in":"path","required":true,"schema":{"type":"string","title":"Customer Id"}},{"name":"month","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},{"type":"null"}],"title":"Month"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageResponse"}}}},"403":{"description":"Not a member, insufficient role, or managed customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Billing is not available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/customers/{customer_id}/billing/invoices":{"get":{"tags":["Billing"],"summary":"List top-up invoices","description":"The paid top-up invoices of the customer, newest first.","operationId":"list_topup_invoices","security":[{"HTTPBearer":[]}],"parameters":[{"name":"customer_id","in":"path","required":true,"schema":{"type":"string","title":"Customer Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopupInvoicesResponse"}}}},"403":{"description":"Not a member, insufficient role, or managed customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Invoicing is not available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/customers/{customer_id}/billing/invoices/{invoice_id}/pdf":{"get":{"tags":["Billing"],"summary":"Download a top-up invoice PDF","description":"The invoice PDF from the accounting system.","operationId":"download_topup_invoice","security":[{"HTTPBearer":[]}],"parameters":[{"name":"customer_id","in":"path","required":true,"schema":{"type":"string","title":"Customer Id"}},{"name":"invoice_id","in":"path","required":true,"schema":{"type":"string","title":"Invoice Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/pdf":{}}},"403":{"description":"Not a member, insufficient role, or managed customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Customer or invoice not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Invoicing is not available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Accounting system error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/customers/{customer_id}/billing/topup":{"post":{"tags":["Billing"],"summary":"Start a prepaid top-up","description":"Create a Stripe Checkout for a prepaid top-up and return its URL.","operationId":"create_topup","security":[{"HTTPBearer":[]}],"parameters":[{"name":"customer_id","in":"path","required":true,"schema":{"type":"string","title":"Customer Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopupRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopupResponse"}}}},"403":{"description":"Not a member, insufficient role, or managed customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Customer or job not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Billing is not available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"400":{"description":"Amount outside the allowed range","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Stripe error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/customers/{customer_id}/billing/topups/{session_id}":{"get":{"tags":["Billing"],"summary":"Get top-up fulfillment status","description":"Tells if the paid credit of this Checkout session is credited. Read-only.","operationId":"get_topup_status","security":[{"HTTPBearer":[]}],"parameters":[{"name":"customer_id","in":"path","required":true,"schema":{"type":"string","title":"Customer Id"}},{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopupStatusResponse"}}}},"403":{"description":"Not a member, insufficient role, or managed customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Customer or session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Billing is not available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Stripe error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/contact-requests":{"post":{"tags":["Contact"],"summary":"Contact sales or support","description":"Ask us to get in touch. The reason selects the team: sales or support. The team contacts\nyou by email, or by phone if you give one. A failed job gives its reason in `contact_reason`,\nand the request then needs the `job_id`. A repeat for the same job keeps the first request,\nwith HTTP 200.","operationId":"create_contact_request","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateContactRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRequestResponse"}}}},"200":{"description":"The first request about the same job, instead","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRequestResponse"}}}},"403":{"description":"Insufficient project role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Job not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The reason needs a failed job with this contact reason","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/customers":{"get":{"tags":["Customers"],"summary":"List customer memberships","description":"List the customers the user belongs to, with the user's role in each.","operationId":"list_customers","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/CustomerMembershipResponse"},"type":"array","title":"Response List Customers"}}}}},"security":[{"HTTPBearer":[]}]}},"/customers/{customer_id}":{"get":{"tags":["Customers"],"summary":"Get customer","description":"Get the customer's name, the user's role and quotas.","operationId":"get_customer","security":[{"HTTPBearer":[]}],"parameters":[{"name":"customer_id","in":"path","required":true,"schema":{"type":"string","title":"Customer Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerResponse"}}}},"403":{"description":"Not a member, or insufficient role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/customers/{customer_id}/projects":{"post":{"tags":["Customers"],"summary":"Create project","description":"Create a self-service project owned by the customer.","operationId":"create_project","security":[{"HTTPBearer":[]}],"parameters":[{"name":"customer_id","in":"path","required":true,"schema":{"type":"string","title":"Customer Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProjectRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"description":"Project limit reached, or invalid country or currency","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Not a member, insufficient role, or managed customer — projects are created by DeepScout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/exports":{"get":{"tags":["Exports"],"summary":"List export files","description":"List the export datasets of the project and their files.","operationId":"list_exports","security":[{"HTTPBearer":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportsResponse"}}}},"404":{"description":"Project, dataset or export file not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Maintenance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/exports/{dataset}/url":{"get":{"tags":["Exports"],"summary":"Get export file URL","description":"Presigned URL of the project's export file for the dataset, optionally of one website.","operationId":"get_export_url","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dataset","in":"path","required":true,"schema":{"type":"string","title":"Dataset"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"website_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileUrlResponse"}}}},"404":{"description":"Project, dataset or export file not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Maintenance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Exports are not enabled for the project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/exports/{dataset}":{"get":{"tags":["Exports"],"summary":"Get export file","description":"Download an exported dataset. A project-scoped API key gives the project, other\ncredentials name it in `project_id`.","operationId":"get_export","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dataset","in":"path","required":true,"schema":{"type":"string","title":"Dataset"}},{"name":"project_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id"}},{"name":"website_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website Id"}}],"responses":{"302":{"description":"Successful Response"},"404":{"description":"Project, dataset or export file not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Maintenance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"400":{"description":"project_id is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Exports are not enabled for the project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/jobs/{job_id}/cancel":{"post":{"tags":["Jobs"],"summary":"Cancel job","description":"Cancel a job before its settlement. The caller cannot cancel an approved scrape job.","operationId":"cancel_job","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobResponse"}}}},"403":{"description":"Insufficient project role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Job not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Job is approved, settling, or already finished","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/jobs/setup":{"post":{"tags":["Setup Jobs"],"summary":"Create website setup job","description":"Create a setup job for the URL, country and currency; the analysis starts right away\nunless the website exists already. An open setup job of the same website in the project\nis returned instead, with HTTP 200. A too-large website gives a failed job with the error\ncode `WEBSITE_TOO_LARGE`. See `POST /contact-requests`.\n\nThe job takes one of the free website analyses of the month. After them, the analysis is\npaid from the credit: its price is held and charged once the website is in the project.\nA failed analysis costs nothing.\n\nThe setup is for the whole website at the domain of the URL. It ignores the path and the\nquery. To scrape only some products, create a URL scrape after the setup (`POST /jobs/scraping` with `urls`).\n\nA project without localization gets the country and currency of the job.","operationId":"create_setup_job","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebsiteSetupJobRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebsiteSetupJobResponse"}}}},"200":{"description":"The open setup job of the same website in the project, instead","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebsiteSetupJobResponse"}}}},"400":{"description":"Invalid website URL, country or currency","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Project not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"Spendable credit is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsufficientFundsResponse"}}}},"403":{"description":"Monthly spend limit is reached, or insufficient project role","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/MonthlyLimitResponse"},{"$ref":"#/components/schemas/ErrorResponse"}],"title":"Response 403 Create Setup Job"}}}},"503":{"description":"Billing accounting is not available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["Setup Jobs"],"summary":"List website setup jobs","description":"List the newest setup jobs of the project, or of one of its websites, with their\nanalysis and training progress. A job without `website_id` is still looking for its\nwebsite, or failed before it found one; jobs of removed websites are left out.","operationId":"list_setup_jobs","security":[{"HTTPBearer":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"website_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebsiteSetupJobResponse"},"title":"Response List Setup Jobs"}}}},"404":{"description":"Project not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/jobs/setup/{job_id}":{"get":{"tags":["Setup Jobs"],"summary":"Get website setup job","description":"Return one setup job with its analysis progress.","operationId":"get_setup_job","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebsiteSetupJobResponse"}}}},"404":{"description":"Job not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Setup Jobs"],"summary":"Remove website setup job","description":"Remove a setup job that never found its website from the project's websites.\nA job that found one is removed with its website (`DELETE /websites/{website_id}`).\nRefused while the job is running.","operationId":"remove_setup_job","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"204":{"description":"Successful Response"},"403":{"description":"Insufficient project role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Job not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The job is running, or it has a website to remove instead","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/jobs/scraping":{"post":{"tags":["Scraping Jobs"],"summary":"Create scraping job","description":"Create a scrape job with its estimate, awaiting the user's approval.\nAn unfinished FULL scrape job of the website in the project is returned instead, with\nHTTP 200.\n\nThe API removes invalid, duplicate and other-website URLs from a URL list: `rejected`\ncounts them and `rejected_urls` lists the first 100 removed ones.","operationId":"create_scraping_job","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateScrapingJobRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedScrapingJobResponse"}}}},"200":{"description":"The unfinished FULL scrape job of the website in the project, instead","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedScrapingJobResponse"}}}},"400":{"description":"No URL accepted, or the list is too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient project role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Project or website not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"FULL catalog is expired, or the project has the newest one","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/CatalogExpiredResponse"},{"$ref":"#/components/schemas/CatalogDeliveredResponse"}],"title":"Response 409 Create Scraping Job"}}}},"422":{"description":"Empty list, or over 100,000 URLs"}}},"get":{"tags":["Scraping Jobs"],"summary":"List scraping jobs","description":"List the newest scrape jobs of the project, or of one of its websites, with their\nlive scrape progress.","operationId":"list_scraping_jobs","security":[{"HTTPBearer":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"website_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ScrapingJobResponse"},"title":"Response List Scraping Jobs"}}}},"404":{"description":"Project not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/jobs/scraping/{job_id}":{"get":{"tags":["Scraping Jobs"],"summary":"Get scraping job","description":"Get one scrape job with its live scrape progress.","operationId":"get_scraping_job","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapingJobResponse"}}}},"404":{"description":"Job not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/jobs/scraping/{job_id}/approve":{"post":{"tags":["Scraping Jobs"],"summary":"Approve scraping job","description":"Approve a job awaiting approval; dispatches or reuses a scrape.\n\nThe approval prices the job again at the current metrics. A higher price is refused once\nwith the new quote on the job; a lower one is accepted. A paid approval reserves the cap of\nthe estimate from the prepaid credit.","operationId":"approve_scraping_job","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapingJobResponse"}}}},"400":{"description":"Job cannot be approved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Job not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Job is not awaiting approval, its price went up, or the FULL catalog is expired or delivered","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/EstimateChangedResponse"},{"$ref":"#/components/schemas/CatalogExpiredResponse"},{"$ref":"#/components/schemas/CatalogDeliveredResponse"}],"title":"Response 409 Approve Scraping Job"}}}},"402":{"description":"Spendable credit is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsufficientFundsResponse"}}}},"403":{"description":"Monthly spend limit is reached, or insufficient project role","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/MonthlyLimitResponse"},{"$ref":"#/components/schemas/ErrorResponse"}],"title":"Response 403 Approve Scraping Job"}}}},"503":{"description":"Billing accounting is not available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/jobs/scraping/{job_id}/url-results":{"get":{"tags":["Scraping Jobs"],"summary":"Get scraping job URL results","description":"Presigned URL of the CSV file with the result of each URL of a settled URL job.\n\nA row has the `url`, its `result` (a UrlResult), and the `product_url` of its product.","operationId":"get_scraping_job_url_results","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileUrlResponse"}}}},"404":{"description":"Job or URL results not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/jobs/matching":{"post":{"tags":["Matching Jobs"],"summary":"Create matching job","description":"Create a matching job with its estimate, awaiting the user's approval.\n\nThe free sample of a project runs at once without approval.","operationId":"create_matching_job","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMatchingJobRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchingJobResponse"}}}},"400":{"description":"The websites cannot be matched","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient project role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Project or website not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"A matching of the project is not finished, or its sample is used","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["Matching Jobs"],"summary":"List matching jobs","description":"List the newest matching jobs of the project with their counters.","operationId":"list_matching_jobs","security":[{"HTTPBearer":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string","title":"Project Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MatchingJobResponse"},"title":"Response List Matching Jobs"}}}},"404":{"description":"Project not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/jobs/matching/{job_id}":{"get":{"tags":["Matching Jobs"],"summary":"Get matching job","description":"Get one matching job with the counters of its run.","operationId":"get_matching_job","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchingJobResponse"}}}},"404":{"description":"Job not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/jobs/matching/{job_id}/approve":{"post":{"tags":["Matching Jobs"],"summary":"Approve matching job","description":"Approve a job awaiting approval; dispatches the matching run.\n\nThe approval prices the job again at the current products. A higher price is refused once\nwith the new quote on the job; a lower one is accepted.","operationId":"approve_matching_job","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchingJobResponse"}}}},"400":{"description":"Job cannot be approved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Job not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Job is not awaiting approval, or its price went up","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/EstimateChangedResponse"}],"title":"Response 409 Approve Matching Job"}}}},"402":{"description":"Spendable credit is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsufficientFundsResponse"}}}},"403":{"description":"Monthly spend limit is reached, or insufficient project role","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/MonthlyLimitResponse"},{"$ref":"#/components/schemas/ErrorResponse"}],"title":"Response 403 Approve Matching Job"}}}},"503":{"description":"Billing accounting is not available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/projects":{"get":{"tags":["Projects"],"summary":"List projects","description":"List the user's projects, default project first.","operationId":"list_projects","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ProjectResponse"},"type":"array","title":"Response List Projects"}}}}},"security":[{"HTTPBearer":[]}]}},"/projects/{project_id}":{"patch":{"tags":["Projects"],"summary":"Update project","description":"Rename a project the user administers, or change its localization. A new currency\napplies to the next exports.","operationId":"update_project","security":[{"HTTPBearer":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProjectRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"description":"Invalid country or currency","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Not the user's project, or insufficient role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Project not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/samples/{website_id}":{"get":{"tags":["Samples"],"summary":"Get product sample file","description":"Download the product sample file of one of the project's websites.","operationId":"get_sample","security":[{"HTTPBearer":[]}],"parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"string","title":"Website Id"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileUrlResponse"}}}},"404":{"description":"Project, website or sample file not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Maintenance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/websites":{"get":{"tags":["Websites"],"summary":"List websites","description":"List the project's websites, newest first.","operationId":"list_websites","security":[{"HTTPBearer":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebsiteResponse"},"title":"Response List Websites"}}}},"404":{"description":"Project not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/websites/{website_id}":{"get":{"tags":["Websites"],"summary":"Get website","description":"One website of the project with its live progress; the polling target of the detail page.\nIts scrape jobs are listed by `GET /jobs/scraping`.","operationId":"get_website","security":[{"HTTPBearer":[]}],"parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"string","title":"Website Id"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebsiteResponse"}}}},"404":{"description":"Project or website not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Websites"],"summary":"Remove website","description":"Remove the website from the project and cancel its idle jobs.\nRefused while a job of the website is running.","operationId":"remove_website","security":[{"HTTPBearer":[]}],"parameters":[{"name":"website_id","in":"path","required":true,"schema":{"type":"string","title":"Website Id"}},{"name":"project_id","in":"query","required":true,"schema":{"type":"string","title":"Project Id"}}],"responses":{"204":{"description":"Successful Response"},"403":{"description":"Not the user's project, or insufficient role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Website not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"A job of the website is running","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"APIKeyResponse":{"properties":{"key_id":{"type":"string","title":"Key Id"},"project_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id"},"scope":{"$ref":"#/components/schemas/APIKeyScope"},"created_at":{"anyOf":[{"type":"string","format":"date-time","examples":["2026-09-16T12:30:00.000Z"]},{"type":"null"}],"title":"Created At"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"key_suffix":{"type":"string","title":"Key Suffix","description":"Last 4 characters of the key, for masked display"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time","examples":["2026-09-16T12:30:00.000Z"]},{"type":"null"}],"title":"Last Used At"},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id","description":"The OAuth client that got the key when the user signed in from it, e.g. an MCP client. Not set on the keys that you create."}},"type":"object","required":["key_id","scope","key_suffix"],"title":"APIKeyResponse"},"APIKeyScope":{"type":"string","enum":["PROJECT","USER"],"title":"APIKeyScope","description":"Scope of an API key."},"AccountResponse":{"properties":{"user":{"$ref":"#/components/schemas/UserInfoResponse"},"project_count":{"type":"integer","title":"Project Count","default":0}},"type":"object","required":["user"],"title":"AccountResponse"},"AnalysisProgressResponse":{"properties":{"config":{"anyOf":[{"$ref":"#/components/schemas/AnalysisStepResponse"},{"type":"null"}]},"homepage":{"anyOf":[{"$ref":"#/components/schemas/AnalysisStepResponse"},{"type":"null"}]},"sitemap":{"anyOf":[{"$ref":"#/components/schemas/AnalysisStepResponse"},{"type":"null"}]},"size":{"anyOf":[{"$ref":"#/components/schemas/AnalysisStepResponse"},{"type":"null"}]},"sitemap_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sitemap Size"},"is_ecommerce":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Ecommerce"},"product_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Product Type"},"language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language"},"products_estimate":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Products Estimate"}},"type":"object","title":"AnalysisProgressResponse","description":"What the analysis of the website found so far."},"AnalysisStepResponse":{"properties":{"state":{"$ref":"#/components/schemas/AnalysisStepState"}},"type":"object","required":["state"],"title":"AnalysisStepResponse"},"AnalysisStepState":{"type":"string","enum":["RUNNING","DONE","FAILED"],"title":"AnalysisStepState"},"BalanceResponse":{"properties":{"currency":{"type":"string","title":"Currency"},"balance":{"type":"string","title":"Balance","examples":["12.68"]},"held":{"type":"string","title":"Held","examples":["12.68"]},"spendable":{"type":"string","title":"Spendable","examples":["12.68"]}},"type":"object","required":["currency","balance","held","spendable"],"title":"BalanceResponse","description":"The prepaid balance, the part held by running jobs, and what remains spendable."},"CatalogDeliveredResponse":{"properties":{"code":{"type":"string","const":"CATALOG_DELIVERED","title":"Code","default":"CATALOG_DELIVERED"},"detail":{"type":"string","title":"Detail"}},"type":"object","required":["detail"],"title":"CatalogDeliveredResponse","description":"The project has the newest FULL catalog of the website, crawled in the last 18 hours."},"CatalogExpiredResponse":{"properties":{"code":{"type":"string","const":"CATALOG_EXPIRED","title":"Code","default":"CATALOG_EXPIRED"},"detail":{"type":"string","title":"Detail"}},"type":"object","required":["detail"],"title":"CatalogExpiredResponse","description":"The FULL catalog of the website is too old for URL scrapes. Approve a FULL scrape,\nor create the URL scrape with `urls_only`."},"ContactReason":{"type":"string","enum":["WEBSITE_TOO_LARGE","JOB_FAILED"],"title":"ContactReason","description":"Why a user asks us to get in touch. The reason selects the team."},"ContactRequestResponse":{"properties":{"contact_request_id":{"type":"string","title":"Contact Request Id"},"team":{"$ref":"#/components/schemas/ContactTeam"},"reason":{"$ref":"#/components/schemas/ContactReason"},"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"created_at":{"type":"string","format":"date-time","title":"Created At","examples":["2026-09-16T12:30:00.000Z"]}},"type":"object","required":["contact_request_id","team","reason","created_at"],"title":"ContactRequestResponse"},"ContactTeam":{"type":"string","enum":["SALES","SUPPORT"],"title":"ContactTeam","description":"The team that gets a contact request."},"CreateAPIKeyRequest":{"properties":{"project_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id","description":"Project ID. Null = user-scoped key."},"name":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Name","description":"User-supplied label"}},"type":"object","title":"CreateAPIKeyRequest"},"CreateAPIKeyResponse":{"properties":{"api_key":{"type":"string","title":"Api Key","description":"Plaintext API key (shown once)"},"key_id":{"type":"string","title":"Key Id"},"scope":{"$ref":"#/components/schemas/APIKeyScope"}},"type":"object","required":["api_key","key_id","scope"],"title":"CreateAPIKeyResponse"},"CreateContactRequest":{"properties":{"reason":{"$ref":"#/components/schemas/ContactReason"},"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id"},"phone":{"anyOf":[{"type":"string","maxLength":30,"pattern":"^\\+?[ ()-]*(?:[0-9][ ()-]*){6,20}$"},{"type":"null"}],"title":"Phone"},"message":{"anyOf":[{"type":"string","maxLength":2000,"minLength":1},{"type":"null"}],"title":"Message"}},"type":"object","required":["reason"],"title":"CreateContactRequest"},"CreateMatchingJobRequest":{"properties":{"project_id":{"type":"string","title":"Project Id"},"reference_website_id":{"type":"string","title":"Reference Website Id"},"competitor_website_ids":{"items":{"type":"string"},"type":"array","title":"Competitor Website Ids"},"sample":{"type":"boolean","title":"Sample","default":false}},"type":"object","required":["project_id","reference_website_id","competitor_website_ids"],"title":"CreateMatchingJobRequest"},"CreateProjectRequest":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name"},"localization":{"$ref":"#/components/schemas/ProjectLocalizationRequest"}},"type":"object","required":["name","localization"],"title":"CreateProjectRequest"},"CreateScrapingJobRequest":{"properties":{"website_id":{"type":"string","title":"Website Id"},"project_id":{"type":"string","title":"Project Id"},"urls":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":100000,"minItems":1},{"type":"null"}],"title":"Urls"},"urls_only":{"type":"boolean","title":"Urls Only","default":false}},"type":"object","required":["website_id","project_id"],"title":"CreateScrapingJobRequest"},"CreateWebsiteSetupJobRequest":{"properties":{"url":{"type":"string","title":"Url"},"country":{"type":"string","title":"Country"},"currency":{"type":"string","title":"Currency"},"project_id":{"type":"string","title":"Project Id"}},"type":"object","required":["url","country","currency","project_id"],"title":"CreateWebsiteSetupJobRequest"},"CreatedScrapingJobResponse":{"properties":{"job_id":{"type":"string","title":"Job Id"},"job_type":{"type":"string","enum":["FULL_SCRAPE","URL_SCRAPE"],"title":"Job Type"},"status":{"$ref":"#/components/schemas/JobRequestStatus"},"project_id":{"type":"string","title":"Project Id"},"website_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website Id"},"estimate":{"anyOf":[{"$ref":"#/components/schemas/EstimateResponse"},{"type":"null"}]},"approval":{"anyOf":[{"$ref":"#/components/schemas/JobApprovalResponse"},{"type":"null"}]},"settlement":{"anyOf":[{"$ref":"#/components/schemas/JobSettlementResponse"},{"type":"null"}]},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"error_code":{"anyOf":[{"$ref":"#/components/schemas/JobErrorCode"},{"type":"null"}]},"contact_reason":{"anyOf":[{"$ref":"#/components/schemas/ContactReason"},{"type":"null"}]},"contact_request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Request Id"},"created_at":{"type":"string","format":"date-time","title":"Created At","examples":["2026-09-16T12:30:00.000Z"]},"updated_at":{"type":"string","format":"date-time","title":"Updated At","examples":["2026-09-16T12:30:00.000Z"]},"finished_at":{"anyOf":[{"type":"string","format":"date-time","examples":["2026-09-16T12:30:00.000Z"]},{"type":"null"}],"title":"Finished At"},"variant":{"$ref":"#/components/schemas/ScrapeVariant"},"url_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Url Count"},"urls":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Urls"},"scrape_progress":{"anyOf":[{"$ref":"#/components/schemas/ScrapeJobProgress"},{"type":"null"}]},"url_results":{"anyOf":[{"additionalProperties":{"type":"integer"},"propertyNames":{"$ref":"#/components/schemas/UrlResult"},"type":"object"},{"type":"null"}],"title":"Url Results"},"rejected":{"$ref":"#/components/schemas/RejectedUrlsResponse"},"rejected_urls":{"items":{"type":"string"},"type":"array","title":"Rejected Urls"}},"type":"object","required":["job_id","job_type","status","project_id","created_at","updated_at","variant","rejected","rejected_urls"],"title":"CreatedScrapingJobResponse","description":"The created job, with the URLs that the API removed from its URL list. A FULL scrape and\na clean list have zero counts. `rejected_urls` has the first invalid and other-website URLs."},"CustomerMembershipResponse":{"properties":{"customer_id":{"type":"string","title":"Customer Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"role":{"$ref":"#/components/schemas/CustomerRole"}},"type":"object","required":["customer_id","role"],"title":"CustomerMembershipResponse"},"CustomerQuotasResponse":{"properties":{"analyses_remaining":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Analyses Remaining"},"analyses_per_month":{"type":"integer","title":"Analyses Per Month"},"currency":{"type":"string","title":"Currency"},"analysis_price":{"type":"string","title":"Analysis Price","examples":["12.68"]}},"type":"object","required":["analyses_per_month","currency","analysis_price"],"title":"CustomerQuotasResponse","description":"The website analyses of the customer: the free ones left, the free ones of every month,\nand the price of one after them."},"CustomerResponse":{"properties":{"customer_id":{"type":"string","title":"Customer Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"role":{"$ref":"#/components/schemas/CustomerRole"},"quotas":{"anyOf":[{"$ref":"#/components/schemas/CustomerQuotasResponse"},{"type":"null"}]}},"type":"object","required":["customer_id","role"],"title":"CustomerResponse"},"CustomerRole":{"type":"string","enum":["OWNER","ADMIN","MEMBER"],"title":"CustomerRole","description":"Role of a user in a customer."},"ErrorCode":{"type":"string","enum":["MISSING_API_KEY","INVALID_API_KEY","NOT_AUTHENTICATED","SESSION_EXPIRED","USER_NOT_FOUND","INSUFFICIENT_ROLE","INSUFFICIENT_SCOPE","PROJECT_ACCESS_DENIED","PROJECT_DISABLED","MANAGED_CUSTOMER","EXPORTS_NOT_ENABLED","NOT_FOUND","PROJECT_NOT_FOUND","WEBSITE_NOT_FOUND","JOB_NOT_FOUND","CUSTOMER_NOT_FOUND","API_KEY_NOT_FOUND","INVOICE_NOT_FOUND","TOPUP_NOT_FOUND","DATASET_NOT_FOUND","EXPORT_FILE_NOT_FOUND","SAMPLE_NOT_FOUND","URL_RESULTS_NOT_FOUND","OAUTH_AUTHORIZATION_NOT_FOUND","VALIDATION_ERROR","INVALID_BODY","METHOD_NOT_ALLOWED","PROJECT_ID_REQUIRED","INVALID_WEBSITE_URL","INVALID_LOCALE","INVALID_URL_LIST","INVALID_MATCHING_SCOPE","INVALID_TOPUP_AMOUNT","PROJECT_LIMIT_REACHED","NO_PENDING_CLAIM","CLAIM_MISMATCH","INSUFFICIENT_FUNDS","MONTHLY_LIMIT_REACHED","JOB_NOT_APPROVABLE","JOB_NOT_AWAITING_APPROVAL","JOB_NOT_CANCELLABLE","JOB_RUNNING","JOB_ALREADY_CLAIMED","CLAIM_EXPIRED","SETUP_JOB_HAS_WEBSITE","WEBSITE_BUSY","MATCHING_BUSY","MATCHING_SAMPLE_USED","ESTIMATE_CHANGED","CATALOG_EXPIRED","CATALOG_DELIVERED","CONTACT_REASON_MISMATCH","EMAIL_LINKED_TO_OTHER_ACCOUNT","BILLING_UNAVAILABLE","ACCOUNTING_ERROR","STRIPE_ERROR","OAUTH_NOT_CONFIGURED","MAINTENANCE","INTERNAL_ERROR","HTTP_ERROR"],"title":"ErrorCode","description":"All error codes of the public API. A client branches on the code, not on the detail."},"ErrorResponse":{"properties":{"code":{"$ref":"#/components/schemas/ErrorCode"},"detail":{"type":"string","title":"Detail"}},"type":"object","required":["code","detail"],"title":"ErrorResponse","description":"Every error: a code to branch on and a detail to show. Some errors add fields."},"EstimateChangedResponse":{"properties":{"code":{"type":"string","const":"ESTIMATE_CHANGED","title":"Code","default":"ESTIMATE_CHANGED"},"detail":{"type":"string","title":"Detail"},"estimate":{"$ref":"#/components/schemas/EstimateResponse"}},"type":"object","required":["detail","estimate"],"title":"EstimateChangedResponse","description":"The price of the job went up since its quote. The job now carries the new quote, also in\n`estimate`; approve it again to accept the new price."},"EstimateResponse":{"properties":{"currency":{"type":"string","title":"Currency"},"unit_price_per_1000":{"type":"string","title":"Unit Price Per 1000","examples":["12.68"]},"quantity":{"type":"integer","title":"Quantity"},"total":{"type":"string","title":"Total","examples":["12.68"]},"cap":{"type":"string","title":"Cap","examples":["12.68"]},"min_charge":{"type":"string","title":"Min Charge","examples":["12.68"]},"difficulty":{"anyOf":[{"$ref":"#/components/schemas/ScrapeDifficulty"},{"type":"null"}]},"input_products":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Input Products"}},"type":"object","required":["currency","unit_price_per_1000","quantity","total","cap","min_charge"],"title":"EstimateResponse","description":"The quote of a job: `quantity` products at `unit_price_per_1000`, in `currency`."},"ExportResponse":{"properties":{"dataset":{"type":"string","title":"Dataset"},"website_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website Id"},"file_name":{"type":"string","title":"File Name"},"download_url":{"type":"string","title":"Download Url"},"exists":{"type":"boolean","title":"Exists"},"size_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Size Bytes"},"updated_at":{"anyOf":[{"type":"string","format":"date-time","examples":["2026-09-16T12:30:00.000Z"]},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["dataset","file_name","download_url","exists"],"title":"ExportResponse","description":"One export file of a project: a whole dataset, or its rows of one website."},"ExportsResponse":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"generating":{"type":"boolean","title":"Generating"},"exports":{"items":{"$ref":"#/components/schemas/ExportResponse"},"type":"array","title":"Exports"}},"type":"object","required":["enabled","generating","exports"],"title":"ExportsResponse","description":"Export files of a project."},"FileUrlResponse":{"properties":{"url":{"type":"string","title":"Url"}},"type":"object","required":["url"],"title":"FileUrlResponse","description":"Presigned URL of a file."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"InsufficientFundsResponse":{"properties":{"code":{"type":"string","const":"INSUFFICIENT_FUNDS","title":"Code","default":"INSUFFICIENT_FUNDS"},"detail":{"type":"string","title":"Detail"},"currency":{"type":"string","title":"Currency"},"missing_topup":{"type":"string","title":"Missing Topup","examples":["12.68"]}},"type":"object","required":["detail","currency","missing_topup"],"title":"InsufficientFundsResponse","description":"The spendable credit is too low. A top-up of `missing_topup` permits the approval."},"JobApprovalResponse":{"properties":{"approved_by":{"type":"string","title":"Approved By"},"approved_at":{"type":"string","format":"date-time","title":"Approved At","examples":["2026-09-16T12:30:00.000Z"]}},"type":"object","required":["approved_by","approved_at"],"title":"JobApprovalResponse"},"JobErrorCode":{"type":"string","enum":["WEBSITE_TOO_LARGE","ANALYSIS_FAILED","TRAINING_FAILED","SCRAPE_FAILED","MATCHING_FAILED"],"title":"JobErrorCode","description":"Tells the client why a job failed."},"JobRequestStatus":{"type":"string","enum":["CREATED","ANALYZING","ESTIMATE_READY","TRAINING","AWAITING_APPROVAL","APPROVED","RUNNING","SETTLING","EXPORTING","COMPLETED","FAILED","CANCELLED"],"title":"JobRequestStatus","description":"The lifecycle of a job. Each job type runs in its own lane.\n\n- WEBSITE_SETUP: CREATED, ANALYZING, ESTIMATE_READY, TRAINING, COMPLETED. The analysis\n  and the training move the job on by themselves.\n- FULL_SCRAPE, URL_SCRAPE and MATCHING: AWAITING_APPROVAL (the user approves the quote),\n  APPROVED, RUNNING, SETTLING (the charge), EXPORTING (the export files), COMPLETED.\n- FAILED ends a job of any lane; CANCELLED ends one that the user cancelled, or an idle one\n  that expired."},"JobRequestType":{"type":"string","enum":["WEBSITE_SETUP","FULL_SCRAPE","URL_SCRAPE","MATCHING"],"title":"JobRequestType"},"JobResponse":{"properties":{"job_id":{"type":"string","title":"Job Id"},"job_type":{"$ref":"#/components/schemas/JobRequestType"},"status":{"$ref":"#/components/schemas/JobRequestStatus"},"project_id":{"type":"string","title":"Project Id"},"website_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website Id"},"estimate":{"anyOf":[{"$ref":"#/components/schemas/EstimateResponse"},{"type":"null"}]},"approval":{"anyOf":[{"$ref":"#/components/schemas/JobApprovalResponse"},{"type":"null"}]},"settlement":{"anyOf":[{"$ref":"#/components/schemas/JobSettlementResponse"},{"type":"null"}]},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"error_code":{"anyOf":[{"$ref":"#/components/schemas/JobErrorCode"},{"type":"null"}]},"contact_reason":{"anyOf":[{"$ref":"#/components/schemas/ContactReason"},{"type":"null"}]},"contact_request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Request Id"},"created_at":{"type":"string","format":"date-time","title":"Created At","examples":["2026-09-16T12:30:00.000Z"]},"updated_at":{"type":"string","format":"date-time","title":"Updated At","examples":["2026-09-16T12:30:00.000Z"]},"finished_at":{"anyOf":[{"type":"string","format":"date-time","examples":["2026-09-16T12:30:00.000Z"]},{"type":"null"}],"title":"Finished At"}},"type":"object","required":["job_id","job_type","status","project_id","created_at","updated_at"],"title":"JobResponse","description":"The stored state of one job, common to every job type.\n\nNull fields are omitted from the response, so each job type stays\ncompact. Per-type responses extend this model with their runtime data."},"JobSettlementResponse":{"properties":{"quantity":{"type":"integer","title":"Quantity"},"currency":{"type":"string","title":"Currency"},"amount":{"type":"string","title":"Amount","examples":["12.68"]},"capped":{"type":"boolean","title":"Capped"},"settled_at":{"type":"string","format":"date-time","title":"Settled At","examples":["2026-09-16T12:30:00.000Z"]}},"type":"object","required":["quantity","currency","amount","capped","settled_at"],"title":"JobSettlementResponse","description":"The charge of the job. A failed job settles at zero."},"LoginProvider":{"type":"string","enum":["google","github"],"title":"LoginProvider"},"MatchingJobResponse":{"properties":{"job_id":{"type":"string","title":"Job Id"},"job_type":{"type":"string","const":"MATCHING","title":"Job Type"},"status":{"$ref":"#/components/schemas/JobRequestStatus"},"project_id":{"type":"string","title":"Project Id"},"website_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website Id"},"estimate":{"anyOf":[{"$ref":"#/components/schemas/EstimateResponse"},{"type":"null"}]},"approval":{"anyOf":[{"$ref":"#/components/schemas/JobApprovalResponse"},{"type":"null"}]},"settlement":{"anyOf":[{"$ref":"#/components/schemas/JobSettlementResponse"},{"type":"null"}]},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"error_code":{"anyOf":[{"$ref":"#/components/schemas/JobErrorCode"},{"type":"null"}]},"contact_reason":{"anyOf":[{"$ref":"#/components/schemas/ContactReason"},{"type":"null"}]},"contact_request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Request Id"},"created_at":{"type":"string","format":"date-time","title":"Created At","examples":["2026-09-16T12:30:00.000Z"]},"updated_at":{"type":"string","format":"date-time","title":"Updated At","examples":["2026-09-16T12:30:00.000Z"]},"finished_at":{"anyOf":[{"type":"string","format":"date-time","examples":["2026-09-16T12:30:00.000Z"]},{"type":"null"}],"title":"Finished At"},"reference_website_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reference Website Id"},"competitor_website_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Competitor Website Ids"},"sample":{"type":"boolean","title":"Sample","default":false},"matching_progress":{"anyOf":[{"$ref":"#/components/schemas/MatchingProgress"},{"type":"null"}]},"overlap":{"anyOf":[{"items":{"$ref":"#/components/schemas/WebsiteOverlap"},"type":"array"},{"type":"null"}],"title":"Overlap"},"websites":{"anyOf":[{"items":{"$ref":"#/components/schemas/MatchingWebsite"},"type":"array"},{"type":"null"}],"title":"Websites"}},"type":"object","required":["job_id","job_type","status","project_id","created_at","updated_at"],"title":"MatchingJobResponse","description":"A matching job with the counters of its run.\n\n`websites` counts, per website of the run, the products it loaded and those new or changed.\n`overlap` of a completed job counts, per pair of its websites, the products that the\nproject's matches connect, also through a third website."},"MatchingPhase":{"type":"string","enum":["MATCHING_PRODUCTS","VERIFYING_MATCHES"],"title":"MatchingPhase"},"MatchingProgress":{"properties":{"products_checked":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Products Checked"},"products_skipped_not_modified":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Products Skipped Not Modified"},"new_matches":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"New Matches"},"phase":{"anyOf":[{"$ref":"#/components/schemas/MatchingPhase"},{"type":"null"}]},"percent":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Percent"},"products_processed":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Products Processed"},"products_total":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Products Total"},"estimated_minutes_left":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Estimated Minutes Left"}},"type":"object","title":"MatchingProgress","description":"Counters of the MATCH tasks and, while the job runs, the phase of its run.\n\n- MATCHING_PRODUCTS: `products_processed` of `products_total` products are matched;\n  `percent` is their share.\n- VERIFYING_MATCHES: the matches are verified by LLM matching and saved. `estimated_minutes_left`\n  follows the step that the verification is in, so it can also grow."},"MatchingWebsite":{"properties":{"website_id":{"type":"string","title":"Website Id"},"products":{"type":"integer","title":"Products"},"modified":{"type":"integer","title":"Modified"}},"type":"object","required":["website_id","products","modified"],"title":"MatchingWebsite","description":"A website of the run: the products it loaded and those new or changed since its baseline."},"MonthlyLimitResponse":{"properties":{"code":{"type":"string","const":"MONTHLY_LIMIT_REACHED","title":"Code","default":"MONTHLY_LIMIT_REACHED"},"detail":{"type":"string","title":"Detail"},"currency":{"type":"string","title":"Currency"},"monthly_limit":{"type":"string","title":"Monthly Limit","examples":["12.68"]}},"type":"object","required":["detail","currency","monthly_limit"],"title":"MonthlyLimitResponse","description":"The job does not fit in the monthly spend limit. A top-up does not help."},"ProjectLocalizationRequest":{"properties":{"country":{"type":"string","title":"Country"},"currency":{"type":"string","title":"Currency"}},"type":"object","required":["country","currency"],"title":"ProjectLocalizationRequest","description":"The market of the project. Its prices are converted to the currency."},"ProjectLocalizationResponse":{"properties":{"locale":{"type":"string","title":"Locale"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"},"currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currency"}},"type":"object","required":["locale"],"title":"ProjectLocalizationResponse","description":"The market of the project and the locale derived from its country."},"ProjectResponse":{"properties":{"project_id":{"type":"string","title":"Project Id"},"name":{"type":"string","title":"Name"},"customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Id"},"is_default":{"type":"boolean","title":"Is Default","default":false},"localization":{"anyOf":[{"$ref":"#/components/schemas/ProjectLocalizationResponse"},{"type":"null"}]}},"type":"object","required":["project_id","name"],"title":"ProjectResponse"},"RejectedUrlsResponse":{"properties":{"invalid":{"type":"integer","title":"Invalid"},"other_website":{"type":"integer","title":"Other Website"},"duplicate":{"type":"integer","title":"Duplicate"}},"type":"object","required":["invalid","other_website","duplicate"],"title":"RejectedUrlsResponse","description":"The number of URLs that the API removed from the list, for each reason."},"ScrapeDifficulty":{"type":"string","enum":["EASY","MEDIUM","HARD"],"title":"ScrapeDifficulty","description":"Billing tier of a website, derived from its scrape config."},"ScrapeJobProgress":{"properties":{"pages":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pages"},"pages_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pages Limit"},"pages_estimate":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pages Estimate"},"phase":{"anyOf":[{"$ref":"#/components/schemas/ScrapePhase"},{"type":"null"}]},"percent":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Percent"}},"type":"object","title":"ScrapeJobProgress","description":"Progress of a scrape job. `phase` is the step of the SCRAPE, HARVEST and UPDATE chain,\nor None after the chain ends. `percent` is of the estimated pages while they are collected,\nand 100 after."},"ScrapePhase":{"type":"string","enum":["COLLECTING_PAGES","PROCESSING_DATA","UPDATING_CATALOG"],"title":"ScrapePhase"},"ScrapeVariant":{"type":"string","enum":["FULL","CATALOG_URLS","URLS_ONLY"],"title":"ScrapeVariant","description":"What a scrape job scrapes."},"ScrapingJobResponse":{"properties":{"job_id":{"type":"string","title":"Job Id"},"job_type":{"type":"string","enum":["FULL_SCRAPE","URL_SCRAPE"],"title":"Job Type"},"status":{"$ref":"#/components/schemas/JobRequestStatus"},"project_id":{"type":"string","title":"Project Id"},"website_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website Id"},"estimate":{"anyOf":[{"$ref":"#/components/schemas/EstimateResponse"},{"type":"null"}]},"approval":{"anyOf":[{"$ref":"#/components/schemas/JobApprovalResponse"},{"type":"null"}]},"settlement":{"anyOf":[{"$ref":"#/components/schemas/JobSettlementResponse"},{"type":"null"}]},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"error_code":{"anyOf":[{"$ref":"#/components/schemas/JobErrorCode"},{"type":"null"}]},"contact_reason":{"anyOf":[{"$ref":"#/components/schemas/ContactReason"},{"type":"null"}]},"contact_request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Request Id"},"created_at":{"type":"string","format":"date-time","title":"Created At","examples":["2026-09-16T12:30:00.000Z"]},"updated_at":{"type":"string","format":"date-time","title":"Updated At","examples":["2026-09-16T12:30:00.000Z"]},"finished_at":{"anyOf":[{"type":"string","format":"date-time","examples":["2026-09-16T12:30:00.000Z"]},{"type":"null"}],"title":"Finished At"},"variant":{"$ref":"#/components/schemas/ScrapeVariant"},"url_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Url Count"},"urls":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Urls"},"scrape_progress":{"anyOf":[{"$ref":"#/components/schemas/ScrapeJobProgress"},{"type":"null"}]},"url_results":{"anyOf":[{"additionalProperties":{"type":"integer"},"propertyNames":{"$ref":"#/components/schemas/UrlResult"},"type":"object"},{"type":"null"}],"title":"Url Results"}},"type":"object","required":["job_id","job_type","status","project_id","created_at","updated_at","variant"],"title":"ScrapingJobResponse","description":"A scrape job with the live progress of its scrape. `variant` tells what it scrapes.\n\n`url_results` of a settled URL job counts its URLs by result."},"TopupInvoiceResponse":{"properties":{"invoice_id":{"type":"string","title":"Invoice Id"},"invoice_code":{"type":"string","title":"Invoice Code"},"created_at":{"type":"string","format":"date-time","title":"Created At","examples":["2026-09-16T12:30:00.000Z"]},"currency":{"type":"string","title":"Currency"},"total":{"type":"string","title":"Total","examples":["12.68"]}},"type":"object","required":["invoice_id","invoice_code","created_at","currency","total"],"title":"TopupInvoiceResponse"},"TopupInvoicesResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/TopupInvoiceResponse"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"TopupInvoicesResponse"},"TopupRequest":{"properties":{"amount":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$"}],"title":"Amount"},"currency":{"type":"string","const":"EUR","title":"Currency","default":"EUR"},"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id"}},"type":"object","required":["amount"],"title":"TopupRequest"},"TopupResponse":{"properties":{"checkout_url":{"type":"string","title":"Checkout Url"},"session_id":{"type":"string","title":"Session Id"}},"type":"object","required":["checkout_url","session_id"],"title":"TopupResponse"},"TopupStatusResponse":{"properties":{"session_id":{"type":"string","title":"Session Id"},"fulfilled":{"type":"boolean","title":"Fulfilled"}},"type":"object","required":["session_id","fulfilled"],"title":"TopupStatusResponse"},"TrainProgress":{"properties":{"pages":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pages"},"pages_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pages Limit"},"pages_estimate":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pages Estimate"},"phase":{"$ref":"#/components/schemas/TrainProgressPhase"},"percent":{"type":"integer","title":"Percent"}},"type":"object","required":["phase","percent"],"title":"TrainProgress","description":"Estimated progress of the website's training."},"TrainProgressPhase":{"type":"string","enum":["COLLECTING_PAGES","ANALYZING_PAGES","UNDERSTANDING_PRODUCTS","EXTRACTING_SAMPLE","PREPARING_SAMPLE","QUALITY_CHECK"],"title":"TrainProgressPhase","description":"Publicly visible phases on API/Console."},"UpdateAccountRequest":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","title":"UpdateAccountRequest"},"UpdateProjectRequest":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":100,"minLength":1},{"type":"null"}],"title":"Name"},"localization":{"anyOf":[{"$ref":"#/components/schemas/ProjectLocalizationRequest"},{"type":"null"}]}},"type":"object","title":"UpdateProjectRequest"},"UrlResult":{"type":"string","enum":["OK","NOT_FOUND","IGNORED_REQUEST","IGNORED_RESPONSE","INVALID_DATA","PRICE_NOT_FOUND","UNKNOWN"],"title":"UrlResult","description":"The result of one URL of a URL scrape job.\n\n- OK: the URL gave a product with a price.\n- NOT_FOUND: the page answered with an error status, for example 404 or 410.\n- IGNORED_REQUEST: the crawler did not download the URL.\n- IGNORED_RESPONSE: the page is not a product page, for example a file, or it did not\n  load after all retries.\n- INVALID_DATA: the page loaded, but its data gave no valid product.\n- PRICE_NOT_FOUND: the URL gave a product without a price.\n- UNKNOWN: the crawl has no record of the URL."},"UsageItemResponse":{"properties":{"job_id":{"type":"string","title":"Job Id"},"job_type":{"anyOf":[{"$ref":"#/components/schemas/JobRequestType"},{"type":"null"}]},"project_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id"},"website_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website Id"},"quantity":{"type":"integer","title":"Quantity"},"amount":{"type":"string","title":"Amount","examples":["12.68"]},"capped":{"type":"boolean","title":"Capped"},"settled_at":{"type":"string","format":"date-time","title":"Settled At","examples":["2026-09-16T12:30:00.000Z"]}},"type":"object","required":["job_id","quantity","amount","capped","settled_at"],"title":"UsageItemResponse","description":"The charge of one job. The job fields are absent when the job was deleted."},"UsageResponse":{"properties":{"month":{"type":"string","title":"Month"},"currency":{"type":"string","title":"Currency"},"total":{"type":"string","title":"Total","examples":["12.68"]},"items":{"items":{"$ref":"#/components/schemas/UsageItemResponse"},"type":"array","title":"Items"}},"type":"object","required":["month","currency","total","items"],"title":"UsageResponse","description":"The job charges of one month, in `currency`."},"UserInfoResponse":{"properties":{"user_id":{"type":"string","title":"User Id"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"provider":{"anyOf":[{"$ref":"#/components/schemas/LoginProvider"},{"type":"null"}],"description":"OAuth provider linked to the account"},"picture":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Picture"}},"type":"object","required":["user_id"],"title":"UserInfoResponse"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WebsiteOverlap":{"properties":{"website_id":{"type":"string","title":"Website Id"},"match_website_id":{"type":"string","title":"Match Website Id"},"products":{"type":"integer","title":"Products"}},"type":"object","required":["website_id","match_website_id","products"],"title":"WebsiteOverlap","description":"The products of two websites that the project's matches connect."},"WebsiteResponse":{"properties":{"website_id":{"type":"string","title":"Website Id"},"domain":{"type":"string","title":"Domain"},"url":{"type":"string","title":"Url"},"project_id":{"type":"string","title":"Project Id"},"job":{"anyOf":[{"oneOf":[{"$ref":"#/components/schemas/WebsiteSetupJobResponse"},{"$ref":"#/components/schemas/ScrapingJobResponse"}],"discriminator":{"propertyName":"job_type","mapping":{"FULL_SCRAPE":"#/components/schemas/ScrapingJobResponse","URL_SCRAPE":"#/components/schemas/ScrapingJobResponse","WEBSITE_SETUP":"#/components/schemas/WebsiteSetupJobResponse"}}},{"type":"null"}],"title":"Job"},"challenge":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Challenge"},"full_scrape_estimate":{"anyOf":[{"$ref":"#/components/schemas/EstimateResponse"},{"type":"null"}],"description":"Price of a full scrape now. The API calculates it at each request from the latest product count of the website."},"added_at":{"anyOf":[{"type":"string","format":"date-time","examples":["2026-09-16T12:30:00.000Z"]},{"type":"null"}],"title":"Added At"},"scraped_at":{"anyOf":[{"type":"string","format":"date-time","examples":["2026-09-16T12:30:00.000Z"]},{"type":"null"}],"title":"Scraped At"}},"type":"object","required":["website_id","domain","url","project_id"],"title":"WebsiteResponse","description":"One website of a project with the job that defines its state."},"WebsiteSetupJobResponse":{"properties":{"job_id":{"type":"string","title":"Job Id"},"job_type":{"type":"string","const":"WEBSITE_SETUP","title":"Job Type"},"status":{"$ref":"#/components/schemas/JobRequestStatus"},"project_id":{"type":"string","title":"Project Id"},"website_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website Id"},"estimate":{"anyOf":[{"$ref":"#/components/schemas/EstimateResponse"},{"type":"null"}]},"approval":{"anyOf":[{"$ref":"#/components/schemas/JobApprovalResponse"},{"type":"null"}]},"settlement":{"anyOf":[{"$ref":"#/components/schemas/JobSettlementResponse"},{"type":"null"}]},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"error_code":{"anyOf":[{"$ref":"#/components/schemas/JobErrorCode"},{"type":"null"}]},"contact_reason":{"anyOf":[{"$ref":"#/components/schemas/ContactReason"},{"type":"null"}]},"contact_request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Request Id"},"created_at":{"type":"string","format":"date-time","title":"Created At","examples":["2026-09-16T12:30:00.000Z"]},"updated_at":{"type":"string","format":"date-time","title":"Updated At","examples":["2026-09-16T12:30:00.000Z"]},"finished_at":{"anyOf":[{"type":"string","format":"date-time","examples":["2026-09-16T12:30:00.000Z"]},{"type":"null"}],"title":"Finished At"},"url":{"type":"string","title":"Url"},"country":{"type":"string","title":"Country"},"currency":{"type":"string","title":"Currency"},"analysis_progress":{"anyOf":[{"$ref":"#/components/schemas/AnalysisProgressResponse"},{"type":"null"}]},"train_progress":{"anyOf":[{"$ref":"#/components/schemas/TrainProgress"},{"type":"null"}]}},"type":"object","required":["job_id","job_type","status","project_id","created_at","updated_at","url","country","currency"],"title":"WebsiteSetupJobResponse","description":"A setup job with its analysis and training progress."}},"securitySchemes":{"HTTPBearer":{"type":"http","description":"An API key","scheme":"bearer"}}},"tags":[{"name":"Account","description":"The signed-in user and their API keys."},{"name":"Customers","description":"The customers the user belongs to, and their projects."},{"name":"Billing","description":"Prepaid credit: balance, top-ups, invoices and usage."},{"name":"Projects","description":"The projects of the user."},{"name":"Jobs","description":"What every job type has in common: cancel."},{"name":"Setup Jobs","description":"Add a website: its analysis and training."},{"name":"Scraping Jobs","description":"Scrape the full catalog or a list of URLs."},{"name":"Matching Jobs","description":"Match the products of websites with each other."},{"name":"Websites","description":"The websites of a project and their state."},{"name":"Exports","description":"The export files of a project."},{"name":"Samples","description":"A sample of the products of a website."},{"name":"Contact","description":"Ask the sales or the support team to get in touch."}],"servers":[{"url":"/v1"}]}