> ## Documentation Index
> Fetch the complete documentation index at: https://docs.artosai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# npm SDK File Loading

> Open templates, documents, source files, and OnlyOffice resources with the Artos npm SDK.

# npm SDK File Loading

Once you have a resource ID, `openFile` is the one method to remember. Tell it
which viewer you are using and it will return the matching data:

```javascript theme={null}
import { openFile } from '@artosai/sdk'

const result = await openFile({
    resourceId,
    accessToken,
    baseUrl,
    viewer: 'apryse' // or 'onlyoffice'
})
```

Here are the two possible responses:

```typescript theme={null}
// viewer: 'apryse'
{
    viewer: 'apryse',
    blob: Blob,
    contentType: string,
    fileName: string | null,
    resourceId: string,
    sourceFileUrl?: string
}

// viewer: 'onlyoffice'
{
    viewer: 'onlyoffice',
    config: object | null,
    token: string | null,
    resourceId: string,
    _raw: object
}
```

The two responses are deliberately different. The Apryse response has the
file bytes; the OnlyOffice response has the editor inputs. Check
`result.viewer` before reading the viewer-specific fields.

## Open the returned file

`openFile` retrieves and authorizes the resource, but it does not create a
viewer component. After an Apryse call, hand the returned `Blob` to Apryse or
create a temporary browser URL:

```javascript theme={null}
const result = await openFile({
    resourceId,
    viewer: 'apryse',
    accessToken,
    baseUrl
})

if (result.viewer !== 'apryse') {
    throw new Error('Expected an Apryse file response')
}

// Apryse WebViewer example:
import WebViewer from '@pdftron/webviewer'

const viewerElement = document.getElementById('apryse-viewer')
const instance = await WebViewer({ path: '/webviewer' }, viewerElement)
await instance.UI.loadDocument(result.blob, {
    filename: result.fileName || 'document'
})
```

For a quick browser preview, use an object URL:

```javascript theme={null}
const previewUrl = URL.createObjectURL(result.blob)
window.open(previewUrl, '_blank')

// Revoke it when the preview is closed or replaced—not immediately after
// window.open(), because the new page may not have loaded the Blob yet.
```

To use OnlyOffice, load its editor API script and add an editor container:

```html theme={null}
<div id="onlyoffice-editor"></div>
<script src="https://YOUR-ONLYOFFICE-HOST/web-apps/apps/api/documents/api.js"></script>
```

Then pass the returned editor inputs to the OnlyOffice editor—not the Blob
fields:

```javascript theme={null}
const result = await openFile({
    resourceId,
    viewer: 'onlyoffice',
    mode: 'edit',
    accessToken,
    baseUrl
})

if (result.viewer !== 'onlyoffice') {
    throw new Error('Expected an OnlyOffice response')
}

// The OnlyOffice API script must already be loaded and this element must exist:
// <div id="onlyoffice-editor"></div>
const editor = new DocsAPI.DocEditor('onlyoffice-editor', {
    ...result.config,
    token: result.token
})
```

The viewer libraries are still part of your application. The SDK supplies the
authorized file or editor configuration; Apryse and OnlyOffice render it.

## Documents

For a regular document preview or download, use the document ID as the
resource ID:

```javascript theme={null}
const result = await openFile({
    resourceId: documentId,
    viewer: 'apryse',
    accessToken,
    baseUrl
})

if (result.viewer === 'apryse') {
    const previewUrl = URL.createObjectURL(result.blob)
    // Pass previewUrl to your viewer, then revoke it when replaced.
}
```

## Templates

Templates work the same way, but you first ask Artos for the template resource
ID:

```javascript theme={null}
import { getTemplateResource, openFile } from '@artosai/sdk'

const template = await getTemplateResource({
    documentId,
    accessToken,
    baseUrl
})

if (!template.templateResourceId) {
    throw new Error('This document has no template file')
}

const result = await openFile({
    resourceId: template.templateResourceId,
    viewer: 'apryse',
    accessToken,
    baseUrl
})
```

## Source files

Source files need one extra lookup. Resolve the source reference to a resource
ID, then pass that ID to `openFile`:

```javascript theme={null}
import {
    getDocumentSources,
    getDocumentSourceResource,
    getSectionFromText,
    openFile
} from '@artosai/sdk'

const section = await getSectionFromText({
    documentId,
    highlightedText,
    accessToken,
    baseUrl
})

const { sources } = await getDocumentSources({
    documentId,
    sectionId: section.sectionId,
    accessToken,
    baseUrl
})

if (sources.length === 0 || !sources[0].documentSourceId) {
    throw new Error('No source file was found for this section')
}

const source = await getDocumentSourceResource({
    documentSourceId: sources[0].documentSourceId,
    accessToken,
    baseUrl
})

const result = await openFile({
    resourceId: source.resourceId,
    viewer: 'apryse',
    accessToken,
    baseUrl
})
```

For `sourcefile-...` resources, `openFile` uses authenticated `POST
/source-file`. Documents, templates, and generated outputs use the
document-session flow. In both cases, you pass the resource ID; you do not
construct an S3 URL or append a session token.

## OnlyOffice

To open a resource in OnlyOffice, use the same method with
`viewer: 'onlyoffice'`:

```javascript theme={null}
const result = await openFile({
    resourceId,
    viewer: 'onlyoffice',
    mode: 'edit', // or 'readonly'
    accessToken,
    baseUrl
})

if (result.viewer === 'onlyoffice') {
    new DocsAPI.DocEditor('onlyoffice-editor', {
        ...result.config,
        token: result.token
    })
}
```

`edit` requests an editable editor. `readonly` disables editing and saving.
Source files, templates, generated outputs, and duplicate outputs may be
forced read-only by the backend regardless of the requested mode.

For editable documents, OnlyOffice sends saves through the callback in the
generated config. Keep `config` and `token` from the same response, leave the
config unchanged, and request a new result when reopening an expired editor
session.
