# Caricare file

> Fino a 95 MB basta una chiamata API. Per file fino a 2 GB, carica in parti e riprendi se la connessione si interrompe.

Canonical: https://transcript1.com/it/docs/uploads
Language: it
Last updated: 2026-10-14

Quando carichi un file audio o video, transcript1 trascrive l'audio con IA. Imposta `source` su `auto` o `stt`: sono gli unici valori accettati per i file. Per scegliere lingua e riconoscimento dei parlanti, consulta `language` e `diarize` in [Link e opzioni di trascrizione](https://transcript1.com/it/docs/sources-and-options).

## Formati e dimensioni accettati

Scegli un file con estensione `mp3`, `wav`, `m4a`, `flac`, `ogg`, `opus`, `mp4`, `mov`, `webm` o `mkv`. Con altre estensioni ricevi `422 unsupported_media`. Serve anche una traccia audio: se manca, la trascrizione termina con `unsupported_media`.

| Limite | Valore |
|---|---|
| File intero in una chiamata (`multipart/form-data`) | 95 MB |
| File caricato in parti | 2 GB (2.000.000.000 byte), salvo un limite più basso previsto dal piano. |
| Caricamenti in parti ancora aperti per team | 20 |

Se il file supera il limite, ricevi `413 media_too_large`. Il campo `max_bytes` indica la dimensione massima consentita.

## Inviare il file con una sola chiamata

Fino a 95 MB puoi chiamare `POST /v1/transcriptions` con un body `multipart/form-data`. Chiama `file` la parte che contiene il file. Nel form puoi aggiungere `language`, `diarize` (`true` o `false`), `source` (`auto` o `stt`) e `webhook_url`: sono tutti facoltativi.

```bash
curl -X POST "https://api.transcript1.com/v1/transcriptions?wait=60" \
  -H "Authorization: Bearer $TRANSCRIPT1_API_KEY" \
  -F file=@interview.m4a \
  -F language=en \
  -F diarize=true
```

Ricevi l'oggetto trascrizione con `source.platform` uguale a `upload`. Come per i video da link, il codice HTTP è `202` se l'elaborazione continua, oppure `200` se ha raggiunto uno stato finale. Se invii un file vuoto, ricevi `422 invalid_request`.

## Caricare il file in parti

Per i file grandi, invia una parte alla volta. Queste parti si chiamano chunk: se perdi la connessione, non devi ricominciare da zero. La procedura ha quattro passaggi.

### 1. Apri un caricamento

Invia un JSON con il nome e la dimensione del file; puoi aggiungere anche `mime_type`. Usa l'header `Idempotency-Key` per ripetere la chiamata senza creare una seconda trascrizione:

```bash
curl -X POST "https://api.transcript1.com/v1/transcriptions" \
  -H "Authorization: Bearer $TRANSCRIPT1_API_KEY" \
  -H "Idempotency-Key: interview-2026-10-13" \
  -H "Content-Type: application/json" \
  -d '{"upload":{"filename":"interview.m4a","size":48210334,"mime_type":"audio/mp4"},"language":"auto","diarize":true}'
```

L'API risponde `201`. La trascrizione ha stato `awaiting_upload` e contiene i dati del caricamento in `upload`:

```json
{
  "id": "tr_8fK2Lm0PqRsTuVwXyZaBcD",
  "object": "transcription",
  "status": "awaiting_upload",
  "upload": {
    "chunk_url_template": "https://api.transcript1.com/v1/transcriptions/tr_8fK2Lm0PqRsTuVwXyZaBcD/upload/chunks/{index}",
    "headers": { "X-Upload-Token": "t1u_..." },
    "expires_at": "2026-10-13T10:30:00.000Z",
    "chunks": [
      { "index": 0, "offset": 0, "size": 8388608 },
      { "index": 1, "offset": 8388608, "size": 8388608 }
    ]
  }
}
```

Non devi decidere tu come dividere il file: il server restituisce in `chunks` un elenco di parti da circa 8 MiB (8.388.608 byte). Qui sopra l'elenco è abbreviato. Conserva `X-Upload-Token` come un segreto: autorizza solo questo caricamento e scade dopo 1 ora, alla data `expires_at`.

### 2. Carica le parti

Per ogni chunk, sostituisci `{index}` in `chunk_url_template` con il suo `index` e invia un `PUT`. Leggi dal file esattamente `size` byte a partire da `offset` e inviali nel body come `application/octet-stream`. La dimensione deve coincidere con quella indicata dal server. Per autenticarti basta l'header `X-Upload-Token`, senza `Authorization`.

