Skip to main content

Apps

Apps are containerized applications you deploy and run on the platform. Use this resource to create an app, upload a code bundle, deploy it, control its lifecycle (start/stop/restart), and watch its status, logs, and metrics.

Access it as client.apps on a Strongly client, or the same path on AsyncStrongly with await. All methods exist on both with identical signatures.

Quick start​

from strongly import Strongly

client = Strongly()

# List (auto-paginates as you iterate) # filters: status, environment_id, search
for app in client.apps.list():
print(app.id)

Methods​

Core​

list​

list(*, status: str | None = None, environment_id: str | None = None, search: str | None = None, limit: int | None = None) -> SyncPaginator[App]

List apps with pagination and filtering.

Parameters

  • status (str | None, optional): Filter by app status.
  • environment_id (str | None, optional): Filter by the runtime environment the app runs in.
  • search (str | None, optional): Search by name or description.
  • limit (int | None, optional): Maximum number of items to return (default: all matching items).

create​

create(*, name: str, description: str | None = None, display_name: str | None = None, source_volume_id: str | None = None, source_folder: str | None = None, github_repo_url: str | None = None, github_branch: str | None = None, github_ssh_key_id: str | None = None, github_subdirectory: str | None = None, instances: int | None = None, cpu: str | None = None, memory: str | None = None, disk: str | None = None, gpu: str | None = None, gpu_type: str | None = None, use_spot: bool | None = None, spot_fallback: bool | None = None, environment_id: str | None = None, environment_variables: Mapping[str, str] | None = None, addons: Sequence[str] | None = None, data_sources: Sequence[str] | None = None, ai_models: Sequence[str] | None = None, ml_models: Sequence[str] | None = None, workflows: Sequence[str] | None = None, feature_stores: Sequence[str] | None = None, agents: Sequence[str] | None = None, volumes: Sequence[str] | None = None, tags: Sequence[str] | None = None) -> App

Create a new app.

