{
 "openapi": "3.1.0",
 "info": {
  "title": "Siftwright API",
  "version": "1.0.0",
  "summary": "Web data endpoints for developers and AI agents, one key, only successful results billed.",
  "description": "Plans: Starter $29/month (10,000 results), Pro $99/month (50,000 results), Business $299/month (250,000 results), Enterprise $999/month (1,500,000 results). Rate limit 60 requests per minute per key. Human docs: https://siftwright.com/docs/. A hosted MCP server exposing the same endpoints is at https://siftwright.com/mcp.",
  "contact": {
   "email": "support@siftwright.com",
   "url": "https://siftwright.com"
  },
  "termsOfService": "https://siftwright.com/terms/"
 },
 "servers": [
  {
   "url": "https://siftwright.com"
  }
 ],
 "tags": [
  {
   "name": "Endpoints"
  }
 ],
 "paths": {
  "/v1/youtube-transcript": {
   "post": {
    "operationId": "youtubeTranscript",
    "summary": "YouTube transcripts",
    "description": "Transcripts (captions) for YouTube videos, Shorts, playlists or channels. Send `url` or `urls`.\n\nBilling: One result per item with status \"ok\". Items that fail are returned but not billed.",
    "tags": [
     "Endpoints"
    ],
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "externalDocs": {
     "url": "https://siftwright.com/docs/#youtube-transcript"
    },
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "url": {
          "type": "string",
          "description": "A single YouTube video, Shorts, playlist or channel URL."
         },
         "urls": {
          "type": "array",
          "items": {
           "type": "string"
          },
          "minItems": 1,
          "maxItems": 10,
          "description": "1 to 10 YouTube URLs."
         },
         "language": {
          "type": "string",
          "default": "en",
          "description": "Preferred caption language code (max 10 characters)."
         },
         "translateTo": {
          "type": "string",
          "description": "Optional language code to translate into (max 10 characters)."
         },
         "preferManual": {
          "type": "boolean",
          "default": true,
          "description": "Prefer manually written captions over auto-generated ones."
         },
         "outputFormats": {
          "type": "array",
          "items": {
           "type": "string",
           "enum": [
            "text",
            "segments",
            "srt",
            "vtt"
           ]
          },
          "default": [
           "text",
           "segments"
          ]
         },
         "includeMetadata": {
          "type": "boolean",
          "default": true
         },
         "maxVideosPerSource": {
          "type": "integer",
          "minimum": 1,
          "maximum": 25,
          "default": 10,
          "description": "For playlists and channels."
         }
        },
        "anyOf": [
         {
          "required": [
           "url"
          ]
         },
         {
          "required": [
           "urls"
          ]
         }
        ]
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Results envelope.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Result"
        }
       }
      }
     },
     "400": {
      "description": "invalid_body or invalid_input: the JSON body is missing or a field is invalid.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "description": "missing_api_key or invalid_api_key.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "402": {
      "description": "subscription_inactive: the subscription is canceled or a payment failed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "405": {
      "description": "method_not_allowed: use POST.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "quota_exceeded (this period's results are used up) or rate_limited (60 requests per minute per key; see Retry-After).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "502": {
      "description": "upstream_error: the tool failed to run. Nothing is billed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "504": {
      "description": "upstream_timeout: the job took too long. Nothing is billed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/v1/screenshot": {
   "post": {
    "operationId": "screenshot",
    "summary": "Website screenshots and PDFs",
    "description": "Render pages in a real browser as PNG, JPEG or PDF. Send `url` or `urls`. Each result has a signed `fileUrl`.\n\nBilling: One result per item with status \"ok\". Items that fail are returned but not billed.",
    "tags": [
     "Endpoints"
    ],
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "externalDocs": {
     "url": "https://siftwright.com/docs/#screenshot"
    },
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "url": {
          "type": "string",
          "description": "A single http(s) URL."
         },
         "urls": {
          "type": "array",
          "items": {
           "type": "string"
          },
          "minItems": 1,
          "maxItems": 5,
          "description": "1 to 5 http(s) URLs."
         },
         "format": {
          "type": "string",
          "enum": [
           "png",
           "jpeg",
           "pdf"
          ],
          "default": "png"
         },
         "fullPage": {
          "type": "boolean",
          "default": true
         },
         "viewportWidth": {
          "type": "integer",
          "minimum": 320,
          "maximum": 3840,
          "default": 1280
         },
         "viewportHeight": {
          "type": "integer",
          "minimum": 240,
          "maximum": 2160,
          "default": 800
         },
         "deviceScaleFactor": {
          "type": "integer",
          "minimum": 1,
          "maximum": 3,
          "default": 1
         },
         "pdfPageFormat": {
          "type": "string",
          "enum": [
           "A4",
           "A3",
           "Letter",
           "Legal"
          ],
          "default": "A4"
         },
         "blockCookieBanners": {
          "type": "boolean",
          "default": true
         },
         "waitForSelector": {
          "type": "string",
          "maxLength": 300,
          "description": "CSS selector to wait for before capture."
         },
         "delaySec": {
          "type": "integer",
          "minimum": 0,
          "maximum": 10,
          "default": 0,
          "description": "Extra delay in seconds before capture."
         }
        },
        "anyOf": [
         {
          "required": [
           "url"
          ]
         },
         {
          "required": [
           "urls"
          ]
         }
        ]
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Results envelope.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Result"
        }
       }
      }
     },
     "400": {
      "description": "invalid_body or invalid_input: the JSON body is missing or a field is invalid.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "description": "missing_api_key or invalid_api_key.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "402": {
      "description": "subscription_inactive: the subscription is canceled or a payment failed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "405": {
      "description": "method_not_allowed: use POST.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "quota_exceeded (this period's results are used up) or rate_limited (60 requests per minute per key; see Retry-After).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "502": {
      "description": "upstream_error: the tool failed to run. Nothing is billed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "504": {
      "description": "upstream_timeout: the job took too long. Nothing is billed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/v1/google-news": {
   "post": {
    "operationId": "googleNews",
    "summary": "Google News search",
    "description": "News articles for a search query.\n\nBilling: One result per article returned with status \"ok\". Items that fail are returned but not billed.",
    "tags": [
     "Endpoints"
    ],
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "externalDocs": {
     "url": "https://siftwright.com/docs/#google-news"
    },
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "query": {
          "type": "string",
          "maxLength": 300
         },
         "maxItems": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 30
         },
         "language": {
          "type": "string",
          "default": "en"
         },
         "country": {
          "type": "string",
          "default": "US"
         }
        },
        "anyOf": [
         {
          "required": [
           "query"
          ]
         }
        ]
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Results envelope.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Result"
        }
       }
      }
     },
     "400": {
      "description": "invalid_body or invalid_input: the JSON body is missing or a field is invalid.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "description": "missing_api_key or invalid_api_key.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "402": {
      "description": "subscription_inactive: the subscription is canceled or a payment failed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "405": {
      "description": "method_not_allowed: use POST.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "quota_exceeded (this period's results are used up) or rate_limited (60 requests per minute per key; see Retry-After).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "502": {
      "description": "upstream_error: the tool failed to run. Nothing is billed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "504": {
      "description": "upstream_timeout: the job took too long. Nothing is billed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/v1/pqc-scan": {
   "post": {
    "operationId": "pqcScan",
    "summary": "Post-quantum TLS readiness scan",
    "description": "Probes public hosts for X25519MLKEM768 / ML-KEM key exchange support. Send `host` or `hosts`. IP addresses and internal names are rejected.\n\nBilling: One result per host that answered. Unreachable hosts are free. Items that fail are returned but not billed.",
    "tags": [
     "Endpoints"
    ],
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "externalDocs": {
     "url": "https://siftwright.com/docs/#pqc-scan"
    },
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "host": {
          "type": "string",
          "description": "A single public domain name."
         },
         "hosts": {
          "type": "array",
          "items": {
           "type": "string"
          },
          "minItems": 1,
          "maxItems": 20,
          "description": "1 to 20 public domain names."
         }
        },
        "anyOf": [
         {
          "required": [
           "host"
          ]
         },
         {
          "required": [
           "hosts"
          ]
         }
        ]
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Results envelope.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Result"
        }
       }
      }
     },
     "400": {
      "description": "invalid_body or invalid_input: the JSON body is missing or a field is invalid.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "description": "missing_api_key or invalid_api_key.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "402": {
      "description": "subscription_inactive: the subscription is canceled or a payment failed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "405": {
      "description": "method_not_allowed: use POST.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "quota_exceeded (this period's results are used up) or rate_limited (60 requests per minute per key; see Retry-After).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "502": {
      "description": "upstream_error: the tool failed to run. Nothing is billed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "504": {
      "description": "upstream_timeout: the job took too long. Nothing is billed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/v1/contact-details": {
   "post": {
    "operationId": "contactDetails",
    "summary": "Contact details from company websites",
    "description": "Public emails, phone numbers and social profiles. Send `url` or `urls`.\n\nBilling: One result per website with status \"ok\". Items that fail are returned but not billed.",
    "tags": [
     "Endpoints"
    ],
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "externalDocs": {
     "url": "https://siftwright.com/docs/#contact-details"
    },
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "url": {
          "type": "string"
         },
         "urls": {
          "type": "array",
          "items": {
           "type": "string"
          },
          "minItems": 1,
          "maxItems": 10,
          "description": "1 to 10 websites or domains."
         },
         "maxPagesPerDomain": {
          "type": "integer",
          "minimum": 1,
          "maximum": 15,
          "default": 6
         }
        },
        "anyOf": [
         {
          "required": [
           "url"
          ]
         },
         {
          "required": [
           "urls"
          ]
         }
        ]
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Results envelope.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Result"
        }
       }
      }
     },
     "400": {
      "description": "invalid_body or invalid_input: the JSON body is missing or a field is invalid.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "description": "missing_api_key or invalid_api_key.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "402": {
      "description": "subscription_inactive: the subscription is canceled or a payment failed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "405": {
      "description": "method_not_allowed: use POST.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "quota_exceeded (this period's results are used up) or rate_limited (60 requests per minute per key; see Retry-After).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "502": {
      "description": "upstream_error: the tool failed to run. Nothing is billed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "504": {
      "description": "upstream_timeout: the job took too long. Nothing is billed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/v1/tech-stack": {
   "post": {
    "operationId": "techStack",
    "summary": "Website tech stack detection",
    "description": "CMS, frameworks, analytics, hosting, email and DNS provider of a website, with evidence. Send `url` or `urls`.\n\nBilling: One result per website with status \"ok\". Items that fail are returned but not billed.",
    "tags": [
     "Endpoints"
    ],
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "externalDocs": {
     "url": "https://siftwright.com/docs/#tech-stack"
    },
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "url": {
          "type": "string"
         },
         "urls": {
          "type": "array",
          "items": {
           "type": "string"
          },
          "minItems": 1,
          "maxItems": 20,
          "description": "1 to 20 websites or domains."
         },
         "includeDns": {
          "type": "boolean",
          "default": true
         }
        },
        "anyOf": [
         {
          "required": [
           "url"
          ]
         },
         {
          "required": [
           "urls"
          ]
         }
        ]
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Results envelope.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Result"
        }
       }
      }
     },
     "400": {
      "description": "invalid_body or invalid_input: the JSON body is missing or a field is invalid.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "description": "missing_api_key or invalid_api_key.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "402": {
      "description": "subscription_inactive: the subscription is canceled or a payment failed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "405": {
      "description": "method_not_allowed: use POST.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "quota_exceeded (this period's results are used up) or rate_limited (60 requests per minute per key; see Retry-After).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "502": {
      "description": "upstream_error: the tool failed to run. Nothing is billed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "504": {
      "description": "upstream_timeout: the job took too long. Nothing is billed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/v1/app-store-reviews": {
   "post": {
    "operationId": "appStoreReviews",
    "summary": "Apple App Store reviews",
    "description": "Reviews by app name, numeric ID or App Store URL. Send `app` or `apps`.\n\nBilling: One result per 25 reviews returned, rounded up per request. Items that fail are returned but not billed.",
    "tags": [
     "Endpoints"
    ],
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "externalDocs": {
     "url": "https://siftwright.com/docs/#app-store-reviews"
    },
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "app": {
          "type": "string"
         },
         "apps": {
          "type": "array",
          "items": {
           "type": "string"
          },
          "minItems": 1,
          "maxItems": 5,
          "description": "1 to 5 app names, IDs or URLs."
         },
         "countries": {
          "type": "array",
          "items": {
           "type": "string",
           "minLength": 2,
           "maxLength": 2
          },
          "maxItems": 5,
          "default": [
           "us"
          ],
          "description": "Two-letter storefront codes."
         },
         "maxReviewsPerApp": {
          "type": "integer",
          "minimum": 1,
          "maximum": 2000,
          "default": 200
         },
         "sortBy": {
          "type": "string",
          "enum": [
           "mostrecent",
           "mosthelpful"
          ],
          "default": "mostrecent"
         },
         "minRating": {
          "type": "integer",
          "minimum": 1,
          "maximum": 5,
          "default": 1
         },
         "maxRating": {
          "type": "integer",
          "minimum": 1,
          "maximum": 5,
          "default": 5
         },
         "keywords": {
          "type": "array",
          "items": {
           "type": "string"
          },
          "maxItems": 20,
          "description": "Only return reviews containing one of these keywords."
         },
         "since": {
          "type": "string",
          "description": "Only reviews on or after this date."
         }
        },
        "anyOf": [
         {
          "required": [
           "app"
          ]
         },
         {
          "required": [
           "apps"
          ]
         }
        ]
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Results envelope.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Result"
        }
       }
      }
     },
     "400": {
      "description": "invalid_body or invalid_input: the JSON body is missing or a field is invalid.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "description": "missing_api_key or invalid_api_key.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "402": {
      "description": "subscription_inactive: the subscription is canceled or a payment failed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "405": {
      "description": "method_not_allowed: use POST.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "quota_exceeded (this period's results are used up) or rate_limited (60 requests per minute per key; see Retry-After).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "502": {
      "description": "upstream_error: the tool failed to run. Nothing is billed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "504": {
      "description": "upstream_timeout: the job took too long. Nothing is billed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/v1/ats-jobs": {
   "post": {
    "operationId": "atsJobs",
    "summary": "Open jobs from company careers pages",
    "description": "Jobs from Greenhouse, Lever, Ashby, SmartRecruiters and Recruitee boards in one schema. Send `company` or `companies`.\n\nBilling: One result per 3 jobs returned, rounded up per request. Items that fail are returned but not billed.",
    "tags": [
     "Endpoints"
    ],
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "externalDocs": {
     "url": "https://siftwright.com/docs/#ats-jobs"
    },
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "company": {
          "type": "string"
         },
         "companies": {
          "type": "array",
          "items": {
           "type": "string"
          },
          "minItems": 1,
          "maxItems": 10,
          "description": "1 to 10 careers-page URLs, company domains or ats:slug values such as greenhouse:airbnb."
         },
         "titleKeywords": {
          "type": "array",
          "items": {
           "type": "string"
          },
          "maxItems": 20,
          "description": "Only jobs whose title matches."
         },
         "excludeTitleKeywords": {
          "type": "array",
          "items": {
           "type": "string"
          },
          "maxItems": 20,
          "description": "Drop jobs whose title matches."
         },
         "locations": {
          "type": "array",
          "items": {
           "type": "string"
          },
          "maxItems": 20,
          "description": "Location filters."
         },
         "departments": {
          "type": "array",
          "items": {
           "type": "string"
          },
          "maxItems": 20,
          "description": "Department filters."
         },
         "remoteOnly": {
          "type": "boolean",
          "default": false
         },
         "postedWithinDays": {
          "type": "integer",
          "minimum": 0,
          "maximum": 365,
          "default": 0,
          "description": "0 means no limit."
         },
         "maxJobsPerCompany": {
          "type": "integer",
          "minimum": 1,
          "maximum": 500,
          "default": 100
         },
         "includeDescription": {
          "type": "boolean",
          "default": false
         }
        },
        "anyOf": [
         {
          "required": [
           "company"
          ]
         },
         {
          "required": [
           "companies"
          ]
         }
        ]
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Results envelope.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Result"
        }
       }
      }
     },
     "400": {
      "description": "invalid_body or invalid_input: the JSON body is missing or a field is invalid.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "description": "missing_api_key or invalid_api_key.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "402": {
      "description": "subscription_inactive: the subscription is canceled or a payment failed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "405": {
      "description": "method_not_allowed: use POST.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "quota_exceeded (this period's results are used up) or rate_limited (60 requests per minute per key; see Retry-After).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "502": {
      "description": "upstream_error: the tool failed to run. Nothing is billed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "504": {
      "description": "upstream_timeout: the job took too long. Nothing is billed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/v1/domain-whois": {
   "post": {
    "operationId": "domainWhois",
    "summary": "Domain WHOIS and DNS lookup",
    "description": "Registrar, dates, nameservers and DNSSEC from RDAP with WHOIS fallback, plus A, MX, SPF and DMARC. Send `domain` or `domains`.\n\nBilling: One result per 3 domains answered by a registry, rounded up per request. Items that fail are returned but not billed.",
    "tags": [
     "Endpoints"
    ],
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "externalDocs": {
     "url": "https://siftwright.com/docs/#domain-whois"
    },
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "domain": {
          "type": "string"
         },
         "domains": {
          "type": "array",
          "items": {
           "type": "string"
          },
          "minItems": 1,
          "maxItems": 50,
          "description": "1 to 50 domain names."
         },
         "includeDns": {
          "type": "boolean",
          "default": true
         }
        },
        "anyOf": [
         {
          "required": [
           "domain"
          ]
         },
         {
          "required": [
           "domains"
          ]
         }
        ]
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Results envelope.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Result"
        }
       }
      }
     },
     "400": {
      "description": "invalid_body or invalid_input: the JSON body is missing or a field is invalid.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "description": "missing_api_key or invalid_api_key.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "402": {
      "description": "subscription_inactive: the subscription is canceled or a payment failed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "405": {
      "description": "method_not_allowed: use POST.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "quota_exceeded (this period's results are used up) or rate_limited (60 requests per minute per key; see Retry-After).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "502": {
      "description": "upstream_error: the tool failed to run. Nothing is billed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "504": {
      "description": "upstream_timeout: the job took too long. Nothing is billed.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  }
 },
 "components": {
  "securitySchemes": {
   "bearerAuth": {
    "type": "http",
    "scheme": "bearer",
    "description": "API key like sw_live_..., from the welcome page after subscribing."
   }
  },
  "schemas": {
   "Error": {
    "type": "object",
    "required": [
     "error"
    ],
    "properties": {
     "error": {
      "type": "object",
      "required": [
       "code",
       "message"
      ],
      "properties": {
       "code": {
        "type": "string",
        "examples": [
         "invalid_api_key"
        ]
       },
       "message": {
        "type": "string"
       }
      }
     }
    }
   },
   "Usage": {
    "type": "object",
    "properties": {
     "plan": {
      "type": "string"
     },
     "used": {
      "type": "integer"
     },
     "quota": {
      "type": "integer"
     },
     "remaining": {
      "type": "integer"
     },
     "period_end": {
      "type": [
       "string",
       "null"
      ],
      "format": "date-time"
     }
    }
   },
   "Result": {
    "type": "object",
    "required": [
     "endpoint",
     "count",
     "billed",
     "results",
     "usage"
    ],
    "properties": {
     "endpoint": {
      "type": "string",
      "enum": [
       "youtube-transcript",
       "screenshot",
       "google-news",
       "pqc-scan",
       "contact-details",
       "tech-stack",
       "app-store-reviews",
       "ats-jobs",
       "domain-whois"
      ]
     },
     "count": {
      "type": "integer",
      "description": "Items returned, including failed ones."
     },
     "billed": {
      "type": "integer",
      "description": "Results counted against your plan."
     },
     "results": {
      "type": "array",
      "items": {
       "type": "object",
       "additionalProperties": true,
       "description": "Endpoint-specific item. Items usually carry a status field; only successful ones are billed."
      }
     },
     "usage": {
      "$ref": "#/components/schemas/Usage"
     }
    }
   }
  }
 }
}
