# Negotiate a direct upload

Source: https://www.jawsdeploy.net/rest-api/package-store-negotiate-upload | Section: Package Store

Request a pre-authorized direct-to-storage upload URL for a package.

`POST /api/packagestore/package/negotiate`

Starts a **direct upload**: for a workspace whose package store is in a region, the server returns a short-lived, write-only URL that points straight at that region's blob storage, so your CI uploads the bytes without routing them through the Jaws web app. For every other workspace the server returns mode `legacy`, and you fall back to the classic [multipart upload](https://www.jawsdeploy.net/rest-api/package-store-upload).

A direct upload is three plain HTTPS calls, no SDK required:

1. `POST /api/packagestore/package/negotiate` (this endpoint) with the workspace and file name. If the response `mode` is `direct`, take the returned `uploadUrl`.
2. `PUT` the raw file bytes to that `uploadUrl`, adding the header `x-ms-blob-type: BlockBlob` (the one Azure-ism). The blob lands in a private pending/quarantine path and is not part of the feed yet.
3. `POST /api/packagestore/package/confirm` to validate and promote it - see [Confirm a direct upload](https://www.jawsdeploy.net/rest-api/package-store-confirm-upload).

The upload URL is scoped to a single blob, is write-only, and expires after 4 hours. It is never logged or stored. Nothing is downloadable until you call confirm.

## Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `WorkspaceId` | body | string | yes | ID of the destination workspace. |
| `FileName` | body | string | yes | Package file name including ID, version and extension, e.g. `Acme.Web.2.5.3.zip`. |

## Errors

| Status | Meaning |
|---|---|
| 400 | Invalid `WorkspaceId`, or a `FileName` that doesn't match the `<PackageId>.<Version>.<ext>` pattern. |
| 401 | Missing or invalid Basic auth credentials, or the service account lacks permission to push packages to this workspace. |

Example request:

```
POST /api/packagestore/package/negotiate HTTP/1.1
Authorization: Basic <base64(...)>
Content-Type: application/json

{
  "WorkspaceId": "ws_abc",
  "FileName": "Acme.Web.2.5.3.zip"
}
```

Example response:

```
// mode "direct" - upload straight to regional storage
{
  "mode": "direct",
  "uploadUrl": "https://jawsfeedsau.blob.core.windows.net/pending/...&sig=..."
}

// mode "legacy" - use the multipart upload endpoint instead
{
  "mode": "legacy"
}
```

