Upload di file
Alcune operazioni API non ricevono direttamente il file binario nella chiamata principale. In questi casi il flusso corretto è sempre in tre passaggi:
- caricare prima il file con l'endpoint dedicato
POST /api/v3/uploads; - leggere l'
upload_idrestituito in risposta; - usare quell'ID nella richiesta successiva, nel campo che rappresenta il documento da allegare.
In pratica, il file viene caricato una sola volta e poi richiamato tramite il suo identificativo numerico.
Oggi questo flusso si usa per i documenti delle richieste di cambio intestatario PEC, che usano i campi contract_upload_id, identity_document_upload_id e order_module_upload_id per riferirsi ai documenti già caricati.
Come funziona il flusso
Quando una chiamata richiede un documento, non devi inserire il contenuto del file dentro il JSON della richiesta finale. Devi invece:
- caricare il file con l'endpoint di upload;
- conservare l'ID restituito;
- passare quell'ID nel campo previsto dalla chiamata applicativa.
Questo approccio ha due vantaggi:
- separa il caricamento del file dalla logica della richiesta principale;
- permette all'API di trattare i documenti come risorse già registrate, identificate in modo univoco.
1. Caricare il file
Il primo passaggio è chiamare POST /api/v3/uploads, che richiede lo scope upload:write.
La richiesta è in formato multipart/form-data, con il file nel campo file. Il file deve rispettare questi limiti:
- dimensione massima di 5 MB;
- estensione tra
pdf,p7m,jpg,jpeg,png,txt,doc,docx,xlsexlsx; - contenuto coerente con l'estensione: ad esempio, un file
.pdfdeve essere davvero un PDF.
Un file che non rispetta questi limiti viene rifiutato con 400 Bad Request.
Esempio
L'esempio seguente invia un file all'endpoint dedicato e ottiene in risposta il suo identificativo.
curl --request POST \
--url 'https://api.shellrent.com/api/v3/uploads' \
--header 'Authorization: Bearer <ACCESS_TOKEN>' \
--form '[email protected]'
Esempio di risposta
Se il caricamento va a buon fine, la risposta è 201 Created:
{
"error": 0,
"message": null,
"data": {
"upload_id": 987654,
"mimetype": "application/pdf",
"filename": "8f1f0e5d7c2a4b3e.pdf",
"original_filename": "modulo-ordine.pdf",
"file_extension": "pdf",
"upload_date": "2026-10-19T08:30:00Z"
},
"meta": null
}
In questa risposta:
upload_idè l'identificativo da usare nelle chiamate successive;filenameè il nome con cui il file è stato salvato;original_filenameè il nome del file che hai inviato;mimetypeefile_extensiondescrivono il tipo di file;upload_dateè la data e ora del caricamento, in UTC.
Il valore davvero importante, per i passaggi successivi, è upload_id.
2. Usare l'ID del file in una richiesta successiva
Dopo l'upload, il file non va più reinviato. Nella chiamata applicativa devi passare il suo ID numerico.
Esempio: cambio intestatario di una casella PEC
La richiesta di cambio intestatario di una casella PEC, POST /api/v3/pec-mailboxes/{pec_id}/owner-changes, richiede lo scope pec:write e tre documenti:
contract_upload_id: il contratto;identity_document_upload_id: il documento d'identità;order_module_upload_id: il modulo d'ordine.
Insieme ai documenti si indica, con owner_id, il profilo del nuovo intestatario.
Dopo aver caricato i tre file con POST /api/v3/uploads, la richiesta ha questa forma:
curl --request POST \
--url 'https://api.shellrent.com/api/v3/pec-mailboxes/12345/owner-changes' \
--header 'Authorization: Bearer <ACCESS_TOKEN>' \
--header 'Content-Type: application/json' \
--data '{
"owner_id": 321,
"contract_upload_id": 987654,
"identity_document_upload_id": 987655,
"order_module_upload_id": 987656
}'
In questo esempio:
- i file sono già stati caricati in precedenza;
987654,987655e987656sono gli ID restituiti daPOST /api/v3/uploads;- la richiesta finale passa solo quegli ID, non il contenuto dei file.
Lo stesso schema vale per il cambio intestatario di un dominio PEC, con POST /api/v3/pec-domains/{pec_domain_id}/owner-changes.
Gli ID devono riferirsi a file caricati dal tuo account, con qualsiasi client: un ID inesistente o di un altro account viene rifiutato con 400 Bad Request, con un messaggio che indica il campo non valido.
Esempio con gli SDK
Con l'SDK PHP:
use Shellrent\Sdk\Model\PecMailboxOwnerChangeCreateRequest;
$upload = function (string $path) use ($client): int {
return $client->account()->uploadFile(new \SplFileObject($path))->getData()->getUploadId();
};
$ownerChange = $client->pec()->createPecMailboxOwnerChange(12345, new PecMailboxOwnerChangeCreateRequest([
'owner_id' => 321,
'contract_upload_id' => $upload('contratto.pdf'),
'identity_document_upload_id' => $upload('documento-identita.pdf'),
'order_module_upload_id' => $upload('modulo-ordine.pdf'),
]));
Con l'SDK Python:
from pathlib import Path
from shellrent_sdk import unwrap
from shellrent_sdk.client.api.account import upload_file
from shellrent_sdk.client.api.pec import create_pec_mailbox_owner_change
from shellrent_sdk.client.models import PecMailboxOwnerChangeCreateRequest, UploadFileBody
from shellrent_sdk.client.types import File
def upload(path: str) -> int:
with Path(path).open("rb") as payload:
body = UploadFileBody(file=File(payload=payload, file_name=Path(path).name))
return unwrap(upload_file.sync_detailed(client=client, body=body)).data.upload_id
owner_change = unwrap(create_pec_mailbox_owner_change.sync_detailed(
12345,
client=client,
body=PecMailboxOwnerChangeCreateRequest(
owner_id=321,
contract_upload_id=upload("contratto.pdf"),
identity_document_upload_id=upload("documento-identita.pdf"),
order_module_upload_id=upload("modulo-ordine.pdf"),
),
))
Buone pratiche
Per evitare errori, è consigliabile:
- verificare dimensione ed estensione dei file prima di caricarli;
- completare prima tutti gli upload necessari;
- salvare gli
upload_idrestituiti; - usare nomi file chiari, così da riconoscere più facilmente i documenti caricati;
- verificare sempre di associare il file corretto al campo corretto della richiesta finale.
In sintesi
Quando una API richiede un documento:
- carica prima il file con
POST /api/v3/uploads, con lo scopeupload:write; - recupera l'
upload_iddalla risposta; - usa quell'ID nella chiamata successiva.
È questo il pattern da seguire ogni volta che un endpoint richiede un file tramite un campo dedicato come *_upload_id.