For agents

Account-free PDF conversion. OpenAPI · Plain-text instructions · Current capabilities

Before you purchase

paperfeel.ing turns an existing PDF into a simulated scan: an image-based, grayscale PDF rendered at 200 DPI. Paid output includes every accepted page without the SAMPLE watermark. It is suitable when the buyer wants a scanned appearance. It is unsuitable when colour, searchable/selectable text or editable form fields must be preserved. Keep the original file.

One purchase buys one document, including all accepted pages, for €1 base plus applicable tax and fees. There is no subscription. Repeat downloads during the retention period are included. For a fixed-tax quote, the itemized quote is the authoritative total. When quote.taxPending is true, Stripe Checkout displays and confirms the final tax-inclusive total before payment; separately charged wallet/network costs may be additional. Read capabilities for current upload byte/page limits and supported billing countries. PDFs must be unencrypted and also pass page-dimension, pixel-budget and output-size checks; a file within the byte/page limits can still fail processing.

Inspect the free first-page sample before paying: it uses the same rendering process as the full output, with SAMPLE burned into the pixels. It does not preview later pages. Examine the PNG if you can inspect images, or present the sample to the buyer; do not claim visual quality was checked if you cannot view it. Check small text, filled fields and editor-added content.

No measured production turnaround estimate is available yet. Preview and full rendering are asynchronous, and duration varies with document complexity and load. Keep one status request in flight: poll about every two seconds during processing or payment, every fifteen seconds for an idle unpaid sample, obey Retry-After and back off errors to thirty seconds. Stop on terminal states, operator-action cases or expiry; use explicit refresh for review cases. The browser pauses in background tabs and refreshes on focus. If your execution window ends, save the existing job state securely and resume polling later; do not start a second purchase.

If a paid conversion permanently fails, the service initiates a refund of the amount it collected, including tax and fees. Separate wallet/network costs are excluded. Provider refund timing varies; refund_pending is not confirmation that funds have returned. A refundActionRequired job needs operator review: stop automatic polling and use the support page with the job reference. Refund review never restores download access. Terms: https://paperfeel.ing/terms.html Support: https://paperfeel.ing/support.html

Documents are stored privately and processed on the server. Unpaid jobs initially expire after one hour; full output expires 24 hours after generation. Source files are deleted after successful full conversion. Payment records and optional feedback have separate retention rules. Review the privacy policy before uploading sensitive documents: https://paperfeel.ing/privacy.html

Inspect example output before uploading

These are public, fictional documents converted with the service. Compare each original with its scanned output without uploading your own document or paying.

Partly filled form: Original https://paperfeel.ing/examples/form-original.pdf Scanned output https://paperfeel.ing/examples/form-paperfeel.pdf

Editor-added text: Original https://paperfeel.ing/examples/edited-original.pdf Scanned output https://paperfeel.ing/examples/edited-paperfeel.pdf

Two-page project brief: Original https://paperfeel.ing/examples/brief-original.pdf Scanned output https://paperfeel.ing/examples/brief-paperfeel.pdf

Discover

Agentic payments (MPP and x402) are disabled by default pending a later rollout. Stripe Checkout is the default purchase route for a human buyer. Agents can still inspect examples, generate free samples, poll/download authorized jobs and submit feedback. Check capabilities.agenticPaymentsEnabled and protocols before attempting payment; disabled agentic endpoints return 503 agentic_payments_disabled without reserving or charging. A disabled flag does not interrupt reconciliation or refunds for existing payments.

Base URL: https://paperfeel.ing. Read /v1/capabilities for currently advertised protocols, purchasesEnabled, billing countries and file limits. capabilities.service describes output characteristics, purchase scope, preview limits, timing availability, public example pairs and policy links. Use /openapi.json for request and response schemas. Only use a payment method listed in protocols; an empty list means purchases are unavailable.

Preview and purchase

POST /v1/jobs with a random Idempotency-Key: 32–128 letters, digits, underscores or hyphens. Save this key before sending, then save job.id and token from the response. Retrying the same creation key recovers the same job while it exists. Treat the creation key as a secret too: it can recover the job token.

Job creation is limited to 10 requests per source per minute and 200 requests globally per UTC hour. Creation retries count toward these limits. On 429, respect Retry-After; an hourly limit may remain exhausted after that delay. Existing job status and download requests do not consume the creation budget.

