Base URL: https://api.inkandordertools.com. Interactive OpenAPI reference: /docs.
Every API call needs your key in the Authorization header:
Authorization: Bearer io_live_xxxxxxxxxxxxxxxxxxxxxxxx
Get a free key on the developer home page or with POST /v1/signup:
curl -X POST https://api.inkandordertools.com/v1/signup \
-H "Content-Type: application/json" -d '{"email":"you@company.com"}'
The key is returned once (HTTP 201). We store only a SHA-256 hash of it. One key per email; a few signups per network per day.
The samples below read it from the INKORDER_API_KEY environment variable.
POST /v1/convertSend a multipart/form-data request with the file in the field file. The response body is the PDF
(Content-Type: application/pdf). Headers X-Quota-Used and X-Quota-Limit show your monthly count.
| Engine | Extensions |
|---|---|
| Headless Chromium | .html .htm |
| LibreOffice | .docx .doc .odt .rtf .txt .md .xlsx .xls .ods .csv .pptx .ppt .odp .epub |
The type is chosen from the file extension. Max upload 25 MB.
GET /v1/usageReturns your plan, quota, usage this calendar month (UTC), and this month's conversion events (metadata only).
{
"key_prefix": "io_live_Abc1", "plan": "free", "quota": 50, "used": 2, "remaining": 48,
"period_start": "2026-09-01T00:00:00.000+00:00",
"events": [{"ts": "...", "input_type": "docx", "bytes_in": 36909, "bytes_out": 25610,
"duration_ms": 640, "success": 1, "error": null}]
}
| Status | Meaning | What to do |
|---|---|---|
| 401 | Missing or invalid API key | Check the Authorization: Bearer header. |
| 413 | File larger than 25 MB | Split or compress the input. |
| 415 | Unsupported file type | Use one of the extensions above. |
| 429 | Monthly quota used up | Upgrade your plan or wait for the 1st of the month (UTC). |
| 502 | Conversion failed (e.g. corrupt file) | Check the file opens locally; retry once. Failed conversions don't count. |
Error bodies are JSON: {"detail": "..."}.
| Plan | Files / month | Price |
|---|---|---|
| Free | 50 | $0 |
| Starter | 1,000 | $29/mo |
| Pro | 10,000 | $99/mo |
Only successful conversions count. Quotas reset on the 1st of each month (UTC). Rejected (401/415/429) and failed requests are free. Paid plans are monthly subscriptions billed through Stripe; cancel any time and your key returns to the Free plan.
The developer API is separate from the Ink & Order PDF app, which stays pay once and runs on your device.
Each sample reads INKORDER_API_KEY (and optionally INKORDER_API_URL) from the environment.
#!/usr/bin/env bash
# Usage: INKORDER_API_KEY=io_live_... ./curl_quickstart.sh report.docx
set -euo pipefail
INKORDER_API_URL="${INKORDER_API_URL:-https://api.inkandordertools.com}"
IN="$1"; OUT="${IN%.*}.pdf"
# Convert: send the file as multipart field "file", get a PDF back.
curl -sS --fail-with-body \
-H "Authorization: Bearer $INKORDER_API_KEY" \
-F "file=@$IN" \
"$INKORDER_API_URL/v1/convert" -o "$OUT"
echo "saved $OUT"
# Check this month's usage (JSON: plan, quota, used, remaining, events).
curl -sS -H "Authorization: Bearer $INKORDER_API_KEY" "$INKORDER_API_URL/v1/usage"
echo
"""Usage: INKORDER_API_KEY=io_live_... python python_requests.py report.docx"""
import os
import sys
import requests
BASE = os.environ.get("INKORDER_API_URL", "https://api.inkandordertools.com")
HEADERS = {"Authorization": f"Bearer {os.environ['INKORDER_API_KEY']}"}
def convert(path: str) -> str:
with open(path, "rb") as f:
r = requests.post(f"{BASE}/v1/convert", headers=HEADERS,
files={"file": (os.path.basename(path), f)}, timeout=120)
if r.status_code == 429:
raise SystemExit("Monthly quota used up - upgrade your plan.")
r.raise_for_status() # 401 bad key, 415 unsupported type, 502 conversion failed
out = os.path.splitext(path)[0] + ".pdf"
with open(out, "wb") as f:
f.write(r.content)
return out
if __name__ == "__main__":
print("saved", convert(sys.argv[1]))
u = requests.get(f"{BASE}/v1/usage", headers=HEADERS, timeout=30).json()
print(f"used {u['used']}/{u['quota']} on {u['plan']}")
// Usage: INKORDER_API_KEY=io_live_... node node_fetch.mjs page.html (Node 18+; no dependencies)
import { readFile, writeFile } from "node:fs/promises";
import path from "node:path";
const BASE = process.env.INKORDER_API_URL ?? "https://api.inkandordertools.com";
const headers = { Authorization: `Bearer ${process.env.INKORDER_API_KEY}` };
async function convert(file) {
const form = new FormData();
form.append("file", new Blob([await readFile(file)]), path.basename(file));
const res = await fetch(`${BASE}/v1/convert`, { method: "POST", headers, body: form });
if (!res.ok) throw new Error(`Ink & Order API ${res.status}: ${await res.text()}`);
const out = file.replace(/\.[^.]+$/, "") + ".pdf";
await writeFile(out, Buffer.from(await res.arrayBuffer()));
return out;
}
console.log("saved", await convert(process.argv[2]));
const u = await (await fetch(`${BASE}/v1/usage`, { headers })).json();
console.log(`used ${u.used}/${u.quota} on ${u.plan}`);