External files

External files are files and folders in your OneDrive, SharePoint, or Google Drive. Access them through a project and your personal provider connection. They remain separate from project source and uploads stored in Veryfront.

The REST, GraphQL, and MCP references list operation fields. GraphQL uses camelCase names, such as folderId, pageInfo, and contentEncoding.

Access

Every call needs two grants:

  • Project access: Your Veryfront credential must allow the operation in the project.
    • Read: Needs project.integrations.read.
    • Create, update, move, create folder, and delete: Need project.integrations.connect. An API key also needs the delete scope to delete.
    • Import: Needs project.uploads.write and upload edit access to the destination.
  • Personal connection: You must connect your own provider account. A connection that another project member made doesn't apply to your calls.

GraphQL and the MCP get_external_file tool accept user credentials only. REST and the other MCP tools also accept agent, run, and service-account credentials when the acting user has a personal connection.

Providers and IDs

The provider value is onedrive, sharepoint, or drive (Google Drive). REST routes start with /projects/{project_reference}/external-files/{provider}.

Item and folder IDs are opaque. Use the id that a listing returns:

  • OneDrive and Google Drive: The provider item ID, or root for the drive root.
  • SharePoint: The root lists the sites you can reach. A site has the ID sp-site:{siteId}, and items inside it use {siteId}|{itemId}.

Each item has a kind of file or folder.

List returns one folder as a page with data and page_info. Pass folder_id to open a folder, or omit it for the provider root. Pass page_info.next as cursor to get the next page.

A cursor works only with the provider, folder, and query that returned it.

Surfacelimit rangeDefault
REST1 to 10020
GraphQL and MCP1 to 200The provider's page size

Add query to search. With folder_id, OneDrive and SharePoint search the folder and its subfolders. Google Drive searches only the items directly inside the folder.

Without folder_id, OneDrive and Google Drive search the whole drive. SharePoint needs a site or folder ID to search.

Read content

A read returns the whole file or an error, never partial content. content_encoding is utf8 for text MIME types with no charset or with UTF-8 or ASCII. Other files use base64, including UTF-16 text. Decode using the returned content_encoding.

Content over 100,000 characters returns limit_exceeded with reason content_too_large. Files over 50 MiB return limit_exceeded with reason file_too_large. Import large files into the project instead.

Create and update

Create adds a new file and never replaces one. OneDrive and SharePoint return conflict when the folder already holds a file with that name. Google Drive allows duplicate names.

Update replaces a file's content. Send the file's etag as If-Match on REST, ifMatch on GraphQL, or if_match on MCP. The write returns conflict when the file changed since you read it.

OneDrive and SharePoint check the etag in the write itself. Google Drive checks it in a separate read before the write, so the write can still overwrite a change made in between.

Set content_encoding to utf8 or base64. It defaults to utf8, except on GraphQL updateExternalFile, which defaults to base64.

Create, create folder, and import accept an idempotency key. A retry with the same key and input within 24 hours returns the first result instead of a second item.

Move changes an item's folder, its name, or both. SharePoint items move only within their site.

Import into the project

Import copies one external file into project Uploads. The upload then follows the Projects API rules for uploads. Import doesn't index the file for knowledge retrieval.

SurfaceDestination without a folderTimestamp prefix default
REST and GraphQLThe Uploads rootfalse
MCP import_external_fileexternal-importstrue without a folder

Set folder_path (GraphQL folderPath) to choose a folder inside Uploads. The upload inherits the folder's visibility unless you set visibility. Veryfront exports Google Docs and Slides as PDF, and Sheets as XLSX.

A full storage quota returns limit_exceeded with reason storage_quota_exceeded. An existing upload at the destination returns conflict.

Delete

Delete removes one file or folder, including the folder's contents. The result status says what the provider did:

  • trashed: OneDrive and SharePoint moved the item to the recycle bin.
  • deleted: Google Drive deleted the item permanently. It skips the Drive trash, so you can't restore it.

A Google Drive folder delete also permanently deletes the items in it that you own. It leaves items that other users own.

