> ISPO SDK documentation. [HTML](https://ispo.ai/docs/documents/Publish_a_file.html) · [Documentation index](https://ispo.ai/docs/llms.txt)

# <a id="publish-a-file"></a>Publish a file

Use this bundle when an app needs to put an artifact in the user's Files library. The host-managed bootstrap already connects the SDK.

## <a id="methods-and-authority"></a>Methods and authority

Use [files.publish](../interfaces/core.FilesApi.md#publish), then [files.list](../interfaces/core.FilesApi.md#list) to verify the receipt. Both use the reviewed `files.publish` request token and the standing `files.publish` capability. Merge this fragment into the existing project descriptor, then complete the host's access review:

```
{ "requests": { "files": ["publish"] } }
```

## <a id="checked-example"></a>Checked example

Call this action from the app's explicit Export action and display the returned receipt only after success.

```
import { files } from '@ispo/sdk'export async function exportNotes(text: string) {  return files.publish({    name: 'notes.md',    mimeType: 'text/markdown',    content: text,  })}
```

## <a id="effects-and-recovery"></a>Effects and recovery

Publication creates a durable Files entry. A repeated call can create another entry; this API has no caller idempotency key. On a timeout or uncertain outcome, inspect the project's Files entries before offering a deliberate retry. Do not equate a timeout with rollback or cancellation. Denial is a normal error state; let the host handle access review.

## <a id="choosing-a-destination"></a>Choosing a destination

```
const picked = await files.pick({ accept: ['image/'], multiple: false })const saved = await files.save({ content: reportBytes, name: 'report.pdf' })
```

`files.pick` and `files.save` use the host powerbox. Their protected requested set still applies, but there is no Gate-2 standing library grant: the user's selection is object-scoped consent. The project never receives the inventory. Cancel resolves `null`; it is not a permission failure. The SDK supplies a bounded interactive timeout, currently 90 seconds by default. Save may create **one** user-named folder under an existing Files parent as part of that same consent confirm; cancel writes neither the folder nor the file. Projects still cannot invent folders outside the powerbox.

A pick returns only the selected object as a private copy or controlled reference. Editing it forks by default.

_Included from the installed project-agent guidance: [data-and-authority.md](http://data-and-authority.md), “Pick and Save”._

## <a id="verify"></a>Verify

Run the project's typecheck and wait for a fresh host build. Export once, confirm that the returned public ID appears in `files.list()`, and open the artifact in Files. Exercise denial and picker cancellation without showing a false success. Store the public ID, not a device-local controlled URL.
