2 creditsPDF Classify API — label a document with your own categories
Give it your own label set; get back the best match, a confidence score, and low-confidence routing to human review.
Classify sends the text of the pages you choose (pages: "all", "first", or an explicit page list) to an LLM against a label set you define — each label just needs a name and a short description, at least two and up to a practical cap. The response returns the best-matching label and a confidence score; anything below the confidence threshold is flagged needs_review and handed to the same review queue the schema-extraction tools use, rather than silently returned as a guess. A scanned page with no text layer is OCR'd first automatically, at extra cost reflected in the response.
How does the PDF Classify API work?
One HTTP request from any language. Every ASHDOCS endpoint uses the same X-API-Key header.
curl -X POST https://www.ashdocs.com/api/v2/tools/pdf-classify \
-H "X-API-Key: ash_live_..." \
-F "file=@document.pdf" \
-F 'options={"labels":[{"name":"invoice","description":"A bill for goods or services"},{"name":"contract","description":"A signed agreement between parties"}]}'import requests
r = requests.post(
"https://www.ashdocs.com/api/v2/tools/pdf-classify",
headers={"X-API-Key": "ash_live_..."},
files=[("file", open("document.pdf", "rb"))],
data={"options": '{"labels":[{"name":"invoice","description":"A bill for goods or services"},{"name":"contract","description":"A signed agreement between parties"}]}'},
)
job = r.json()
print(job["status"], job.get("url"))import { readFile } from "node:fs/promises";
const form = new FormData();
form.append("file", new Blob([await readFile("document.pdf")]), "document.pdf");
form.append("options", JSON.stringify({"labels":[{"name":"invoice","description":"A bill for goods or services"},{"name":"contract","description":"A signed agreement between parties"}]}));
const res = await fetch("https://www.ashdocs.com/api/v2/tools/pdf-classify", {
method: "POST",
headers: { "X-API-Key": "ash_live_..." },
body: form,
});
const job = await res.json();
console.log(job.status, job.url);using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "ash_live_...");
using var form = new MultipartFormDataContent();
form.Add(new ByteArrayContent(await File.ReadAllBytesAsync("document.pdf")), "file", "document.pdf");
form.Add(new StringContent("{\"labels\":[{\"name\":\"invoice\",\"description\":\"A bill for goods or services\"},{\"name\":\"contract\",\"description\":\"A signed agreement between parties\"}]}"), "options");
var res = await client.PostAsync("https://www.ashdocs.com/api/v2/tools/pdf-classify", form);
var job = await res.Content.ReadAsStringAsync();
Console.WriteLine(job);import java.io.ByteArrayOutputStream;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
public class Sample {
static final String BOUNDARY = "AshdocsBoundary7MA4YWxkTrZu0gW";
public static void main(String[] args) throws Exception {
ByteArrayOutputStream body = new ByteArrayOutputStream();
addFile(body, "file", "document.pdf");
addField(body, "options", "{\"labels\":[{\"name\":\"invoice\",\"description\":\"A bill for goods or services\"},{\"name\":\"contract\",\"description\":\"A signed agreement between parties\"}]}");
body.write(("--" + BOUNDARY + "--\r\n").getBytes(StandardCharsets.UTF_8));
HttpRequest req = HttpRequest.newBuilder(URI.create("https://www.ashdocs.com/api/v2/tools/pdf-classify"))
.header("X-API-Key", "ash_live_...")
.header("Content-Type", "multipart/form-data; boundary=" + BOUNDARY)
.POST(HttpRequest.BodyPublishers.ofByteArray(body.toByteArray()))
.build();
HttpResponse<String> res = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.body());
}
static void addFile(ByteArrayOutputStream body, String name, String path) throws Exception {
body.write(("--" + BOUNDARY + "\r\nContent-Disposition: form-data; name=\"" + name + "\"; filename=\""
+ Path.of(path).getFileName() + "\"\r\nContent-Type: application/octet-stream\r\n\r\n").getBytes(StandardCharsets.UTF_8));
body.write(Files.readAllBytes(Path.of(path)));
body.write("\r\n".getBytes(StandardCharsets.UTF_8));
}
static void addField(ByteArrayOutputStream body, String name, String value) throws Exception {
body.write(("--" + BOUNDARY + "\r\nContent-Disposition: form-data; name=\"" + name + "\"\r\n\r\n"
+ value + "\r\n").getBytes(StandardCharsets.UTF_8));
}
}#include <stdio.h>
#include <curl/curl.h>
int main(void) {
CURL *curl = curl_easy_init();
if (!curl) return 1;
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "X-API-Key: ash_live_...");
curl_mime *mime = curl_mime_init(curl);
curl_mimepart *part;
part = curl_mime_addpart(mime);
curl_mime_name(part, "file");
curl_mime_filedata(part, "document.pdf");
part = curl_mime_addpart(mime);
curl_mime_name(part, "options");
curl_mime_data(part, "{\"labels\":[{\"name\":\"invoice\",\"description\":\"A bill for goods or services\"},{\"name\":\"contract\",\"description\":\"A signed agreement between parties\"}]}", CURL_ZERO_TERMINATED);
curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
curl_easy_setopt(curl, CURLOPT_URL, "https://www.ashdocs.com/api/v2/tools/pdf-classify");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
CURLcode rc = curl_easy_perform(curl);
printf("\n");
curl_mime_free(mime);
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
return rc == CURLE_OK ? 0 : 1;
}Common use cases
- →Sorting an inbound documents folder by type
- →Routing a mixed upload queue to the right downstream pipeline
- →Flagging ambiguous documents for human review instead of guessing