Skip to main content

Code API

The Code API provides endpoints to handle code uploads so you can trigger new builds and deployments via API to your app's environments.

We do this process through pre-signed URLs. This is a three-step process:

  1. Request a pre-signed URL
  2. Zip and Upload your code to the pre-signed URL
  3. Notify Quave ONE about the upload

Ignoring unnecessary files

It's important to avoid sending files that will be generated at build time, like .git, node_modules, .meteor/local, etc as they are usually large and not needed to build your app, if you do so you will probably wait a long time for the upload to complete or even reach a limit.

Our CLI does this respecting .zcloudignore files but as you are sending the file you need to do it yourself.

For a bash equivalent, you could use rsync with exclude patterns:

rsync -av --exclude='node_modules' \
--exclude='.git' \
--exclude='.meteor/local' \
source/ destination/

Then instead of zipping the source directory you should zip the destination directory.

Ok, let's learn the steps to upload your code.

1. Request Storage Key

First, request a pre-signed URL, with a storage key by sending a POST request to the /api/public/v1/app-env/request-storage-key endpoint.

Body ParameterTypeDescription
envNameStringThe environment name (required)
fileExtensionStringThe extension of the file to upload (optional). Allowed values are .zip, .tgz, .tar.gz. Defaults to .tgz.

Example request:

curl -X POST \
-H 'Authorization: YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"envName": "my-environment"}' \
https://api.quave.cloud/api/public/v1/app-env/request-storage-key

Example Response:

{
"uploadUrl": "https://storage.aws.com/bucket-name/...",
"storageKey": "s3://bucket-name/environment/account-id/app-id/random-id-my-environment.zip",
"envUrl": "https://app.quave.cloud/account/account-id/app/app-id/env/env-id"
}

2. Zip and Upload Your Code

After receiving the pre-signed URL, zip and upload your code to the pre-signed URL.

To zip your code, you can use the following command:

tar -czvf ../project.tgz --exclude="node_modules" --exclude=".git" --exclude="*.zip" --exclude="*.env" *

Example using curl:

curl -X PUT \
-H 'Content-Type: application/x-gzip' \
--data-binary '@/path/to/your/file.tgz' \
"PRESIGNED_URL_FROM_PREVIOUS_STEP"

Important notes:

  • The pre-signed URL expires after 60 minutes
  • Make sure to set the correct Content-Type header
  • Use the exact URL returned in the uploadUrl field

3. Notify Upload Event

Finally, notify Quave ONE that the upload is complete by sending a POST request to the /api/public/v1/app-env/upload-storage-event endpoint.

Body ParameterTypeDescription
envNameStringThe environment name (required)
storageKeyStringThe storage key received from the request-key endpoint
startupConfigObjectOptional partial persistent startup configuration with command, args, shell, or workingDir.
clearStartupConfigBooleanSet to true to clear the complete saved startup override. Cannot be combined with startupConfig.
replaceStartupConfigBooleanSet to true with startupConfig to replace the complete saved override instead of merging omitted fields.

Example request:

curl -X POST \
-H 'Authorization: YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"envName": "my-environment",
"storageKey": "s3://bucket-name/path/to/file.zip",
"startupConfig": {
"command": "bun run start:worker",
"shell": true
},
"replaceStartupConfig": true
}' \
https://api.quave.cloud/api/public/v1/app-env/upload-storage-event

Example Response:

{
"status": "Ok",
"uploadEventId": "upload-event-id"
}

The uploadEventId identifies the asynchronous source-upload event. You can use it to correlate this upload with latestDeployment.uploadEventId from the App Environment Status API while a source build is still BUILDING and before it becomes the current deployment.

Complete Flow Example

Here's a complete example using bash:

# Set your variables
ENV_NAME="my-environment"
API_TOKEN="YOUR_TOKEN"
FILE_PATH="/path/to/your/file.tgz"
API_URL="https://api.quave.cloud/api/public/v1"

# Step 1: Request pre-signed URL
RESPONSE=$(curl -X POST \
-H "Authorization: ${API_TOKEN}" \
-H 'Content-Type: application/json' \
-d "{\"envName\": \"${ENV_NAME}\"}" \
"${API_URL}/app-env/request-storage-key")

# Extract values from response
UPLOAD_URL=$(echo $RESPONSE | jq -r '.uploadUrl')
STORAGE_KEY=$(echo $RESPONSE | jq -r '.storageKey')

# Step 2: Upload file to storage
curl -X PUT \
-H 'Content-Type: application/x-gzip' \
--data-binary "@${FILE_PATH}" \
"$UPLOAD_URL"

# Step 3: Notify upload event
UPLOAD_EVENT_RESPONSE=$(curl -X POST \
-H "Authorization: ${API_TOKEN}" \
-H 'Content-Type: application/json' \
-d "{
\"envName\": \"${ENV_NAME}\",
\"storageKey\": \"${STORAGE_KEY}\",
\"startupConfig\": {
\"command\": \"bun run start:worker\",
\"shell\": true
},
\"replaceStartupConfig\": true
}" \
"${API_URL}/app-env/upload-storage-event")

UPLOAD_EVENT_ID=$(echo $UPLOAD_EVENT_RESPONSE | jq -r '.uploadEventId')

Error Handling

Common errors and their solutions:

ErrorSolution
Pre-signed URL expiredRequest a new pre-signed URL
Invalid content typeEnsure you're sending the correct Content-Type header
Environment not foundVerify the environment name is correct
Invalid storage keyUse the exact storage key from the request-storage-key response

Important Notes

  • The Code API is designed for uploading application code and related files, it's designed to be used with our CLI option as deployment configuration;
  • For apps using GitHub connected repositories, use the GitHub integration instead by pushing new commits to the configured branch;
  • Always complete all three steps in the process;
  • The upload-event response includes uploadEventId for correlating status polling with the exact source upload;
  • The optional startup configuration is saved on the app environment before the build. It affects runtime only and is not included in the build hash;
  • Startup configuration patches preserve omitted saved fields. Send replaceStartupConfig: true with startupConfig when the object is the complete desired override and omitted fields must be removed. Use clearStartupConfig: true to restore all image defaults;
  • Startup configuration is supported for regular Apps and Functions, but not for Jobs or Databases & Services. See Startup Command Overrides;
  • Keep your pre-signed URLs secure and don't share them;
  • The upload must be completed within the pre-signed URL expiration time;