Skip to content

Guides

File inputs & retrieval

Mahvash offers several ways to bring files to a model. Learn what each file interface is for, how indexing and retrieval work, and how to choose the right path for direct inputs, reusable assets and searchable document collections.

Choose a file path

Mahvash has several file interfaces because they serve different integration jobs, not because every upload creates a separate kind of storage. Pick the first row that matches your goal:

NeedUseWhy
Give the model a file with one question or across a chatMahvash asset + asset_idsOne project-scoped UUID can be passed to any supported request.
Use an OpenAI-compatible SDK or a batch/v1/filesfile-... IDs and the direct wire format fit supported SDK methods.
Transfer a large file reliablyResumable upload sessionSend numbered, checksummed parts, then complete the upload.
Search a collection of documentsVector store + filesFiles are indexed before file_search can retrieve them.
Make retrieval available to a whole projectProject data sourceAttaches an indexed store to the project; it does not upload or index files.
  • Assets (/api/v1/chat/assets) are reusable project files identified by a UUID. Pass them to a request with asset_ids.
  • Files (/v1/files) are OpenAI-style file objects (file-...) for SDK compatibility, batches and vector stores. /api/v1/chat/files offers the same objects inside the product envelope.
  • Uploads (/api/v1/chat/uploads) split one large file into numbered, retryable parts.
  • Vector stores (/v1/vector_stores) index files so file_search can find relevant passages.
  • Project data sources make an indexed store part of a project's retrieval.

Give a model a file directly

When a user attaches a document or image to one question, the model should read it — not search it. Upload it as an asset once and reference it by UUID:

# Upload once. Keep the returned asset UUID in your own records.
curl https://api.mahvashai.ir/api/v1/chat/assets/upload \
  -H "Authorization: Bearer $MAHVASH_API_KEY" \
  -F "file=@./contract.pdf"

# Reuse it in any supported request of the same project
curl https://api.mahvashai.ir/v1/responses \
  -H "Authorization: Bearer $MAHVASH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "auto", "input": "List the termination clauses.", "asset_ids": ["<asset-uuid>"]}'
  • Assets must be ready and belong to the same project as the request.
  • A request may reference a limited number of assets (by default at most 10, with a combined size limit of 50 MiB). Duplicates are removed while keeping order.
  • If the selected model cannot read a file type, a project with managed tools enabled can have Mahvash extract the text or describe the image first. Scanned documents without a text layer are refused.

Note:Never send binary files as base64 inside JSON. Upload them with multipart/form-data and pass the resulting ID.

OpenAI-compatible files

/v1/files follows the OpenAI Files API, so SDK methods like files.create work unchanged. Each file has a purpose: user_data (the default) for general inputs, batch for batch input files, and other OpenAI values such as assistants or vision.

with open("handbook.pdf", "rb") as handle:
    uploaded = mahvash.files.create(file=handle, purpose="user_data")

print(uploaded.id)  # file-<uuid>

store = mahvash.vector_stores.create(name="Employee handbook")
mahvash.vector_stores.files.create(vector_store_id=store.id, file_id=uploaded.id)

Metadata (GET /v1/files/{id}) and content (GET /v1/files/{id}/content) are separate: the content endpoint returns the raw bytes with the stored MIME type, not JSON.

Large and unreliable uploads

For large files or unreliable networks, use a resumable upload session. You declare the file first, send it in numbered parts, then complete it:

# 1. Open a session for the whole file
curl https://api.mahvashai.ir/api/v1/chat/uploads \
  -H "Authorization: Bearer $MAHVASH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filename": "archive.pdf", "bytes": 10485760, "mime_type": "application/pdf", "purpose": "user_data"}'

# 2. Send numbered parts; each may be retried independently
curl -X PUT https://api.mahvashai.ir/api/v1/chat/uploads/upload-<uuid>/parts/1 \
  -H "Authorization: Bearer $MAHVASH_API_KEY" \
  -H "X-Part-SHA256: <lowercase-sha256-of-part-1>" \
  -F "data=@./archive.part1"

curl -X PUT https://api.mahvashai.ir/api/v1/chat/uploads/upload-<uuid>/parts/2 \
  -H "Authorization: Bearer $MAHVASH_API_KEY" \
  -H "X-Part-SHA256: <lowercase-sha256-of-part-2>" \
  -F "data=@./archive.part2"

# 3. Complete: parts 1..part_count must add up to the declared bytes
curl https://api.mahvashai.ir/api/v1/chat/uploads/upload-<uuid>/complete \
  -H "Authorization: Bearer $MAHVASH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"part_count": 2}'
  • Parts are numbered from 1, may be uploaded in any order, and can be retried or replaced until completion. Send each part's SHA-256 in X-Part-SHA256 so corruption is detected.
  • On completion, parts 1..part_count must be contiguous and add up exactly to the declared bytes. The result is a normal file object.
  • A session expires after about an hour by default. Cancel sessions you abandon.

How retrieval works

Retrieval answers questions over collections that are too large to send with every request. It has three separate steps, and it helps to keep them apart:

  1. 1Upload a file — it is now stored, but not searchable.
  2. 2Index it by attaching it to a vector store. Mahvash extracts the text, splits it into chunks, and builds a searchable index. The vector store file moves from in_progress to completed (or failed).
  3. 3Search it: a file_search tool in a Responses request retrieves the most relevant chunks and gives them to the model, which answers with citations.
# Create a store in the project that will query it
curl https://api.mahvashai.ir/v1/vector_stores \
  -H "Authorization: Bearer $MAHVASH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Support policies"}'

# Attach an uploaded file; indexing starts now
curl https://api.mahvashai.ir/v1/vector_stores/vs_<uuid>/files \
  -H "Authorization: Bearer $MAHVASH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"file_id": "file-<uuid>"}'

# Poll until "status" is "completed" (or handle "failed")
curl https://api.mahvashai.ir/v1/vector_stores/vs_<uuid>/files/file-<uuid> \
  -H "Authorization: Bearer $MAHVASH_API_KEY"

A store only answers from files whose indexing has completed. Querying a store whose files are not ready fails clearly instead of answering from partial data.

Scope, placement and lifecycle

  • Project scope. Every file, asset and store belongs to one project. A foreign or inaccessible ID answers 404. A file_search can only name stores your organization owns.
  • Placement. A vector store's retrieval_placement decides where its index lives: local keeps documents in Mahvash's own index, hosted indexes them through a provider account. The default resolves to local, and a project can set a different default for new stores.
  • Deletion is explicit. Detaching a data source stops project retrieval; removing a file from a store deletes its index entries but not the file; deleting the file is a separate call. Plan cleanup according to your retention policy.
  • Downloads are yours to protect. Content you download from Mahvash should be served to your users only through your own access checks.