{"openapi":"3.1.0","info":{"title":"Markdown to PDF Converter","description":"Open, no-auth API that turns Markdown into a formatted PDF (FastAPI + ReportLab). POST Markdown, get a clean paginated PDF: headings, lists, tables, code, blockquotes and rules.\n\n## Endpoints\n\nBase URL `https://mdtopdf.tigzig.com`\n\n- `POST /v1/convert/text` - JSON body, returns the PDF file directly. Canonical; the MCP tool wraps this one.\n- `POST /v1/convert` - upload a `.md`, `.markdown` or `.txt` file as `multipart/form-data`, returns the PDF file directly.\n- `POST /v1/convert/text/hosted` - JSON body, returns `{\"pdf_url\": \"...\"}` instead of the binary, for clients that would rather have a link.\n\n```bash\ncurl -X POST https://mdtopdf.tigzig.com/v1/convert/text \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"content\": \"# Title\\n\\nHello **world**\", \"filename\": \"out.pdf\"}' \\\n  --output out.pdf\n```\n\n```bash\ncurl -X POST https://mdtopdf.tigzig.com/v1/convert \\\n  -F 'file=@notes.md' \\\n  --output out.pdf\n```\n\n## Limits\n\nEvery one of these is enforced, so none of them should be a surprise you meet by being refused.\n\n- **10 requests per minute** and **200 per day**, per IP.\n- **1 MB** per document, which is roughly 400 pages of ordinary prose.\n- **50,000 characters** in a single unbroken paragraph. Laying out one very long paragraph costs far more than the same text split up, so a document with no blank lines in it is refused with `PARAGRAPH_TOO_LONG` rather than run slowly.\n- **15 seconds** per conversion. Almost everything finishes in a few seconds; a document that exceeds this is stopped and returns `CONVERSION_TIMEOUT`.\n\nEvery response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`, and a `429` carries `Retry-After` with a real number of seconds. Concurrent requests are QUEUED rather than refused, so a burst waits a moment instead of failing and you do not need to serialise your calls.\n\n## Request encoding\n\nThe request body must be UTF-8; JSON requires it (RFC 8259). Send the body UTF-8 encoded rather than GBK or Latin-1.\n\n## Markdown supported\n\n- Headings `h1` to `h6`\n- Bold, italic, strikethrough, inline code\n- Links, clickable in the PDF\n- Bullet and numbered lists with real nesting (two-space indentation works)\n- Task lists\n- Tables, any column count; wide tables shrink to fit rather than failing\n- Fenced code blocks\n- Blockquotes and horizontal rules\n- Emoji, mapped to matching symbols rather than a blank box\n- Currency and maths symbols\n\n## Page breaks\n\nMarkdown has no page break, so this API adds one. Put any of `:::pagebreak:::`, `\\pagebreak`, `\\newpage` or `<!-- pagebreak -->` on a line by itself and the content after it starts on a new page. Markers inside fenced code blocks are left alone.\n\n## Plain text files\n\nUpload a `.txt` file to `POST /v1/convert` and its single line breaks are kept, so a letter stays laid out the way it was written. A `.md` file follows standard Markdown rules, where a single newline is just a space.\n\n## Symbols\n\nGreek letters (alpha, beta, sigma, Delta, Omega), maths and logic operators (`<=`, `>=`, `!=`, `~=`, sqrt, sum, product, integral, partial, infinity, element-of, subset, union) and arrows both single and double all render correctly, as do typographic punctuation, dashes, curly quotes and the dollar, pound, euro, yen and cent signs.\n\nThe rupee, won, rouble, naira, lira and bitcoin signs are drawn by none of the bundled fonts, so they are written out instead: `₹1,950` converts to `Rs.1,950`. The amount is preserved, the sign is not.\n\n## Not supported\n\nListed so you can plan around it. None of these fail the conversion.\n\n- Images are skipped; the surrounding text is unaffected.\n- Non-Latin scripts (Devanagari, Arabic, CJK, Cyrillic) render as filled boxes, because the bundled fonts have no glyphs for them.\n- Uncommon emoji with no equivalent symbol fall back to a small dot.\n- Raw HTML tags are ignored, though their text is kept.\n\n## Errors\n\nEvery `4xx` and `5xx` returns the same envelope:\n\n```json\n{\"error\": {\"code\": \"...\", \"message\": \"...\", \"path\": \"...\", \"example\": \"...\"}, \"help\": {}}\n```\n\n`code` is a stable slug, `message` says what to change, and `example` is a curl line that works. Malformed JSON is a `400`; well-formed JSON that fails the schema is a `422`.\n\nThe slugs: `INVALID_JSON_BODY`, `INVALID_REQUEST_BODY`, `FILE_NOT_TEXT`, `DOCUMENT_TOO_LARGE`, `PARAGRAPH_TOO_LONG`, `CONVERSION_TIMEOUT`, `SERVICE_BUSY`, `STORAGE_BUDGET_EXCEEDED`, `NOT_FOUND`, `ENDPOINT_NOT_FOUND` on a convert-like path, `METHOD_NOT_ALLOWED`, `RATE_LIMITED`.\n\n## MCP server\n\n`https://mdtopdf.tigzig.com/mcp` over Streamable HTTP, tool `convert_markdown_to_pdf`, which returns a hosted PDF URL rather than the binary. Add it as a custom connector in Claude, ChatGPT, Cursor, LM Studio or n8n.\n\n## More Tigzig tools\n\nFree, no auth: market and fund data, macro and credit indicators, portfolio and risk analytics, India corporate filings, SQL databases. Catalog at `https://api.tigzig.com/.well-known/api-catalog`, guide at `https://www.tigzig.com/llms.txt`.","version":"1.2.0"},"paths":{"/v1/convert":{"post":{"summary":"Upload a Markdown or text file, get the PDF file back","description":"Upload a Markdown or plain-text file and get the PDF back in the response body.\n\nSend the file as multipart/form-data under the field name `file`. Accepts .md, .markdown\nand .txt; a .txt is treated as plain text so its single line breaks are preserved, while\n.md follows standard Markdown rules. The response is application/pdf, not JSON, and the\ndownload name is taken from the uploaded filename. A file that is not UTF-8 text (a .pdf\nor .docx, say) returns 400 FILE_NOT_TEXT rather than failing mid-conversion.\n\nSupports headings, bold, italic, strikethrough, inline and fenced code, links, nested and\nnumbered lists, task lists, tables with column alignment, blockquotes, rules, Greek and\nmaths symbols, and the page-break markers described in the API description.","operationId":"convert_markdown_v1_convert_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_convert_markdown_v1_convert_post"}}},"required":true},"responses":{"200":{"description":"The generated PDF, returned as the response body.","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/convert/text":{"post":{"summary":"Send Markdown as JSON, get the PDF file back (canonical)","description":"Send Markdown as JSON and get the PDF back in the response body.\n\nBody: {\"content\": \"# your **markdown**\", \"filename\": \"out.pdf\"} - `content` is required,\n`filename` is optional and only names the download. The body must be UTF-8 (RFC 8259).\nThe response is application/pdf, not JSON; if your HTTP client is awkward with binary\nbodies, POST /v1/convert/text/hosted instead and get a URL to the PDF.\n\nSupports headings, bold, italic, strikethrough, inline and fenced code, links, nested and\nnumbered lists, task lists, tables with column alignment, blockquotes, rules, Greek and\nmaths symbols, and the page-break markers described in the API description.","operationId":"convert_markdown_text_endpoint_v1_convert_text_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkdownText"},"examples":{"note":{"summary":"A short note - the smallest thing worth converting","value":{"content":"# Meeting note\n\nAgreed to ship on Friday. **Owner:** Priya.\n","filename":"meeting-note.pdf"}},"report":{"summary":"A short report with a heading, a list and a table","value":{"content":"# Quarterly summary\n\nRevenue held steady while costs fell.\n\n## Highlights\n\n- Costs down 8% quarter on quarter\n- Two new enterprise accounts\n- Churn unchanged at 1.2%\n\n## Numbers\n\n| Metric | Q2 | Q3 |\n|---|---|---|\n| Revenue | 4.10 | 4.15 |\n| Costs | 2.80 | 2.58 |\n\n> Costs fell mainly on the infrastructure move.\n","filename":"quarterly-summary.pdf"}}}}},"required":true},"responses":{"200":{"description":"The generated PDF, returned as the response body.","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/convert/text/hosted":{"post":{"summary":"Send Markdown as JSON, get a hosted PDF link back (the MCP tool)","description":"Convert Markdown text into a formatted PDF and return a hosted URL to it.\n\nGive it Markdown (including AI-generated Markdown) and get back a URL to a cleanly\nformatted PDF: headings, lists, tables, code, blockquotes, rules. Send a JSON body\n{\"content\": \"# your **markdown**\", \"filename\": \"out.pdf\"} - the text must be UTF-8.\nReturns {\"pdf_url\": \"...\"}. Generated files are served from /static/pdfs and cleaned\nup after 24h. (This is the hosted variant of POST /v1/convert/text - a URL instead of\nthe binary - because an MCP tool result is text and cannot carry a PDF payload.)","operationId":"convert_markdown_to_pdf","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkdownText"},"examples":{"note":{"summary":"A short note - the smallest thing worth converting","value":{"content":"# Meeting note\n\nAgreed to ship on Friday. **Owner:** Priya.\n","filename":"meeting-note.pdf"}},"report":{"summary":"A short report with a heading, a list and a table","value":{"content":"# Quarterly summary\n\nRevenue held steady while costs fell.\n\n## Highlights\n\n- Costs down 8% quarter on quarter\n- Two new enterprise accounts\n- Churn unchanged at 1.2%\n\n## Numbers\n\n| Metric | Q2 | Q3 |\n|---|---|---|\n| Revenue | 4.10 | 4.15 |\n| Costs | 2.80 | 2.58 |\n\n> Costs fell mainly on the infrastructure move.\n","filename":"quarterly-summary.pdf"}}}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"Body_convert_markdown_v1_convert_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_convert_markdown_v1_convert_post"},"ConversionResponse":{"properties":{"pdf_url":{"type":"string","title":"Pdf Url"}},"type":"object","required":["pdf_url"],"title":"ConversionResponse","description":"Response for the hosted (URL-returning) conversion."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"MarkdownText":{"properties":{"content":{"type":"string","title":"Content"},"filename":{"type":"string","title":"Filename","default":"document.pdf"}},"type":"object","required":["content"],"title":"MarkdownText","example":{"content":"# Title\n\nHello world","filename":"out.pdf"}},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}