Sample request
cURL
curl --request POST \
--url 'https://api.pdf.co/v1/pdf/convert/to/pdfa' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_API_KEY' \
--data '{
"url": "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf"
}'
const API_KEY = "YOUR_API_KEY";
const headers = {
"Content-Type": "application/json",
"x-api-key": API_KEY,
};
const submission = await fetch(
"https://api.pdf.co/v1/pdf/convert/to/pdfa",
{
method: "POST",
headers,
body: JSON.stringify({
url: "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf",
name: "sample-invoice-pdfa.pdf",
}),
}
);
if (!submission.ok) {
throw new Error(`PDF.co submission HTTP ${submission.status}`);
}
const job = await submission.json();
if (job.error || !job.jobId) {
throw new Error(job.message ?? "PDF.co request failed");
}
let result;
while (true) {
await new Promise((resolve) => setTimeout(resolve, 3000));
const check = await fetch("https://api.pdf.co/v1/job/check", {
method: "POST",
headers,
body: JSON.stringify({ jobid: job.jobId }),
});
if (!check.ok) {
throw new Error(`PDF.co job-check HTTP ${check.status}`);
}
result = await check.json();
if (result.status === "failed" || result.status === "aborted") break;
if (result.error) {
throw new Error(result.message ?? "PDF.co job-check failed");
}
if (result.status === "success") break;
if (result.status !== "working") {
throw new Error("Unexpected PDF.co job status");
}
}
console.log(result.status, result.isCompliant);
console.log(result.url);
console.log(result.validationReportUrl);
import time
import requests
API_KEY = "YOUR_API_KEY"
headers = {"x-api-key": API_KEY}
submission = requests.post(
"https://api.pdf.co/v1/pdf/convert/to/pdfa",
headers=headers,
json={
"url": "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf",
"name": "sample-invoice-pdfa.pdf",
},
timeout=30,
)
submission.raise_for_status()
job = submission.json()
if job.get("error") or not job.get("jobId"):
raise RuntimeError(job.get("message", "PDF.co request failed"))
while True:
time.sleep(3)
check = requests.post(
"https://api.pdf.co/v1/job/check",
headers=headers,
json={"jobid": job["jobId"]},
timeout=30,
)
check.raise_for_status()
result = check.json()
if result.get("status") in ("failed", "aborted"):
break
if result.get("error"):
raise RuntimeError(result.get("message", "PDF.co job-check failed"))
if result.get("status") == "success":
break
if result.get("status") != "working":
raise RuntimeError("Unexpected PDF.co job status")
print(result.get("status"), result.get("isCompliant"))
print(result.get("url"))
print(result.get("validationReportUrl"))
These samples stop with an exception on HTTP or API request errors. A job-check error does not mean the job has completed. For a transient error such as HTTP 429 or 5xx, retry job-check with the same
jobId after a delay; do not submit another conversion just to resume polling. Explicit failed and aborted jobs are terminal and can have no artifact URLs. Read the returned status and error message; neither status proves conformance.using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", "YOUR_API_KEY");
var payload = JsonSerializer.Serialize(new Dictionary<string, object>
{
["url"] = "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf",
["name"] = "sample-invoice-pdfa.pdf",
});
var response = await client.PostAsync(
"https://api.pdf.co/v1/pdf/convert/to/pdfa",
new StringContent(payload, Encoding.UTF8, "application/json")
);
var json = await response.Content.ReadAsStringAsync();
// After a successful submission, use the returned jobId to poll
// https://api.pdf.co/v1/job/check. Handle HTTP/API request errors separately.
// Continue for "working"; stop only for "success", "failed" or "aborted".
// A missing or unknown status is an error, not a completed job.
Console.WriteLine(json);
OkHttpClient client = new OkHttpClient();
String jsonPayload = "{\"url\": \"https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf\", \"name\": \"sample-invoice-pdfa.pdf\"}";
Request request = new Request.Builder()
.url("https://api.pdf.co/v1/pdf/convert/to/pdfa")
.addHeader("x-api-key", "YOUR_API_KEY")
.addHeader("Content-Type", "application/json")
.post(RequestBody.create(MediaType.parse("application/json"), jsonPayload))
.build();
// After a successful submission, use the returned jobId to poll
// https://api.pdf.co/v1/job/check. Handle HTTP/API request errors separately.
// Continue for "working"; stop only for "success", "failed" or "aborted".
// A missing or unknown status is an error, not a completed job.
try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}
<?php
$payload = json_encode([
"url" => "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf",
"name" => "sample-invoice-pdfa.pdf",
]);
$curl = curl_init("https://api.pdf.co/v1/pdf/convert/to/pdfa");
curl_setopt_array($curl, [
CURLOPT_HTTPHEADER => [
"x-api-key: YOUR_API_KEY",
"Content-Type: application/json",
],
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => $payload,
]);
// After a successful submission, use the returned jobId to poll
// https://api.pdf.co/v1/job/check. Handle HTTP/API request errors separately.
// Continue for "working"; stop only for "success", "failed" or "aborted".
// A missing or unknown status is an error, not a completed job.
echo curl_exec($curl);
curl_close($curl);
{
"pageCount": 1,
"error": false,
"status": 200,
"duration": 31,
"name": "sample-invoice.pdf",
"validationReportName": "sample-invoice-pdfa-validation.json",
"jobId": "EXAMPLEJOBID0123456789ABCDEFGHIJ--166-400",
"credits": 25,
"remainingCredits": 400000
}
{
"error": true,
"status": 400,
"message": "Bad request. Typically due to bad input parameters or unreachable input URLs (e.g., access restrictions like login or password)."
}
{
"error": true,
"status": 401,
"message": "Unauthorized. Authentication is required and has failed or has not yet been provided."
}
{
"error": true,
"status": 402,
"message": "Not enough credits."
}
{
"error": true,
"status": 403,
"message": "Access forbidden for input URL."
}
{
"error": true,
"status": 404,
"message": "The requested resource could not be found."
}
{
"error": true,
"status": 429,
"message": "Too many requests in a given time period."
}
{
"error": true,
"status": 442,
"message": "Input document is damaged or of incorrect type."
}
{
"error": true,
"status": 452,
"message": "Invalid URL."
}
{
"error": true,
"status": 454,
"message": "Invalid parameters."
}
{
"error": true,
"status": 500,
"message": "Something went wrong. Please try again or contact support."
}
cURL
curl --request POST \
--url 'https://api.pdf.co/v1/pdf/convert/to/pdfa' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_API_KEY' \
--data '{
"url": "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf"
}'
const API_KEY = "YOUR_API_KEY";
const headers = {
"Content-Type": "application/json",
"x-api-key": API_KEY,
};
const submission = await fetch(
"https://api.pdf.co/v1/pdf/convert/to/pdfa",
{
method: "POST",
headers,
body: JSON.stringify({
url: "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf",
name: "sample-invoice-pdfa.pdf",
}),
}
);
if (!submission.ok) {
throw new Error(`PDF.co submission HTTP ${submission.status}`);
}
const job = await submission.json();
if (job.error || !job.jobId) {
throw new Error(job.message ?? "PDF.co request failed");
}
let result;
while (true) {
await new Promise((resolve) => setTimeout(resolve, 3000));
const check = await fetch("https://api.pdf.co/v1/job/check", {
method: "POST",
headers,
body: JSON.stringify({ jobid: job.jobId }),
});
if (!check.ok) {
throw new Error(`PDF.co job-check HTTP ${check.status}`);
}
result = await check.json();
if (result.status === "failed" || result.status === "aborted") break;
if (result.error) {
throw new Error(result.message ?? "PDF.co job-check failed");
}
if (result.status === "success") break;
if (result.status !== "working") {
throw new Error("Unexpected PDF.co job status");
}
}
console.log(result.status, result.isCompliant);
console.log(result.url);
console.log(result.validationReportUrl);
import time
import requests
API_KEY = "YOUR_API_KEY"
headers = {"x-api-key": API_KEY}
submission = requests.post(
"https://api.pdf.co/v1/pdf/convert/to/pdfa",
headers=headers,
json={
"url": "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf",
"name": "sample-invoice-pdfa.pdf",
},
timeout=30,
)
submission.raise_for_status()
job = submission.json()
if job.get("error") or not job.get("jobId"):
raise RuntimeError(job.get("message", "PDF.co request failed"))
while True:
time.sleep(3)
check = requests.post(
"https://api.pdf.co/v1/job/check",
headers=headers,
json={"jobid": job["jobId"]},
timeout=30,
)
check.raise_for_status()
result = check.json()
if result.get("status") in ("failed", "aborted"):
break
if result.get("error"):
raise RuntimeError(result.get("message", "PDF.co job-check failed"))
if result.get("status") == "success":
break
if result.get("status") != "working":
raise RuntimeError("Unexpected PDF.co job status")
print(result.get("status"), result.get("isCompliant"))
print(result.get("url"))
print(result.get("validationReportUrl"))
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", "YOUR_API_KEY");
var payload = JsonSerializer.Serialize(new Dictionary<string, object>
{
["url"] = "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf",
["name"] = "sample-invoice-pdfa.pdf",
});
var response = await client.PostAsync(
"https://api.pdf.co/v1/pdf/convert/to/pdfa",
new StringContent(payload, Encoding.UTF8, "application/json")
);
var json = await response.Content.ReadAsStringAsync();
// After a successful submission, use the returned jobId to poll
// https://api.pdf.co/v1/job/check. Handle HTTP/API request errors separately.
// Continue for "working"; stop only for "success", "failed" or "aborted".
// A missing or unknown status is an error, not a completed job.
Console.WriteLine(json);
OkHttpClient client = new OkHttpClient();
String jsonPayload = "{\"url\": \"https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf\", \"name\": \"sample-invoice-pdfa.pdf\"}";
Request request = new Request.Builder()
.url("https://api.pdf.co/v1/pdf/convert/to/pdfa")
.addHeader("x-api-key", "YOUR_API_KEY")
.addHeader("Content-Type", "application/json")
.post(RequestBody.create(MediaType.parse("application/json"), jsonPayload))
.build();
// After a successful submission, use the returned jobId to poll
// https://api.pdf.co/v1/job/check. Handle HTTP/API request errors separately.
// Continue for "working"; stop only for "success", "failed" or "aborted".
// A missing or unknown status is an error, not a completed job.
try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}
<?php
$payload = json_encode([
"url" => "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf",
"name" => "sample-invoice-pdfa.pdf",
]);
$curl = curl_init("https://api.pdf.co/v1/pdf/convert/to/pdfa");
curl_setopt_array($curl, [
CURLOPT_HTTPHEADER => [
"x-api-key: YOUR_API_KEY",
"Content-Type: application/json",
],
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => $payload,
]);
// After a successful submission, use the returned jobId to poll
// https://api.pdf.co/v1/job/check. Handle HTTP/API request errors separately.
// Continue for "working"; stop only for "success", "failed" or "aborted".
// A missing or unknown status is an error, not a completed job.
echo curl_exec($curl);
curl_close($curl);
{
"pageCount": 1,
"error": false,
"status": 200,
"duration": 31,
"name": "sample-invoice.pdf",
"validationReportName": "sample-invoice-pdfa-validation.json",
"jobId": "EXAMPLEJOBID0123456789ABCDEFGHIJ--166-400",
"credits": 25,
"remainingCredits": 400000
}
{
"error": true,
"status": 400,
"message": "Bad request. Typically due to bad input parameters or unreachable input URLs (e.g., access restrictions like login or password)."
}
{
"error": true,
"status": 401,
"message": "Unauthorized. Authentication is required and has failed or has not yet been provided."
}
{
"error": true,
"status": 402,
"message": "Not enough credits."
}
{
"error": true,
"status": 403,
"message": "Access forbidden for input URL."
}
{
"error": true,
"status": 404,
"message": "The requested resource could not be found."
}
{
"error": true,
"status": 429,
"message": "Too many requests in a given time period."
}
{
"error": true,
"status": 442,
"message": "Input document is damaged or of incorrect type."
}
{
"error": true,
"status": 452,
"message": "Invalid URL."
}
{
"error": true,
"status": 454,
"message": "Invalid parameters."
}
{
"error": true,
"status": 500,
"message": "Something went wrong. Please try again or contact support."
}
PDF Conversion
PDF to PDF/A
Convert a PDF to PDF/A-3b and receive the converted PDF and a veraPDF report when conversion and validation complete.
Sample request
cURL
curl --request POST \
--url 'https://api.pdf.co/v1/pdf/convert/to/pdfa' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_API_KEY' \
--data '{
"url": "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf"
}'
const API_KEY = "YOUR_API_KEY";
const headers = {
"Content-Type": "application/json",
"x-api-key": API_KEY,
};
const submission = await fetch(
"https://api.pdf.co/v1/pdf/convert/to/pdfa",
{
method: "POST",
headers,
body: JSON.stringify({
url: "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf",
name: "sample-invoice-pdfa.pdf",
}),
}
);
if (!submission.ok) {
throw new Error(`PDF.co submission HTTP ${submission.status}`);
}
const job = await submission.json();
if (job.error || !job.jobId) {
throw new Error(job.message ?? "PDF.co request failed");
}
let result;
while (true) {
await new Promise((resolve) => setTimeout(resolve, 3000));
const check = await fetch("https://api.pdf.co/v1/job/check", {
method: "POST",
headers,
body: JSON.stringify({ jobid: job.jobId }),
});
if (!check.ok) {
throw new Error(`PDF.co job-check HTTP ${check.status}`);
}
result = await check.json();
if (result.status === "failed" || result.status === "aborted") break;
if (result.error) {
throw new Error(result.message ?? "PDF.co job-check failed");
}
if (result.status === "success") break;
if (result.status !== "working") {
throw new Error("Unexpected PDF.co job status");
}
}
console.log(result.status, result.isCompliant);
console.log(result.url);
console.log(result.validationReportUrl);
import time
import requests
API_KEY = "YOUR_API_KEY"
headers = {"x-api-key": API_KEY}
submission = requests.post(
"https://api.pdf.co/v1/pdf/convert/to/pdfa",
headers=headers,
json={
"url": "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf",
"name": "sample-invoice-pdfa.pdf",
},
timeout=30,
)
submission.raise_for_status()
job = submission.json()
if job.get("error") or not job.get("jobId"):
raise RuntimeError(job.get("message", "PDF.co request failed"))
while True:
time.sleep(3)
check = requests.post(
"https://api.pdf.co/v1/job/check",
headers=headers,
json={"jobid": job["jobId"]},
timeout=30,
)
check.raise_for_status()
result = check.json()
if result.get("status") in ("failed", "aborted"):
break
if result.get("error"):
raise RuntimeError(result.get("message", "PDF.co job-check failed"))
if result.get("status") == "success":
break
if result.get("status") != "working":
raise RuntimeError("Unexpected PDF.co job status")
print(result.get("status"), result.get("isCompliant"))
print(result.get("url"))
print(result.get("validationReportUrl"))
These samples stop with an exception on HTTP or API request errors. A job-check error does not mean the job has completed. For a transient error such as HTTP 429 or 5xx, retry job-check with the same
jobId after a delay; do not submit another conversion just to resume polling. Explicit failed and aborted jobs are terminal and can have no artifact URLs. Read the returned status and error message; neither status proves conformance.using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", "YOUR_API_KEY");
var payload = JsonSerializer.Serialize(new Dictionary<string, object>
{
["url"] = "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf",
["name"] = "sample-invoice-pdfa.pdf",
});
var response = await client.PostAsync(
"https://api.pdf.co/v1/pdf/convert/to/pdfa",
new StringContent(payload, Encoding.UTF8, "application/json")
);
var json = await response.Content.ReadAsStringAsync();
// After a successful submission, use the returned jobId to poll
// https://api.pdf.co/v1/job/check. Handle HTTP/API request errors separately.
// Continue for "working"; stop only for "success", "failed" or "aborted".
// A missing or unknown status is an error, not a completed job.
Console.WriteLine(json);
OkHttpClient client = new OkHttpClient();
String jsonPayload = "{\"url\": \"https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf\", \"name\": \"sample-invoice-pdfa.pdf\"}";
Request request = new Request.Builder()
.url("https://api.pdf.co/v1/pdf/convert/to/pdfa")
.addHeader("x-api-key", "YOUR_API_KEY")
.addHeader("Content-Type", "application/json")
.post(RequestBody.create(MediaType.parse("application/json"), jsonPayload))
.build();
// After a successful submission, use the returned jobId to poll
// https://api.pdf.co/v1/job/check. Handle HTTP/API request errors separately.
// Continue for "working"; stop only for "success", "failed" or "aborted".
// A missing or unknown status is an error, not a completed job.
try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}
<?php
$payload = json_encode([
"url" => "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf",
"name" => "sample-invoice-pdfa.pdf",
]);
$curl = curl_init("https://api.pdf.co/v1/pdf/convert/to/pdfa");
curl_setopt_array($curl, [
CURLOPT_HTTPHEADER => [
"x-api-key: YOUR_API_KEY",
"Content-Type: application/json",
],
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => $payload,
]);
// After a successful submission, use the returned jobId to poll
// https://api.pdf.co/v1/job/check. Handle HTTP/API request errors separately.
// Continue for "working"; stop only for "success", "failed" or "aborted".
// A missing or unknown status is an error, not a completed job.
echo curl_exec($curl);
curl_close($curl);
{
"pageCount": 1,
"error": false,
"status": 200,
"duration": 31,
"name": "sample-invoice.pdf",
"validationReportName": "sample-invoice-pdfa-validation.json",
"jobId": "EXAMPLEJOBID0123456789ABCDEFGHIJ--166-400",
"credits": 25,
"remainingCredits": 400000
}
{
"error": true,
"status": 400,
"message": "Bad request. Typically due to bad input parameters or unreachable input URLs (e.g., access restrictions like login or password)."
}
{
"error": true,
"status": 401,
"message": "Unauthorized. Authentication is required and has failed or has not yet been provided."
}
{
"error": true,
"status": 402,
"message": "Not enough credits."
}
{
"error": true,
"status": 403,
"message": "Access forbidden for input URL."
}
{
"error": true,
"status": 404,
"message": "The requested resource could not be found."
}
{
"error": true,
"status": 429,
"message": "Too many requests in a given time period."
}
{
"error": true,
"status": 442,
"message": "Input document is damaged or of incorrect type."
}
{
"error": true,
"status": 452,
"message": "Invalid URL."
}
{
"error": true,
"status": 454,
"message": "Invalid parameters."
}
{
"error": true,
"status": 500,
"message": "Something went wrong. Please try again or contact support."
}
cURL
curl --request POST \
--url 'https://api.pdf.co/v1/pdf/convert/to/pdfa' \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_API_KEY' \
--data '{
"url": "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf"
}'
const API_KEY = "YOUR_API_KEY";
const headers = {
"Content-Type": "application/json",
"x-api-key": API_KEY,
};
const submission = await fetch(
"https://api.pdf.co/v1/pdf/convert/to/pdfa",
{
method: "POST",
headers,
body: JSON.stringify({
url: "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf",
name: "sample-invoice-pdfa.pdf",
}),
}
);
if (!submission.ok) {
throw new Error(`PDF.co submission HTTP ${submission.status}`);
}
const job = await submission.json();
if (job.error || !job.jobId) {
throw new Error(job.message ?? "PDF.co request failed");
}
let result;
while (true) {
await new Promise((resolve) => setTimeout(resolve, 3000));
const check = await fetch("https://api.pdf.co/v1/job/check", {
method: "POST",
headers,
body: JSON.stringify({ jobid: job.jobId }),
});
if (!check.ok) {
throw new Error(`PDF.co job-check HTTP ${check.status}`);
}
result = await check.json();
if (result.status === "failed" || result.status === "aborted") break;
if (result.error) {
throw new Error(result.message ?? "PDF.co job-check failed");
}
if (result.status === "success") break;
if (result.status !== "working") {
throw new Error("Unexpected PDF.co job status");
}
}
console.log(result.status, result.isCompliant);
console.log(result.url);
console.log(result.validationReportUrl);
import time
import requests
API_KEY = "YOUR_API_KEY"
headers = {"x-api-key": API_KEY}
submission = requests.post(
"https://api.pdf.co/v1/pdf/convert/to/pdfa",
headers=headers,
json={
"url": "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf",
"name": "sample-invoice-pdfa.pdf",
},
timeout=30,
)
submission.raise_for_status()
job = submission.json()
if job.get("error") or not job.get("jobId"):
raise RuntimeError(job.get("message", "PDF.co request failed"))
while True:
time.sleep(3)
check = requests.post(
"https://api.pdf.co/v1/job/check",
headers=headers,
json={"jobid": job["jobId"]},
timeout=30,
)
check.raise_for_status()
result = check.json()
if result.get("status") in ("failed", "aborted"):
break
if result.get("error"):
raise RuntimeError(result.get("message", "PDF.co job-check failed"))
if result.get("status") == "success":
break
if result.get("status") != "working":
raise RuntimeError("Unexpected PDF.co job status")
print(result.get("status"), result.get("isCompliant"))
print(result.get("url"))
print(result.get("validationReportUrl"))
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", "YOUR_API_KEY");
var payload = JsonSerializer.Serialize(new Dictionary<string, object>
{
["url"] = "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf",
["name"] = "sample-invoice-pdfa.pdf",
});
var response = await client.PostAsync(
"https://api.pdf.co/v1/pdf/convert/to/pdfa",
new StringContent(payload, Encoding.UTF8, "application/json")
);
var json = await response.Content.ReadAsStringAsync();
// After a successful submission, use the returned jobId to poll
// https://api.pdf.co/v1/job/check. Handle HTTP/API request errors separately.
// Continue for "working"; stop only for "success", "failed" or "aborted".
// A missing or unknown status is an error, not a completed job.
Console.WriteLine(json);
OkHttpClient client = new OkHttpClient();
String jsonPayload = "{\"url\": \"https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf\", \"name\": \"sample-invoice-pdfa.pdf\"}";
Request request = new Request.Builder()
.url("https://api.pdf.co/v1/pdf/convert/to/pdfa")
.addHeader("x-api-key", "YOUR_API_KEY")
.addHeader("Content-Type", "application/json")
.post(RequestBody.create(MediaType.parse("application/json"), jsonPayload))
.build();
// After a successful submission, use the returned jobId to poll
// https://api.pdf.co/v1/job/check. Handle HTTP/API request errors separately.
// Continue for "working"; stop only for "success", "failed" or "aborted".
// A missing or unknown status is an error, not a completed job.
try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}
<?php
$payload = json_encode([
"url" => "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf",
"name" => "sample-invoice-pdfa.pdf",
]);
$curl = curl_init("https://api.pdf.co/v1/pdf/convert/to/pdfa");
curl_setopt_array($curl, [
CURLOPT_HTTPHEADER => [
"x-api-key: YOUR_API_KEY",
"Content-Type: application/json",
],
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => $payload,
]);
// After a successful submission, use the returned jobId to poll
// https://api.pdf.co/v1/job/check. Handle HTTP/API request errors separately.
// Continue for "working"; stop only for "success", "failed" or "aborted".
// A missing or unknown status is an error, not a completed job.
echo curl_exec($curl);
curl_close($curl);
{
"pageCount": 1,
"error": false,
"status": 200,
"duration": 31,
"name": "sample-invoice.pdf",
"validationReportName": "sample-invoice-pdfa-validation.json",
"jobId": "EXAMPLEJOBID0123456789ABCDEFGHIJ--166-400",
"credits": 25,
"remainingCredits": 400000
}
{
"error": true,
"status": 400,
"message": "Bad request. Typically due to bad input parameters or unreachable input URLs (e.g., access restrictions like login or password)."
}
{
"error": true,
"status": 401,
"message": "Unauthorized. Authentication is required and has failed or has not yet been provided."
}
{
"error": true,
"status": 402,
"message": "Not enough credits."
}
{
"error": true,
"status": 403,
"message": "Access forbidden for input URL."
}
{
"error": true,
"status": 404,
"message": "The requested resource could not be found."
}
{
"error": true,
"status": 429,
"message": "Too many requests in a given time period."
}
{
"error": true,
"status": 442,
"message": "Input document is damaged or of incorrect type."
}
{
"error": true,
"status": 452,
"message": "Invalid URL."
}
{
"error": true,
"status": 454,
"message": "Invalid parameters."
}
{
"error": true,
"status": 500,
"message": "Something went wrong. Please try again or contact support."
}
POST /v1/pdf/convert/to/pdfa
This endpoint converts a source PDF to the PDF/A-3b archival format and validates the converted file with veraPDF, the open-source PDF/A validator. When conversion and validation complete, the final job result includes both the converted PDF and the validation report, even if the output is non-compliant. The initial response contains neither file. Rejected inputs and failed conversion or validation can leave one or both files unavailable; see Understanding the validation result and Forms, JavaScript, metadata and signatures.
Quick start
A request containing onlyurl is enough to start a conversion.
Request body
{
"url": "https://pdfco-test-files.s3.us-west-2.amazonaws.com/document-parser/sample-invoice.pdf"
}
To see the request size limits, please refer to the Request Size Limits.
Asynchronous only
This endpoint has no synchronous mode and no
async parameter. Every request runs in the background, and the first response returns a jobId rather than the PDF or report URL.- You submit the request, and PDF.co accepts the job and returns its
jobId. - The source PDF is converted to PDF/A-3b.
- veraPDF validates the converted file and produces the report.
- The job is finalized, and the PDF and report links become available.
jobId, or by supplying a callback URL — see Webhooks & Callbacks.
Request body
Attributes are case-sensitive and should be inside JSON for POST request. for example:
{ "url": "https://example.com/file1.pdf" } There are no query parameters.string
required
URL of the source PDF. The endpoint processes the complete document. The URL must be reachable by PDF.co — see supported file sources. For a protected source location, provide a temporary or presigned URL.
string
Callback URL notified when the job finishes. Use it instead of polling. See Webhooks & Callbacks.
string
Output file name. If omitted, it derives the name from
url when possible. The validation report is named after the output file.integer
default:"60"
Number of minutes before the temporary output and report URLs expire. After this period, generated files are deleted from PDF.co Temporary Files Storage. The maximum retention depends on your subscription plan and is capped at seven days for PDF/A. See Link expiry and retention.
The
generateReport, pdfaVersion, and compatibilityPolicy fields are accepted for backward compatibility but ignored. They cannot disable validation or change the output format. Validation always runs, and the output profile is always PDF/A-3b.Responses
The initial response confirms that the job was accepted, returns itsjobId, and assigns the planned output file names. It does not guarantee that these files will be produced. Both file links are available when conversion and validation complete.
Submission response
{
"pageCount": 1,
"error": false,
"status": 200,
"duration": 31,
"name": "sample-invoice.pdf",
"validationReportName": "sample-invoice-pdfa-validation.json",
"jobId": "EXAMPLEJOBID0123456789ABCDEFGHIJ--166-400",
"credits": 25,
"remainingCredits": 400000
}
| Field | Type | Description |
|---|---|---|
pageCount | integer | Page count reported when the job is accepted. Conversion has not run at this stage, so read the page count of the converted file from the final job result. |
error | boolean | false when the job was accepted. |
status | integer | HTTP status code of the submission request. This is not the job status, which is a string and is returned by Background Job Check. |
duration | integer | Time taken to accept the request, in milliseconds. It does not include conversion or validation. |
name | string | File name of the converted PDF. |
validationReportName | string | File name of the validation report. |
jobId | string | Identifier of the background job. |
credits | integer | Credits consumed by the conversion request. See Credits per API Function. |
remainingCredits | integer | Credits remaining for the account. |
name and validationReportName are assigned when the job is accepted, so you can record the planned output file names before the job finishes. The matching url and validationReportUrl are not known at this point and are returned only if the corresponding files are produced.Final job result
{
"status": "success",
"message": "Success",
"url": "https://pdf-temp-files.s3.us-west-2.amazonaws.com/example/sample-invoice.pdf",
"pageCount": 1,
"outputLinkValidTill": "2026-09-18T08:33:38+00:00",
"validationStatus": "completed",
"isCompliant": true,
"pdfaProfile": "PDF/A-3B",
"validator": "veraPDF",
"validatorVersion": "1.30.1",
"validatedAt": "2026-09-18T07:33:24+00:00",
"validationReportUrl": "https://pdf-temp-files.s3.us-west-2.amazonaws.com/example/sample-invoice-pdfa-validation.json",
"validationReportName": "sample-invoice-pdfa-validation.json",
"validationReportLinkValidTill": "2026-09-18T08:33:38+00:00",
"failedRules": 0,
"failedChecks": 0,
"warnings": [
{
"code": "documentModified",
"message": "The PDF was rewritten for PDF/A. Change details are reported where available."
}
],
"jobId": "EXAMPLEJOBID0123456789ABCDEFGHIJ--166-400",
"credits": 2,
"remainingCredits": 399998,
"duration": 116
}
| Field | Type | Description |
|---|---|---|
status | string | Job status: working, success, failed, or aborted. See Available Status Values. |
message | string | Message describing the result. |
url | string | Temporary URL of the converted PDF/A file. |
pageCount | integer | Number of pages in the output PDF. |
outputLinkValidTill | string | UTC timestamp when the output URL expires. |
validationStatus | string | Validation processing state. completed means veraPDF finished validating the output. |
isCompliant | boolean | veraPDF conformance result for the output file. |
pdfaProfile | string | PDF/A profile the output was validated against. Always PDF/A-3B. |
validator | string | Name of the validator. Always veraPDF. |
validatorVersion | string | Version of the validator that produced the report. |
validatedAt | string | UTC timestamp of the validation run. |
validationReportUrl | string | Temporary URL of the detailed veraPDF report, in JSON. |
validationReportName | string | File name of the validation report. |
validationReportLinkValidTill | string | UTC timestamp when the report URL expires. |
failedRules | integer | Number of PDF/A rules the output failed. |
failedChecks | integer | Number of individual checks the output failed. |
warnings | array | Conversion notes describing what changed during conversion. See Conversion warnings. |
jobId | string | Identifier of the background job. |
credits | integer | Credits consumed by the request. See Credits per API Function. |
remainingCredits | integer | Credits remaining for the account. |
duration | integer | Time taken for the job-status check, in milliseconds. It does not measure conversion time. |
error: true with a status code and message. See the response examples and Response Codes.
Understanding the validation result
A job that reaches validation has one of the three validation outcomes below. Input rejection and failures before validation are described separately. The job status and the conformance result are separate answers, so read both.Input rejection or failure before validation
The job status isfailed when input inspection rejects the PDF or processing fails before validation can run. Signed PDFs and password-protected PDFs that require a password are rejected before conversion. These rejections and other pre-validation failures return neither a converted PDF URL nor a validation report URL; read the error message to identify the cause. The separate validator-error outcome below retains the converted PDF URL, but compliance remains unknown.
The initial submission can return a jobId before this failure is detected. Read the terminal job-check result or callback for the failure. The failed-job refund rules below apply.
Compliant output
status is success, isCompliant is true, and failedRules and failedChecks are 0. Conversion and validation both completed, and veraPDF confirmed the output conforms to PDF/A-3b.
Non-compliant output
status is success and isCompliant is false.
A successful job can return
isCompliant: false. Conversion and validation both ran and the request is charged; the source document was defective in a way the conversion could not resolve. Do not treat status: "success" on its own as proof of conformance — check isCompliant.failedRules and failedChecks give the counts, and the report at validationReportUrl names the specific rules that failed so you can correct the source document.
Validation error
The validator could not run to completion, so compliance is unknown. The job status isfailed and the conversion charge is refunded once. The converted PDF is kept and its URL is still returned.
No report is returned when none was produced. Check validationReportUrl before attempting to download it.
Charges and refunds
PDF/A conversion is asynchronous only. The processing charge covers only the first page, even for a multi-page PDF. The remaining pages are not charged at completion, polling or callback. The returnedpageCount describes the output, not the number of billable pages. See Credits per API Function for the endpoint rate.
A failed job refunds the original processing debit once, including input rejection, conversion failure and validation error. A completed validation with isCompliant: false is still charged. Job-check fees for polls that returned working are not refunded, and repeatedly checking a failed job does not refund the charge again.
Conversion warnings
Routine CMYK color-space and CropBox preservation are recorded in internal logs. They are not included inwarnings. Font, layer, OCR and attachment corrections remain warnings. Ghostscript warnings, including output that cannot be fully classified, are retained.
Forms, JavaScript, metadata and signatures
Conversion rewrites the PDF and has these input-handling limits:- Forms: Editable fields may be flattened into page content. The
formFieldsChangeddetail reports a reduced field count. Review the displayed values in the output; there is no automatic visual comparison or guarantee that every field appearance is preserved. - JavaScript and calculated values: JavaScript actions are removed. The saved display is preserved on a best-effort basis. Conversion does not run calculation scripts, recalculate values or correct stale field appearances. If calculations matter, recalculate and update the displayed values in a PDF editor, then save before submitting.
- Metadata: Creation and modification dates can change, and custom metadata fields can be lost. Preservation of every custom field is not guaranteed.
- Digital signatures: Digitally signed source PDFs are rejected before conversion because rewriting cannot preserve the original signature on the converted PDF. Empty, unsigned signature fields are allowed. Keep the signed original and submit an unsigned PDF. There is no option to remove signatures during conversion or automatically attach the original.
- Password protection: Source PDFs that require a password are rejected before conversion. This endpoint has no password parameter. Unlock the PDF before submitting it; supplying a password to this conversion request does not enable processing of a protected input.
jobId before input inspection. For a signed input, the terminal job-check result or callback reports failure with a clear signature error. No converted PDF or validation report is produced for this rejection. The existing failed-job refund rules apply.
These are conversion limits, not a statement that PDF/A forbids forms or signatures. A new signature may be added after conversion if the signing process keeps the output compliant with PDF/A.
Converting to PDF/A rewrites the document. The warnings array reports conversion changes and problems on a best-effort basis, using these codes:
| Code | Meaning |
|---|---|
documentModified | The PDF was rewritten for PDF/A. Change details are reported where available. |
nonEmbeddedFonts | The source references fonts that are not embedded. They may have been substituted, changing the output appearance. Carries fontNames. |
fontInspectionIncomplete | Source fonts could not be fully inspected. Font substitution may have occurred. Review the output appearance. |
formFieldsChanged | The output has fewer interactive form fields. Fields may have been flattened or removed. Review the displayed values. Carries inputCount and outputCount. |
annotationsChanged | The output has fewer annotations of a given type. They may have been removed or flattened into page content. Carries annotationType, inputCount and outputCount. |
annotationsRemoved | Conversion diagnostics indicate that some non-printing annotations were removed for PDF/A compatibility. |
textRepresentationChanged | Some characters could not be preserved as font glyphs. Review the appearance and text extraction. |
linkFlagsCorrected | Link annotation flags were adjusted for PDF/A: printing was enabled and incompatible visibility flags were cleared. Carries a count field. The count is the number of link flags corrected, not the number of links removed. |
linkPreprocessingIncomplete | Link settings could not be fully checked and corrected. Conversion continued with the original input; incompatible links may be removed. |
changeInspectionIncomplete | Change inspection was incomplete. Some changes or removed features may not be listed. |
pdfaConversionIncomplete | Input features prevented the converter from maintaining PDF/A output. Check isCompliant and the validation report. |
conversionWarningDetailsUnavailable | Conversion reported additional diagnostics that could not be fully classified. Review the output and the validation report. |
The public response uses
warnings. Stored jobs from the earlier details format are also returned under warnings. Validation-report fields are separate.Link expiry and retention
Bothurl and validationReportUrl are temporary, signed links that expire. The expiration request field sets the retention time in minutes, subject to your subscription plan and a PDF/A maximum of seven days.
A compliance record that disappears is not a record. If you need a durable audit trail, download both the converted PDF and the validation report and store them yourself. Check
outputLinkValidTill and validationReportLinkValidTill for the exact expiry times.Behavior notes
- This is a veraPDF validation report, not third-party certification. PDF.co runs the veraPDF engine itself, so the report records what the validator checked and found — it is not an independent certification of the file.
- The report is a separate JSON file and is never embedded inside the output PDF. Attaching it after validation would change the file, and the report would no longer describe the exact PDF returned.
- Conversion rewrites the document, so its appearance or interactive features can differ from the original. Reported changes are best-effort and may not cover every difference.
Inconsistent URL Encoding in cURL Output: When using cURL to make API requests, the output JSON may show URL characters encoded as Unicode escape sequences. For example, the ampersand character (
&) may appear as \u0026 in the cURL output. This is normal JSON encoding behavior and does not affect the validity of the URL. The URL will function correctly when used, as JSON parsers automatically decode these escape sequences. If you’re parsing the response programmatically, your JSON parser will handle this conversion automatically.Was this page helpful?