Bates numbering
Litigation, discovery and compliance production live and die by the ability to point at one exact page across thousands. This endpoint applies Bates numbering — sequential, prefixed identifiers stamped onto every page — automatically across a PDF or a set of PDFs.
Run it online
Run this on our servers with your account. Free tools run in your browser; this one bills your KIT balance per the price above.
Where Bates numbering comes from and why it stuck
The convention takes its name from the Bates stamping machine, a mechanical numbering device patented in the 1890s and long used by law firms to hand-stamp sequential numbers onto paper before filing. The physical machines are gone, but the convention survived intact into the digital era precisely because it solved a real problem: once every page of a production has a unique, sequential identifier like ABC000001, any document can be located, cited or referenced unambiguously by a single string, no matter how large the production grows.
What the stamp actually contains
A Bates stamp is a consistent identifier applied to every page — typically a prefix specific to the case, matter or party, followed by a zero-padded sequential number that increments page by page across the entire set. You control the prefix, the starting number and the padding width, and the numbering continues correctly across multiple documents processed as one production run, so page 1 of document two picks up exactly where document one left off.
How the request is structured
POST the PDF (or PDFs) and your prefix, starting number and formatting preferences to /pdf/stamp. It runs asynchronously like every task in this API: you get a task_id immediately, and the stamped output is delivered to your signed webhook, or held at a signed link valid for 24 hours if you'd rather retrieve it directly.
How it fits into a production workflow
Bates stamping is almost never the first or only step — it typically follows redaction, Bates-adjacent to an OCR pass for searchability, and precedes final delivery to opposing counsel or a court's e-filing system. Because it's a REST call, it plugs cleanly into a document management or e-discovery pipeline that needs stamping applied consistently every time a production goes out, without a paralegal manually tracking the next number by hand.
What it costs
It's a flat $0.002 per request, keeping the cost of stamping a large production predictable and proportionate rather than tied to an opaque per-page markup. A task that fails after automatic retries is never billed, and the source documents are removed after the retention window, never used for anything beyond producing your stamped output.
What you can do with it
Discovery productions in litigation
A law firm produces thousands of pages to opposing counsel; Bates stamping gives every page a unique, citable identifier before it goes out the door.
Multi-document evidence sets
Several exhibits are compiled into one production; the numbering continues sequentially across all of them so no page reference is ambiguous.
Compliance and regulatory filings
Regulated industries need auditable, sequentially identified document sets for record-keeping, achieved automatically at export time.
Internal document control
A records department stamps internal reports with sequential identifiers to track versions and references across departments.
FAQ
What is Bates numbering?
It's a system of stamping every page in a document set with a unique, sequential identifier — typically a prefix plus a zero-padded number — so any page can be cited unambiguously, a convention that traces back to mechanical Bates stamping machines used in legal filing.
How do I apply Bates numbering via API?
POST your PDF or PDFs, along with the prefix and starting number, to /pdf/stamp; the stamped file is delivered by webhook or a signed link.
Can numbering continue across multiple documents?
Yes, when processed together as one production run, numbering continues sequentially from one document to the next without resetting.
Can I customize the prefix and number format?
Yes, you set the prefix text, the starting number, and the digit padding to match your case or matter's numbering convention.
Is the Bates numbering API free to use?
There's no free tier — free tiers get abused and slow everyone down. Access runs on a prepaid ForHosting KIT balance: top up from $10.00 (it never expires) and each request is charged at its published price, so a call with no balance returns HTTP 402. No subscription, no tokens, no invented credits, and a failed task is never charged.
How is this different from adding page numbers?
Bates stamping uses a fixed-format sequential identifier meant to be unique and citable across an entire production, unlike simple page numbers which typically just count pages within one document.
Can I stamp a large batch of documents at once?
Yes, submit them as part of the same production run so the sequence carries through correctly; each request is billed independently and predictably.
What happens if a stamping task fails?
It retries automatically up to three times; if it still can't complete, you get a clear error and are never charged for the failed attempt.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/pdf/stamp \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"pdf":"https://ejemplo.com/documento.pdf"}'const res = await fetch("https://api.kit.forhosting.com/pdf/stamp", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"pdf": "https://ejemplo.com/documento.pdf"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/pdf/stamp",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"pdf": "https://ejemplo.com/documento.pdf"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/pdf/stamp", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"pdf":"https://ejemplo.com/documento.pdf"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"pdf":"https://ejemplo.com/documento.pdf"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/pdf/stamp", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"pdf": "https://ejemplo.com/documento.pdf"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "pdf.stamp",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_mb | 25 |
max_pages | 200 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
413 | input_too_large | The file exceeds the size limit. |