{"openapi":"3.1.0","info":{"title":"Paper Owl Fax API","version":"0.1.0","summary":"Send a fax to a US or Canadian number. The user reviews and pays before anything is sent.","description":"Paper Owl Fax sends one fax to one US or Canadian number. Create a draft, show the user the rendered pages and the price, then either charge an in-chat approved Stripe shared payment token (send) or send the user to the review page to pay with Stripe Checkout. Nothing is sent until payment succeeds. Failed faxes are refunded automatically. $1.99 covers up to 5 pages, plus $0.25 for each page after that, up to 50 pages. Not for unsolicited advertising, bulk sending, or protected health information.","contact":{"name":"Paper Owl Fax support","email":"support@sendpaperowl.com","url":"https://sendpaperowl.com/#support"},"termsOfService":"https://sendpaperowl.com/legal/terms","x-logo":{"url":"https://api.sendpaperowl.com/brand/paper-owl-icon-512.png"},"x-muse":{"name":"Paper Owl Fax","company":"Vectis Studio LLC","description":"Send a fax to any US or Canadian number from chat. You see every page and the price, and approve the charge before anything is sent. Failed faxes are refunded automatically.","websiteUrl":"https://sendpaperowl.com","docsUrl":"https://api.sendpaperowl.com/fax/muse.md","supportEmail":"support@sendpaperowl.com","privacyPolicyUrl":"https://sendpaperowl.com/legal/privacy","termsUrl":"https://sendpaperowl.com/legal/terms","iconUrl":"https://api.sendpaperowl.com/brand/paper-owl-icon-512.png","examplePrompts":["Fax this signed form to my insurance agent at 501 555 0134.","Fax the lease PDF at this link to my landlord at (479) 555 0188.","Did my fax to the records office go through?"],"auth":"none","serverUrl":"https://api.sendpaperowl.com/fax/mcp"}},"servers":[{"url":"https://api.sendpaperowl.com/fax/v1"}],"externalDocs":{"description":"Paper Owl Fax docs","url":"https://api.sendpaperowl.com/fax/docs"},"security":[],"tags":[{"name":"Fax","description":"Draft, pay for, send and track a fax."}],"paths":{"/drafts":{"post":{"operationId":"create_fax_draft","tags":["Fax"],"summary":"Create a fax draft and get the price","description":"Prepare a fax to one US or Canadian fax number and get its price. This creates an unpaid draft only: nothing is sent and nothing is charged. Provide \"from_name\" (required: the name of the person or business sending the fax; ask the user, never guess), \"to\", and exactly one document source: \"text\" (plain text or simple Markdown, rendered to US Letter pages), \"pdf_base64\", or \"pdf_url\" (public https, 10 MB max). Optionally add a cover page. Every page gets a header line in its top margin reading \"From: {from_name} via Paper Owl Fax\" with the sending fax number, date and time, because federal law requires a fax to identify its sender. $1.99 covers up to 5 pages, plus $0.25 for each page after that, up to 50 pages. Returns a draft_id, the page count, the price, a preview_url showing every rendered page, a review_url, and when the draft expires (24 hours). Next, show the user the sender name, the recipient number, page count and price, and offer the preview link before asking for payment. Then either ask the user to approve the charge in chat and call send_fax, or, if your client cannot take payments, give the user the review_url to check the pages and pay there. Will not: send to more than one number, send outside the US and Canada, send unsolicited advertising, or handle medical records or other protected health information.","x-safety":{"side_effects":"Creates an unpaid draft only. Sends nothing, charges nothing."},"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Optional. A unique value per logical request, for example a UUID. Retrying with the same key and body within 24 hours returns the first response instead of repeating the action. Reusing a key with a different body is refused.","schema":{"type":"string","maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFaxDraftInput"}}}},"responses":{"201":{"description":"Draft created. Show the user the recipient, pages and price, and offer preview_url.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fax"}}}},"400":{"description":"The request was invalid. See error.code and error.message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The document is larger than 10 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The pdf_url could not be downloaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited. Retry after the number of seconds in the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/drafts/{id}":{"get":{"operationId":"get_fax_status","tags":["Fax"],"summary":"Get fax status","description":"Look up a fax by draft_id. Read only; changes nothing and charges nothing. Returns the status (draft, paid, sending, delivered, failed, refunded, cancelled or expired), pages, price, timestamps, a plain-language failure reason if it failed, the refund status, and a next_step sentence you can relay to the user. Use it after send_fax, or after the user pays on the review page. While sending, check again about once a minute.","x-safety":{"side_effects":"None. Read only."},"parameters":[{"name":"id","in":"path","required":true,"description":"Draft ID returned when the draft was created.","schema":{"type":"string","pattern":"^fax_[A-Za-z0-9_-]{32}$"}}],"responses":{"200":{"description":"Current status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fax"}}}},"400":{"description":"The request was invalid. See error.code and error.message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No draft with that ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited. Retry after the number of seconds in the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/drafts/{id}/send":{"post":{"operationId":"send_fax","tags":["Fax"],"summary":"Charge the user and send the fax","description":"CHARGES THE USER MONEY. Charges exactly the price quoted by create_fax_draft, then sends the fax. Only call this after the user has seen the recipient, page count and price, has approved that exact charge in chat, and has confirmed the fax is not an unsolicited advertisement. Pass the draft_id, the Stripe shared payment token (spt_...) granted by that approval, and attest_not_advertisement: true. Never invent or reuse a token. The charge is never more than the quote, even if the approval allows more. If the charge fails, nothing is sent and the draft stays unpaid so the user can try again. Safe to retry: calling it again for the same draft never charges or sends twice. Set dry_run: true to check the draft and the approval without charging. If your client cannot take payments in chat, do not call this; give the user the review_url instead. After it returns, use get_fax_status to follow delivery. A fax that fails after the carrier's retries is refunded automatically.","x-safety":{"side_effects":"Charges the user the quoted price and sends the fax. Irreversible once sent.","requires_user_confirmation":true,"idempotent":"Repeating the call for the same draft never charges or sends twice."},"parameters":[{"name":"id","in":"path","required":true,"description":"Draft ID returned when the draft was created.","schema":{"type":"string","pattern":"^fax_[A-Za-z0-9_-]{32}$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Optional. A unique value per logical request, for example a UUID. Retrying with the same key and body within 24 hours returns the first response instead of repeating the action. Reusing a key with a different body is refused.","schema":{"type":"string","maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendFaxBody"}}}},"responses":{"200":{"description":"Paid and handed to the carrier, or already paid earlier (no second charge).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fax"}}}},"400":{"description":"The request was invalid. See error.code and error.message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The payment was declined. Nothing was charged or sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No draft with that ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The draft is not in a state that allows this action.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"The draft expired before it was paid. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited. Retry after the number of seconds in the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Payments are temporarily unavailable. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/drafts/{id}/cancel":{"post":{"operationId":"cancel_fax_draft","tags":["Fax"],"summary":"Cancel an unpaid draft","description":"Cancel an unpaid fax draft by draft_id so it can no longer be paid for or sent. Nothing is charged. Only works before payment; a paid fax cannot be cancelled here. Calling it again on a cancelled draft is harmless. Use it when the user changes their mind or wants to start over with a different number or document.","x-safety":{"side_effects":"Cancels an unpaid draft. Nothing was charged. Repeating it is harmless."},"parameters":[{"name":"id","in":"path","required":true,"description":"Draft ID returned when the draft was created.","schema":{"type":"string","pattern":"^fax_[A-Za-z0-9_-]{32}$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Optional. A unique value per logical request, for example a UUID. Retrying with the same key and body within 24 hours returns the first response instead of repeating the action. Reusing a key with a different body is refused.","schema":{"type":"string","maxLength":255}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelFaxBody"}}}},"responses":{"200":{"description":"Cancelled (or already cancelled).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fax"}}}},"400":{"description":"The request was invalid. See error.code and error.message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No draft with that ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The draft is not in a state that allows this action.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited. Retry after the number of seconds in the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"CreateFaxDraftInput":{"type":"object","properties":{"from_name":{"type":"string","minLength":2,"maxLength":100,"description":"Required. The name of the person or business sending the fax, as it should appear to the recipient, for example \"Ada Lovelace\" or \"Lovelace Consulting LLC\". Printed in the top margin of every page with the sending fax number, date and time, as federal law requires. Ask the user for it; do not guess."},"to":{"type":"string","minLength":7,"maxLength":40,"description":"Recipient fax number in the United States or Canada, for example +15015550134 or (501) 555-0134. One number only."},"text":{"description":"Document as plain text or simple Markdown (headings, lists, bold). Rendered to US Letter pages. Use a form feed character to force a page break.","type":"string","minLength":1,"maxLength":200000},"pdf_base64":{"description":"Document as a base64 encoded PDF, 10 MB maximum.","type":"string","maxLength":13981030},"pdf_url":{"description":"Document as a public https URL that returns a PDF, 10 MB maximum. Private and internal addresses are refused.","type":"string","maxLength":2048},"cover_page":{"type":"object","properties":{"to_name":{"description":"Recipient name or department printed on the cover page.","type":"string","maxLength":100},"subject":{"description":"Short subject line.","type":"string","maxLength":150},"note":{"description":"Short message printed on the cover page.","type":"string","maxLength":2000}},"additionalProperties":false,"description":"Optional cover page added as the first page. It counts toward the page total and price. The sender is taken from from_name."}},"required":["from_name","to"],"additionalProperties":false},"SendFaxBody":{"type":"object","properties":{"payment_token":{"type":"string","minLength":4,"maxLength":256,"description":"The Stripe shared payment token (starts with spt_) granted when the user approved the exact price in chat. Never invent one."},"attest_not_advertisement":{"type":"boolean","const":true,"description":"Must be true. Confirms the user said this fax is not an unsolicited advertisement."},"dry_run":{"description":"If true, check the draft and the payment approval without charging or sending anything. Optional; the real call does the same checks first.","type":"boolean"}},"required":["payment_token","attest_not_advertisement"],"additionalProperties":false},"CancelFaxBody":{"type":"object","properties":{"dry_run":{"description":"If true, report whether the draft can be cancelled without cancelling it.","type":"boolean"}},"additionalProperties":false},"Fax":{"type":"object","properties":{"draft_id":{"type":"string"},"status":{"type":"string","enum":["draft","paid","sending","delivered","failed","refunded","cancelled","expired"],"description":"draft, paid, sending, delivered, failed, refunded, cancelled or expired."},"recipient":{"type":"string","description":"Recipient fax number in E.164 form."},"recipient_display":{"type":"string","description":"Recipient fax number formatted for people."},"from_name":{"type":"string","description":"Sender name printed in the header of every page."},"pages":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Total pages, including any cover page."},"price":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Price in cents."},"currency":{"type":"string","const":"usd"},"display":{"type":"string","description":"Price for people, for example $1.99."}},"required":["amount_cents","currency","display"],"additionalProperties":false},"preview_url":{"type":"string","description":"Page that shows every rendered page. Offer it to the user before they pay."},"review_url":{"type":"string","description":"Review and pay page for clients without in-chat payments. Also shows live status."},"expires_at":{"type":"string","description":"When an unpaid draft expires (ISO 8601)."},"created_at":{"type":"string"},"paid_at":{"type":["string","null"]},"sent_at":{"description":"When the fax was handed to the carrier.","type":["string","null"]},"delivered_at":{"type":["string","null"]},"failed_at":{"type":["string","null"]},"refunded_at":{"type":["string","null"]},"cancelled_at":{"type":["string","null"]},"payment_method":{"anyOf":[{"type":"string","enum":["in_chat","checkout"]},{"type":"null"}]},"failure_reason":{"description":"Plain-language reason when status is failed or refunded.","type":["string","null"]},"refund_status":{"type":"string","enum":["refunded","pending","not_applicable"]},"next_step":{"type":"string","description":"What the agent should tell the user or do next."}},"required":["draft_id","status","recipient","recipient_display","from_name","pages","price","preview_url","review_url","expires_at","created_at","paid_at","sent_at","delivered_at","failed_at","refunded_at","cancelled_at","payment_method","failure_reason","refund_status","next_step"],"additionalProperties":false},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable code.","enum":["INVALID_INPUT","INVALID_NUMBER","UNSUPPORTED_DESTINATION","DOCUMENT_INVALID","DOCUMENT_TOO_LARGE","TOO_MANY_PAGES","URL_NOT_ALLOWED","FETCH_FAILED","NOT_FOUND","DRAFT_EXPIRED","INVALID_STATE","ATTESTATION_REQUIRED","PAYMENT_TOKEN_INVALID","PAYMENT_DECLINED","PAYMENT_IN_PROGRESS","CHARGE_EXCEEDS_QUOTE","RATE_LIMITED","PAYMENTS_UNAVAILABLE","INTERNAL"]},"message":{"type":"string","description":"Plain-language explanation that can be shown to the user."},"details":{"type":"object","additionalProperties":true}}}}}}}}