POST raw application/pdf bytes to the returned uploadUrl, with X-Job-Token: token. Resolve relative URLs against the service base URL. Use X-Job-Token on all subsequent job requests. Retrying identical bytes is safe; different bytes conflict. Upload admission is bounded per API instance: 503 upload_capacity_busy means keep the file locally and retry after Retry-After. A 408 upload_interrupted means retry the same bytes; after a lost response, poll the existing job and POST complete-upload if it already accepted the file. Poll GET /v1/jobs/{id}, normally every two seconds, until sampleAvailable is true. Stop on failed or expired processing.

GET /v1/jobs/{id}/sample returns the free first-page PDF with SAMPLE embedded in its pixels; ?format=png returns a PNG. No payment is needed for the sample.

When ready to purchase, POST /v1/jobs/{id}/quote with {"country":"<buyer billing country>"}; add "stablecoin":true for x402. Read capabilities.taxMode first. In stripe_checkout mode, send {} for a base-price quote: taxPending=true means the buyer must confirm the final tax-inclusive total in Stripe Checkout, which collects their billing address. This mode supports only Checkout and does not advertise a fixed country list. In manual mode, the country field is required to calculate tax for every payment method, including MPP and x402. Supply the buyer’s actual billing country using an uppercase two-letter code advertised in capabilities.countries; if unknown, ask the buyer before requesting the quote. Inspect the itemized total and obtain buyer spending authorization before payment. EUR amounts are integer cents; USDC amounts are atomic units (1 USDC = 1,000,000 units). Timestamps are Unix milliseconds. A new quote replaces the previous unreserved quote; do not refresh a quote during an uncertain payment.

Only when explicitly advertised in capabilities.protocols: POST /v1/jobs/{id}/purchase/mpp or /v1/jobs/{id}/purchase/x402 with {"quoteId":"<quote.id>"} and a stable Idempotency-Key (16–128 letters, digits, underscores or hyphens). Keep X-Job-Token. An initial request without payment credentials returns 402 with WWW-Authenticate for MPP or PAYMENT-REQUIRED for x402. This reserves an attempt but does not itself collect payment. Use the appropriate SDK to answer the challenge: Authorization: Payment for MPP, PAYMENT-SIGNATURE for x402. Validate the requested amount, currency/asset, network and recipient against the approved quote and wallet policy.

A successful 202 purchase response includes statusUrl and Payment-Receipt (MPP) or PAYMENT-RESPONSE (x402). Payment is confirmed; rendering may still be running. Poll statusUrl until downloadAvailable is true, then GET /v1/jobs/{id}/download with X-Job-Token. Polling and repeat downloads never charge and do not require payment credentials.

Save the downloaded PDF before job.expiresAt. Unpurchased jobs initially expire after one hour; an active purchase reserves files for up to 24 hours, and full output is available for 24 hours after generation. DELETE /v1/jobs/{id} revokes access and removes stored files. Only delete once output is safely saved and the purchase is resolved.

Why billing country is required

In stripe_checkout mode, Stripe collects the billing location and calculates tax using the merchant’s existing Stripe Tax registrations; the website quote is the pre-tax base/fee snapshot. In manual mode, the service uses the buyer’s billing country to select its configured tax rate and supported selling market. This is service pricing information, not an MPP or x402 protocol requirement. Read the current list from capabilities.countries; do not hard-code countries, infer the country from the wallet/network, choose a country for a lower price, or default to the merchant’s country. If the buyer’s country is unknown, obtain it before requesting a paid quote. A free preview does not require it. Unsupported countries return 422. Fixed-rate manual quotes do not offer tax-ID exemptions. Checkout tax uses Stripe’s billing-address calculation; no tax registration or filing is created automatically.

Payment methods

MPP uses Stripe card payments in EUR with a buyer-authorized Shared Payment Token (SPT). It does not use stablecoins in this service. Obtain the SPT through the buyer’s authorized payment system; never supply the merchant’s Stripe secret key.

x402 v2 uses the exact scheme with USDC on Base mainnet (eip155:8453), asset 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913. The quote includes the locked USDC amount and payTo recipient. The buyer controls their wallet and spending budget. This is not a testnet route.

