Storage Upload API
POST /v1/storage/uploads
Creates a temporary S3 upload URL.
Authentication: optional for public image uploads.
Request body:
purposestring, required:profile_photoortrip_coverfilenamestring, requiredcontent_typestring, requiredcontent_lengthinteger, optionalparent_typestring, optional fortrip_cover:tripparent_idinteger, required wheneverparent_typeis sent
Defaults:
profile_photoandtrip_coverdefault topublic.
Validation:
profile_photomust not sendparent_typeorparent_id.trip_covermay omitparent_typeandparent_id.- If a
trip_coverparent is provided, it must useparent_type="trip"andparent_id.
Permissions:
profile_photo: no authentication required.trip_cover: no authentication required.
Behavior
The API returns a presigned S3 PUT URL. The client uploads bytes directly to S3 using upload_url and must send the exact headers returned by this endpoint.
Do not send Tripsy auth headers to S3.
Profile photos and trip cover images are stored in public image storage. Use public_url when updating photo_url or cover_image_url.
Profile photo example
curl -X POST "https://api.tripsy.app/v1/storage/uploads" \
-H "Content-Type: application/json" \
-d '{
"purpose": "profile_photo",
"filename": "avatar.jpg",
"content_type": "image/jpeg"
}'
{
"upload_url": "https://storage.example.com/upload/...",
"method": "PUT",
"headers": {
"Content-Type": "image/jpeg",
"x-amz-acl": "public-read"
},
"object_key": "2a9f6b3ea63a4f0d8cb8fba0abed9d2b2a9f6b3ea63a4f0d8cb8fba0abed9d2b2a9f6b3ea63a4f0d8cb8fba0abed9d2b2a9f6b3ea63a4f0d8cb8fba0abed9d2b.jpg",
"bucket": "PUBLIC_PROFILE_IMAGES_BUCKET",
"purpose": "profile_photo",
"visibility": "public",
"expires_at": "2026-04-22T13:15:00Z",
"public_url": "https://cdn.example.com/profile-images/2a9f6b3ea63a4f0d8cb8fba0abed9d2b.jpg"
}
Client migration flow
- Call
POST /v1/storage/uploads. - Upload bytes to
upload_url. - For
profile_photo, callPATCH /v1/meand sendphoto_url=public_url. - For
trip_cover, callPATCH /v1/trips/{id}and sendcover_image_url=public_url.
Public image uploads may happen before the user or trip exists. Attaching the returned public_url is the step that still requires the normal authenticated update API.