O3O DocBuilder and conversion
The o3oscript language
Reference for o3oscript v1, the declarative JSON script that builds text documents, spreadsheets and presentations through POST /v1/build: structure, units, meta, save, fonts, constraints and errors; each operation is detailed on three sub-pages.
On this page
o3oscript is a DECLARATIVE language written in JSON: you describe the document you want rather than write commands. There are no variables, loops, conditions or function calls, so a script cannot run forever or touch the server. Loops and conditions live in your code, which generates the JSON. One script builds exactly ONE document of one of three types and saves it in one or more formats.
{
"o3oscript": 1,
"type": "text",
"meta": {
"title": "Tên tài liệu"
},
"body": [
{
"type": "paragraph",
"text": "Nội dung"
}
],
"save": [
{
"format": "docx"
}
]
}Overall structure#
Root keys
o3oscriptintegerrequiredLanguage version, always1.typestringrequiredtext(text document),sheet(spreadsheet) orslides(presentation).metaobjectoptionalDocument properties, see meta.savearray, 1–5 itemsrequiredFiles to save, see save.pageobjectoptionaltextonly. Paper size and margins.styleobjectoptionaltextonly. Default text style.headerobjectoptionaltextonly. Page header.footerobjectoptionaltextonly. Page footer.bodyarray, 1–20,000 blocksoptionalRequired whentype = text. Content blocks in order.sheetsarray, 1–50 sheetsoptionalRequired whentype = sheet.slide_sizestringoptionalDefault:16:9slidesonly.16:9or4:3.slide_styleobjectoptionalslidesonly. Style shared by every slide.slidesarray, 1–500 slidesoptionalRequired whentype = slides.
Three document types#
type | Content keys | Save formats | Reference |
|---|---|---|---|
text | page, style, header, footer, body | docx, odt, pdf | o3oscript for text |
sheet | sheets | xlsx, ods, pdf | o3oscript for spreadsheets |
slides | slide_size, slide_style, slides | pptx, odp, pdf | o3oscript for presentations |
Units#
- Every length (margins, spacing, widths, heights, coordinates) is in millimetres.
- Font sizes and border widths are in points (pt).
- Colours are
#RRGGBBstrings, e.g.#1D55B8. - Line spacing is a percentage:
100is single,150is one and a half. - Text table column widths are RELATIVE numbers: columns share the table width in proportion.
Document properties: meta#
The meta object
titlestring, ≤ 255optionalDocument title.subjectstring, ≤ 255optionalSubject.authorstring, ≤ 255optionalAuthor.keywordsarray, ≤ 32 strings of ≤ 64optionalKeywords.descriptionstring, ≤ 2000optionalDescription.langstringoptionalDefault:vi-VNDocument language such asviorvi-VN; affects spell checking and hyphenation.
{
"meta": {
"title": "Hợp đồng cung cấp dịch vụ",
"subject": "Hợp đồng số HD-2026-091",
"author": "Phòng Pháp chế",
"keywords": [
"hợp đồng",
"dịch vụ"
],
"description": "Bản dựng tự động từ hệ thống quản lý hợp đồng.",
"lang": "vi-VN"
}
}Files to save: save#
Each save entry
formatstringrequiredOne of docx, odt, pdf, xlsx, ods, pptx, odp, matching thetype(see the document type table).filenamestring, 1–255optionalDefault:tai-lieu.<format>Result file name. Must not contain/ \ : * ? " < > |or control characters.pdfabooleanoptionalDefault:falseOnly meaningful withformat = pdf: export PDF/A-2b.
{
"save": [
{
"format": "docx",
"filename": "hop-dong.docx"
},
{
"format": "pdf",
"filename": "hop-dong.pdf",
"pdfa": true
}
]
}Fonts#
Font names are 1 to 64 characters. The DocBuilder v1 image has: Liberation Sans, Liberation Serif, Liberation Mono, Carlito, Caladea, DejaVu Sans, Noto Sans, Noto Serif. Missing fonts are replaced by LibreOffice with the closest match. Liberation Serif, Liberation Sans and Carlito share the metrics of Times New Roman, Arial and Calibri, so documents using those fonts usually keep their layout.
Sample scripts#
| File | type | Units | Content | See |
|---|---|---|---|---|
bao-gia.json | text | 28 | License quotation: header and footer, a table, nested lists, a page break. | Text |
bang-luong.json | sheet | 34 | Two-sheet payroll: formulas, cross-sheet references, dates, number formats. | Spreadsheet |
gioi-thieu.json | slides | 12 | Three slides: title slide, multi-level bullets, a base64 image, speaker notes. | Presentation |
All three scripts pass the schema and work as-is with POST /v1/build. Script unit counting is explained on Building documents.
Run-time checks#
- Every row of a text table must have as many cells as
headerorcolumns. - Lists nest at most 3 levels deep.
- Sheet names must be unique.
- Base64 images must decode and be no larger than 10 MB.
- Images given by
urlfollow the same SSRF rules as every other URL DocBuilder downloads.
Reading script errors#
Script errors point at the location with a JSON Pointer: /body/2/level is the level key of the third body element (counting from 0). script_invalid lists every schema failure in detail.errors; script_error gives one location in detail.path; script_too_large reports detail.units and detail.limit.
script_invalid example.{
"error": {
"code": "script_invalid",
"message": "Kịch bản không hợp lệ.",
"detail": {
"errors": [
{
"path": "/body/2/level",
"message": "7 lớn hơn giá trị tối đa 6"
}
]
},
"request_id": "req_0123456789abcdef"
}
}The JSON Schema#
The authoritative schema is JSON Schema draft-07, $id https://office.o3o.vn/api/schema/o3oscript-v1.schema.json, shipped in the DocBuilder image at /app/o3oscript-v1.schema.json. To validate scripts on your side in Python or JavaScript, see Building documents.
Coming later#
Not in o3oscript v1 (the schema rejects unknown keys): charts, merged cells in text tables, automatic tables of contents, footnotes, named styles, pivot tables, conditional formatting, slide transitions, custom slide masters, and Excel-style exclamation-mark sheet references.