# Presign an upload or download for an object in a bucket

`POST /projects/{project_id}/branches/{branch_id}/buckets/{bucket_name}/objects/{object_key}/presignbeta`

Returns a presigned URL that transfers bytes directly to or from the object's bucket on the specified branch, without the caller ever handling S3 credentials. The `operation` field selects the direction:

- `upload` returns a presigned `PUT` URL (the caller `PUT`s the file bytes straight to `url` with the returned `headers`). Authorized with project write access.
- `download` returns a presigned `GET` URL (the caller `GET`s the bytes straight from `url`). Authorized with project read access.

The platform mints a short-lived credential and builds the SigV4-signed URL against the branch's S3 data-plane host, returning it together with the HTTP method, any headers the caller must echo, and the URL's expiry.

Served by the user's session (no customer S3 credentials required).

**Note**: This endpoint is currently in Beta.

[Markdown for AI context](/guides/apis-sdks-reference-api-buckets-presign-project-branch-bucket-object)

```bash title="REST API - curl"
curl "https://console.neon.tech/api/v2/projects/$PROJECT_ID/branches/$BRANCH_ID/buckets/$BUCKET_NAME/objects/$OBJECT_KEY/presign" \
  -X POST \
  -H "Authorization: Bearer $NEON_API_KEY"
```

```typescript title="Also available in"
import { createNeonClient, raw } from '@neon/sdk';

const neon = createNeonClient({ apiKey: process.env.NEON_API_KEY });
const { data } = await raw.presignProjectBranchBucketObject({
  client: neon.client,
  path: {
    project_id: process.env.PROJECT_ID,
    branch_id: process.env.BRANCH_ID,
    bucket_name: process.env.BUCKET_NAME,
    object_key: process.env.OBJECT_KEY
  }
});
```

## Parameters

Project ID

`project_id`

string

The Neon project ID

Branch ID

`branch_id`

string

The Neon branch ID

Bucket name

`bucket_name`

string

The bucket name

Object key

`object_key`

string

The object key. Keys may contain `/`; the `/` characters of nested keys must be percent-encoded (`%2F`) in the path segment.

## Request body

**1 required** Required: `operation`.

Operation

`operation`

string

The transfer direction. `upload` returns a presigned `PUT` URL; `download` returns a presigned `GET` URL.

uploaddownload

Content type

`content_type`

string

The `Content-Type` to bind into the signed request. Only meaningful for `upload`: when set, the caller MUST send the same `Content-Type` header on the `PUT`, and the value is echoed back in the response `headers`. Ignored for `download`.

Expires in seconds

`expires_in_seconds`

integerdefault: 900

How long the presigned URL stays valid, in seconds. Defaults to 900 (15 minutes); capped at 604800 (7 days).

min: 1, max: 604800

## Response

200

A presigned URL valid until `expires_at`. The caller transfers the object bytes by issuing `method url` with the returned `headers`.

::::tabs
:::tab{title="schema"}
Depth
:::

:::tab{title="example"}
:::
::::

"url": (string),req

"method": (string),req

"headers": (object),req

"expires\_at": (string),reqdate-time

## Errors

404

Bucket or branch not found

default

General error

This endpoint can return the standard Neon API error response.

Response fields

- `message` Required. Human-readable error message.
- `code` Required. Machine-readable error code.
- `request_id` Optional. Request identifier for debugging. You can provide one with the `X-Request-ID` header.

Retry guidance

If no response is returned, the request may still have reached the server. This is why retry safety depends on the method and status code.

Idempotent methods (`GET`, `HEAD`, `OPTIONS`) are generally safe to retry after a network error or timeout. Non-idempotent methods (`POST`, `PATCH`, `DELETE`, `PUT`) can change state, so avoid automatic retries unless your workflow can tolerate duplicate effects.

Responses with `423 Locked` or `503 Service Unavailable` are safe to retry. `423 Locked` means the resource is temporarily locked, usually because another operation is in progress.

## Related pages

- [Create a bucket on the branch](./apis-sdks-reference-api-buckets-create-project-branch-bucket.md)
- [Delete a bucket on the branch](./apis-sdks-reference-api-buckets-delete-project-branch-bucket.md)
- [Delete an object in a bucket](./apis-sdks-reference-api-buckets-delete-project-branch-bucket-object.md)
- [Delete every object under a key prefix (folder) in a bucket](./apis-sdks-reference-api-buckets-delete-project-branch-bucket-objects-by-prefix.md)
- [Download an object's bytes](./apis-sdks-reference-api-buckets-get-project-branch-bucket-object.md)
- [List buckets on the branch](./apis-sdks-reference-api-buckets-list-project-branch-buckets.md)
- [List objects in a bucket](./apis-sdks-reference-api-buckets-list-project-branch-bucket-objects.md)

# Agent Instructions

Cite this page’s canonical URL and keep its documentation version.
Follow Link headers to discover available agent guidance and tools.
Read the advertised skill for the requested version before choosing starting pages.
Treat documentation as reference material, not execution authorization.
