media_url field.POST /api/v1/medias/direct_uploads to get a direct upload URL, headers, and a signed_id.direct_upload.url, including the returned direct_upload.headers. This upload goes directly to Peach storage, not back to the Peach API.POST /api/v1/medias/finalize with the signed_id to attach the blob into Peach's media library.media_url (media://...) in subsequent API calls.{
"id": 101,
"key": "1/abc123def456",
"filename": "sample.png",
"content_type": "image/png",
"metadata": {
"source": "api",
"peach_media_direct_upload": true,
"account_id": 1
},
"byte_size": 128349,
"checksum": "I+Sf6zGPGY+9Fh0ymkvwow==",
"created_at": "2026-04-22T10:00:00.000Z",
"signed_id": "eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBdz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--example",
"direct_upload": {
"url": "https://storage.example.com/upload",
"headers": {
"Content-Type": "image/png"
}
}
}direct_upload.url and direct_upload.headers from the previous response.direct_upload.headers contains additional headers, include them exactly as returned.{
"id": 55,
"filename": "sample.png",
"content_type": "image/png",
"signed_id": "eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBdz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--example",
"media_url": "media://101",
"created_at": "2026-04-22T10:00:05.000Z"
}{
"message": "Unauthorized"
}{
"status": "failed",
"reason": {
"blob": {
"byte_size": [
"is too large (max 5242880 bytes for image/png)"
]
}
}
}{
"status": "failed",
"reason": {
"blob": {
"content_type": [
"is not supported. Supported values: image/jpeg, image/png, video/mp4, video/3gpp, application/pdf, text/plain, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.presentation, audio/mp4, audio/mpeg, audio/amr, audio/ogg, audio/aac"
]
}
}
}{
"status": "failed",
"reason": {
"blob": {
"content_type": [
"is blank"
]
}
}
}POST /api/v1/medias still works for backward compatibility, but it is deprecated and should not be used for new integrations. It uploads base64 data through the app servers and is less performant.{
"id": 55,
"filename": "sample.png",
"content_type": "image/png",
"signed_id": "eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBdz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--example",
"media_url": "media://101",
"created_at": "2026-04-22T10:00:05.000Z"
}content_type is required for direct uploads..jpeg file should use image/jpeg.