2 creditsAsk a PDF API — question answering with verified citations
Ask a question in plain English; get an answer with page-level citations that are checked against the real page text before they're returned.
Ask a PDF answers a natural-language question by first selecting the most relevant pages (a lexical overlap score against the question, not a full vector index) and sending only those to an LLM, which keeps cost and latency down on long documents. Every citation the model returns is independently checked as a real substring of the page text it claims to come from — a citation that doesn't actually appear on that page is dropped, and the response's confidence score is reduced for each one dropped, rather than passing through an unverifiable quote.
How does the Ask a PDF 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-ask \
-H "X-API-Key: ash_live_..." \
-F "file=@document.pdf" \
-F 'options={"question":"What is the total amount due?"}'import requests
r = requests.post(
"https://www.ashdocs.com/api/v2/tools/pdf-ask",
headers={"X-API-Key": "ash_live_..."},
files=[("file", open("document.pdf", "rb"))],
data={"options": '{"question":"What is the total amount due?"}'},
)
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({"question":"What is the total amount due?"}));
const res = await fetch("https://www.ashdocs.com/api/v2/tools/pdf-ask", {
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("{\"question\":\"What is the total amount due?\"}"), "options");
var res = await client.PostAsync("https://www.ashdocs.com/api/v2/tools/pdf-ask", 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", "{\"question\":\"What is the total amount due?\"}");
body.write(("--" + BOUNDARY + "--\r\n").getBytes(StandardCharsets.UTF_8));
HttpRequest req = HttpRequest.newBuilder(URI.create("https://www.ashdocs.com/api/v2/tools/pdf-ask"))
.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, "{\"question\":\"What is the total amount due?\"}", CURL_ZERO_TERMINATED);
curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
curl_easy_setopt(curl, CURLOPT_URL, "https://www.ashdocs.com/api/v2/tools/pdf-ask");
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
- →Answering a support question against a manual
- →Pulling one fact out of a long contract without reading it
- →Letting a chatbot cite the exact page it got an answer from