Hand the API a file for one purpose, then pass its id as file_id (or the field an operation names) to what uses it: a brand document, a toll-free number's opt-in evidence, a 10DLC campaign's screenshot, a library image, the logo. Three ways in, one per call: a public https url (fetched once, no redirects, no private addresses); base64 data with content_type (small files: a request over ~6 MB is refused); or an upload session, for a local file: send content_type and size_bytes without url or data, then PUT the bytes to upload.url with upload.headers within 15 minutes (curl -T file -H "Content-Type: image/png" "<upload.url>"). The bytes are checked by their contents against the purpose (sms_opt_in_evidence: PNG up to 400 KB; sms_document: PDF, PNG or JPEG up to 3 MB; image: PNG, JPEG, GIF or WebP up to 5 MB), never by the label. Files are private, never served back, and expire 24 hours after they're made: what uses one keeps its own copy. Send an Idempotency-Key so a retry makes one file. Requires the sms:manage or templates:write or branding:write capability.
Parameters1 field
Field
Type
Description
Idempotency-Key
string · header
Any unique string (1–256 characters, e.g. a UUID). Retrying with the same key and the same body within 24 hours returns the first result instead of sending again; the same key with a different body is `409 invalid_idempotent_request`, and one still in flight is `409 concurrent_idempotent_requests`.
Request body6 fields
Field
Type
Description
purposerequired
enumsms_opt_in_evidence | sms_document | image
What the file is for, which sets what it may be: `sms_opt_in_evidence` (PNG, up to 400 KB), `sms_document` (PDF, PNG or JPEG, up to 3 MB), `image` (PNG, JPEG, GIF or WebP, up to 5 MB). The bytes decide the type, never the name or the label.
url
string
A public https address to fetch the file from (no redirects, no private addresses, 12 seconds). One of `url`, `data`, or neither (an upload session).
data
string
The bytes, base64 (no `data:` prefix), with `content_type`. A request over ~6 MB is refused before it arrives, so this fits about 4 MB; agents should prefer `url` or an upload session for anything but small files.
Required with `data` and for an upload session (it is signed into the PUT); refused with `url`.
size_bytes
integer
An upload session only: the exact size of the file you'll PUT, in bytes (signed into the PUT). Within the purpose's maximum.
filename
string
A name for the file (shown on what uses it). Defaults to the URL's last path part, or `file.<ext>`.
Response · 201 fields12 fields
Field
Type
Description
objectrequired
string
—
idrequired
string
—
purposerequired
enumsms_opt_in_evidence | sms_document | image
What the file is for: `sms_opt_in_evidence` (PNG, up to 400 KB), `sms_document` (PDF, PNG or JPEG, up to 3 MB), `image` (PNG, JPEG, GIF or WebP, up to 5 MB).
statusrequired
enumawaiting_upload | ready | failed
`ready`: checked and usable by `file_id`. `awaiting_upload`: an upload session whose bytes haven't been PUT yet (reading the file checks again). `failed`: the uploaded bytes were refused (`failure_reason` says why).
filenamerequired
string
—
content_typerequired
string
The type the file's bytes carry (checked by their contents), or, before an upload session's bytes arrive, the type declared.
size_bytesrequired
integer
—
sha256required
string | null
The hex SHA-256 of the bytes once `ready`.
failure_reasonrequired
string | null
—
uploadrequired
object | null
An upload session's PUT, in the create response only (null otherwise).
created_atrequired
string
—
expires_atrequired
string
The file is deleted at this time, 24 hours after it was created, whether or not it was used. An operation that used it keeps its own copy.