MCP confirmation

update_external_file and delete_external_file require confirm: true. confirm: false refuses the call without changes.

Errors

All names in the operation table return the same stable codes. REST returns them as a Problem with code and, where a code has more than one cause, reason.

MCP returns the same members under the same names in the error condition. GraphQL returns them in extensions.code and extensions.reason.

CodeMeaningWhat to do
not_readyReason provider_connection_required: your connection is missing or expired. REST uses HTTP 428.Connect or reconnect at the connect URL, then retry.
limit_exceededReason provider_rate_limited, or a delay in retry_after_seconds on REST and MCP or extensions.retryAfterSeconds on GraphQL: the provider rate-limited the call, or another import is busy. REST uses HTTP 429.Wait for that delay when it is present (REST also sends Retry-After). Without it, back off exponentially. Then retry.
limit_exceededAny other case, such as file_too_large, storage_quota_exceeded, or a plan limit.Don't retry. Change the request.
conflictA name clash, a stale etag, or an idempotency key conflict.For a name clash, pick another name or destination. For a stale etag, read the item again. For a key conflict, see Idempotency conflicts.
not_foundThe item or project doesn't exist or you can't access it.Check the ID, your role, and your API key scopes.
forbiddenThe provider refuses the action on the item, or an import lacks upload edit access to the destination or the upload admin access that visibility needs. MCP and the other GraphQL fields also use it when your role or API key scope doesn't allow the operation.Don't retry. Get the access, or choose another item or destination.
forbiddenReason personal_connection_required: GraphQL or the MCP get_external_file tool got agent, run, or service-account credentials.Call with user credentials.
invalid_inputThe request is invalid, including a cursor from another listing.Fix the request.
unauthenticatedThe request has no valid credentials. REST uses HTTP 401.Sign in or send a valid API key.
internalReason provider_unavailable: the provider didn't answer. REST uses HTTP 503.Back off, then retry.
internalNo reason: the server failed. REST uses HTTP 500.Don't retry automatically. Report the error if it persists.

The connect URL is connect_url on REST and MCP, and extensions.connection.connectUrl on GraphQL.

REST, GraphQL externalFileContent, and GraphQL createExternalFile return not_found, not forbidden, when your project role or API key scope doesn't allow the operation.

Idempotency conflicts

A conflict for an idempotency key carries idempotency.state:

  • in_progress: The first request is still running. Retry with the same key and input after the delay in idempotency.retry_after_seconds on REST, or idempotency.retryAfterSeconds on GraphQL and MCP.
  • payload_mismatch: Another request used the key with different input. Use a new key for the new input.
  • outcome_unknown: Veryfront can't tell whether the first request changed anything. Check the destination before you retry, using idempotency.recovery when it is present. A new key can create a second item.

Operation names

OperationRESTGraphQLMCP
List or searchGET .../external-files/{provider}externalFileslist_external_files
Get metadataGET .../external-files/{provider}/{file_id}externalFileget_external_file
Read contentGET .../external-files/{provider}/{file_id}/contentexternalFileContentread_external_file_content
Create filePOST .../external-files/{provider}createExternalFilecreate_external_file
Update filePUT .../external-files/{provider}/{file_id}updateExternalFileupdate_external_file
Move or renamePOST .../external-files/{provider}/{file_id}/movemoveExternalFilemove_external_file
DeleteDELETE .../external-files/{provider}/{file_id}deleteExternalFiledelete_external_file
Create folderPOST .../external-files/{provider}/folderscreateExternalFoldercreate_external_folder
ImportPOST .../external-files/{provider}/{file_id}/importimportExternalFileimport_external_file

Deprecated names

These names still work but keep their old errors. Move to the names above:

  • REST /providers/{provider}/... routes: Use the /projects/{project_reference}/external-files/{provider} routes.
  • search_external_files and searchExternalFiles: Use list with query.
  • read_external_file and readExternalFile: Use read content. The old names cut content at the size limit.
  • write_external_file and uploadExternalFile: Use create or update. The old names can overwrite an existing OneDrive or SharePoint file.