opencloudportDocs

Code and variables

Deploy code to an app's Compute, roll back, and set the variables it reads.

The app needs Compute first, and it must be ready (active). Otherwise these calls get 409 no_compute or 409 compute_not_ready.

Deploy

POST /api/v1/apps/{id}/deployments, as multipart/form-data:

  • A metadata field with JSON:

Prop

Type

  • One file field per module, named by its path (index.js, lib/util.js). Types follow the extension:
ExtensionBecomes
.js, .mjsES module
.cjsCommonJS module
.wasmWebAssembly
.txt, .html, .sqlText
.binBinary data
.mapSource map

Up to 100 files and 10 MB. The request must say its Content-Length (curl and fetch do).

  • Static files (HTML, CSS, scripts for the browser, images, fonts) as fields named assets/<path>: assets/index.html is served at /, assets/css/site.css at /css/site.css. Up to 20,000 files, 25 MB each and 50 MB in total per upload. Content types follow the extension.
  • Code whose own folder is called assets (Vite puts a server build's chunks in dist/server/assets/): name its fields modules/<path>, which is always code. modules/assets/chunk.js is the module assets/chunk.js.

Static files

Files are served before your code: a request for a file gets the file, and anything else reaches your code, which can also fetch files itself through env.ASSETS. With files and no code, it's a static site. assets_config works like Cloudflare's static assets settings:

Prop

Type

curl https://opencloudport.com/api/v1/apps/$APP_ID/deployments \
  -H "Authorization: Bearer $OCP_KEY" \
  -F 'metadata={"assets_config": {"not_found_handling": "single-page-application"}}' \
  -F 'assets/index.html=@dist/index.html' \
  -F 'assets/assets/app.js=@dist/assets/app.js'
curl https://opencloudport.com/api/v1/apps/$APP_ID/deployments \
  -H "Authorization: Bearer $OCP_KEY" \
  -F 'metadata={"main_module": "index.js", "compatibility_flags": ["nodejs_compat"]}' \
  -F 'index.js=@dist/index.js' \
  -F 'lib/util.js=@dist/lib/util.js'

Answers 201 once the code is live, with the deployment:

{
  "data": {
    "id": "dep_…",
    "object": "deployment",
    "app_id": "app_…",
    "status": "active",
    "main_module": "index.js",
    "compatibility_date": "2026-10-01",
    "compatibility_flags": ["nodejs_compat"],
    "modules": [{ "name": "index.js", "type": "esm", "size": 1840, "sha256": "…" }],
    "assets": { "count": 0, "size_bytes": 0 },
    "assets_config": null,
    "size_bytes": 1840,
    "source_deployment_id": null,
    "error": null,
    "created_at": "…",
    "finished_at": "…"
  }
}

Sending only what changed

A deploy with many static files (images, video, fonts) doesn't have to send them all again. Ask first which ones this workspace has already deployed:

curl https://opencloudport.com/api/v1/apps/$APP_ID/deployments/upload-session \
  -H "Authorization: Bearer $OCP_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "files": [{ "path": "index.html", "sha256": "…" }, { "path": "video/intro.mp4", "sha256": "…" }] }'

It answers { "data": { "missing": ["index.html"], "known": ["video/intro.mp4"] } }. Then deploy with only the missing files, and list the known ones by hash in metadata.assets_manifest (path → sha256 of the file's content). Only what you send counts toward the 50 MB per upload. Only files this workspace has deployed before count as known. The SDK's deploy() and deploy_from_sandbox do this for you.

Files left out: .assetsignore

As on Cloudflare, a .assetsignore file at the top of your static files lists files not to publish, one gitignore-style pattern per line (wrangler.json, .dev.vars, *.map, drafts/, !keep.map). The .assetsignore file itself is never published either.

A deployment is deploying, active, superseded (a newer one replaced it) or failed. If the code is refused, you get 422 deployment_rejected with the reason, and the failed deployment is kept so you can look at it. Code that fails to start (an error at the top of a file, a missing module, a node: import without nodejs_compat) is refused this way, with the error, and the app keeps running its previous code.

Roll back

POST /api/v1/apps/{id}/deployments/{deploymentId}/redeploy deploys an earlier deployment's code and files again, as a new deployment whose source_deployment_id points at the original.

List and get deployments

EndpointWhat it does
GET /api/v1/apps/{id}/deploymentsNewest first. Paged with limit and starting_after.
GET /api/v1/apps/{id}/deployments/{deploymentId}One deployment, with source: { "type": "git", repo, branch, commit, commit_message, build_id }, { "type": "sandbox", sandbox_id, folder, code_folder }, or null for an upload.

To deploy what a sandbox built without uploading it yourself, see Deploy what a sandbox built.

Variables

Settings and secrets your code reads as env.NAME. Changes apply straight away, without a new deployment.

EndpointWhat it does
GET /api/v1/apps/{id}/envEvery variable. Secrets come back with value: null.
PUT /api/v1/apps/{id}/env/{NAME}Sets one. 201 if it's new, 200 if it replaced one.
DELETE /api/v1/apps/{id}/env/{NAME}Removes one.

Prop

Type

curl -X PUT https://opencloudport.com/api/v1/apps/$APP_ID/env/STRIPE_KEY \
  -H "Authorization: Bearer $OCP_KEY" -H "Content-Type: application/json" \
  -d '{"value": "sk_live_…"}'

Names are letters, digits and underscores, starting with a letter or underscore, and can't be a service's name. An app can have up to 100.

On this page