O3O DocBuilder and conversion
o3oscript for presentations
Every operation of a type = slides script: slide size, shared style, four layouts, multi-level bullets, images, backgrounds and speaker notes, each with a parameter table and an example.
On this page
A type = "slides" script builds a deck of 1 to 500 slides in the slides array. Save formats: pptx, odp, pdf.
Size and shared style: slide_size, slide_style#
Root key and the slide_style object
slide_size16:9 | 4:3optionalDefault:16:9Slide aspect ratio.slide_style.fontstringoptionalShared font.slide_style.title_color#RRGGBBoptionalTitle colour.slide_style.text_color#RRGGBBoptionalBody text colour.slide_style.background#RRGGBBoptionalDefault background.slide_style.title_sizenumber 4–400 (pt)optionalTitle font size.slide_style.text_sizenumber 4–400 (pt)optionalBody font size.
{
"slide_size": "16:9",
"slide_style": {
"font": "Liberation Sans",
"title_color": "#C04A1B",
"text_color": "#222222",
"background": "#FFFFFF",
"title_size": 36,
"text_size": 22
}
}Slides: slide#
The slide object
layouttitle | title_content | title_only | blankoptionalDefault:title_contentLayout, see the table below.titlestring, ≤ 500optionalSlide title.subtitlestring, ≤ 1000optionalSubtitle, used with thetitlelayout.bulletsarray, 1–50optionalBullets.imageobjectoptionalOne image on the slide.notesstring, ≤ 20,000optionalSpeaker notes.background#RRGGBBoptionalBackground of this slide only.
layout | Used for |
|---|---|
title | Title slide: title and subtitle. |
title_content | Title and bulleted content (default). |
title_only | Title only, the rest left free for an image. |
blank | Empty slide. |
{
"layout": "title",
"title": "Báo cáo quý III năm 2026",
"subtitle": "Phòng Kinh doanh · 30/09/2026",
"notes": "Giới thiệu người trình bày và mục tiêu buổi họp."
}Bullets: bullets#
Each bullet
textstring, ≤ 2000requiredText. A bullet can also be a plain string.levelinteger 0–4optionalDefault:0Indent level; 0 is the outermost.boldbooleanoptionalBold.
{
"layout": "title_content",
"title": "Kết quả chính",
"bullets": [
"Doanh thu tăng so với quý II",
{
"text": "Khu vực phía Bắc dẫn đầu",
"level": 1
},
{
"text": "Cần đẩy mạnh kênh đối tác",
"bold": true
}
],
"notes": "Nhấn mạnh kết quả của khu vực phía Bắc.",
"background": "#F7F9FC"
}Images on slides#
The slide image object
srcobjectrequiredImage source{"url"}or{"base64", "mime"}, same as in text documents.xnumber (mm)optionalHorizontal position.ynumber (mm)optionalVertical position.widthnumber (mm)optionalWidth.heightnumber (mm)optionalHeight.altstring, ≤ 1000optionalAlternative text.
{
"layout": "title_only",
"title": "Sơ đồ triển khai",
"image": {
"src": {
"url": "https://example.com/images/so-do-trien-khai.png"
},
"x": 20,
"y": 40,
"width": 200,
"height": 110,
"alt": "Sơ đồ triển khai ba máy chủ"
}
}Coming soon
Slide transitions, custom slide masters and charts.
Complete example: product introduction#
gioi-thieu.json builds three slides: a title slide, multi-level content and a slide with a base64 image (so the example runs offline). The script has 12 units: the slide count plus the total number of bullets.
{
"o3oscript": 1,
"type": "slides",
"meta": {
"title": "Giới thiệu O3O Office Online",
"author": "Công ty Cổ phần O3O",
"lang": "vi-VN"
},
"slide_size": "16:9",
"slide_style": {
"font": "Liberation Sans",
"title_color": "#C04A1B",
"text_color": "#222222",
"background": "#FFFFFF",
"title_size": 36,
"text_size": 22
},
"slides": [
{
"layout": "title",
"title": "O3O Office Online",
"subtitle": "Bộ soạn thảo văn bản, bảng tính và trình chiếu chạy trên máy chủ của chính bạn",
"notes": "Chào mừng. Bài trình bày dài khoảng 5 phút."
},
{
"layout": "title_content",
"title": "Ba thành phần",
"bullets": [
"Trình soạn thảo cộng tác ngay trong trình duyệt",
{
"text": "Đấu vào Nextcloud qua giao thức WOPI",
"level": 1
},
{
"text": "Hoặc nhúng thẳng vào ứng dụng bằng O3O.Editor",
"level": 1
},
"DocBuilder: dựng và chuyển đổi tài liệu qua API",
{
"text": "Kịch bản o3oscript dạng JSON",
"level": 1
},
{
"text": "Bản cộng đồng miễn phí 50 kết nối đồng thời",
"bold": true
}
],
"notes": "Nhấn mạnh: dữ liệu nằm trên máy chủ của khách hàng."
},
{
"layout": "title_content",
"title": "Ba ứng dụng, ba màu",
"bullets": [
"Xanh dương: văn bản",
"Cam: trình chiếu",
"Xanh lá: bảng tính"
],
"image": {
"src": {
"base64": "iVBORw0KGgoAAAANSUhEUgAAAKAAAABaCAIAAACwpMoFAAAAsUlEQVR42u3RMQ0AIAwAwapgIYhhZccMyhiRhoA6aC55BX8x9lXhwgLAAizAAizAAizAgAVYgAVYgAVYgAELsAALsAALsAALMGABFmABFmABVgJ+q6twgAELsAALsAALsAADFmABFmABFmABBizAAizAAizAAizAgAVYgAVYgAVYGbidqcIBBizAAizAAizAAgxYgAVYgAVYgAUYsAALsAALsAALsAADFmABFmABFmClPpawm2fxo+U6AAAAAElFTkSuQmCC",
"mime": "image/png"
},
"alt": "Ba dải màu của ba ứng dụng"
},
"notes": "Ảnh minh hoạ là ba dải màu thương hiệu, nhúng dạng base64 để ví dụ chạy được khi không có mạng."
}
],
"save": [
{
"format": "pptx",
"filename": "gioi-thieu.pptx"
}
]
}curl -sS http://localhost:8080/v1/build \
-H "Authorization: Bearer O3O_DEMO_KEY" \
-H "Content-Type: application/json" \
--data-binary @gioi-thieu.json \
-o gioi-thieu.pptx -w "HTTP %{http_code}\n"import { readFile, writeFile } from "node:fs/promises";
const BASE_URL = "http://localhost:8080";
const HEADERS = { Authorization: "Bearer O3O_DEMO_KEY" };
const script = JSON.parse(await readFile("gioi-thieu.json", "utf8"));
const res = await fetch(`${BASE_URL}/v1/build`, {
method: "POST",
headers: { ...HEADERS, "Content-Type": "application/json" },
body: JSON.stringify(script),
signal: AbortSignal.timeout(90_000),
});
if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
await writeFile("gioi-thieu.pptx", Buffer.from(await res.arrayBuffer()));import json
import requests
BASE_URL = "http://localhost:8080"
HEADERS = {"Authorization": "Bearer O3O_DEMO_KEY"}
with open("gioi-thieu.json", encoding="utf-8") as f:
script = json.load(f)
r = requests.post(f"{BASE_URL}/v1/build", headers=HEADERS, json=script, timeout=90)
if not r.ok:
raise RuntimeError(f"{r.status_code}: {r.text}")
with open("gioi-thieu.pptx", "wb") as fh:
fh.write(r.content)<?php
$payload = file_get_contents("gioi-thieu.json");
$ch = curl_init("http://localhost:8080/v1/build");
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ["Authorization: Bearer O3O_DEMO_KEY", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 90,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($body === false || $status >= 400) {
throw new RuntimeException("HTTP $status: " . ($body === false ? curl_error($ch) : $body));
}
file_put_contents("gioi-thieu.pptx", $body);using System.Net.Http.Headers;
using System.Text;
using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(90) };
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "O3O_DEMO_KEY");
var json = await File.ReadAllTextAsync("gioi-thieu.json");
using var res = await http.PostAsync("http://localhost:8080/v1/build",
new StringContent(json, Encoding.UTF8, "application/json"));
if (!res.IsSuccessStatusCode)
throw new HttpRequestException($"{(int)res.StatusCode}: {await res.Content.ReadAsStringAsync()}");
await File.WriteAllBytesAsync("gioi-thieu.pptx", await res.Content.ReadAsByteArrayAsync());