Upload logo URL
Obtain a pre-signed S3 URL to upload an organization logo directly from the browser or client.
POST /api/app/branding/logo
Returns a short-lived pre-signed S3 PUT URL and the public CDN URL the logo will be accessible at once uploaded. The actual file upload goes directly from your client to S3 — it does not pass through the Recomly API.
After uploading the file to S3, call Update branding with the returned logoUrl and logoKey to persist the logo against your organization.
Requires the customBranding feature entitlement.
Request
See API Basics for required headers.
Body
| Field | Type | Required | Description |
|---|---|---|---|
contentType | "image/png" | "image/jpeg" | "image/gif" | Yes | MIME type of the logo file you will upload. |
Upload flow
This endpoint is step one of a three-step flow:
- Call this endpoint with the
contentTypeof your file. - PUT the file to
uploadUrldirectly from your client. IncludeContent-Type: <contentType>as a header. No auth header — the URL is self-authenticating. - Call Update branding with
logoUrlandlogoKeyfrom the response to save the logo against your organization.
If your organization already has a saved logo, calling this endpoint automatically removes the old S3 object. You must still complete step 3 — until then, the old logoUrl remains in your branding record.
The pre-signed URL expires after 5 minutes. Complete the S3 PUT upload before then. If the URL has expired, call this endpoint again to get a fresh one.
Sample request
curl -X POST https://api.recomly.com/api/app/branding/logo \
-H "Authorization: Bearer rk_live_abc123:def456" \
-H "Content-Type: application/json" \
-d '{ "contentType": "image/png" }'Sample response
Status: 200 OK
{
"uploadUrl": "https://recomly-uploads-prod.s3.amazonaws.com/logos/a1b2c3d4-0000-4000-8000-e5f6a7b8c9d0/1744051800000-550e8400-e29b-41d4-a716-446655440000.png?X-Amz-Algorithm=...&X-Amz-Expires=300&...",
"publicUrl": "https://app.recomly.com/logos/a1b2c3d4-0000-4000-8000-e5f6a7b8c9d0/1744051800000-550e8400-e29b-41d4-a716-446655440000.png",
"key": "logos/a1b2c3d4-0000-4000-8000-e5f6a7b8c9d0/1744051800000-550e8400-e29b-41d4-a716-446655440000.png"
}Response fields
| Field | Type | Description |
|---|---|---|
uploadUrl | string | Pre-signed S3 PUT URL. PUT your logo file to this URL. Expires in 5 minutes. |
publicUrl | string | The CDN URL the logo will be accessible at once uploaded. Pass this to the Update branding endpoint as logoUrl. |
key | string | Internal S3 object key. Pass this to the Update branding endpoint as logoKey. |
Uploading the file to S3
# Step 2 — PUT the file directly to the pre-signed URL (no auth header)
curl -X PUT "<uploadUrl>" \
-H "Content-Type: image/png" \
--data-binary @logo.pngA successful upload returns HTTP 200 with an empty body. Any non-200 response means the upload failed — check that the URL has not expired and that the Content-Type header matches the value you passed in step 1.
Error responses
See API Basics for standard status codes and error response format.
| Status | When |
|---|---|
400 Bad Request | contentType is missing or not one of the allowed MIME types. |
403 Forbidden | Caller does not have the admin role, or the customBranding feature is not enabled for this organization. |

