{"note":"OpenAPI conversion -- returning structured metadata","name":"selectpdf-com","description":"SelectPdf REST API","version":"2.0.0","base_url":"https://selectpdf.com/","endpoints":7,"raw":"@lap v0.3\n# Machine-readable API spec. Each @endpoint block is one API call.\n@api SelectPdf REST API\n@base https://selectpdf.com/\n@version 2.0.0\n@common_fields {parameters: map # Conversion parameters.}\n@endpoints 7\n@toc api2(7)\n\n@endpoint POST /api2/convert\n@desc Convert HTML or URL to PDF\n@returns(200) PDF returned in the response body. `X-SelectPdf-Pages` carries the page count.\n@returns(202) Async accepted (only when `async=true`). `X-SelectPdf-Job-Id` carries the job UUID; poll `/api2/asyncjob` to retrieve the result.\n@errors {400: Bad request — `url` or `html` not supplied, or other validation failure. Response body is plain text., 401: Unauthorized — license key missing, invalid, or quota exhausted., 429: Concurrency limit hit for the calling account. Throttled., 499: Conversion error — engine failure, network failure fetching the URL, etc. Body is plain text.}\n\n@endpoint POST /api2/convert/demo\n@desc Public, keyless, rate-limited HTML to PDF (demo)\n@returns(200) 5-page-capped, watermarked PDF returned in the response body.\n@errors {400: Body is a JSON object describing the rejection. Shapes:   - `{ \"error\":\"unsafe_url\", \"field\":\"url\", \"reason\":\"private_ip\" }` (SSRF guard)   - `{ \"error\":\"unsupported_in_demo\", \"field\":\"user_password\", \"upgrade\":\"https://selectpdf.com/pricing/\" }`   - `{ \"error\":\"missing_input\" }` if neither `url` nor `html` were supplied, 413: Request body exceeds the demo cap (default 1 MB). Use the production endpoint for larger payloads., 429: Rate limited. Body is `{ \"error\":\"rate_limited\", \"reason\":\"per_ip\"|\"daily_cap\", \"upgrade\":\"…\" }`. `Retry-After` header carries seconds to wait., 499: Conversion error. Body is plain text., 503: Demo concurrency cap reached. Body is `{ \"error\":\"rate_limited\", \"reason\":\"concurrency\", \"upgrade\":\"…\" }`. `Retry-After` is short (default 5s).}\n\n@endpoint POST /api2/asyncjob\n@desc Poll a previously-submitted async job\n@returns(200) Job complete. Body matches the originating endpoint (PDF / text / JSON).\n@returns(202) Job still processing. Retry the call after a short delay.\n@errors {400: Bad request — missing or malformed `job_id`., 401: Unauthorized — license key invalid., 499: Job failed or its output is no longer available.}\n\n@endpoint POST /api2/pdfmerge\n@desc Merge multiple PDF files into one\n@returns(200) Merged PDF returned in the response body.\n@returns(202) Async accepted. Poll `/api2/asyncjob` with the returned `X-SelectPdf-Job-Id`.\n@errors {400: Missing files, fewer than 2 input files supplied, or other validation failure., 401: Unauthorized., 429: Concurrency throttled., 499: Merge failed — bad PDF, wrong password, etc.}\n\n@endpoint POST /api2/pdftotext\n@desc Extract text from a PDF, or search within a PDF\n@returns(200) Plain text (or HTML, or JSON array for Search) in body.\n@returns(202) Async accepted. Poll `/api2/asyncjob`.\n@errors {400: Missing PDF input (no `url` and no upload), or invalid `action`., 401: Unauthorized., 429: Concurrency throttled., 499: Extraction failed — corrupt PDF, wrong password, etc.}\n\n@endpoint POST /api2/webelements\n@desc Retrieve web-elements JSON from a completed async HTML→PDF job\n@returns(200) JSON array of matched elements with bounding boxes.\n@errors {400: Bad request — invalid `job_id`., 401: Unauthorized., 499: Job not found, not yet complete, or web-elements file already cleaned up.}\n\n@endpoint POST /api2/usage\n@desc Read account subscription + usage\n@returns(200) Account usage report.\n@errors {401: Unauthorized — license key invalid or expired.}\n\n@end\n"}