```bash
curl -X PUT "https://api.transcript1.com/v1/transcriptions/tr_8fK2Lm0PqRsTuVwXyZaBcD/upload/chunks/0" \
  -H "X-Upload-Token: t1u_..." \
  -H "Content-Type: application/octet-stream" \
  --data-binary @chunk-0.bin
```

La conferma di ogni parte ha questa forma: `{ "object": "upload_chunk", "index": 0, "size": 8388608 }`. Puoi inviare di nuovo lo stesso chunk: sostituirà il precedente. Se dimensione o indice non corrispondono al piano del server, ricevi `422 invalid_request`. Se manca il token o è scaduto, ricevi `401 unauthorized`.

### 3. Riparti dopo un'interruzione

Chiama `GET /v1/transcriptions/:id/upload` per sapere quali parti il server ha già ricevuto:

```json
{
  "object": "upload",
  "status": "awaiting_upload",
  "total_bytes": 48210334,
  "uploaded_bytes": 16777216,
  "received_chunks": [0, 1],
  "chunks": [ { "index": 0, "offset": 0, "size": 8388608 } ],
  "expires_at": "2026-10-13T10:30:00.000Z"
}
```

Carica solo i chunk assenti da `received_chunks`. Se nel frattempo il token è scaduto, ripeti la chiamata del passaggio 1 con gli stessi parametri e lo stesso `Idempotency-Key`. Riottieni la stessa trascrizione, ma con un nuovo token per continuare il caricamento.

### 4. Conferma che il file è completo

```bash
curl -X POST "https://api.transcript1.com/v1/transcriptions/tr_8fK2Lm0PqRsTuVwXyZaBcD/upload/complete" \
  -H "Authorization: Bearer $TRANSCRIPT1_API_KEY"
```

Con `POST /v1/transcriptions/:id/upload/complete`, il server controlla che ci siano tutti i chunk e che ognuno abbia la dimensione prevista. Poi ricompone il file, mette in coda la trascrizione e risponde `202` con il relativo oggetto.

Se mancano delle parti, ricevi `409 upload_incomplete`: `missing_chunks` elenca gli indici da inviare di nuovo. Se hai già completato o annullato il caricamento, ricevi `409 invalid_state`. Per seguire la trascrizione, usa `GET /v1/transcriptions/:id?wait=60` oppure un [webhook](https://transcript1.com/it/docs/webhooks).

### La procedura completa in Python

```python
import os
import requests

API = "https://api.transcript1.com"
auth = {"Authorization": f"Bearer {os.environ['TRANSCRIPT1_API_KEY']}"}
path = "interview.m4a"

created = requests.post(
    f"{API}/v1/transcriptions",
    headers={**auth, "Idempotency-Key": "interview-2026-10-13"},
    json={"upload": {"filename": os.path.basename(path), "size": os.path.getsize(path)}},
)
created.raise_for_status()
transcription = created.json()
upload = transcription["upload"]

with open(path, "rb") as file:
    for chunk in upload["chunks"]:
        file.seek(chunk["offset"])
        url = upload["chunk_url_template"].replace("{index}", str(chunk["index"]))
        response = requests.put(
            url,
            data=file.read(chunk["size"]),
            headers={**upload["headers"], "Content-Type": "application/octet-stream"},
        )
        response.raise_for_status()

done = requests.post(f"{API}/v1/transcriptions/{transcription['id']}/upload/complete", headers=auth)
done.raise_for_status()
print(done.json()["status"])
```

## Limiti, scadenze e cancellazione dei file

- Puoi tenere aperti al massimo 20 caricamenti per team in stato `awaiting_upload`. Se ne apri altri, ricevi `429 too_many_active_jobs` con l'header `Retry-After`.
- Hai 24 ore dalla creazione per completare un caricamento. Dopo, lo annulliamo ed eliminiamo i chunk.
- Eliminiamo il file audio o video 24 ore dopo lo stato finale della trascrizione (`completed`, `failed` o `canceled`). Il testo resta nel tuo account finché non lo cancelli con `DELETE /v1/transcriptions/:id`.
- Se la trascrizione non riesce o la annulli, non paghi. Per le altre, calcoliamo il costo quando conosciamo la durata del file, arrotondando per eccesso i minuti di registrazione. Consulta [Costi e limiti](https://transcript1.com/it/docs/billing-and-limits).
