Documentation menu

Upload endpoints - request a signed URL, PUT the archive, complete the upload, then create an application from it.

Uploads

Deploying without a repository takes three calls and one PUT. The archive goes straight to storage over a signed URL, so it never passes through the API.

  1. POST /api/upload/request-url — get a signed URL and an uploadId
  2. PUT the zip to that URL
  3. POST /api/upload/complete — tell the platform the bytes landed
  4. POST /api/applications/create-from-upload — build and deploy it

Tip

Zip the contents of the project directory, not the directory itself. A single top-level folder inside the archive puts every path one level deeper than the build expects.

Request an upload URL#

POST/api/upload/request-url

Reserves an upload and returns a signed URL valid for 15 minutes. maxSize is 100 MB by default; passing a larger fileSize is rejected before you waste the transfer.

permission
create:projects

Parameters

fileNamestringdefault source.zip
Name recorded for the archive
contentTypestringdefault application/zip
Must match the Content-Type you PUT with
fileSizenumberoptional
Bytes. Checked against maxSize up front
targetOrganisationIdstringsession only
Required when using a session token
curl -X POST https://api.light-cloud.com/api/upload/request-url \
  -H "Authorization: Bearer $LIGHT_CLOUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"fileSize\": $(wc -c < source.zip)}"
200ResponseSigned URL and upload id
{
  "uploadId": "upl_8Xa1",
  "signedUrl": "https://storage.googleapis.com/lc-uploads/...",
  "gcsPath": "uploads/org_1Ab/upl_8Xa1/source.zip",
  "expiresAt": "2026-08-28T07:15:00.000Z",
  "maxSize": 104857600
}

Upload the archive#

The PUT goes to the signed URL, not to the API. No Authorization header — the signature is the authorisation. The Content-Type must match what you asked for, or the signature will not verify.

curl -X PUT "$SIGNED_URL" \
  -H "Content-Type: application/zip" \
  --upload-file source.zip

Complete the upload#

POST/api/upload/complete

Confirms the bytes landed and records what the archive is. The detection fields are hints carried through to the create call — leave them out and the platform inspects the archive itself.

permission
create:projects

Parameters

uploadIdstringrequired
From request-url
detectedFrameworkstringoptional
What you believe this is
detectedRuntimestringoptional
Container only
detectedDeploymentTypestringoptional
static or container
detectedBuildCommandstringoptional
Command that produces the build
detectedOutputDirectorystringoptional
Static only
targetOrganisationIdstringsession only
Required when using a session token
curl -X POST https://api.light-cloud.com/api/upload/complete \
  -H "Authorization: Bearer $LIGHT_CLOUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"uploadId": "upl_8Xa1", "detectedDeploymentType": "static"}'
200ResponseUpload ready to build from
{
  "uploadId": "upl_8Xa1",
  "status": "ready",
  "size": 4823910
}

Clean up abandoned uploads#

POST/api/upload/cleanup

Discards uploads that were reserved but never completed.

permission
create:projects

Parameters

targetOrganisationIdstringsession only
Required when using a session token
curl -X POST https://api.light-cloud.com/api/upload/cleanup \
  -H "Authorization: Bearer $LIGHT_CLOUD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
200ResponseHow many were discarded
{ "removed": 3 }

The whole flow#

#!/usr/bin/env bash
set -euo pipefail

API=https://api.light-cloud.com
AUTH=(-H "Authorization: Bearer $LIGHT_CLOUD_API_KEY" -H "Content-Type: application/json")

(cd dist && zip -qr ../source.zip .)

upload=$(curl -sS -X POST "$API/api/upload/request-url" "${AUTH[@]}" \
  -d "{\"fileSize\":$(wc -c < source.zip)}")

UPLOAD_ID=$(echo "$upload" | jq -r .uploadId)
SIGNED_URL=$(echo "$upload" | jq -r .signedUrl)

curl -sS -X PUT "$SIGNED_URL" \
  -H "Content-Type: application/zip" \
  --upload-file source.zip

curl -sS -o /dev/null -X POST "$API/api/upload/complete" "${AUTH[@]}" \
  -d "{\"uploadId\":\"$UPLOAD_ID\",\"detectedDeploymentType\":\"static\"}"

curl -sS -X POST "$API/api/applications/create-from-upload" "${AUTH[@]}" \
  -d "{
    \"name\": \"marketing-site\",
    \"uploadId\": \"$UPLOAD_ID\",
    \"deploymentType\": \"static\",
    \"outputDirectory\": \".\"
  }"