10. Document Custom Fields
Document Custom Fields
This scenario demonstrates how to attach custom fields to a document during creation and how to retrieve them later. Custom fields are intended mainly for integrations to enrich documents with external data that is not part of the metadata definition.
Key features:
Attach custom fields during document creation
Expose custom fields as imported fields in the sharing UI
Retrieve custom fields via the document detail endpoint
During the sharing flow, the creator can place imported fields in the UI based on the custom fields attached to the document.
Prerequisites
Before creating a document with custom fields, you need:
A valid authentication token (see the "Authentication & Security" section for details)
A PDF file to upload as the document content
Knowledge of the document metadata definition and workflow you want to use
Custom fields are always stored and returned as strings. For the "date" type, you can provide either ISO string or epoch millis; the API normalizes the value to ISO.
Step 1 - Upload a PDF file
Before creating a document, upload the PDF file that will serve as the document content.
The file is uploaded as a multipart/form-data request
The response includes the file ID that will be used when creating the document
The response includes storage quota information
Endpoint
POST /files/saveFile
Request
POST /files/saveFile?token=ZgDNkfj9gCMoRlKcrFqunoYolUCj4JfqVTdfGRW1PaZUKLLM2CmmnhuswjLSm3rp
Content-Type: multipart/form-data
{
"file": "blob",
"fileName": "My PDF file"
}
Response
The response contains the following important properties:
fileId - Located at
file.idin the response.Example value:
FdhJ4O7EoCT5IQJNPzTwO18WScwF1eDZEJdjwcJLIx1pzDhhFpwf9WffZpxzGIXB
The PDF file has been successfully uploaded and stored in the system. The response includes the file ID that will be referenced in the next step.
Step 2 - Create a document with custom fields
This step creates a new document and attaches custom fields in the request body.
Each custom field includes key, displayName, type, and value
Allowed types are string, number, and date
All values are stored and returned as strings; date values are normalized to ISO
Endpoint
POST /documents
Request
POST /documents?token=ZgDNkfj9gCMoRlKcrFqunoYolUCj4JfqVTdfGRW1PaZUKLLM2CmmnhuswjLSm3rp
Content-Type: application/json
{
"body": {
"documentType": "d_default",
"documentTitle": "Invoice - March 2024",
"pdfFile": {
"content": "FdhJ4O7EoCT5IQJNPzTwO18WScwF1eDZEJdjwcJLIx1pzDhhFpwf9WffZpxzGIXB"
},
"customFields": [
{
"key": "invoiceNumber",
"displayName": "Invoice Number",
"type": "string",
"value": "INV-2024-001"
},
{
"key": "totalAmount",
"displayName": "Total Amount",
"type": "number",
"value": 12500
},
{
"key": "dueDate",
"displayName": "Due Date",
"type": "date",
"value": "2024-03-09T10:30:00.000Z"
}
]
},
"definitionType": "ext",
"workflow": "wf_archive"
}
Response
{
"results": [
{
"documentId": "63e49a35-9a2e-454d-b683-0b114f7225ca",
"documentTitle": "Invoice - March 2024",
"customFields": [
{
"key": "invoiceNumber",
"displayName": "Invoice Number",
"type": "string",
"value": "INV-2024-001"
},
{
"key": "totalAmount",
"displayName": "Total Amount",
"type": "number",
"value": "12500"
},
{
"key": "dueDate",
"displayName": "Due Date",
"type": "date",
"value": "2024-03-09T10:30:00.000Z"
}
],
"workflow": {
"workflowType": "wf_archive",
...
},
...
}
],
...
}
The response contains the following important properties:
documentId - Located at
results[0].documentIdin the response.The unique identifier of the created document.
Example value:
63e49a35-9a2e-454d-b683-0b114f7225ca
The document has been created and the custom fields have been stored with it. The response includes the document ID used in the next step.
Step 3 - Retrieve document details including custom fields
Fetch the document details to verify that custom fields are stored and returned as part of the document body. The response includes the normalized values.
The response includes the full document metadata
Custom fields are returned in the customFields array
Date values are returned as ISO strings
Endpoint
GET /documents/:documentId
Request
GET /documents/63e49a35-9a2e-454d-b683-0b114f7225ca?token=ZgDNkfj9gCMoRlKcrFqunoYolUCj4JfqVTdfGRW1PaZUKLLM2CmmnhuswjLSm3rp
Response
{
"results": [
{
"documentId": "63e49a35-9a2e-454d-b683-0b114f7225ca",
"documentTitle": "Invoice - March 2024",
"customFields": [
{
"key": "invoiceNumber",
"displayName": "Invoice Number",
"type": "string",
"value": "INV-2024-001"
},
{
"key": "totalAmount",
"displayName": "Total Amount",
"type": "number",
"value": "12500"
},
{
"key": "dueDate",
"displayName": "Due Date",
"type": "date",
"value": "2024-03-09T10:30:00.000Z"
}
],
...
}
],
...
}
The document details include the custom fields you provided during creation. You do not need to call this endpoint after every document creation, but if you fetch the document later, you will see these values in the response.
Custom Fields Summary
You have created a document with custom fields and retrieved them back via the document detail endpoint.
Key Concepts
Custom fields: Additional key-value data that you attach to documents
Storage format: All values are stored and returned as strings
Date normalization: Date values are returned in ISO format
Example Implementation
See our OpenAPI documentation to learn about the full set of API endpoints and parameters.
Please use proper exception handling and function decomposition in your own code. The code is provided for illustrative purposes only and is not intended for production use.
// Create a document with custom fields
const URL = "https://sandbox.circularo.com";
const API_PATH = "/api/v1";
const TOKEN = "YOUR_AUTH_TOKEN"; // Obtained from login or API key
try {
// Step 1: Upload a PDF file
const formData = new FormData();
formData.append('fileName', 'Document for Annotation');
formData.append('file', fs.createReadStream('path/to/document.pdf')); // Using Node.js fs module
const uploadResponse = await fetch(`${URL}${API_PATH}/files/saveFile?token=${TOKEN}`, {
method: 'POST',
body: formData
});
if (!uploadResponse.ok) {
throw new Error(`File upload failed: ${uploadResponse.status} ${uploadResponse.statusText}`);
}
const uploadData = await uploadResponse.json();
const fileId = uploadData.file.id;
// Step 2: Create a new document with custom fields
const createResponse = await fetch(`${URL}${API_PATH}/documents?token=${TOKEN}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
body: {
documentType: "d_default",
documentTitle: "Invoice - March 2024",
pdfFile: {
content: fileId
},
customFields: [
{ key: "invoiceNumber", displayName: "Invoice Number", type: "string", value: "INV-2024-001" },
{ key: "totalAmount", displayName: "Total Amount", type: "number", value: 12500 },
{ key: "dueDate", displayName: "Due Date", type: "date", value: "2024-03-09T10:30:00.000Z" }
]
},
definitionType: "ext",
workflow: "wf_archive"
})
});
if (!createResponse.ok) {
throw new Error(`Document creation failed: ${createResponse.status} ${createResponse.statusText}`);
}
const createData = await createResponse.json();
const documentId = createData.results[0].documentId;
// Step 3: Get the document (optional)
const getResponse = await fetch(`${URL}${API_PATH}/documents/${documentId}?token=${TOKEN}`);
if (!getResponse.ok) {
throw new Error(`Failed to retrieve document: ${getResponse.status} ${getResponse.statusText}`);
}
const documentData = await getResponse.json();
console.log('Document contains following custom fields:');
console.log(documentData.results[0].customFields);
} catch (error) {
console.error('Error in document annotation process:', error.message);
}