Custom JSON schema extraction
Instead of the whole content of a document you can ask for specific fields. You describe them with a JSON Schema and send it in the schema field together with format=json. DocSlice reads the document, extracts the values and returns an object that follows your schema.
SCHEMA='{"type":"object","properties":{"invoice_number":{"type":"string","description":"Invoice number"},"date":{"type":"string","description":"Issue date, YYYY-MM-DD"},"total":{"type":"number","description":"Total amount"}},"required":["invoice_number","total"]}'
curl -s https://api.docslice.app/v1/convert \
-H "Authorization: Bearer $DOCSLICE_API_KEY" \
-F "file=@invoice.pdf" \
-F "format=json" \
-F "schema=$SCHEMA"
import json
import os
import requests
api_key = os.environ["DOCSLICE_API_KEY"]
schema = {
"type": "object",
"properties": {
"invoice_number": {"type": "string", "description": "Invoice number"},
"date": {"type": "string", "description": "Issue date, YYYY-MM-DD"},
"total": {"type": "number", "description": "Total amount"},
},
"required": ["invoice_number", "total"],
}
with open("invoice.pdf", "rb") as handle:
response = requests.post(
"https://api.docslice.app/v1/convert",
headers={"Authorization": f"Bearer {api_key}"},
files={"file": ("invoice.pdf", handle, "application/pdf")},
data={"format": "json", "schema": json.dumps(schema)},
timeout=120,
)
print(json.dumps(response.json(), indent=2))
const fs = require("node:fs");
const schema = {
type: "object",
properties: {
invoice_number: { type: "string", description: "Invoice number" },
date: { type: "string", description: "Issue date, YYYY-MM-DD" },
total: { type: "number", description: "Total amount" },
},
required: ["invoice_number", "total"],
};
const form = new FormData();
form.append("file", new Blob([fs.readFileSync("invoice.pdf")], { type: "application/pdf" }), "invoice.pdf");
form.append("format", "json");
form.append("schema", JSON.stringify(schema));
fetch("https://api.docslice.app/v1/convert", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.DOCSLICE_API_KEY}` },
body: form,
})
.then((response) => response.json())
.then((data) => console.log(JSON.stringify(data, null, 2)));
<?php
$schema = [
'type' => 'object',
'properties' => [
'invoice_number' => ['type' => 'string', 'description' => 'Invoice number'],
'date' => ['type' => 'string', 'description' => 'Issue date, YYYY-MM-DD'],
'total' => ['type' => 'number', 'description' => 'Total amount'],
],
'required' => ['invoice_number', 'total'],
];
$curl = curl_init('https://api.docslice.app/v1/convert');
curl_setopt_array($curl, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('DOCSLICE_API_KEY')],
CURLOPT_POSTFIELDS => [
'file' => new CURLFile('invoice.pdf', 'application/pdf', 'invoice.pdf'),
'format' => 'json',
'schema' => json_encode($schema),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 120,
]);
echo curl_exec($curl);
curl_close($curl);
Write a good schema
{
"type": "object",
"properties": {
"invoice_number": {"type": "string", "description": "Invoice number"},
"date": {"type": "string", "description": "Issue date, YYYY-MM-DD"},
"total": {"type": "number", "description": "Total amount"}
},
"required": ["invoice_number", "total"]
}
- Give every property a type and a short description. The description is what tells the extractor what to look for and in which format.
- Use
requiredfor the fields you cannot do without. - Keep names stable and meaningful: they become the keys of your answer.
Rules
A schema must be a JSON object with a non-empty properties object, and each property must itself be an object. Regular-expression keywords are not accepted. A schema that does not follow the rules is refused with 400 and a message that says why, for example Schema must define a non-empty 'properties' object; a value that is not valid JSON is refused with Invalid JSON schema provided.
Reading the answer
schema_appliedistruewhen the AI layer extracted the values and they conform to your schema. If it isfalse,datais not a verified match for your schema: either the AI extractor was unavailable and a simpler matcher answered, or the AI answered with data that does not conform to the schema (a missing required field, a wrong type). In both cases the request still succeeds, so checkschema_appliedand validatedatain your own code before relying on it.input_truncatedistruewhen the document text is longer than the 25,000 characters sent to the extractor: the text beyond that limit was not read. Split very long documents, or extract from the part that matters.- Pages are counted as for any conversion.
Tips
- Ask only for what a reader could find in the document, and check optional fields in your own code before relying on them.
- Use clear formats in descriptions (
YYYY-MM-DD, "amount as a number without currency symbol"). - For repeated structures, such as invoice lines, describe an
arrayof objects.