# Bundle upload URL

> A presigned URL to stage a pushed bundle. Tar the directory, PUT it, then validate or publish with the returned key.

Source: https://docs.generalinput.com/api/workflows/bundle-upload-url



<Endpoint method="POST" path="/v1/workflows/:id/bundle-upload-url" />

<Access scope="workflows:manage" />

Push. Nothing changes on the workflow until you [validate](/api/workflows/validate) or [publish](/api/workflows/publish) the staged key.

## Response [#response]

```json
{
  "uploadUrl": "https://storage.example/…?X-Amz-Signature=…",
  "bundleKey": "workflows/wf_01HX…/cli-staging/8f3c2b14-90de-4a67-b512-c8093e7a61df.tar.gz",
  "contentType": "application/gzip"
}
```

`PUT` the archive to `uploadUrl` with `Content-Type` set to exactly `contentType`; the signature covers it. Pass `bundleKey` back verbatim: validate and publish reject any key outside the workflow's own staging prefix.

## Example [#example]

```sh
RESP=$(curl -s -X POST "https://cloud.generalinput.com/v1/workflows/wf_01HX/bundle-upload-url" \
  -H "Authorization: Bearer $GI_API_KEY")
tar -czf bundle.tar.gz -C ./digest .
curl -s -X PUT "$(jq -r .uploadUrl <<<"$RESP")" \
  -H "Content-Type: application/gzip" --data-binary @bundle.tar.gz
BUNDLE_KEY=$(jq -r .bundleKey <<<"$RESP")
```

Leave out anything that is not part of the bundle (`node_modules`, `.git`, the `.geni-resource.json` marker).
