Everything you need to convert one document or ten thousand.
Nothing leaves your machine. No account, no network, no AI.
pip install tablewise
tablewise report.pdf # -> ~/md-repo/report.md
tablewise budget.xlsx -o ./md-repo # choose the output folder
tablewise contract.docx -n "Contract" # choose the output name
tablewise scan.pdf --dry-run # print the engine command only
tablewise report.pdf --force # overwrite an existing .md
| Flag | Meaning |
|---|---|
-o, --salida | Output folder (default ~/md-repo). |
-n, --nombre | Output name, without extension. |
--force | Overwrite an existing .md. |
--dry-run | Print the engine command, convert nothing. |
--python | Interpreter that carries the engines (or TABLEWISE_PYTHON). |
--markitdown | MarkItDown executable (or TABLEWISE_MARKITDOWN). |
-q, --quiet | Only errors. |
Exit codes: 0 ok, 1 the engine produced no file,
2 invalid input. The desktop app is python tablewise_app.py.
Base URL: https://api.tablewise.dev. Every request needs
Authorization: Bearer $TABLEWISE_API_KEY.
curl -X POST https://api.tablewise.dev/v1/signup \
-H "Content-Type: application/json" \
-d '{"email":"you@company.com"}'
The key is returned once. Free plan: 50 units a month.
curl -X POST https://api.tablewise.dev/v1/convert \
-H "Authorization: Bearer $TABLEWISE_API_KEY" \
-F "file=@budget.xlsx" \
-F "mode=fidelity"
mode is fidelity (default, own engines) or
fast (MarkItDown). Response:
{
"markdown": "---\nsource: \"budget.xlsx\"\nengine: \"excel\"\nconverted: 2026-10-22\n---\n\n...",
"engine": "excel",
"units": 1,
"usage": {"units_used": 1, "units_limit": 50, "period": "2026-10"}
}
import os
import requests
r = requests.post(
"https://api.tablewise.dev/v1/convert",
headers={"Authorization": f"Bearer {os.environ['TABLEWISE_API_KEY']}"},
files={"file": ("budget.xlsx", open("budget.xlsx", "rb"))},
data={"mode": "fidelity"},
timeout=120,
)
r.raise_for_status()
open("budget.md", "w").write(r.json()["markdown"])
const fs = require("fs");
const form = new FormData();
form.append("file", new Blob([fs.readFileSync("budget.xlsx")]), "budget.xlsx");
form.append("mode", "fidelity");
const res = await fetch("https://api.tablewise.dev/v1/convert", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.TABLEWISE_API_KEY}` },
body: form,
});
const data = await res.json();
fs.writeFileSync("budget.md", data.markdown);
curl https://api.tablewise.dev/v1/me \
-H "Authorization: Bearer $TABLEWISE_API_KEY"
{"email":"you@company.com","plan":"free","period":"2026-10",
"units_used":12,"units_limit":50,"units_left":38,"resets_at":"2026-11-01T00:00:00+00:00"}
curl -X POST https://api.tablewise.dev/v1/batch \
-H "Authorization: Bearer $TABLEWISE_API_KEY" \
-F "files=@jan.xlsx" -F "files=@feb.xlsx" -F "files=@mar.xlsx"
Up to 100 files per call. Each one is charged independently: a bad file returns its own error and refunds its units, the rest still convert.
{"results": [
{"filename": "jan.xlsx", "markdown": "...", "engine": "excel", "units": 1},
{"filename": "feb.xlsx", "error": {"code": "unsupported_type", "message": "..."}}
], "usage": {"units_used": 12, "units_limit": 5000, "period": "2026-10"}}
curl -X POST https://api.tablewise.dev/v1/billing/checkout \
-H "Authorization: Bearer $TABLEWISE_API_KEY"
Returns {"checkout_url": "https://checkout.stripe.com/..."}.
The new plan is active as soon as Stripe confirms the payment.
curl -X POST https://api.tablewise.dev/v1/billing/portal \
-H "Authorization: Bearer $TABLEWISE_API_KEY"
Returns a Stripe-hosted page where the customer updates the card or cancels. Cancelling downgrades the key to the free plan when the paid period ends.
| Status | Code | When |
|---|---|---|
| 400 | invalid_email, bad_mode, bad_signature | Malformed input. |
| 401 | missing_key, invalid_key | No key or unknown key. |
| 402 | quota_exceeded | Not enough units left this month. |
| 413 | too_large, document_too_big | Over 25 MB or 2,000 units. |
| 415 | unsupported_type | Extension not supported. |
| 422 / 500 | conversion_failed, office_lock_file | Engine error (units refunded). |
| 429 | rate_limited | Too many requests per minute. |
| 503 | billing_disabled, engine_unavailable | Feature not configured or engine missing. |
| 504 | timeout | Engine exceeded the time limit (units refunded). |
.xlsx .xlsm .xltx .xltm .xls — own engine, merged cells and sheet structure..pdf .docx .pptx — Docling, table reconstruction..doc .rtf .odt .ppt .xls — pre-converted with the system tools..csv .html .epub .msg .eml .json .xml .txt .md — MarkItDown.Every output starts with exactly three keys. source is the file
name only, never the path: a path leaks folder structure and adds nothing to a
retrieval system.
---
source: "2026-budget.xlsx"
engine: "excel"
converted: 2026-10-22
---
Stable, parseable, and cheap to filter: engine = excel is the
set of files whose tables you can trust most.