RubanTag API
REST API for automated PDF/UA-1 tagging. Available on Pro and Enterprise plans.
Overview
The RubanTag API lets you upload PDF files, poll for processing status, and download the tagged output - all programmatically. The flow is always:
- POST a PDF to
/api/upload.php- receive auuid - Poll
/api/status.php?uuid=every few seconds untilstatus === "done" - GET
/api/download.php?uuid=&type=pdffor the tagged PDF
Authentication
Include your API key in every request using the X-API-Key header. Bearer token syntax is also accepted.
X-API-Key: rtag_your_api_key_here # or Authorization: Bearer rtag_your_api_key_here
Generate API keys from your API Keys page. Keys start with rtag_ and are shown only once on creation.
Base URL
All endpoints are relative to this base URL. HTTPS is required.
Error responses
All errors return JSON with ok: false and an error string. HTTP status codes follow standard conventions.
| Status | Meaning |
|---|---|
| 400 | Bad request - invalid file, missing parameter, or file too large |
| 401 | Unauthorized - missing or invalid API key |
| 429 | Rate limit reached - monthly quota exceeded |
{"ok": false, "error": "Monthly limit reached (500 PDFs). Upgrade your plan for more.", "upgrade": true}
POST /api/upload.php
Upload a PDF for tagging. Returns a job UUID immediately. Processing is asynchronous.
Request - multipart/form-data
| Field | Type | Required | Description |
|---|---|---|---|
| file | required | PDF file to tag. Max 50 MB (Pro) / 100 MB (Enterprise). |
Response 200
{
"ok": true,
"uuid": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"job_id": 42
}
Example
curl -X POST https://tag.rubansoftwares.com/api/upload.php \ -H "X-API-Key: rtag_your_key_here" \ -F "pdf=@report.pdf"
GET /api/status.php
Poll the processing status of a job. Call every 2-3 seconds until status is done or failed.
Query parameters
| Param | Required | Description |
|---|---|---|
| uuid | required | The UUID returned by upload.php |
Response - processing
{
"ok": true,
"status": "processing",
"progress": 45,
"score": null,
"result_url": null
}
Response - done
{
"ok": true,
"status": "done",
"progress": 100,
"score": 87,
"score_label": "Good",
"page_count": 12,
"result_url": "https://tag.rubansoftwares.com/result.php?job=f47ac10b-...",
"tags": [
{"tag_type": "H1", "count": 3},
{"tag_type": "P", "count": 48},
{"tag_type": "Table", "count": 2}
]
}
Response - failed
{
"ok": true,
"status": "failed",
"error": "Could not parse PDF structure."
}
Example (poll loop)
import requests, time
KEY = "rtag_your_key_here"
UUID = "f47ac10b-58cc-4372-a567-0e02b2c3d479"
while True:
r = requests.get(
f"https://tag.rubansoftwares.com/api/status.php?uuid={UUID}",
headers={"X-API-Key": KEY}
).json()
if r["status"] == "done":
print("Score:", r["score"])
break
if r["status"] == "failed":
raise Exception(r.get("error"))
time.sleep(2)
GET /api/download.php
Download the tagged PDF or the HTML accessibility report. Job must be in done status.
Query parameters
| Param | Required | Description |
|---|---|---|
| uuid | required | Job UUID |
| type | required | pdf - tagged PDF file, report - HTML accessibility report |
Returns the file with Content-Disposition: attachment. On error returns JSON.
Example
curl -O "https://tag.rubansoftwares.com/api/download.php?uuid=f47ac10b-...&type=pdf" \ -H "X-API-Key: rtag_your_key_here"
Plans & API limits
| Plan | API access | Calls/month | Max file size | PDFs/month |
|---|---|---|---|---|
| Guest | No | - | 5 MB | 3/day |
| Free | No | - | 10 MB | 20 |
| Pro | Yes | 500 | 50 MB | 500 |
| Enterprise | Yes | Unlimited | 100 MB | Unlimited |
Tag types
The tagger detects and emits the following PDF structure tags:
| Tag | Description |
|---|---|
H1 - H6 | Heading hierarchy detected by font size ranking |
P | Body paragraph text |
Table / TR / TH / TD | Table structure with header cells |
Figure | Images and graphics |
L / LI | List container and list items |
Artifact | Headers, footers, page numbers (decorative) |
Full code examples
Python - upload + wait + download
import requests, time, sys
API_KEY = "rtag_your_key_here"
BASE_URL = "https://tag.rubansoftwares.com"
HEADERS = {"X-API-Key": API_KEY}
# 1. Upload
with open("input.pdf", "rb") as f:
r = requests.post(f"{BASE_URL}/api/upload.php",
headers=HEADERS, files={"pdf": f})
r.raise_for_status()
uuid = r.json()["uuid"]
print(f"Job UUID: {uuid}")
# 2. Poll
while True:
r = requests.get(f"{BASE_URL}/api/status.php?uuid={uuid}", headers=HEADERS).json()
print(f" Status: {r['status']} ({r.get('progress', 0)}%)")
if r["status"] == "done":
print(f" Score: {r['score']} - {r['score_label']}")
break
if r["status"] == "failed":
sys.exit(f"Failed: {r.get('error')}")
time.sleep(2)
# 3. Download tagged PDF
r = requests.get(f"{BASE_URL}/api/download.php?uuid={uuid}&type=pdf", headers=HEADERS)
with open("tagged_output.pdf", "wb") as f:
f.write(r.content)
print("Saved tagged_output.pdf")
Node.js (fetch)
const fs = require('fs');
const path = require('path');
const API_KEY = 'rtag_your_key_here';
const BASE_URL = 'https://tag.rubansoftwares.com';
async function tagPDF(filePath) {
// 1. Upload
const form = new FormData();
form.append('pdf', new Blob([fs.readFileSync(filePath)]), path.basename(filePath));
const up = await fetch(`${BASE_URL}/api/upload.php`, {
method: 'POST', headers: {'X-API-Key': API_KEY}, body: form
});
const {uuid} = await up.json();
// 2. Poll
let done = false;
while (!done) {
await new Promise(r => setTimeout(r, 2000));
const st = await fetch(`${BASE_URL}/api/status.php?uuid=${uuid}`,
{headers: {'X-API-Key': API_KEY}}).then(r => r.json());
if (st.status === 'done') { console.log('Score:', st.score); done = true; }
if (st.status === 'failed') { throw new Error(st.error); }
}
// 3. Download
const dl = await fetch(`${BASE_URL}/api/download.php?uuid=${uuid}&type=pdf`,
{headers: {'X-API-Key': API_KEY}});
fs.writeFileSync('tagged.pdf', Buffer.from(await dl.arrayBuffer()));
console.log('Saved tagged.pdf');
}
tagPDF('document.pdf').catch(console.error);
PHP
<?php
$key = 'rtag_your_key_here';
$base = 'https://tag.rubansoftwares.com';
// 1. Upload
$ch = curl_init("$base/api/upload.php");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["X-API-Key: $key"],
CURLOPT_POSTFIELDS => ['pdf' => new CURLFile('/path/to/file.pdf')],
]);
$uuid = json_decode(curl_exec($ch), true)['uuid'];
curl_close($ch);
// 2. Poll
do {
sleep(2);
$ch = curl_init("$base/api/status.php?uuid=$uuid");
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["X-API-Key: $key"]]);
$job = json_decode(curl_exec($ch), true);
curl_close($ch);
} while ($job['status'] === 'pending' || $job['status'] === 'processing');
echo "Score: " . $job['score'] . "\n";
// 3. Download
$ch = curl_init("$base/api/download.php?uuid=$uuid&type=pdf");
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["X-API-Key: $key"]]);
file_put_contents('tagged.pdf', curl_exec($ch));
curl_close($ch);