Skip to content

Reference

Migrating from another system

Mapping common online office suite concepts to the O3O API, differences to watch and the migration steps.

On this page

Online office suites share many concepts: an editor configuration, a document version identifier, save callbacks, a conversion service. This page maps those concepts to the O3O API so a move to O3O has a clear path. The field names, signing scheme and behaviour below are O3O's own.

Concept map#

Common conceptO3ONotes
Embedded editor created from a configuration object in the browsernew O3O.Editor(id, config), loaded from /o3o/api.jsapi.js derives the server address from its own script tag.
URL the server downloads the source file fromdocument.urlDownloaded by the O3O server, not the browser; subject to SSRF rules.
Document version identifier that groups co-editorsdocument.keyMatches ^[A-Za-z0-9._-]{1,128}$; use a new key after the closed callback.
File type and display namedocument.fileType, document.title12 accepted extensions.
Edit or view-only modeeditor.mode: edit / viewview does not count as a connection.
Current user and interface languageeditor.user.id, editor.user.name, editor.lang
URL notified when the document is savededitor.callbackUrlSee Callbacks and webhooks.
Configuration signed as a JWTtoken HS256, the payload is the config itselfNo wrapper object inside the payload.
Status in the save callbackstatus: saved / closedWith the final, autosave, modifiedByUser flags; no numeric status codes.
Callback reply body in a prescribed shapeAny 2xx statusThe reply body is ignored.
Callback authenticationX-O3O-Signature, X-O3O-TimestampHMAC SHA-256
Downloading the saved fileSigned url in the callback and in onSavedValid for O3O_EMBED_RETAIN_HOURS hours.
Browser-side eventsonReady, onDocumentLoaded, onModified, onSaved, onClose, onLimitReached, onError
Editor object methodssave(), close(), destroy(), setReadOnly(), getInfo()
Interface customisationuiSize, toolbar style, close button, print, export, copy, user list. Logo, colours, dark theme: coming soon.
Format conversion service with an asynchronous modePOST /v1/convertGET /v1/jobs/{id}GET /v1/files/{id}Source is file (multipart) or url (JSON).
Building documents without a browserPOST /v1/build + o3oscriptScripts are declarative JSON, not executable code.
Mail merge, template fillingPOST /v1/template/render{{field}} and table row loops; enterprise edition only.
Connecting a file store over WOPI/hosting/discovery, CheckFileInfo, GetFile, PutFileNextcloud through the richdocuments app.
Per-connection licensing1 connection = 1 concurrent editing sessionSee How connections are counted.
Health checksGET /o3o/healthz, GET /v1/status

Differences to watch#

  • Callbacks have only two states, saved and closed, and carry a signed download URL. Download the file before the URL expires.
  • A callback receiver only needs to answer 2xx. O3O tries 3 times (first try, after 10 seconds, after 60 seconds), so the receiver must be idempotent.
  • After the closed callback, the next opening must use a new document.key.
  • Only HS256 JWTs are accepted; any other algorithm, none included, is rejected.
  • Conversion only works within one document family (text, spreadsheet, presentation); synchronous mode returns the file directly.
  • Document build scripts are declarative JSON following the o3oscript schema; no client code is executed.
  • Read-only sessions do not count; reaching the cap disconnects nobody, and new sessions open read-only.
Coming soon

A /compat/* compatibility layer for running existing integration code unchanged.

Migration steps#

  1. Inventory

    List where the editor is opened, the callback receivers, the conversion calls and the document build scripts in the current system.
  2. Set up a test machine

    Run the Docker bundle following Self-hosting and try the /o3o/demo page.
  3. Map the configuration

    Build the O3O.Editor config from the table above; sign it as a JWT on your server.
  4. Rewrite the callback receiver

    Verify the signature, be idempotent, answer 2xx at once, download url in the background.
  5. Move document processing calls

    Conversions to /v1/convert, document building to o3oscript, mail merge to /v1/template/render.
  6. Test the limits

    Test the cap with O3O_GATE_CONNECTION_CAP and handle 429 as described in Plan limits.
  7. Switch over gradually

    Run both systems side by side, move one module at a time; compare saved files before turning the old system off.
The O3O side after migrating
// Browser, after loading http://localhost:8080/o3o/api.js
const editor = new O3O.Editor("o3o-editor", {
  document: {
    url: "https://example.com/files/hop-dong.docx", // the O3O server downloads this file
    title: "Hợp đồng mẫu.docx",
    fileType: "docx",
    key: "hopdong-42-v7"                             // a new key for every content version
  },
  editor: {
    mode: "edit",
    lang: "vi",
    user: { id: "u-1001", name: "Nguyễn Văn A" },
    callbackUrl: "https://example.com/o3o/callback" // receives saved and closed
  },
  token: tokenFromServer,                           // JWT signed by your server
  events: {
    onSaved: (e) => console.log(e.version, e.url),
    onLimitReached: (e) => console.warn(e.message),
    onError: (e) => console.error(e.code, e.message)
  }
});
# Synchronous conversion: returns the PDF directly
curl -s http://localhost:8080/v1/convert \
  -H "Authorization: Bearer O3O_DEMO_KEY" \
  -F file=@bao-cao.docx -F to=pdf -o bao-cao.pdf

# Asynchronous: get a job, poll it, download the file
curl -s http://localhost:8080/v1/convert \
  -H "Authorization: Bearer O3O_DEMO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/files/bao-cao.docx", "to": "pdf", "async": true}'
curl -s http://localhost:8080/v1/jobs/job_4f1c2a9b0d3e5f6a7b8c9d0e -H "Authorization: Bearer O3O_DEMO_KEY"
curl -s http://localhost:8080/v1/files/file_9a8b7c6d5e4f3a2b1c0d9e8f -H "Authorization: Bearer O3O_DEMO_KEY" -o bao-cao.pdf