For a human checkout, POST /v1/jobs/{id}/checkout with {"quoteId":"<quote.id>"} and an Idempotency-Key. Open the returned Stripe URL for the buyer. Repeating the same request resumes or recovers the existing session after checking its current state. An expired unpaid session is released only after confirmed provider resolution; then obtain a fresh quote. A complete session with payment still processing remains pending. payment_recovery_required means operator support is needed; do not authorize another payment. Confirm success through job status, never the redirect alone. For manual quotes, the Checkout billing country must match the quote. For taxPending quotes, Checkout confirms the final amount; fulfillment validates the frozen subtotal/catalog, complete automatic-tax calculation and exact PaymentIntent amount/currency, then records a separate final quote without changing the submitted base-price quote.

Retries and privacy

After an uncertain payment response, poll the existing job first. Preserve the job token, quote, purchase idempotency key and exact submitted payment credential securely. Do not create a new job, change routes or issue a new payment authorization to resolve uncertainty. Retry only the same attempt; unresolved outcomes need reconciliation. If job status confirms payment is unpaid after payment_declined, payment_action_required or payment_verification_failed, request a fresh quote and fresh buyer-authorized credential, or use human Checkout. A 402 alone is not evidence that a new attempt is safe. Known action-required intents are canceled before reopening purchase; never reuse the failed payment proof. POST /v1/jobs/{id}/cancel-payment only cancels attempts that can safely be cancelled. Stop purchasing on paid, refund_pending, refunded or disputed states.

GET /v1/jobs/{id}/recovery returns a private browser recovery link. The token is in its fragment, not its query string. Tokens, creation keys, recovery links, payment credentials and document contents must not appear in logs or support messages. Job IDs and transaction hashes alone cannot access documents. The browser session endpoint is optional; header-authenticated agents do not need cookies.

Inspect JSON error codes as well as HTTP status. 400: invalid request/key/credential. 402: payment challenge or payment error; only a response with the protocol challenge header is an SDK challenge. A download 402 or payment_declined response is not a challenge. 404: missing job or invalid token. 409: state conflict, quote expiry or unresolved attempt—poll before changing anything. 410: expired/deleted job. 413/422: upload limits, invalid PDF or unsupported country; parsing can also fail asynchronously in job status. Known invalid/encrypted/page/pixel/output limits fail on the first attempt with an allowlisted code; unknown worker/storage failures retain bounded retries. 429: wait for Retry-After. 503: service/provider unavailable or purchases disabled—poll before retrying a payment. Stop on failed/expired processing or refund_pending/refunded/disputed payment, and respect expiresAt. A paid job may still be rendering: keep polling until downloadAvailable.

Send feedback

Example without a job or token: POST /v1/feedback with Content-Type: application/json and a fresh Idempotency-Key, body {"category":"bug","summary":"Unable to start checkout","details":"Checkout returned an error before payment was completed.","operation":"POST /v1/jobs/{id}/checkout","paymentMethod":"checkout","httpStatus":503,"errorCode":"checkout_unavailable"}. Use your observed status/error, not this illustrative value.

Feedback is available independently of conversion and purchase: no account, job, upload or successful payment is required. If the user requests feedback or a service limitation prevents the task, check capabilities.feedback.enabled and POST /v1/feedback with a fresh 32–128 character Idempotency-Key. Send category (bug, missing_feature, feature_request or documentation), summary (5–160 characters), and details (10–4000 characters). Optional contact (3–300 characters) is an email address, reply URL or handle with its platform; include it only with the person’s permission. It permits a reply about this request, not marketing. Optional operation, errorCode, paymentMethod (checkout, mpp or x402), and httpStatus (400–599) describe a failed API call. Omit jobId if the job was never created, has expired, or its token is unavailable; those situations must not prevent reporting a payment failure. An optional jobId requires that job’s X-Job-Token; the service retains only processing-version/error diagnostics. No purchase or account is required.

Do not submit PDF contents, filenames, recovery links, credentials or unrelated personal information. Feedback and contact details are separate from document retention: they expire after 90 days and are removed by scheduled cleanup. A 202 receipt includes id, status: received and expiresAt; it does not promise a reply or implementation. Reuse the same key and identical body after a lost response. A changed body conflicts (409). Respect Retry-After on 429; limits are 10 new submissions per source IP/day and 200 globally/hour. Unconfigured feedback returns 503. There is no public endpoint for reading feedback.