SPB Git forge

spb/doc-api

Public
2commits 1branches 0releases
15.7 MBsize
maindefault branch
14 days agolast push
Python 88.3% TypeScript 7.6% Shell 4.1%
5.2 KB

# Gemini Files API — upload protocol, files.*, files:register, generatedFiles

Status: DOCUMENTED + LIVE_VERIFIED (resumable, multipart and raw uploads; get/list/delete; register of a public GCS object; generatedFiles list; 2026-09-18). Sources: https://ai.google.dev/api/files · https://ai.google.dev/gemini-api/docs/generate-content/files · https://ai.google.dev/gemini-api/docs/generate-content/file-input-methods · discovery media.upload (mediaUpload.protocols), File, RegisterFilesRequest Machine-readable: generated/fragments/parameters/gemini-files.json, generated/fragments/endpoints/gemini-core.json (files/media/generatedFiles), generated/fragments/objects/gemini-core-objects.json#File Last verified: 2026-09-18

# 1. Limits and lifetime

Value
Per file 2 GB (mediaUpload.maxSize 2147483648)
Per project 20 GB
Retention 48 h (expirationTime = create + 48 h observed), then auto-deleted
Cost free, all regions
Download user uploads cannot be downloaded (metadata only); generated files via downloadUri
When to use total request > 20 MB (image/audio guides) / > 100 MB (file-input-methods; PDFs > 50 MB), or reuse across requests

# 2. Resumable upload — step by step (verified)

Step 1 — start session (POST https://generativelanguage.googleapis.com/upload/v1beta/files, JSON metadata):

text
x-goog-api-key: <key>
X-Goog-Upload-Protocol: resumable
X-Goog-Upload-Command: start
X-Goog-Upload-Header-Content-Length: 200
X-Goog-Upload-Header-Content-Type: text/plain
Content-Type: application/json

{"file": {"display_name": "atlas-probe.txt"}}

→ 200, empty body, response headers: X-Goog-Upload-URL: https://generativelanguage.googleapis.com/upload/v1beta/files?upload_id=…&upload_protocol=resumable, X-Goog-Upload-Control-URL, X-Goog-Upload-Status: active, X-Goog-Upload-Chunk-Granularity: 8388608 (8 MiB).

Step 2 — send bytes (POST <X-Goog-Upload-URL>):

text
Content-Length: 200
X-Goog-Upload-Offset: 0
X-Goog-Upload-Command: upload, finalize
<raw bytes>

→ 200 {"file": {...}} + X-Goog-Upload-Status: final. For chunked uploads send X-Goog-Upload-Command: upload per chunk (offsets multiple of the granularity) and finalize last; query/cancel go to the control URL. The upload URL contains the session id, not your API key — but still keep it out of logs.

Alternatives (verified): POST /upload/v1beta/files?uploadType=multipart with Content-Type: multipart/related; boundary=… (part 1 application/json metadata, part 2 the media) → 200; POST /upload/v1beta/files?uploadType=media with raw bytes and the media Content-Type → 200 (no display name).

# 3. File object

json
{"name": "files/w7x6n2hlpxrq", "displayName": "atlas-probe.txt", "mimeType": "text/plain", "sizeBytes": "174",
 "createTime": "…", "updateTime": "…", "expirationTime": "2026-09-21T03:46:49.478571266Z",
 "sha256Hash": "ZmVhNTIx…", "uri": "https://generativelanguage.googleapis.com/v1beta/files/w7x6n2hlpxrq",
 "state": "ACTIVE", "source": "UPLOADED"}

state ∈ PROCESSING | ACTIVE | FAILED (+ error: Status) — poll files.get until ACTIVE for video/audio (tiny txt/PDF were ACTIVE immediately). source ∈ UPLOADED | GENERATED | REGISTERED. videoMetadata.videoDuration for videos. Custom ids: file.name = "files/<id>", ≤ 40 chars [a-z0-9-], no leading/trailing dash. sha256Hash is base64 of the hex digest string.

# 4. Other methods

Method Result (live)
GET /v1beta/files?pageSize=&pageToken= {"files": [...], "nextPageToken"?}; also /v1/files
GET /v1beta/files/{id} File; unknown or deleted → 403 PERMISSION_DENIED You do not have permission to access the File <id> or it may not exist. (never 404)
DELETE /v1beta/files/{id} {}; later fileData use → 403
POST /v1beta/files:register {"uris": ["gs://bucket/object"]} registers GCS objects without copying; live with the public gs://cloud-samples-data/generative-ai/image/scones.jpg → {"files": [{"name": "files/…", "displayName": "<id>", "mimeType": "image/jpeg", "sizeBytes": "394671", "uri": "…", "source": "REGISTERED"}]} (no state/expirationTime; docs: valid up to 30 days, 2 GB/file, no storage cap). One failure fails the whole request.
GET /v1beta/generatedFiles?pageSize= {} (none); items `{name: generatedFiles/…, mimeType, state: GENERATING

# 5. Using a file

json
{"contents": [{"role": "user", "parts": [{"text": "What is the secret word?"}, {"fileData": {"fileUri": "<File.uri>", "mimeType": "text/plain"}}]}]}

mimeType optional (taken from the File). Verified: txt → PELICAN; 1-page PDF → ATLAS (536 prompt tokens: IMAGE 520 + TEXT 16; countTokens reports the same page as DOCUMENT 560).

# 6. SDK

Python client.files.upload(file=path|io, config=types.UploadFileConfig(mime_type=, display_name=, name=)), client.files.get(name=), .list(), .delete(name=); Node ai.files.upload({file, config:{mimeType, displayName}}), ai.files.get/list/delete. SDKs implement the resumable protocol. Examples: examples/gemini/files/ (curl script does the two-step protocol by hand).