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:

  1. POST a PDF to /api/upload.php - receive a uuid
  2. Poll /api/status.php?uuid= every few seconds until status === "done"
  3. GET /api/download.php?uuid=&type=pdf for 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

https://tag.rubansoftwares.com

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.

StatusMeaning
400Bad request - invalid file, missing parameter, or file too large
401Unauthorized - missing or invalid API key
429Rate 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.

POST /api/upload.php

Request - multipart/form-data

FieldTypeRequiredDescription
pdf 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.

GET /api/status.php?uuid={uuid}

Query parameters

ParamRequiredDescription
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.

GET /api/download.php?uuid={uuid}&type={type}

Query parameters

ParamRequiredDescription
uuidrequiredJob UUID
typerequiredpdf - 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

PlanAPI accessCalls/monthMax file sizePDFs/month
GuestNo-5 MB3/day
FreeNo-10 MB20
ProYes50050 MB500
EnterpriseYesUnlimited100 MBUnlimited

Tag types

The tagger detects and emits the following PDF structure tags:

TagDescription
H1 - H6Heading hierarchy detected by font size ranking
PBody paragraph text
Table / TR / TH / TDTable structure with header cells
FigureImages and graphics
L / LIList container and list items
ArtifactHeaders, 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);