---
title: "Work with files"
description: "Choose the right file workflow, upload files safely, share revocable links, and attach stable file IDs to your Inttegro resources."
canonical: "https://studio.inttegro.com/guides/work-with-files"
format: inttegro-machine-docs/v1
language: "Python"
sdk_version: "v12.0.0"
reader_profile: optional
reader_manifest: "https://studio.inttegro.com/machine/python/readers/index.json"
reader_identification: "Optional: declare your client only if known and your current-session capabilities; use reader_manifest for supplemental recommendations."
preamble_estimated_tokens: 520
model_token_report: "https://studio.inttegro.com/machine/token-report.json"
preamble_questions: 5
preamble_source: "curated"
recommended_mcp_tools: ["get_integration_guide","check_integration_readiness","create_file_link"]
estimated_tokens: 3276
token_estimate_method: "utf8_bytes_divided_by_4"
---

## Machine preamble

**Summary:** Choose server upload, delegated upload request, or revocable file link by who holds the bytes and who needs access; retain the returned file ID.

### Five questions

#### Q1. Who should upload the bytes?

If your backend has them, use [Upload a file](https://studio.inttegro.com/machine/python/api/files.md#upload-a-file). If a customer or supplier holds them, create a purpose-bound [upload request](https://studio.inttegro.com/machine/python/api/file-uploads.md#create-an-upload-request); do not hand them your server API key.

#### Q2. What should resources store after upload?

Store the stable file ID, not a raw third-party storage URL. For product media, follow [Create or update a product](https://studio.inttegro.com/machine/python/api/products.md) with the returned ID.

#### Q3. When is a file link appropriate?

Use a revocable [file link](https://studio.inttegro.com/machine/python/api/file-links.md#create-a-file-link) for supported public product image or video access. For downloads, imports, or support documents, use authenticated [file content delivery](https://studio.inttegro.com/machine/python/api/files.md#download-file-contents).

#### Q4. Does a delegated upload request mean a file already exists?

No. It authorizes one upload; wait for its resulting file record before attaching an ID or assuming the bytes are available. The [upload-request reference](https://studio.inttegro.com/machine/python/api/file-uploads.md) defines its lifecycle and constraints.

#### Q5. Which file operations can MCP perform?

With an authenticated connection and confirmation, [upload_file](https://studio.inttegro.com/machine/python/inttegro-mcp/tools.md#upload_file) accepts canonical base64 content up to 5 MiB, while [create_file_link](https://studio.inttegro.com/machine/python/inttegro-mcp/tools.md#create_file_link) creates an expiring bearer URL for a supported file purpose. The catalog does not expose delegated upload-request creation; use its [API reference](https://studio.inttegro.com/machine/python/api/file-uploads.md).

## Document content

# Work with files

Files in Inttegro are durable assets with stable `file_...` IDs. Instead of scattering raw storage URLs across your products and support flows, you upload bytes once, keep the returned file ID, and let Inttegro control access, sharing, and lifecycle. This guide shows you when to upload directly, when to delegate uploads, how to share files safely, and which file-specific failures you should plan for.

> Mcp Guide Callout is interactive content. Use the canonical page to view it.

## Prerequisites

- A file purpose chosen before upload:
  - `'product_download'`
    for downloadable product assets.
  - `'product_image'`
    for product images.
  - `'product_video'`
    for product videos.
  - `'products_import'`
    for product-catalog CSV imports with the required import schema and no more
    than 10,000 data rows.
  - `'support_document'`
    for support attachments and evidence.
- A plan for where the resulting file ID will live. Product media should store returned file IDs via [Create a product](https://studio.inttegro.com/machine/python/api/products.md#create-a-product) or [Update a product](https://studio.inttegro.com/machine/python/api/products.md#update-a-product), not raw third-party URLs.

## Choose the right workflow

| Need                                                              | Use                                                                | Why                                                                   |
| ----------------------------------------------------------------- | ------------------------------------------------------------------ | --------------------------------------------------------------------- |
| Your backend already has the bytes                                | [Upload a file](https://studio.inttegro.com/machine/python/api/files.md#upload-a-file)                              | Multipart upload from your server.                                    |
| A customer, supplier, or reviewer should send the file themselves | [Create an upload request](https://studio.inttegro.com/machine/python/api/file-uploads.md#create-an-upload-request) | Inttegro returns a purpose-bound upload URL for one delegated upload. |
| You need revocable public access to a stored file                 | [Create a file link](https://studio.inttegro.com/machine/python/api/file-links.md#create-a-file-link)               | Inttegro gives you a time-boxed or access-limited public URL.         |

Use [Download file contents](https://studio.inttegro.com/machine/python/api/files.md#download-file-contents) when delivery should stay behind your own server. Stream delivery returns the bytes in the authenticated response; redirect delivery returns a short-lived download URL in the `Location` header. This is the right delivery path for `'product_download'`, `'products_import'`, and `'support_document'`, because file links only support `'product_image'` and `'product_video'`.

## Send bytes to Inttegro

Choose the upload path that matches who is actually holding the file.

### Server upload

Use direct upload when your backend already has the bytes—for example, when an internal admin tool uploads product artwork or when your own service is syncing downloadable assets.

**Upload from your server — POST /files/create**

```python
import os

from inttegro import InttegroClient

client = InttegroClient(api_key=os.environ["INTTEGRO_API_KEY"])

result = client.files.create(
    file="./hero.png",
    purpose="product_image",
    title="Hero image",
    custom_data={
    "product_ref": "SKU-12345",
  },
    idempotency_key="upload-hero-image-001",
)
```

Use [`custom_data`](https://python.inttegro.dev/v12.0.0/inttegro/upload_request.html#UploadRequest) for your own string key-value data. [`metadata`](https://python.inttegro.dev/v12.0.0/inttegro/upload_request.html#UploadRequest) is returned by the API and cannot be supplied.

The response gives you a stable [`file.id`](https://python.inttegro.dev/v12.0.0/inttegro/file.html#File). Store that ID on the Inttegro resource that needs the asset.

### Delegated upload

Use delegated upload when someone outside your backend should provide the file. Your server creates the request, then passes the returned [`upload_request.upload_url`](https://python.inttegro.dev/v12.0.0/inttegro/upload_request.html#UploadRequest) to the uploader.

**Create an upload request — POST /upload\_requests/create**

```python
import os
from datetime import datetime

import inttegro
from inttegro import InttegroClient

client = InttegroClient(api_key=os.environ["INTTEGRO_API_KEY"])

result = client.upload_requests.create(inttegro.upload_request.CreateRequest(
  purpose="support_document",
  constraints=inttegro.upload_request.ConstraintsInput(
    max_size=10485760,
    content_types=[
      "application/pdf",
    ],
    extensions=[
      ".pdf",
    ],
  ),
  display=inttegro.upload_request.DisplayInput(
    title="Upload proof of purchase",
    help_text="Attach the PDF receipt from your order confirmation.",
  ),
  recipient=inttegro.file.PartyInput(
    type=inttegro.chime.RecipientType.EMAIL,
    email="customer@example.com",
  ),
  resource=inttegro.file.ResourceInput(
    type="case",
    id="case_123",
  ),
  expires_at=datetime.fromisoformat("2030-06-06T12:30:00Z".replace("Z", "+00:00")),
))
```

The request expires after 24 hours unless you set a future [`expires_at`](https://python.inttegro.dev/v12.0.0/inttegro/upload_request.html#CreateRequest.expires_at), and permits three failed attempts unless you set [`attempts.max_attempts`](https://python.inttegro.dev/v12.0.0/inttegro/upload_request.html#AttemptsRequest.max_attempts). Size values must be nonnegative and remain within the selected purpose; MIME types, extensions, and an exact filename can only narrow that purpose. See [Create an upload request](https://studio.inttegro.com/machine/python/api/file-uploads.md#create-an-upload-request) for the complete validation rules.

Store the returned [`upload_request.upload_url`](https://python.inttegro.dev/v12.0.0/inttegro/upload_request.html#UploadRequest) securely and give it only to the uploader. It is returned once by create and is not returned by lookup, page, or cancel. Have the uploader send `multipart/form-data` directly to [Fulfill an upload request](https://studio.inttegro.com/machine/python/api/file-uploads.md#fulfill-an-upload-request).

## Share files safely

File links are for controlled public access. They work for `'product_image'` and `'product_video'`, and they let you set delivery behavior, expiry, and access limits.

The inline example keeps [`access.allow_download`](https://python.inttegro.dev/v12.0.0/inttegro/file_link.html#AccessRequest.allow_download) set to `True` because attachment disposition is valid only when downloads are allowed. File links expire after 24 hours by default, and [`access.max_accesses`](https://python.inttegro.dev/v12.0.0/inttegro/file_link.html#AccessRequest.max_accesses) set to `0` means unlimited successful opens.

**Create a public file link — POST /file\_links/create**

```python
import os
from datetime import datetime

import inttegro
from inttegro import InttegroClient

client = InttegroClient(api_key=os.environ["INTTEGRO_API_KEY"])

result = client.file_links.create(inttegro.file_link.CreateRequest(
  file_id="file_4q6YcQk1RzPv2mDa8nFw0sHu",
  delivery=inttegro.file_link.DeliveryInput(
    mode="inline",
  ),
  access=inttegro.file_link.AccessRequest(
    allow_download=True,
    max_accesses=25,
  ),
  expires_at=datetime.fromisoformat("2030-06-06T12:30:00Z".replace("Z", "+00:00")),
))
```

Give the returned top-level [`url`](https://python.inttegro.dev/v12.0.0/inttegro/file_link.html#Creation) to the consumer. They open that URL via [Open a file link](https://studio.inttegro.com/machine/python/api/file-links.md#open-a-file-link). If access should end early, revoke it with [Revoke a file link](https://studio.inttegro.com/machine/python/api/file-links.md#revoke-a-file-link).

## Attach file IDs to products

Treat Inttegro file IDs as the contract between your product catalog and stored media.

- Use `'product_image'` for hero images and galleries.
- Use `'product_video'` for product videos you may want to share publicly.
- Use `'product_download'` for downloadable assets delivered after purchase.
- Use `'products_import'` only for CSV product-catalog imports. The file must follow the required import schema, contain no more than 10,000 data rows, and stay within 32 MiB.

Store the returned file IDs on your product records through [Create a product](https://studio.inttegro.com/machine/python/api/products.md#create-a-product) or [Update a product](https://studio.inttegro.com/machine/python/api/products.md#update-a-product). Do not save temporary upload URLs, local filenames, or third-party CDN URLs as your source of truth. That breaks lifecycle controls, makes deletions harder, and bypasses the purpose validation you applied at upload time.

## Handle file-specific failures

File APIs return stable error codes. Use [Error Codes](https://studio.inttegro.com/machine/python/api/error-codes.md#file-apis) to decide whether to ask for a different file, retry later, refresh an expired public URL, or clean up the resource that still references the file.

## Related resources

- [Upload a file](https://studio.inttegro.com/machine/python/api/files.md#upload-a-file) - Multipart upload from your own backend.
- [Download file contents](https://studio.inttegro.com/machine/python/api/files.md#download-file-contents) - Server-side delivery for any stored file.
- [Create a file link](https://studio.inttegro.com/machine/python/api/file-links.md#create-a-file-link) - Revocable public access for linkable files.
- [Create an upload request](https://studio.inttegro.com/machine/python/api/file-uploads.md#create-an-upload-request) - Delegated upload for customers or external partners.
- [Update a product](https://studio.inttegro.com/machine/python/api/products.md#update-a-product) - Store returned file IDs on product records.
