Cloud Office API reference
These public server-to-server APIs create browser sessions for viewing or editing documents using Thinkfree-managed Office resources. Your backend can list account-owned storages, request a document open URL, and read its reported state without operating an Office server. Save and download are available after a successful open and before the document closes.
Endpoint catalog
The base URL is https://api.thinkfree.com. These five endpoints are the complete public Cloud Office API. Every endpoint requires the Authorization header. Session creation accepts two Content-Types at the same path.
| Method | Path | Request format | Success response | Purpose |
|---|---|---|---|---|
GET | /api/office/v1/storages | No body or query | 200, JSON (data: array) | List account-owned storages |
POST | /api/office/v1/client-sessions | JSON or multipart | 201, JSON (data: object) | Create a document session and open URL |
GET | /api/office/v1/client-sessions/{clientSessionId} | Path parameter only | 200, JSON (data: object) | Read the last reported document state |
POST | /api/office/v1/client-sessions/{clientSessionId}/save | Path parameter only | 200, JSON (data: object) | Save an open Editor document to connected or temporary storage |
GET | /api/office/v1/client-sessions/{clientSessionId}/download | Path parameter only | 200, binary file | Return the open document file to the API caller |
Register and configure storage in Developer Console Storages. These APIs do not create, update, delete, or browse storages. Choose the mode when creating a session; no API changes an existing Viewer session to Editor.
Prerequisites and authentication
Create an API Key in the Developer Console and keep it in a server-side
secret store. The default key lifetime is No expiration; choosing a shorter lifetime limits exposure. All API dates
are ISO 8601 UTC instants, such as 2026-08-09T02:55:00Z.
Send it on every request:
Authorization: Bearer tfoak-replace-with-your-key
Never put an API Key in browser JavaScript, a mobile binary, a document URL, source control, analytics, or logs. Revoke it immediately if it may have been exposed. Expired and revoked keys cannot authenticate.
Common request and response headers
| Header | Required / behavior when omitted | Meaning |
|---|---|---|
Authorization | Required. A missing or unusable key returns 401 / 4010 | Bearer {API_KEY}. Status, save, and download require the same key that created the session |
Content-Type | Required for session creation | application/json for storage or multipart/form-data with a boundary for upload. Other APIs have no request body and do not require it |
X-Request-ID | Optional. Missing, blank, or longer than 64 characters: the server generates a UUID | Request correlation value returned in the same response header. It does not prevent duplicate requests |
Success and documented error responses include Cache-Control: no-store, X-Request-ID, X-Thinkfree-Success, X-Thinkfree-Code, and X-Thinkfree-Code-Description. The last three headers contain string versions of the JSON success, code, and codeDescription fields. Only a successful download returns binary instead of JSON.
Common JSON response
Every JSON response explicitly reports success or failure. The endpoint-specific payload is nested under data.
{
"success": true,
"code": 0,
"codeDescription": "SUCCESS",
"data": {}
}
{
"success": false,
"code": 4043,
"codeDescription": "CLIENT_SESSION_NOT_FOUND",
"errorMessage": "The client session was not found",
"errorDetail": "Optional request-specific detail"
}
| Field | Type | Required | Meaning / allowed values |
|---|---|---|---|
success | boolean | Yes | true for success; false for failure |
code | integer | Yes | Stable numeric result code; 0 means success |
codeDescription | string | Yes | Stable symbolic description such as SUCCESS or CLIENT_SESSION_NOT_FOUND |
data | endpoint-specific | Yes on success; omitted on failure | Successful endpoint payload |
errorMessage | string | Yes on failure; omitted on success | Safe human-readable failure explanation |
errorDetail | string | No - default: omitted | Additional safe detail when available; do not branch application logic on its wording |
Branch on numeric code. Use codeDescription for readable logs and errorMessage/errorDetail for diagnostics.
Creation formats and response groups
POST /api/office/v1/client-sessions selects the document source from the request Content-Type:
application/json for connected storage, or multipart/form-data with file and an application/json request part for an uploaded file.
Both formats require clientType; use "BROWSER" for a working browser session. The server reports the resulting documentSourceType; it is not a request selector.
clientSessionId identifies this API session. documentLifecycleId identifies the document event history reported for it. Keep these IDs separate; status and operation URLs use clientSessionId.
| Response field | Caller | Purpose |
|---|---|---|
browser.openUrl | Intended user's browser | Opens Office without an API Key header. Deliver this URL only to the intended user. |
browser.openUrlExpiresAt | Customer application | Deadline for first use of the open URL, not the lifetime of an open editor or the API endpoints. |
api.statusUrl | Customer backend | GET the last document state received by Developers. |
api.saveUrl | Customer backend | POST a save request. Included only for EDITOR. |
api.downloadUrl | Customer backend | GET the current document as binary bytes after a successful open and before close. |
In EDITOR mode, the user can edit for up to 12 hours from document opening. After 12 hours, the user can no longer edit in that session. The open URL's 5-minute deadline applies only to the initial opening.
Office's own Save/Download buttons and your backend's API calls are separate ways to use the session. An Office download goes to the user's browser; the API download returns bytes to the API caller. Status, save, and download endpoints require the exact API Key that created the session. Another key from the same account cannot access it. A returned endpoint does not mean the operation is available in every state.
User, document, and session IDs
To retain user and document identity across sessions, your backend should keep a mapping from each application user and document record to the IDs it sends to Office. Assign an ID once, store it with that record, and reuse it when the same user opens the same document again. This lets Office distinguish collaborators and associate document activity with the intended user and document.
-
userId- Your application supplies this optional request field. It identifies one application user. Reuse it across that user's sessions and documents, even if their name, email, or avatar changes. Give every different user a different value. -
docId- Your application supplies this optional request field. It identifies one document within your Developer Console account and storage connection. Reuse it when reopening or co-editing that document. Give every different document a different value. -
clientSessionId- Developers returns this response field. It identifies one API session. Every successful creation request returns a new value, even whenuserIdanddocIdstay the same. Use the returned value for status, save, and download calls. -
documentLifecycleId- Developers returns this response field. It identifies the document event history for the session. It does not replace your application'sdocId.
userId and docId are optional. If you omit userId, no stable user identity is retained across independent sessions; Developers does not infer your application's signed-in user. If you omit docId, Developers assigns a separate document identity to each new session. Opening the same path again therefore does not retain that identity automatically.
For a connected-storage document, keep storageId, documentPath, and docId consistent across participants and later opens. The following examples assume the same storage connection:
-
Alex opens the proposal:
userId:user-1042,docId:proposal-2026-0042. Store the returnedclientSessionId. -
Alex opens the same proposal again:
userId:user-1042,docId:proposal-2026-0042. Store the newclientSessionId; keepuserIdanddocId. -
Another user joins the proposal:
userId:user-2073,docId:proposal-2026-0042. Create a separate session for that participant. -
Alex opens a different proposal:
userId:user-1042,docId:proposal-2026-0043. Use the other document's path and a new session.
Do not generate a new random userId or docId on every open of the same user or document. Conversely, sharing one userId between different users or one docId between different documents can make Office treat them as the same entity, mixing collaboration participants or document history. When your backend requests a session for a new document or a separate Save As copy, use that document's own docId instead of reusing the original's. Keep the original ID when opening the original document.
Each Upload & Edit request creates a separate temporary source file. Matching filenames or file bytes do not establish that two uploads are the same document. Give a separately uploaded copy its own document ID. Do not reuse docId to retrieve an earlier upload or its edits; this API does not support reopening a previous upload by docId. Use connected storage when participants must repeatedly open the same stored document.
These IDs describe users and documents; they do not authenticate a user or grant document access. Your backend must authenticate its user and check document permissions before creating a session.
List storage connections
API role
GET /api/office/v1/storages returns non-secret summaries of storage connections owned by the API Key
account. Use the returned storageId when creating a browser client session. Only an ACTIVE connection can open a
document.
Request
curl --fail-with-body \
-H "Authorization: Bearer tfoak-replace-with-your-key" \
https://api.thinkfree.com/api/office/v1/storages
| Field | Location | Type | Required | Meaning / allowed values |
|---|---|---|---|---|
Authorization | header | string | Yes | Bearer {API_KEY} |
X-Request-ID | header | string | No - default: server-generated UUID | Client correlation ID, maximum 64 characters |
Response
{
"success": true,
"code": 0,
"codeDescription": "SUCCESS",
"data": [
{
"storageId": "74a73536-3024-48c2-a850-76cf7872323f",
"name": "Production documents",
"description": "Documents used by the production service",
"type": "S3",
"status": "ACTIVE"
}
]
}
| Field | Type | Required | Meaning / allowed values |
|---|---|---|---|
data | array | Yes | Connection summaries; empty when the account has no supported connections |
data[].storageId | string | Yes | Permanent storage UUID; pass it as storageId |
data[].name | string | Yes | Editable display name, 1–100 characters; not an API identifier |
data[].description | string | Yes | Display-only owner description, 1–200 characters |
data[].type | string enum | Yes | S3, S3_COMPATIBLE, or WEBDAV |
data[].status | string enum | Yes | PROVISIONING, ACTIVE, SYNC_FAILED, DELETING, or DELETE_FAILED |
Credentials, provider tokens, buckets, endpoints, and prefixes are never returned.
Errors for this API are 4010 INVALID_API_KEY and 5001 STORAGE_ADAPTER_LIST_FAILED.
type is S3 (Amazon S3), S3_COMPATIBLE (S3-compatible Object Storage), or WEBDAV.
status is ACTIVE (usable), PROVISIONING (registration in progress), SYNC_FAILED (settings could not be applied), DELETING (removal in progress), or DELETE_FAILED (removal failed). Use only ACTIVE entries for session creation; check other entries in Console Storages. This status does not guarantee that an individual file exists or that storage is reachable at that moment.
This request has no path parameters, query parameters, body, or pagination. It returns the complete list, or data: [] when no connections are available.
Create browser client session
API role
POST /api/office/v1/client-sessions verifies an account-owned active storage connection, then creates one
browser client session with one Cloud Office open URL for the requested mode, plus lifecycle tracking.
The API Key owner must also own the identified storage.
The storage document size limit is 300 MB (314,572,800 bytes, 300 MiB) for Word, Cell, and Show. Files within this limit must still have a supported, processable format and content. The multipart upload limit is separate: 100 MB (104,857,600 bytes, 100 MiB).
Creating links does not deduct Credits (creditsCharged: 0). Each successful open costs 5 Credits in viewer mode or 10 Credits in editor mode; failed opens are not charged. Link creation requires capacity for 5 Credits with VIEWER or 10 Credits with EDITOR, including enabled paid overage within its limit. Insufficient capacity returns HTTP 402 / 4020 INSUFFICIENT_CREDIT.
Request
curl --fail-with-body \
-X POST https://api.thinkfree.com/api/office/v1/client-sessions \
-H "Authorization: Bearer tfoak-replace-with-your-key" \
-H "Content-Type: application/json" \
-d '{
"clientType": "BROWSER",
"mode": "EDITOR",
"storageId": "74a73536-3024-48c2-a850-76cf7872323f",
"documentPath": "proposals/proposal-2026-0042.docx",
"userId": "user-1042",
"docId": "proposal-2026-0042",
"fileDisplayName": "customer-proposal.docx",
"userDisplayName": "Alex Kim",
"userEmail": "alex@example.com",
"userAvatarUrl": "https://example.com/profiles/alex.png",
"language": "en_US",
"skin": "default"
}'
| Field | Location | Type | Required | Meaning / allowed values |
|---|---|---|---|---|
Authorization | header | string | Yes | Bearer {API_KEY} |
Content-Type | header | string | Yes | application/json |
X-Request-ID | header | string | No - default: server-generated UUID | Client correlation ID, maximum 64 characters |
clientType | body | string enum | Yes | BROWSER |
mode | body | string enum | Yes | VIEWER (read only) or EDITOR (edit and save); no default |
storageId | body | string | Yes | UUID of a storage owned by the API Key account |
documentPath | body | string | Yes | Slash-separated relative path and filename, maximum 1,024 characters |
fileDisplayName | body | string | No - default: final filename in documentPath | Filename displayed in Office, up to 255 characters. Does not rename the source. No path separators or control characters; include a supported document extension. |
userId | body | string | No - a separate anonymous user for each session | 1–128 Unicode letters/digits, spaces, or ._@+()-; same value for the same user, different values for different users; independent of profile changes |
userDisplayName | body | string | No - omitted when absent | Display name, maximum 256 characters; not an identity key |
userEmail | body | string | No - omitted when absent | Profile email, maximum 254 characters; not used for authentication |
userAvatarUrl | body | HTTPS URL string | No - omitted when absent | Public HTTPS image URL requiring no authentication; maximum 2,048 characters, no embedded credentials or fragment. Beta: Office does not yet display this image as the user's profile icon. |
docId | body | string | No - default: generated for each new client session | 1–48 ASCII letters, digits, _, or -; same value for the same document, different values for different documents |
language | body | string | No - omitted from Office request when absent | Two groups of 2–8 ASCII letters separated by _, such as en_US or ko_KR; Office chooses its configured locale when absent |
skin | body | string | No - omitted from Office request when absent | 1–32 ASCII letters, digits, _, or -; Office chooses its configured skin when absent |
Use / as the path separator and a path relative to the configured root. Do not send .. traversal, a bucket name, an endpoint, or credentials.
Supported file types are doc, docx, odt, xls, xlsx, ods, ppt, pptx, and odp.
The example maps Alex to user-1042 and this stored proposal to proposal-2026-0042. Replace them with IDs from your application's user and document records, and reuse those values when reopening this document. For co-editing, keep the storage, path, and docId the same for every participant and use each participant's own userId. See ID reuse and session examples. language and skin are passed to Office only when you provide them.
The extension of fileDisplayName selects the document app. If the storage path has no extension, provide a fileDisplayName matching the actual document format. This name does not change the source path or convert the file.
Optional values and string input
Use only the field names listed in the request tables. If the JSON body or the multipart request part contains an unsupported field name, the API rejects the request with HTTP 400 and code 4001 INVALID_DOCUMENT_REQUEST; the API does not ignore that field.
Do not send null, empty, or whitespace-only values for required fields. An omitted or null optional string follows its table's omission rule. userId, docId, language, and skin are trimmed; whitespace-only values are treated as omitted. Profile fields are also trimmed, but overlong values and control characters are rejected. userEmail must have email-address syntax.
An absent or blank fileDisplayName uses the path's filename or the multipart filename. The display filename is trimmed and normalized to Unicode NFC; this does not rename the stored file. Send documentPath relative to the storage root with / separators. The server trims whitespace and leading/trailing /, converts \ to /, and rejects path segments equal to . or ... This field is a path string, not a URL: do not URL-encode spaces or Unicode characters inside JSON.
Response
HTTP 201 Created confirms session creation, not that Office has opened the document. The response identifies the created resource with
data.clientSessionId and data.api.statusUrl; this endpoint does not return a Location header.
{
"success": true,
"code": 0,
"codeDescription": "SUCCESS",
"data": {
"clientSessionId": "9169250d-5328-4d45-844b-9a37cb52f7ac",
"clientType": "BROWSER",
"documentSourceType": "STORAGE",
"documentLifecycleId": "0d102ee8-cbdd-4667-a5cf-f2e3a1007927",
"mode": "EDITOR",
"status": "CREATED",
"creditsCharged": 0,
"createdAt": "2026-08-08T14:55:00Z",
"browser": {
"openUrl": "https://office.developers.thinkfree.com/cloud-office/api/open-document?ticket=<ticket>",
"openUrlExpiresAt": "2026-08-08T15:00:00Z"
},
"api": {
"statusUrl": "https://api.thinkfree.com/api/office/v1/client-sessions/9169250d-5328-4d45-844b-9a37cb52f7ac",
"saveUrl": "https://api.thinkfree.com/api/office/v1/client-sessions/9169250d-5328-4d45-844b-9a37cb52f7ac/save",
"downloadUrl": "https://api.thinkfree.com/api/office/v1/client-sessions/9169250d-5328-4d45-844b-9a37cb52f7ac/download"
}
}
}
| Field | Type | Required | Meaning / allowed values |
|---|---|---|---|
data.clientSessionId | UUID string | Yes | Opaque client session identifier used by api.statusUrl |
data.clientType | string enum | Yes | BROWSER for successful creation |
data.documentSourceType | string enum | Yes | STORAGE; the document came from the requested storage connection. This is independent of viewer/editor mode. |
data.documentLifecycleId | UUID string | Yes | Opaque ID for the document activity reported in this session. Keep it as returned; use clientSessionId in API paths |
data.mode | string enum | Yes | Requested VIEWER or EDITOR mode |
data.browser | object | Yes for BROWSER | Office launch information for the browser |
data.browser.openUrl | HTTPS URL string | Yes | Single-use URL for the selected mode |
data.browser.openUrlExpiresAt | ISO 8601 UTC string | Yes | Deadline for opening this URL, 5 minutes after issuance. This deadline does not end an already opened document. |
data.api | object | Yes | API endpoints requiring the creating API Key |
data.api.statusUrl | HTTPS URL string | Yes | Document status endpoint; requires the exact creating API Key |
data.api.saveUrl | HTTPS URL string | Required for EDITOR; omitted for VIEWER | Document save API; requires a successful open |
data.api.downloadUrl | HTTPS URL string | Yes | Current-document download API; requires a successful open |
data.status | string enum | Yes | Initial value CREATED; use api.statusUrl for later lifecycle state |
data.creditsCharged | integer | Yes | Credits deducted for this request; 0 because charging occurs on successful open |
data.createdAt | ISO 8601 UTC string | Yes | Client-session creation instant |
Office uses the user identity, optional profile, document information, language, and skin supplied in your request. These values are not echoed in the response. Keep userId stable; changes to userDisplayName,
userEmail, or userAvatarUrl do not identify a different user. Optional profile fields reject control characters; blank values
are treated as omitted.
The image at userAvatarUrl must be readable by anyone without login, authentication headers, or authentication cookies. This Beta field does not yet set the Office profile icon.
| Extensions | Viewer application | Editor application |
|---|---|---|
doc, docx, odt | Word viewer | Word editor |
xls, xlsx, ods | Cell viewer | Cell editor |
ppt, pptx, odp | Show viewer | Show editor |
Errors for this API are 4001 INVALID_DOCUMENT_REQUEST, 4010 INVALID_API_KEY, 4020 INSUFFICIENT_CREDIT,
4021 SUBSCRIPTION_ACCESS_UNAVAILABLE, 4041 STORAGE_CONNECTION_NOT_FOUND, 4150 UNSUPPORTED_MEDIA_TYPE,
5021 STORAGE_UNAVAILABLE, and 5022 OFFICE_OPEN_URL_UNAVAILABLE. The API returns HTTP 415 with code 4150 when
the creation endpoint receives neither supported Content-Type.
Open browser.openUrl before browser.openUrlExpiresAt. The URL can be used once. Request a new browser client session if the ticket has expired or has already been used.
A viewer opens the document in read-only mode. Keep the open URL out of logs, analytics and support messages.
The URL grants access to the document. Deliver it only to the intended signed-in user and keep it out of referrers. Office saves connected-storage documents back to that storage. Save and download are available after a successful open and before the document closes.
Upload and create a browser client session
API role
POST /api/office/v1/client-sessions creates the same Cloud Office browser client session resource from an
uploaded file. It does not require a storage connection. Use it for short-lived editing when your application can send
the source bytes. Save and download are available after a successful open and before the document closes.
Creating links does not deduct Credits (creditsCharged: 0). Each successful open costs 5 Credits in viewer mode or 10 Credits in editor mode; failed opens are not charged. Link creation requires capacity for 5 Credits with VIEWER or 10 Credits with EDITOR, including enabled paid overage within its limit. Insufficient capacity returns HTTP 402 / 4020 INSUFFICIENT_CREDIT.
Request
Send multipart data and let your HTTP client generate the boundary. Do not manually set Content-Type without a valid
boundary.
curl --fail-with-body \
-X POST https://api.thinkfree.com/api/office/v1/client-sessions \
-H "Authorization: Bearer tfoak-replace-with-your-key" \
-F "file=@./sample.docx" \
-F 'request={"clientType":"BROWSER","mode":"EDITOR","fileDisplayName":"customer-proposal.docx","userId":"user-1042","docId":"upload-2026-0081","userDisplayName":"Alex Kim","userEmail":"alex@example.com","userAvatarUrl":"https://example.com/profiles/alex.png","language":"en_US","skin":"default"};type=application/json'
| Field | Location | Type | Required | Meaning / allowed values |
|---|---|---|---|---|
Authorization | header | string | Yes | Bearer {API_KEY} |
Content-Type | header | string | Yes | multipart/form-data; boundary=...; normally generated by the HTTP client |
X-Request-ID | header | string | No - default: server-generated UUID | Client correlation ID, maximum 64 characters |
request | multipart | JSON object | Yes | Session settings with Content-Type application/json. Do not include storageId or documentPath. |
clientType | request JSON | string enum | Yes | BROWSER |
mode | request JSON | string enum | Yes | VIEWER (read only) or EDITOR (edit and save); no default |
file | multipart | binary | Yes | Non-empty Office file, maximum 100 MB (104,857,600 bytes, 100 MiB); bytes must start with the OOXML/ODF ZIP or legacy OLE container signature required by the filename extension family |
fileDisplayName | request JSON | string | No - default: multipart file's filename | Name shown in Office, maximum 255 characters; its extension selects the document app. No /, \, or control characters; the whole name must not be . or .. |
userId | request JSON | string | No - a separate anonymous user for each session | 1–128 Unicode letters/digits, spaces, or ._@+()-; same value for the same user, different values for different users; independent of profile changes |
userDisplayName | request JSON | string | No - omitted when absent | Display name, maximum 256 characters; not an identity key |
userEmail | request JSON | string | No - omitted when absent | Profile email, maximum 254 characters; not used for authentication |
userAvatarUrl | request JSON | HTTPS URL string | No - omitted when absent | Public HTTPS image URL requiring no authentication; maximum 2,048 characters, no embedded credentials or fragment. Beta: Office does not yet display this image as the user's profile icon. |
docId | request JSON | string | No - default: generated for each new client session | 1–48 ASCII letters, digits, _, or -; same value for the same document, different values for different documents |
language | request JSON | string | No - omitted from Office request when absent | Two groups of 2–8 ASCII letters separated by _, such as en_US or ko_KR; Office chooses its configured locale when absent |
skin | request JSON | string | No - omitted from Office request when absent | 1–32 ASCII letters, digits, _, or -; Office chooses its configured skin when absent |
The example maps the user to user-1042 and this uploaded copy to upload-2026-0081. Keep the user ID for that user, and allocate a different document ID for a separately uploaded copy. The filename does not establish document identity. See user, document, and session IDs.
The uploaded file is kept as a temporary document for the session. Supported extensions are doc, docx,
odt, xls, xlsx, ods, ppt, pptx, and odp. Renaming arbitrary bytes to one of these extensions does not create
a valid Office file: the request is rejected before storage and Credit charging when the outer container signature does
not match the extension family. Office validates the complete document structure when it opens the file.
Response
HTTP 201 Created confirms session creation, not that Office has opened the document. The response identifies the created resource with
data.clientSessionId and data.api.statusUrl; this endpoint does not return a Location header. The response contract
is identical to a connected-storage browser client session. Both return api.downloadUrl.
{
"success": true,
"code": 0,
"codeDescription": "SUCCESS",
"data": {
"clientSessionId": "9169250d-5328-4d45-844b-9a37cb52f7ac",
"clientType": "BROWSER",
"documentSourceType": "UPLOAD",
"documentLifecycleId": "0d102ee8-cbdd-4667-a5cf-f2e3a1007927",
"mode": "EDITOR",
"status": "CREATED",
"creditsCharged": 0,
"createdAt": "2026-08-10T10:00:00Z",
"browser": {
"openUrl": "https://office.developers.thinkfree.com/cloud-office/api/open-document?ticket=<ticket>",
"openUrlExpiresAt": "2026-08-10T10:05:00Z"
},
"api": {
"statusUrl": "https://api.thinkfree.com/api/office/v1/client-sessions/9169250d-5328-4d45-844b-9a37cb52f7ac",
"saveUrl": "https://api.thinkfree.com/api/office/v1/client-sessions/9169250d-5328-4d45-844b-9a37cb52f7ac/save",
"downloadUrl": "https://api.thinkfree.com/api/office/v1/client-sessions/9169250d-5328-4d45-844b-9a37cb52f7ac/download"
}
}
}
| Field | Type | Required | Meaning / allowed values |
|---|---|---|---|
data.clientSessionId | UUID string | Yes | Opaque ID used by the status, save, and download endpoints |
data.clientType | string enum | Yes | BROWSER for the Upload & Edit endpoint |
data.documentSourceType | string enum | Yes | UPLOAD; the document entered Cloud Office through Upload & Edit. The requested mode selects one browser.openUrl. |
data.documentLifecycleId | UUID string | Yes | Opaque ID for the document activity reported in this session; not an API path parameter |
data.mode | string enum | Yes | Requested VIEWER or EDITOR mode |
data.browser | object | Yes for BROWSER | Office launch information for the browser |
data.browser.openUrl | HTTPS URL string | Yes | Single-use URL for the selected mode |
data.browser.openUrlExpiresAt | ISO 8601 UTC string | Yes | Deadline for opening this URL, 5 minutes after issuance. This deadline does not end an already opened document. |
data.api | object | Yes | API endpoints requiring the creating API Key |
data.api.statusUrl | HTTPS URL string | Yes | Document status endpoint; requires the exact creating API Key |
data.api.saveUrl | HTTPS URL string | Required for EDITOR; omitted for VIEWER | Document save API; requires a successful open |
data.api.downloadUrl | HTTPS URL string | Yes | Current-document download API; requires a successful open |
data.status | string enum | Yes | Initial value CREATED |
data.creditsCharged | integer | Yes | Credits deducted for this request; 0 because charging occurs on successful open |
data.createdAt | ISO 8601 UTC string | Yes | Upload client session creation instant |
Office uses the document and user information supplied in your upload request. These values are not echoed in this response.
Upload & Edit does not support Save As to another storage connection. Use Bring Your Own Storage when Office must save changes to storage controlled by your application.
Temporary uploads are not a durable archive. Save and download are available after a successful open and before the document closes. Errors are 4001 INVALID_DOCUMENT_REQUEST, 4010 INVALID_API_KEY, 4150 UNSUPPORTED_MEDIA_TYPE,
5021 STORAGE_UNAVAILABLE, and 5022 OFFICE_OPEN_URL_UNAVAILABLE. The API returns HTTP 415 with code 4150 when
the outer request or JSON part has an unsupported Content-Type. Missing parts or invalid JSON return 4001 INVALID_DOCUMENT_REQUEST. Insufficient capacity returns HTTP 402 / 4020 INSUFFICIENT_CREDIT; subscription restrictions return HTTP 402 / 4021 SUBSCRIPTION_ACCESS_UNAVAILABLE.
Read browser client session status
API role
GET /api/office/v1/client-sessions/{clientSessionId} returns the document status and event summary last reported by Office.
It requires the exact active API Key that created the session. This endpoint does not query Office or the browser in real time.
After a successful close event, status remains readable until the reported close time plus one hour. Without a close event, the deadline is the first successful open plus 12 hours. Before any successful open, it is creation plus 12 hours. At the deadline, the API returns HTTP 410/code 4101. A late close event can change this deadline; event occurrence times, not receipt times, determine the window.
CREATED means no successful open has been recorded. OPEN means an open was recorded without a later recorded close;
it does not prove that the browser is still connected. CLOSED means a close was recorded, not that every edit was saved.
Check lastSavedAt and lastFailure separately. Limit polling frequency and total wait rather than waiting indefinitely.
Request
curl --fail-with-body \
-H "Authorization: Bearer tfoak-replace-with-your-key" \
"https://api.thinkfree.com/api/office/v1/client-sessions/9169250d-5328-4d45-844b-9a37cb52f7ac"
| Field | Location | Type | Required | Meaning / allowed values |
|---|---|---|---|---|
Authorization | header | string | Yes | Exact Bearer {API_KEY} used to create the browser client session |
clientSessionId | path | UUID string | Yes | Value returned by session creation with either JSON or multipart |
X-Request-ID | header | string | No - default: server-generated UUID | Client correlation ID, maximum 64 characters |
Response
The following closed-session example includes every optional field. An earlier failed save remains in lastFailure; it does not mean that status lookup failed.
{
"success": true,
"code": 0,
"codeDescription": "SUCCESS",
"data": {
"clientSessionId": "9169250d-5328-4d45-844b-9a37cb52f7ac",
"clientType": "BROWSER",
"documentSourceType": "STORAGE",
"documentLifecycleId": "0d102ee8-cbdd-4667-a5cf-f2e3a1007927",
"status": "CLOSED",
"lastEventAt": "2026-08-08T14:58:00Z",
"documentOpenedAt": "2026-08-08T14:55:09Z",
"lastSavedAt": "2026-08-08T14:56:12Z",
"saveCount": 1,
"closedAt": "2026-08-08T14:58:00Z",
"lastFailure": {
"eventType": "SAVE",
"occurredAt": "2026-08-08T14:57:00Z"
},
"createdAt": "2026-08-08T14:55:00Z"
}
}
| Field | Type | Required | Meaning / allowed values |
|---|---|---|---|
data.clientSessionId | UUID string | Yes | Requested Developers client session identifier |
data.clientType | string enum | Yes | BROWSER for the currently available endpoints |
data.documentSourceType | string enum | Yes | Original document source: STORAGE or UPLOAD |
data.documentLifecycleId | UUID string | Yes | Opaque ID for the document activity reported in this session; not an API path parameter |
data.status | string enum | Yes | CREATED, OPEN, FAILED, or CLOSED |
data.lastEventAt | ISO 8601 UTC string | No - omitted before the first Office event | Most recent Office lifecycle event time |
data.documentOpenedAt | ISO 8601 UTC string | No - omitted until a successful open is reported | First successful open time reported by Office; starts the 12-hour window |
data.lastSavedAt | ISO 8601 UTC string | No - omitted until a save succeeds | Time of the most recent successful save event received from Office, for connected storage or an upload |
data.saveCount | integer | Yes | Number of successful save events received; starts at 0 |
data.closedAt | ISO 8601 UTC string | No - omitted until closed | Close time reported by Office; not a save confirmation |
data.lastFailure | object | No - omitted when no failure was reported | Most recent failure summary |
data.lastFailure.eventType | string enum | Yes when lastFailure exists | OPEN, SAVE, SAVE_AS, AUTO_SAVE, LOCK, UNLOCK, CLOSE, CLOSE_AFTER_SAVE, DOWNLOAD, DOWNLOAD_PDF, PRINT |
data.lastFailure.occurredAt | ISO 8601 UTC string | Yes when lastFailure exists | Failure time reported by Office |
data.createdAt | ISO 8601 UTC string | Yes | Client-session creation time |
FAILED means document opening failed. A failed save is reported in lastFailure without changing an otherwise active
editor to FAILED. This status response does not retry a save or close the document. Stop polling when the expected event is observed or the wait limit is reached. Errors are 4001 INVALID_DOCUMENT_REQUEST, 4010 INVALID_API_KEY, and
4043 CLIENT_SESSION_NOT_FOUND, and 4101 CLIENT_SESSION_EXPIRED.
lastFailure describes a failed event reported by Office. The allowed event names do not guarantee that every Office version reports every event.
Save the document
POST /api/office/v1/client-sessions/{clientSessionId}/save
This API asks Office to save the current document to its original storage. Connected-storage documents use that storage; uploads use temporary storage. It does not overwrite a file on the user's PC.
A successful response requires confirmation from Office. An unknown result does not prove that the save failed; inspect the document and its status before retrying.
Request
POST /api/office/v1/client-sessions/9169250d-5328-4d45-844b-9a37cb52f7ac/save
Authorization: Bearer tfoak-replace-with-your-key
X-Request-ID: save-example-001
| Field | Location | Type | Required | Meaning |
|---|---|---|---|---|
Authorization | header | string | Yes | Exact API Key that created the session |
clientSessionId | path | UUID | Yes | Session to save |
X-Request-ID | header | string | No; server-generated UUID by default | Correlation value, up to 64 characters; does not prevent duplicate saves |
This API has no request body or query parameters. Only Editor sessions may save. Developers must have received a successful OPEN. Requests must arrive before first open plus 12 hours; a successful close event ends availability immediately.
The creating API Key and storage must remain active. Both save and download apply the access conditions below. Save also returns HTTP 403 / 4031 DOCUMENT_SAVE_NOT_ALLOWED for Viewer documents. Common errors are 4001, 4010, 4041, 4042, 4043, 4094, 4101, 4102, 5023, 5031, and 5041; see the result code catalog.
Success response
Office confirmation returns HTTP 200 with this JSON body:
{
"success": true,
"code": 0,
"codeDescription": "SUCCESS",
"data": {
"clientSessionId": "9169250d-5328-4d45-844b-9a37cb52f7ac",
"documentLifecycleId": "0d102ee8-cbdd-4667-a5cf-f2e3a1007927",
"saved": true
}
}
| Field | Type | Required | Meaning |
|---|---|---|---|
data.clientSessionId | UUID | Yes | Session whose document was saved |
data.documentLifecycleId | UUID | Yes | Opaque ID for the document activity associated with this save |
data.saved | boolean | Yes on success | true after Office confirms completion |
The status API updates lastSavedAt and saveCount from a separate save event, not this response. HTTP 504/code 5041 means the save outcome could not be confirmed, not that saving definitely failed. Check the document and reported state before repeating the write.
Download the current document
GET /api/office/v1/client-sessions/{clientSessionId}/download
This API returns the current document file from Office. STORAGE and UPLOAD sessions, in Viewer or Editor, use the same route. Downloading does not overwrite the original storage file. Browser edits that have not reached Office are not guaranteed to be included.
Developers does not substitute an older file from the original storage.
Request
GET /api/office/v1/client-sessions/9169250d-5328-4d45-844b-9a37cb52f7ac/download
Authorization: Bearer tfoak-replace-with-your-key
| Field | Location | Type | Required / omission behavior | Meaning |
|---|---|---|---|---|
Authorization | Header | string | Required; missing or invalid: 4010 | Exact API Key that created the session |
clientSessionId | Path | UUID string | Required; malformed: 4001 | Session whose open document is downloaded |
X-Request-ID | Header | string | Optional; generated when missing, blank, or longer than 64 characters | Correlates this download request |
There is no request body or query. The creating API Key and storage must remain active.
Document-operation access
After authenticating the creating API Key, Developers checks close status, the deadline, and successful opening in that order. If no successful open has been reported, the deadline is creation plus 12 hours. These checks apply to both save and download.
| Request time | Result |
|---|---|
| No successful open reported, less than 12 hours after creation | HTTP 409 / 4094 DOCUMENT_NOT_OPEN |
| No successful open or close reported, at least 12 hours after creation | HTTP 410 / 4101 CLIENT_SESSION_EXPIRED |
| After open, before close and first open plus 12 hours | Requests the operation from Office; an unavailable or closed Office connection returns an error |
| After successful close is reported | HTTP 410 / 4102 DOCUMENT_CLOSED |
| No close reported, but 12 hours have passed since first open | HTTP 410 / 4101 CLIENT_SESSION_EXPIRED |
Success response
A successful response contains unchanged file bytes and these headers, without character encoding conversion. Access deadlines are checked when Developers examines the request.
| Field | Type | Required | Meaning |
|---|---|---|---|
| Body | binary | Yes | Current document file returned by Office |
Content-Type | header string | Yes | application/octet-stream |
Content-Disposition | header string | Yes | Attachment with a UTF-8 filename |
Content-Length | header integer | When the file size is known | File size in bytes; clients must also support responses without this header |
Cache-Control | header string | Yes | no-store |
X-Thinkfree-Success | header string | Yes | true |
X-Thinkfree-Code | header string | Yes | 0 |
X-Thinkfree-Code-Description | header string | Yes | SUCCESS |
X-Request-ID | header string | Yes | Request correlation value |
Downloads have no separate file-size limit for documents that Office has opened successfully. The session availability conditions above still apply.
Errors detected before file transmission return the common JSON envelope instead of a file. If transmission is interrupted after it starts, the connection fails; discard the incomplete file. HTTP 200 and success headers alone do not confirm that the entire file arrived. Download uses the common errors listed under save; 4031 applies only to save. Office connection or file errors can return 4042 or 5023. 5041 applies only to save. Save and download do not deduct additional Credits.
File response example
The body contains raw binary, not the literal <document bytes> marker below. Content-Length contains the actual byte count.
HTTP/1.1 200 OK
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="customer-proposal.docx"; filename*=UTF-8''customer-proposal.docx
Content-Length: <actual byte length>
Cache-Control: no-store
X-Thinkfree-Success: true
X-Thinkfree-Code: 0
X-Thinkfree-Code-Description: SUCCESS
X-Request-ID: download-example-001
<document bytes>
Save, then download
These commands target a document already open in Editor. Replace YOUR_CLIENT_SESSION_ID and the API Key. Confirm HTTP 200, success: true, and data.saved: true from the first command before running the second. A failed save or missing response is not a successful save.
curl --fail-with-body -X POST \
-H "Authorization: Bearer tfoak-replace-with-your-key" \
https://api.thinkfree.com/api/office/v1/client-sessions/YOUR_CLIENT_SESSION_ID/save
curl --fail \
-H "Authorization: Bearer tfoak-replace-with-your-key" \
--dump-header download-headers.txt \
--output customer-proposal.docx \
https://api.thinkfree.com/api/office/v1/client-sessions/YOUR_CLIENT_SESSION_ID/download
Check the download HTTP status, Content-Type, and Content-Disposition. A successful response writes the document bytes to customer-proposal.docx. Do not treat an error JSON body as an Office file. To inspect an error, examine the response body instead of saving it as a document.
Result code catalog
Use numeric code to choose how your application handles a result; codeDescription is its stable readable name.
| HTTP | Numeric code | Code description | Meaning |
|---|---|---|---|
| 200/201 | 0 | SUCCESS | Request completed successfully |
| 400 | 4001 | INVALID_DOCUMENT_REQUEST | Required value, format, path, type, or client-session UUID is invalid |
| 401 | 4010 | INVALID_API_KEY | Key is missing, malformed, unknown, expired, or revoked |
| 402 | 4020 | INSUFFICIENT_CREDIT | Available Credits and enabled overage cannot cover the requested document open |
| 402 | 4021 | SUBSCRIPTION_ACCESS_UNAVAILABLE | The account cannot use this operation with its current subscription state |
| 404 | 4041 | STORAGE_CONNECTION_NOT_FOUND | Connection is missing, inactive, or owned by another account |
| 404 | 4042 | DOCUMENT_NOT_FOUND | Office cannot find the open document. Check that the document is still open before saving or downloading. |
| 404 | 4043 | CLIENT_SESSION_NOT_FOUND | Session is missing or was created with a different API Key |
| 410 | 4101 | CLIENT_SESSION_EXPIRED | Status or document-operation access window has ended |
| 415 | 4150 | UNSUPPORTED_MEDIA_TYPE | A browser client session creation request uses a Content-Type that the selected endpoint does not accept |
| 500 | 5001 | STORAGE_ADAPTER_LIST_FAILED | Connection summaries could not be loaded |
| 502 | 5021 | STORAGE_UNAVAILABLE | Storage provider could not be reached |
| 502 | 5022 | OFFICE_OPEN_URL_UNAVAILABLE | A short-lived Office viewer or editor URL could not be created |
| 403 | 4031 | DOCUMENT_SAVE_NOT_ALLOWED | Viewer sessions cannot save |
| 409 | 4094 | DOCUMENT_NOT_OPEN | No successful open reported |
| 410 | 4102 | DOCUMENT_CLOSED | A successful close was reported |
| 503 | 5031 | OFFICE_DOCUMENT_OPERATION_UNAVAILABLE | Save/download is temporarily unavailable |
| 502 | 5023 | OFFICE_DOCUMENT_OPERATION_FAILED | Office reported a failed save or could not return a valid document file |
| 504 | 5041 | DOCUMENT_SAVE_RESULT_UNKNOWN | Save outcome is not confirmed; do not assume failure |
The documented API responses also include X-Request-ID. Keep it for support correlation, but never attach API Keys, storage
credentials, editor URLs, or customer files to a support message.
Production checklist
- Use a separately revocable, preferably expiring API Key per application and environment.
- Require
data[].status=ACTIVEwhen selecting a storage connection. - Deliver the selected canonical
data.browser.openUrlonly to the intended browser. - For API save/download, confirm the result. Do not report completion without a confirmed success response or file.
- Branch on numeric
code, retainX-Request-ID, and never log credentials or bearer URLs. - For connected storage, enable versioning and test concurrent editing, save, timeout, and recovery with disposable files.
- Use
documentOpenedAtandclosedAtwith the status-access rules above to determine the query deadline. Keep it separate frombrowser.openUrlExpiresAt.
Read-only GET requests may use bounded exponential-backoff retries for transient failures. Do not blindly retry session creation; each successful request creates a separate browser client session.
X-Request-ID correlates requests; it is not an idempotency key and does not prevent duplicate session creation.