An app has no default size: it runs at exactly the size it is given. Set environment_id (the app runs at that environment's size), or cpu and memory (disk optional). deploy refuses an app with neither and names what is missing.

Parameters

  • name (str): App name.
  • description (str | None, optional): App description.
  • display_name (str | None, optional): Name shown in the UI.
  • source_volume_id (str | None, optional): Build from a volume's code, as last synced (what a workspace's Sync pushes): the volume's ID.
  • source_folder (str | None, optional): The folder of that volume's code holding strongly.manifest.yaml; omit for the whole code.
  • github_repo_url (str | None, optional): Build from a GitHub repository instead: its SSH URL (git@github.com:owner/repo.git). Needs github_branch and github_ssh_key_id.
  • github_branch (str | None, optional): The branch to build.
  • github_ssh_key_id (str | None, optional): The ID of one of your SSH keys (Profile > Integrations) GitHub accepts for the repository.
  • github_subdirectory (str | None, optional): The repository folder holding strongly.manifest.yaml; omit for the root.
  • instances (int | None, optional): Number of replicas.
  • cpu (str | None, optional): CPU cores, e.g. "0.5", "2" or "500m".
  • memory (str | None, optional): Memory, e.g. "1GB" or "512MB".
  • disk (str | None, optional): Disk, e.g. "10GB".
  • gpu (str | None, optional): Number of GPUs as a string, e.g. "1".
  • gpu_type (str | None, optional): GPU type when gpu is set, e.g. "nvidia-t4".
  • use_spot (bool | None, optional): True runs the app on spot capacity (cheaper; it can be reclaimed, and the app restarts on a new node).
  • spot_fallback (bool | None, optional): With use_spot: True (the API's default) falls back to on-demand capacity when no spot is available; False waits for spot.
  • environment_id (str | None, optional): Runtime environment the app runs in (and at the size of).
  • environment_variables (Mapping[str, str] | None, optional): Environment variables as a name -> value mapping.
  • addons (Sequence[str] | None, optional): Add-on IDs to connect (credentials reach the app through STRONGLY_SERVICES).
  • data_sources (Sequence[str] | None, optional): Data source IDs to connect.
  • ai_models (Sequence[str] | None, optional): AI model IDs to connect.
  • ml_models (Sequence[str] | None, optional): Model registry model IDs to connect.
  • workflows (Sequence[str] | None, optional): Deployed workflow IDs the app may trigger.
  • feature_stores (Sequence[str] | None, optional): Feature store IDs the app reads features from.
  • agents (Sequence[str] | None, optional): Deployed agent IDs the app talks to.
  • volumes (Sequence[str] | None, optional): Volume IDs the app mounts: a project's volume you have not shared at /volumes/local/<name>, every shared volume (yours included) at /volumes/shared/<name>; code/ read-only, data/ read and write, each written file saved as a new version. Needs a disk: disk, or an environment that has one.
  • tags (Sequence[str] | None, optional): Tags.

Returns

  • App: The newly created App.

Raises

  • ValueError: Both a volume and a GitHub source are given, or a GitHub source without its branch or SSH key.

retrieve​

retrieve(app_id: str) -> App

Get a single app by ID.

update​

update(app_id: str, *, name: str | None = None, description: str | None = None, display_name: str | None = None, instances: int | None = None, cpu: str | None = None, memory: str | None = None, disk: str | None = None, use_spot: bool | None = None, spot_fallback: bool | None = None, environment_id: str | None = None, environment_variables: Mapping[str, str] | None = None, addons: Sequence[str] | None = None, data_sources: Sequence[str] | None = None, ai_models: Sequence[str] | None = None, ml_models: Sequence[str] | None = None, workflows: Sequence[str] | None = None, feature_stores: Sequence[str] | None = None, agents: Sequence[str] | None = None, volumes: Sequence[str] | None = None, tags: Sequence[str] | None = None, port: int | None = None) -> App

Update an app's definition.

Sizes are checked as given: cpu must be a number of cores and memory / disk sizes such as "1GB". List arguments replace the whole set. A change reaches the running app when it is redeployed (deploy).

delete​

delete(app_id: str) -> None

Delete an app.

Lifecycle & actions​

start​

start(app_id: str) -> App

Start an app; returns the app.

stop​

stop(app_id: str) -> App

Stop an app; returns the app.

restart​

restart(app_id: str) -> App

Restart an app (a rolling restart of its pods); returns the app.

deploy​

deploy(app_id: str, **kwargs) -> App

Deploy an app at exactly its size.

Its environment's size, or the cpu and memory set on it. An app with neither is refused with a ValidationError naming what is missing; set it with update.

Parameters

  • app_id (str): The app ID.
  • **kwargs (Any): Optional deployment configuration options.

Returns

  • App: The app; the deployment has started (poll status).

deploy_upload​

deploy_upload(app_id: str, file: str | Path | BinaryIO, **kwargs) -> App

Deploy a zip bundle to an existing app.

Parameters

  • app_id (str): The app ID.
  • file (str | Path | BinaryIO): Path to a zip file, or a file-like object (opened in binary mode).
  • **kwargs (Any): Additional form fields to include.

Returns

  • App: The app, its new source building.

Examples

result = client.apps.deploy_upload("app-id", "my-app.zip")

Other​

add_member​

add_member(resource_id: str, *, user_id: str, role: str) -> Permissions

Share the resource with a user.

Parameters

  • resource_id (str): The resource's id.
  • user_id (str): The user to share it with.
  • role (str): "editor" (use and change it) or "user" (use it only; types without a use-only tier, such as knowledge bases, take "editor" only).

analytics​

analytics(app_id: str, *, range: str | None = None) -> dict[str, Any]

Get the app's usage over 7d, 30d or 90d.

analytics_users​

analytics_users(app_id: str, *, range: str | None = None, q: str | None = None, sort: str | None = None) -> SyncPaginator[AppUsageUser]

List who used the app over the range: sessions, minutes, requests, last seen.

build_logs​

build_logs(app_id: str, *, limit: int | None = None, level: str | None = None) -> dict[str, Any]

Get the image build's log lines, which say why a build failed.

build_status​

build_status(app_id: str) -> dict[str, Any]

Get the app's image build: queued, building, completed or failed.

create_with_upload​

create_with_upload(file: str | Path | BinaryIO, *, name: str | None = None, description: str | None = None, framework: str | None = None, runtime: str | None = None, **kwargs) -> App

Create a new app by uploading a zip bundle.

Parameters

  • file (str | Path | BinaryIO): Path to a zip file, or a file-like object (opened in binary mode).
  • name (str | None, optional): App name. Defaults to the filename without extension.
  • description (str | None, optional): App description.
  • framework (str | None, optional): App framework (e.g. "express", "react").
  • runtime (str | None, optional): App runtime (e.g. "node18").
  • **kwargs (Any): Additional form fields to include.

Returns

  • App: The new app, with its build.

Examples

app = client.apps.create_with_upload(
"my-app.zip",
name="My App",
description="An awesome app",
)

delete_plan​

delete_plan(app_id: str, plan_id: str) -> dict[str, Any]

Stop offering a plan; returns the paid access with the plans that remain.

get_user​

get_user(app_id: str, user_id: str) -> AppUser

One of the app's users.

list_users​

list_users(app_id: str, *, status: str | None = None, q: str | None = None, sort: str | None = None) -> SyncPaginator[AppUser]

List the app's users: status, role and free access.

logs​

logs(app_id: str, *, lines: int | None = None, since: str | None = None, container: str | None = None) -> Any

Get app logs.

Parameters

  • app_id (str): The app ID.
  • lines (int | None, optional): Number of log lines to return.
  • since (str | None, optional): ISO timestamp; return logs after this time.
  • container (str | None, optional): Specific container name.

metrics​

metrics(app_id: str) -> dict[str, Any]

Measure a running app now (about 6 seconds).

Returns cpu (usage_millicores, limit_millicores, percent) and memory (usage_bytes, limit_bytes, percent) against the app's size summed over replicas, network (receive_bytes_per_second, transmit_bytes_per_second, total_bytes_per_second, window_seconds), response_time (avg_ms, min_ms, max_ms, samples), replicas (ready, total, measured), containers (every container of every replica with its usage and size, platform containers marked by role), platform_containers_total and measured_at. Raises ConflictError (409) when the app is not running, and an API error with the reason when a measurement fails.

paid_access(app_id: str) -> dict[str, Any]

Get the app's paid access: masked Stripe keys, whether it charges, grace days, plans.

permissions​

permissions(resource_id: str) -> Permissions

Return who can reach the resource: its owner, members and their roles, and visibility.

Parameters

  • resource_id (str): The resource's id.

rebuild​

rebuild(app_id: str, *, bundle_source_type: str | None = None, bundle_source: Mapping[str, Any] | None = None) -> App

Build a new version of an app from source; the build runs on after this answers.

With no source it rebuilds from where the current version came from (its volume folder or GitHub branch, as it is now).

remove_member​

remove_member(resource_id: str, user_id: str) -> None

Stop sharing the resource with a user.

Parameters

  • resource_id (str): The resource's id.
  • user_id (str): The user to stop sharing it with.

remove_user​

remove_user(app_id: str, user_id: str) -> None

Remove a user from the app; their platform account is kept.

reset_user_password​

reset_user_password(app_id: str, user_id: str) -> AppUser

Email a user a password reset link to the app's branded page; returns the user.

set_env​

set_env(app_id: str, environment_variables: Mapping[str, str]) -> App

Replace the app's environment variables (they apply on its next start).

set_plan​

set_plan(app_id: str, plan_id: str, **plan) -> dict[str, Any]

Create or replace a plan.

Plan: name, description, kind (individual or team), stripe_price_id, min_seats, trial_days. Returns the paid access.

set_visibility​

set_visibility(resource_id: str, visibility: str) -> Permissions

Make the resource public (every user can find and use it) or private.

Parameters

  • resource_id (str): The resource's id.
  • visibility (str): "public" or "private".

status​

status(app_id: str) -> AppStatus

Get app deployment status.

subscriptions​

subscriptions(app_id: str, *, status: str | None = None, q: str | None = None, sort: str | None = None) -> SyncPaginator[AppSubscription]

List the app's subscriptions: payer, plan, seats and status.

update_auth​

update_auth(app_id: str, **settings) -> dict[str, Any]

Change the app's branded sign-in.

Settings: enabled, slug, signup_enabled, access (instant or approval), allowed_domains and logo. Returns {app_id, auth}.

update_paid_access​

update_paid_access(app_id: str, *, stripe_secret_key: str | None = None, stripe_webhook_secret: str | None = None, enabled: bool | None = None, grace_days: int | None = None) -> dict[str, Any]

Set up or change paid access with the owner's own Stripe account.

update_user​

update_user(app_id: str, user_id: str, *, active: bool | None = None, free_access: bool | None = None) -> AppUser

Let a user sign in (or not), or let them use a paid app without a plan.