Get started
Choosing an integration
Four ways to bring O3O Office Online into your system: connect Nextcloud, write your own WOPI host, embed with O3O.Editor, or use only the DocBuilder API. Compares the work involved, the components used and how connections are counted.
All four approaches use the same Docker stack; they differ in where files live and who talks to the editing server. You can combine several of them on one server.
| Approach | Best when | What you write | Counts connections |
|---|---|---|---|
| Nextcloud | You already use, or will use, Nextcloud as the file store | No code, configuration only | Yes, per editing session |
| Your own WOPI host | You have your own storage and files must stay there | Three WOPI operations: CheckFileInfo, GetFile, PutFile | Yes, per editing session |
O3O.Editor embedding | A web app that only has a download URL and a URL to receive edits | One script tag, JWT signing, one callback endpoint | Yes in edit mode, not in view mode |
| DocBuilder only | Background processing: conversion, reports, contracts, invoices | REST calls | No; subject to the plan's rate limits |
Nextcloud#
Nextcloud talks to the editing server through the richdocuments app over the WOPI protocol. Users open files directly from Files and co-edit with colleagues; files always stay in Nextcloud.
- Install
richdocumentsand runrichdocuments:activate-configwith-wset to the editing server's internal address and-cset to the address the editing server uses to call Nextcloud back. Without-c,wopi_callback_urlis reset to empty. - List Nextcloud's WOPI origin in
O3O_ONLINE_ALIASGROUP2(group 1 is always reserved for o3o-gate). - Nextcloud must trust the internal host name
o3o-nextcloud(O3O_NC_TRUSTED_DOMAINS). - To let o3o-gate admit read-only sessions once the cap is reached, set
O3O_WOPI_ALLOWED_HOSTS. - richdocuments derives
public_wopi_urlfrom discovery; do not set it by hand. If it is wrong, fixO3O_ONLINE_SERVER_NAMEand runactivate-configagain with both-wand-c.
Your own WOPI host#
Your storage system acts as the WOPI host: the editing server calls it back to read file information, fetch the content and write the edited version. You keep full control of permissions and versioning.
- Read
/hosting/discoveryto get the editor pageurlsrcfor each file extension. - Issue an
access_tokenfor the user, build an iframe and post a form tourlsrcwithWOPISrcpointing at your file API. - Answer
GET /wopi/files/{id}(CheckFileInfo),GET /wopi/files/{id}/contents(GetFile) andPOST /wopi/files/{id}/contents(PutFile). - List your WOPI host origin in
O3O_ONLINE_ALIASGROUP2so the editing server accepts it.
{
"BaseFileName": "contract.docx",
"Size": 48213,
"Version": "7",
"OwnerId": "u-1001",
"UserId": "u-1001",
"UserFriendlyName": "Jane Doe",
"UserCanWrite": true,
"SupportsUpdate": true,
"SupportsLocks": false,
"LastModifiedTime": "2026-09-21T10:00:00.0000000Z"
}O3O.Editor embedding#
No Nextcloud or WOPI needed: o3o-gate acts as the WOPI host. Your page only provides the URL of the source file and, to receive edits, a callback URL. Your server signs the configuration with JWT HS256.
<script src="http://localhost:8080/o3o/api.js"></script>
<div id="editor" style="height:720px"></div>
<script>
// JWT signed by YOUR SERVER with O3O_EMBED_JWT_SECRET; the payload holds document, editor, ui and exp
const editor = new O3O.Editor("editor", {
document: { url: "https://files.example.com/contract.docx", title: "Contract.docx", fileType: "docx", key: "contract-42-v7" },
editor: { mode: "edit", lang: "en", user: { id: "u-1001", name: "Jane Doe" },
callbackUrl: "https://app.example.com/o3o/callback" },
token: signedConfigJwt,
events: { onSaved: (e) => console.log("saved version", e.version) }
});
</script>- Events:
onReady,onDocumentLoaded,onModified,onSaved,onError,onClose,onLimitReached. - Methods:
save(),close(),destroy(),setReadOnly(),getInfo(). - Save callbacks carry
X-O3O-Signature(HMAC SHA-256); o3o-gate tries up to 3 times. - At the cap the editor still opens, read-only, and fires
onLimitReached.
Dark editor theme, watermarks, per-command button visibility, save as another file, creating a blank document without a url, version history in the embedding layer.
DocBuilder only#
When nobody needs to edit interactively, your system calls the /v1/* REST API to convert files, build documents from o3oscript scripts or fill templates. DocBuilder work does not count as connections but is subject to the plan's rate and file size limits.
The example below builds a PDF of meeting minutes: save the script from the JSON tab as minutes.json, then send it with the command in the cURL tab.
curl -s -X POST http://localhost:8080/v1/build \
-H "Authorization: Bearer $O3O_DEMO_KEY" \
-H "Content-Type: application/json" \
--data-binary @minutes.json \
-o minutes.pdf{
"o3oscript": 1,
"type": "text",
"body": [
{
"type": "heading",
"level": 1,
"text": "Meeting minutes"
},
{
"type": "paragraph",
"text": "Content built with O3O DocBuilder."
}
],
"save": [
{
"format": "pdf",
"filename": "minutes.pdf"
}
]
}| Endpoint | Purpose | Community | Enterprise |
|---|---|---|---|
GET /v1/status | Service status, no authentication | Yes | Yes |
GET /v1/formats | Input and output format matrix | Yes | Yes |
GET /v1/limits | Effective limits and current usage | Yes | Yes |
POST /v1/convert | Format conversion within a document family | Yes | Yes |
POST /v1/build | Build a document from an o3oscript script | Yes | Yes |
POST /v1/template/render | Fill a docx or odt template with JSON data | No | Yes |
POST /v1/extract/text | Extract plain text | Yes | Yes |
POST /v1/extract/meta | Extract metadata | Yes | Yes |
POST /v1/extract/thumbnail | Thumbnail of one page | Yes | Yes |
GET /v1/jobs/{id} | Status of an asynchronous job | Yes | Yes |
GET /v1/files/{id} | Download a result file | Yes | Yes |
Quick decision#
Already running Nextcloud?
Use Nextcloud: no code, users open files right in Files.Own file store, and files must not leave it?
Write a WOPI host: the editing server reads and writes directly to your store.A web app that just needs to open a file by URL?
UseO3O.Editor: o3o-gate keeps the working copy and returns edits through callbacks.No interactive editing needed?
Use DocBuilder only: conversion and generation over REST, no connections counted.