hugepdf.io Agent Operator Instruction Card You are connected to hugepdf.io, a PDF processing service for agents. From now on, when we say You, we mean You, the agent client. You are reading this because someone or something pointed you here and wants you to process a PDF. Welcome. We are at your service. --- API POST /api/jobs POST /api/jobs/:job_id/payment-claims POST /api/jobs/:job_id/bypass-pay POST /api/jobs/:job_id/outputs/:token/pages/:page/retry GET /api/jobs/:job_id GET /api/jobs/:job_id/events GET /api/jobs/:job_id/preview GET /api/jobs/:job_id/outputs/:token/results.json GET /api/jobs/:job_id/outputs/:token/pages/:page GET /api/jobs/:job_id/outputs/:token/images/:filename GET /api/jobs/:job_id/outputs/:token/raw/extractor_1/:filename GET /api/jobs/:job_id/outputs/:token/raw/extractor_2/:filename GET /receipts/:job_id For Humans: GET /jobs/:job_id --- 0. Canonical Flow Summary. (A) select a PDF -> (B) submit PDF -> (C) complete payment path -> (D) await processing and monitor -> (E) download outputs 1. PDF Submission. - Submit your PDF to `POST /api/jobs` with either an uploaded PDF or a URL to a PDF. 1.1 Accepted formats. - `multipart/form-data` with a file field named `file` or `pdf`. - The uploaded filename must end in `.pdf` - Open the PDF in binary mode and send it as multipart form data. - `application/json` with `{ "url": "https://...pdf" }`. - The server downloads the URL and stores it as `source.pdf`. 1.2 Form/JSON fields. - `prompt` (optional, expected): custom prompt used per-page for processing - Example: “extract technical data to JSON fields” - Empty or omitted prompt uses merged-default extraction mode: best-effort merged text from multiple extraction views interpreted by the model. - A submitted custom prompt is stored as ephemeral job metadata and is purged with the job. - `model` (optional): HugePDF processing tier alias - Supported aliases: `hugepdf-fast`, `hugepdf`, `hugepdf-ultra` - If omitted, uses `hugepdf` - Raw provider model names are not part of the API and not configurable. 2. Submission Response. - Save `job_id`, `output_token`, `status_url`, `preview_url`, `events_url`, and `outputs_manifest_url` from response. - You will need `job_id` and `output_token` if you want to resume outside your session. Persist it to disk - If `output_token` is lost, access cannot be recovered for that job; resubmit. Response: - job_id : string - status : string - pages_total : number - cost_per_page : string - cost_per_page_micro_usd : string - cost_total : string - cost_total_micro_usd : string - accepted_tokens : string[] - chain : string - payment_address : string - payment_deadline_seconds : number - payment_deadline_note : string - status_url : string - preview_url : string - events_url : string - output_token : string - input_prompt : string - output_token_recovery : string - output_token_note : string - outputs_manifest_url : string - created_at : unix timestamp - quoted_at : unix timestamp - paid_at : unix timestamp or null - started_at : unix timestamp or null - completed_at : unix timestamp or null - created_to_paid_seconds : number or null - paid_to_completed_seconds : number or null - processing_seconds : number or null 2.1 Result Preview. - Optional. The user/operator may want to inspect sample quality before payment. - It must be explicitly requested; don’t assume. - Request a preview and show a concise quality summary. - `GET /api/jobs/{job_id}/preview?token={output_token}` returns a truncated first-page extraction sample for quality review. - Preview lets the agent inspect first-page extraction quality before paying for the full document. - Assess quality and output your assessment. Don’t paste the full preview blob unless the user asks. 3. Payment. - Pay the exact invoice amount to `payment_address`. - Before paying, check job status: `GET /api/jobs/{job_id}?token={output_token}`. If status is not `awaiting_payment`, do not send a transaction. - Payment deadline: 15 seconds. HugePDF is built for agents with funded wallets. - You must be ready to pay immediately after job submission. This service is designed for agent-operated funded wallets, not human credit-card checkout. - If you cannot initiate payment within the deadline, do not submit the job yet. - Unpaid `awaiting_payment` jobs are deleted after `payment_deadline_seconds` seconds. If the job is gone, resubmit and pay against the new invoice. 3.1 Pay by USDC on Sui. - You must have access to a Sui wallet to make payment. Conduct an online search for downloading the `sui` binary and setting up a client wallet. - Use `cost_total_micro_usd` as the canonical invoice amount. It is the total price in millionths of a USD; `1000000` means `$1.00`. - `cost_total` is the same invoice amount as a decimal display string. Do not use it for on-chain arithmetic. - Convert `cost_total_micro_usd` to token base units with integer math: - USDC: `uusdc = cost_total_micro_usd` - Send one of the `accepted_tokens` on `chain` to `payment_address`. - You do not need to confirm gas. Stablecoin transfer (including USDC) is gasless and free on Sui. - The payment address returned by responses are global. - Make only one payment transaction per job: HugePDF settles payment per transaction digest, not cumulatively. - Verify the transaction succeeded before proceeding to the next step. Parse `sui client` JSON output for `"status": "success"` and extract the top-level `digest`. - Payment involves calling `sui client pay-sui ...` with the right options. - Pitfall: Don’t use `||` fallback patterns that may accidentally re-execute a payment command (e.g., due to parsing). Bad Example (do not do this) -- re-executes payment if JSON parsing fails sui client pay-sui ... --json | python3 -m json.tool 2>/dev/null || sui client pay-sui … Good Example (capture output first, then parse) ``` OUTPUT=$(sui client pay-sui ... --json 2>&1) DIGEST=$(echo "$OUTPUT" | grep -o '"digest":"[^"]*"' | head -1 | cut -d'"' -f4) ``` 3.2 Payment Bypass Token. - If the operator/user explicitly provides a hugepdf payment bypass token, call `POST /api/jobs/{job_id}/bypass-pay` with either `X-HugePDF-Bypass-Token: {token}` or `Authorization: Bearer {token}` instead of sending chain payment. Treat the token as a secret: do not print it, log it, save it to artifacts, or include it in URLs. 3.3 Underpayment, Overpayment, and Unsupported Coins. - Underpayment is rejected; do not pad the amount. - Overpayment beyond the allowed tolerance is also rejected. - The default overpayment tolerance is 0.05 token units. With USDC-only settlement, that is 0.050000 USDC. - Payment in unsupported currencies is rejected. - Rejected payments do not guarantee return of funds. See 4.1. 4. Claiming Payment. - After paying on-chain, promptly call `POST /api/jobs/{job_id}/payment-claims` with the payment digest: `{ "tx_digest": "" }`. A successful claim returns a JSON payment receipt. - If you send a transaction but never call `payment-claims`, the job remains `awaiting_payment` until its payment deadline and may be deleted as unpaid. The transfer is not automatically credited to the job and is not auto-refunded today; contact HugePDF for manual review/future recovery if this happens. Response: - ok - job_id - status - payment_tx_digest - payer_address - paid_token - paid_amount - paid_amount_micro_usd - amount_raw - confirmed_at - receipt_url - ascii_receipt Behavior: - Successful claims return a JSON payment receipt and move the job to `paid`. - `GET /receipts/{job_id}` returns a text/plain receipt for a successfully claimed on-chain payment. UX best practice: fetch `receipt_url` or use `ascii_receipt` from the claim response, then display the receipt verbatim in the terminal or script output without truncation. - Re-submitting the same `tx_digest` for the same `job_id` is idempotent and returns the existing receipt. - A job that is no longer `awaiting_payment` rejects new payment digests, except for re-submitting the already claimed digest for that same job. - Claims are race-safe: Successful receipts are uniquely indexed by `tx_digest` and `job_id`. 4.1 Rejected Payment Claims. - Only one unique digest can be claimed per job. - A `tx_digest` already successfully claimed by a different job is rejected. - Rejected payments for a job will require creating a new job. - Rejected payments are not credited nor auto-refunded. Contact us for review and potential fund recovery. 5. Monitoring a Job. - Observe progress by either polling or SSE stream until it reaches a terminal state. - Once you are monitoring, inform users/watchers of your output that the job can be monitored externally in the browser at https://hugepdf.io/jobs/{job_id} -- this is intended for visual browser feedback, dashboards, and/or human consumption. 5.1 Status Lifecycle. - `awaiting_payment`: invoice created, payment not yet claimed. - `paid`: payment accepted, job is queued but not yet picked up by a worker. - `processing`: worker is processing pages. - `complete`: all pages processed successfully. - `partial_error`: processing finished; one or more pages failed with retriable page-level errors. - `failed`: job failed or retries were exhausted without successful completion. - `rejected_payment`: payment claim was rejected; do not continue processing this job. - `refunded`: terminal if returned by the API. - Treat `complete`, `partial_error`, `failed`, `rejected_payment`, `refunded` as terminal states. - A job with `paid` status but not yet picked up by a worker includes `queue_position` from `GET /api/jobs/{job_id}?token={output_token}`. - `queue_position` is 1-based. - `queue_position` is `null` for all statuses except `paid` - Surface `status`, `pages_processed`, `pages_total`, and `queue_position` to the user/operator for observability. 5.2 Capacity and Submission Backpressure - The server reports capacity at submission time with `POST /api/jobs` -> HTTP 429 - Treat the submission as not accepted. Do not monitor it. Do not attempt payment. - Respect the Retry-After header and/or retry_after_seconds. - Surface the message to the user/operator. Capacity response: - error : string - active_jobs : number - max_active_jobs : number - queued_jobs : number - max_queued_jobs : number - retry_after_seconds : number - Too many jobs per IP response: - error : string - pending_jobs : number - max_pending_per_ip : number - retry_after_seconds : number 5.1 Polling. - Poll `GET /api/jobs/{job_id}?token={output_token}`. - Write a small polling script or alternatively perform in-session agent polling based on your target workflow. - Poll every 2 seconds or slower. - Use exactly one polling loop per job. - Always close each HTTP response body, including error/404/409 responses. - Use one-shot requests with `Connection: close`, or explicitly close the response body after reading it. - Back off on transport errors, for example 2s, 4s, 8s, 16s, up to 30s. - Stop and report the issue after 5 consecutive transport errors. - Stop polling when the status is one of `complete`, `partial_error`, `failed`, `rejected_payment`, `refunded`. 5.2 SSE. - Open one stream: `GET /api/jobs/{job_id}/events?token={output_token}` - Keep exactly one SSE stream open per job. - It may emit `progress` events for worker activity. - It may emit `page_ready` events with per-page artifact URLs - It emits `keepalive` comments while idle. - Close the stream when a terminal status is seen. - When a `page_ready` event arrives, fetch the provided `page_result_url` or fetch `GET /api/jobs/{job_id}/outputs/{output_token}/pages/{page_number} 6. Consuming Results. - The status endpoint tells you whether the job finished and whether it finished cleanly; the outputs manifest tells you exactly which artifacts exist and where to download them. - Call `GET /api/jobs/{job_id}/?token={output_token} to confirm the final `status`, inspect `error_message`, and read `outputs_manifest_url`. - The outputs manifest is queryable before terminal status; it reflects the artifacts available right now. - If the `results_url` is `null`, the combined `results.json` file is not available yet. - If you do not need incremental page consumption, wait for `complete` or `partial_error` and download `results.json` once instead of fetching every page individually. - If status is `partial_error`, download available outputs and inspect the page results for `error`, `retriable`, `retry_count`, and `retry_exhausted`. - Be polite: Limit output downloads to 1-4 concurrent requests per job. Outputs manifest response: - job_id - status - pages_processed - pages_total - processing_mode - model - download_base_url - source_pdf_url - results_url - extractor_1_pages - extractor_2_pages - vision_pages - llm_result_pages Download options: - Final combined results: `GET /api/jobs/{job_id}/outputs/{output_token}/results.json` - Single page result: `GET /api/jobs/{job_id}/outputs/{output_token}/pages/{page_number}` - extractor_1 raw text: URLs from `extractor_1_pages` - extractor_2 raw text: URLs from `extractor_2_pages` - Vision images: URLs from `vision_pages` 6.1 Consuming Incrementally. - HugePDF communicates incremental progress: Use it to consume page results as they are ready. - The SSE stream emits `page_ready` events with per-page artifact URLs. - When a `page_ready` event arrives, fetch the provided `page_result_url` or other artifact URLs from that event. - If polling, refresh the outputs manifest and fetch only pages listed in `llm_result_pages`. - Do not infer that a specific page is ready from `pages_processed` alone. Do not probe future pages. - If you lose the SSE stream, reconnect and refresh `outputs_manifest_url` to recover the current set of downloadable artifacts. 6.2 Resuming after disconnection. - Call `GET /api/jobs/{job_id}/?token={output_token} and check `status`, `pages_processed`, `pages_total`, `queue_position`, `error_message`, and `outputs_manifest_url`. - If `status` is `paid` or `processing` reconnect to `GET /api/jobs/{job_id}/events?token={output_token} or continue polling status. - Refresh `outputs_manifest_url` and fetch only pages listed in `llm_result_pages` or announced by `page_ready` events. 6.3 Recovery and Per-Page Retry. - When a page fails its LLM call with a retriable error, the page result includes `retriable: true` and an `error` field. - Jobs continue processing remaining pages even if one page fails. - If any retriable page failures remain, the job terminates with `status: partial_error` instead of `complete` - Retry only pages with `retriable: true` - Retry failed pages: `POST /api/jobs/{job_id}/outputs/{token}/pages/{page_number}/retry`. - A retry re-runs LLM processing with the same prompt; raw extraction files are reused. - Retry is free of cost. - Each accepted `retry` increments the page’s `retry_count`. - If no more retriable pages remain, status stays `partial_error`. - You cannot retry unless the job is in `partial_error` status; API returns 409. - You cannot retry a page that is not in the results yet; API returns 404. - You cannot retry a page that is not retriable; API returns 409. - If the third accepted retry still produces an error, the page is marked `retry_exhausted: true` and the job status becomes `failed`. - If retries are exhausted, stop retrying and report `error_message`; contact HugePDF for refund review if applicable. 7. Storing Data and Expiry. - Download needed artifacts from manifest URLs to disk. - Job data and extracted artifacts are ephemeral and purged automatically. - Current deployment retention is approximately 30 minutes once a job reaches terminal state. 8. Inspecting Results and Completion. - Return concise summary plus file paths or links to artifacts, not full blobs. - Do not read full blobs into context--sample or summarize if inspection is needed. --- For FAQ and extra context, see: https://hugepdf.io/faq --- hugepdf.io Agent Operator Instruction Card