# S3 Presign Responses

For client uploads, return a presigned object URL and any headers that were part
of the signature.

```ts
type PresignedUrlResponse = {
    key: string
    uploadUrl: string
    uploadHeaders?: Record<string, string>
    publicUrl?: string
    downloadUrl?: string
    expiresIn: number
}
```

Do not return browser-forbidden headers such as `Content-Length` in
`uploadHeaders`: the browser sets them itself and ignores a script-set value.
Signing `Content-Length` is fine as long as it equals the file size, which is
how `@useupup/server` limits an upload to the size it approved. If the content
type is signed, return it in `uploadHeaders` so upup can send the exact same
value. [Upload Files to S3 from React with Presigned URLs](/docs/guides/s3-presigned-url-upload-react/)
builds a complete endpoint.

```ts
return Response.json({
    key,
    uploadUrl,
    uploadHeaders: {
        'Content-Type': body.type || 'application/octet-stream',
    },
    downloadUrl,
    expiresIn: 3600,
})
```

Use `@useupup/server` when you want the server package to host these routes.
