Run: Profiles
Section titled “Run: Profiles”Use the Profiles endpoints to manage named application profiles within a Hoody Run container. A profile bundles default preferences (operating system, app kind, source filter, candidate selection mode, terminal session, and so on) with optional source overrides and a sourcing policy. One profile can be selected as the active default; its defaults are then applied to subsequent requests that do not explicitly override them.
The endpoints below let you list existing profiles, create new ones, partially update them, switch the active profile, and delete profiles by name.
List profiles
Section titled “List profiles”GET /api/v1/run/profiles
Section titled “GET /api/v1/run/profiles”Return every configured profile along with its default preferences and source overrides.
This endpoint takes no parameters.
curl -X GET "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.com/api/v1/run/profiles" \ -H "Authorization: Bearer $HOODY_TOKEN"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-run-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.run.profiles.list();Response
Section titled “Response”[ { "name": "default", "description": "Default profile (inherits global sources)", "defaults": { "os": "any", "kind": "any", "source": ["any"], "pick": "ask", "limit": 20 }, "sources_mode": "inherit", "sources": [], "policy": { "require_verified": false, "require_integrity": false, "deny_providers": [], "deny_source_ids": [] } }, { "name": "workstation", "description": "GUI-focused profile pinned to Linux package sources", "defaults": { "os": "linux", "kind": "gui", "source": ["nix", "appimage"], "pick": "first" }, "sources_mode": "allowlist", "sources": [ { "source_id": "nixpkgs", "enabled": true, "priority": 10 } ], "policy": { "require_verified": true, "deny_providers": ["system"] } }]Create a profile
Section titled “Create a profile”POST /api/v1/run/profiles
Section titled “POST /api/v1/run/profiles”Create a new user profile with default preferences and optional source overrides. Returns the updated list of all profiles.
This endpoint takes no parameters.
Request Body
Section titled “Request Body”A request body is required. See the run_ProfileConfig schema in the referenced schemas section for the supported fields. The name field is required.
curl -X POST "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.com/api/v1/run/profiles" \ -H "Authorization: Bearer $HOODY_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "workstation", "description": "GUI-focused profile pinned to Linux package sources", "defaults": { "os": "linux", "kind": "gui", "source": ["nix", "appimage"], "pick": "first" }, "sources_mode": "allowlist", "sources": [ { "source_id": "nixpkgs", "enabled": true, "priority": 10 } ] }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-run-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.run.profiles.create({ name: 'workstation', description: 'GUI-focused profile pinned to Linux package sources', defaults: { os: 'linux', kind: 'gui', source: ['nix', 'appimage'], pick: 'first' }, sources_mode: 'allowlist', sources: [ { source_id: 'nixpkgs', enabled: true, priority: 10 } ]});Response
Section titled “Response”[ { "name": "default", "description": "Default profile (inherits global sources)", "defaults": { "os": "any", "kind": "any", "source": ["any"], "pick": "ask", "limit": 20 }, "sources_mode": "inherit", "sources": [], "policy": { "require_verified": false, "require_integrity": false, "deny_providers": [], "deny_source_ids": [] } }, { "name": "workstation", "description": "GUI-focused profile pinned to Linux package sources", "defaults": { "os": "linux", "kind": "gui", "source": ["nix", "appimage"], "pick": "first" }, "sources_mode": "allowlist", "sources": [ { "source_id": "nixpkgs", "enabled": true, "priority": 10 } ], "policy": { "require_verified": false, "require_integrity": false, "deny_providers": [], "deny_source_ids": [] } }]{ "error": "Profile configuration must include a non-empty name", "code": "MISSING_PROFILE_NAME", "status": 400}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_PROFILE_NAME | Missing profile name | The profile configuration did not include a non-empty name | Set name before creating the profile |
INVALID_BODY | Invalid request body | The body does not fit ProfileConfig (for example an unknown sources_mode, or a wrongly typed field) | Check the field named in the error and the ProfileConfig schema |
INVALID_JSON | Malformed JSON | The request body is not valid JSON | Send a JSON object |
{ "error": "A profile named 'workstation' already exists", "code": "PROFILE_ALREADY_EXISTS", "status": 409}| Error Code | Title | Description | Resolution |
|---|---|---|---|
PROFILE_ALREADY_EXISTS | Profile already exists | A profile with the same name already exists | Choose a unique profile name or update the existing profile instead |
{ "error": "Failed to persist updated profile configuration", "code": "CONFIG_SAVE_FAILED", "status": 503}| Error Code | Title | Description | Resolution |
|---|---|---|---|
CONFIG_SAVE_FAILED | Configuration save failed | The updated profile configuration could not be persisted | Check storage health and retry |
Update a profile
Section titled “Update a profile”PATCH /api/v1/run/profiles/{profile}
Section titled “PATCH /api/v1/run/profiles/{profile}”Partially update a profile with a JSON merge patch (RFC 7396) onto the stored profile. Nested objects (defaults, policy) merge field by field, so {"defaults":{"limit":3}} keeps the other defaults; null resets a field to its default; arrays (sources, defaults.source, the policy deny lists) replace the stored list as a unit. The merged profile is validated before it is stored: an invalid value, an unknown top-level field or a different name is a 400 and nothing changes. Unknown keys inside a nested object are ignored, as on create.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
profile | path | string | Yes | Profile name |
Request Body
Section titled “Request Body”A request body is required. See the run_ProfileUpdate schema in the referenced schemas section for the supported fields. Only include the fields you want to change; the profile’s name is taken from the path and cannot be changed here.
curl -X PATCH "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.com/api/v1/run/profiles/workstation" \ -H "Authorization: Bearer $HOODY_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "description": "GUI-focused profile pinned to Linux package sources (verified only)", "policy": { "require_verified": true, "deny_providers": ["system"] } }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-run-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.run.profiles.update('workstation', { description: 'GUI-focused profile pinned to Linux package sources (verified only)', policy: { require_verified: true, deny_providers: ['system'] }});Response
Section titled “Response”{ "name": "workstation", "description": "GUI-focused profile pinned to Linux package sources (verified only)", "defaults": { "os": "linux", "kind": "gui", "source": ["nix", "appimage"], "pick": "first" }, "sources_mode": "allowlist", "sources": [ { "source_id": "nixpkgs", "enabled": true, "priority": 10 } ], "policy": { "require_verified": true, "require_integrity": false, "deny_providers": ["system"], "deny_source_ids": [] }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INVALID_PROFILE | Invalid profile update | A field has a value its type refuses (for example an unknown pick mode), the body is not an object, it names a field that cannot be patched, or it tries to change the name | Fix the field named in the error; nothing was stored |
INVALID_JSON | Malformed JSON | The request body is not valid JSON | Send a JSON object |
{ "error": "No profile named 'workstation' exists", "code": "PROFILE_NOT_FOUND", "status": 404}| Error Code | Title | Description | Resolution |
|---|---|---|---|
PROFILE_NOT_FOUND | Profile not found | No profile exists with the requested name | Call profiles.list and choose a valid profile name |
{ "error": "Failed to persist updated profile configuration", "code": "CONFIG_SAVE_FAILED", "status": 503}| Error Code | Title | Description | Resolution |
|---|---|---|---|
CONFIG_SAVE_FAILED | Configuration save failed | The updated profile configuration could not be persisted | Check storage health and retry |
Select the active profile
Section titled “Select the active profile”POST /api/v1/run/profiles/{profile}/select
Section titled “POST /api/v1/run/profiles/{profile}/select”Set the named profile as the currently active profile. Its defaults will be applied to all subsequent requests that do not explicitly override them.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
profile | path | string | Yes | Profile name to select |
This endpoint takes no request body.
curl -X POST "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.com/api/v1/run/profiles/workstation/select" \ -H "Authorization: Bearer $HOODY_TOKEN"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-run-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.run.profiles.use('workstation');Response
Section titled “Response”{ "selected_profile": "workstation"}{ "error": "No profile named 'workstation' exists", "code": "PROFILE_NOT_FOUND", "status": 404}| Error Code | Title | Description | Resolution |
|---|---|---|---|
PROFILE_NOT_FOUND | Profile not found | No profile exists with the requested name | Call profiles.list and choose a valid profile name |
{ "error": "Failed to persist updated profile selection", "code": "CONFIG_SAVE_FAILED", "status": 503}| Error Code | Title | Description | Resolution |
|---|---|---|---|
CONFIG_SAVE_FAILED | Configuration save failed | The updated profile selection could not be persisted | Check storage health and retry |
Delete a profile
Section titled “Delete a profile”DELETE /api/v1/run/profiles/{profile}
Section titled “DELETE /api/v1/run/profiles/{profile}”Remove a profile by name. The built-in default profile and the currently selected profile cannot be deleted (409); select another profile first.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
profile | path | string | Yes | Profile name |
This endpoint takes no request body.
curl -X DELETE "https://{projectId}-{containerId}-run-1.{server}.containers.hoody.com/api/v1/run/profiles/workstation" \ -H "Authorization: Bearer $HOODY_TOKEN"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-run-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.run.profiles.delete('workstation');Response
Section titled “Response”The profile was deleted successfully. The response has no body.
{ "error": "No profile named 'workstation' exists", "code": "PROFILE_NOT_FOUND", "status": 404}| Error Code | Title | Description | Resolution |
|---|---|---|---|
PROFILE_NOT_FOUND | Profile not found | No profile exists with the requested name | Call profiles.list and choose a valid profile name |
| Error Code | Title | Description | Resolution |
|---|---|---|---|
BUILTIN_PROFILE | Built-in profile | The built-in default profile cannot be deleted | Update its defaults with client.run.profiles.update() instead |
PROFILE_SELECTED | Profile is selected | The profile is the currently selected profile | Select another profile with client.run.profiles.use() first |
{ "error": "Failed to persist updated profile configuration", "code": "CONFIG_SAVE_FAILED", "status": 503}| Error Code | Title | Description | Resolution |
|---|---|---|---|
CONFIG_SAVE_FAILED | Configuration save failed | The updated profile configuration could not be persisted | Check storage health and retry |
Referenced schemas
Section titled “Referenced schemas”The schemas below define the request and response shapes used by the Profiles endpoints. Use them as a reference when constructing request bodies; only the fields marked required must be present.
run_ProfileConfig
Section titled “run_ProfileConfig”The full profile object. Used by the create endpoint and returned by the list and create responses.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Unique profile name |
description | string | No | Human-readable profile description |
defaults | run_ProfileDefaults | No | Default selector values applied when the profile is active |
sources_mode | run_ProfileSourceMode | No | How the profile interacts with the global source list |
sources | array of run_ProfileSourceOverride | No | Per-source overrides (enable/disable/reprioritize). Default: [] |
policy | run_PolicyConfig | No | Sourcing policy applied while this profile is active |
run_ProfileUpdate
Section titled “run_ProfileUpdate”The partial profile object used by the update endpoint. Only the fields present in the body are applied; everything else keeps its stored value. The profile’s name is taken from the path and cannot be changed here.
| Field | Type | Required | Description |
|---|---|---|---|
description | string | No | Human-readable profile description. Send null to clear it. |
defaults | run_ProfileDefaultsUpdate | No | Merged field by field into the stored profile defaults. A null field resets it; null for the whole object resets every default. |
sources_mode | string | null | No | Source mode: inherit or allowlist. Send null to reset it to inherit. |
sources | array of run_ProfileSourceOverride | No | Per-source overrides (enable/disable/reprioritize). Replaces the stored list as a unit. |
policy | run_PolicyConfigUpdate | No | Merged field by field into the stored policy, so setting one flag keeps the deny lists. A null field resets it; the deny lists replace as a unit. |
run_ProfileDefaultsUpdate
Section titled “run_ProfileDefaultsUpdate”The same fields as run_ProfileDefaults, each nullable: send null for a field to reset it to its default.
| Field | Type | Required | Description |
|---|---|---|---|
os | string, nullable | No | Target app runtime OS (not the host OS). One of linux, windows, any |
kind | string, nullable | No | Application kind filter. One of gui, cli, any |
source | array of run_SourceKind, nullable | No | Default source filter |
pick | string, nullable | No | Candidate selection mode. One of ask, first, index, id |
terminal_id | integer, nullable | No | Default terminal session ID. Range: 1 to 65535 |
display | string, nullable | No | Default X11 DISPLAY number |
limit | integer, nullable | No | Default maximum candidates to return. Range: 1 to 100 |
run_PolicyConfigUpdate
Section titled “run_PolicyConfigUpdate”The same fields as run_PolicyConfig, each nullable: send null for a field to reset it.
| Field | Type | Required | Description |
|---|---|---|---|
require_verified | boolean, nullable | No | Require verified sources |
require_integrity | boolean, nullable | No | Require integrity-checked sources |
deny_providers | array of run_SourceKind, nullable | No | Providers to deny |
deny_source_ids | array of string, nullable | No | Specific source IDs to deny |
run_ProfileDefaults
Section titled “run_ProfileDefaults”| Field | Type | Required | Description |
|---|---|---|---|
os | run_Os | No | Target app runtime OS (not the host OS). One of linux, windows, any |
kind | run_AppKind | No | Application kind filter. One of gui, cli, any |
source | array of run_SourceKind | No | Default source filter. One of nix, pkgx, appimage, oci, registry, system, any. Default: [] |
pick | run_PickMode | No | Candidate selection mode. One of ask, first, index, id |
terminal_id | integer | No | Default terminal session ID. Range: 1 to 65535 |
display | string | No | Default X11 DISPLAY number |
limit | integer | No | Default maximum candidates to return. Range: 1 to 100 |
run_ProfileSourceOverride
Section titled “run_ProfileSourceOverride”| Field | Type | Required | Description |
|---|---|---|---|
source_id | string | Yes | ID of the source to override |
enabled | boolean | No | Override enabled state |
priority | integer | No | Override priority |
run_PolicyConfig
Section titled “run_PolicyConfig”| Field | Type | Required | Description |
|---|---|---|---|
require_verified | boolean | No | Require verified sources |
require_integrity | boolean | No | Require integrity-checked sources |
deny_providers | array of run_SourceKind | No | Providers to deny. Default: [] |
deny_source_ids | array of string | No | Specific source IDs to deny. Default: [] |
run_PickMode
Section titled “run_PickMode”Selection mode for candidates:
ask: return candidate list without selecting (default)first: automatically select the highest-ranked candidateindex: select by 0-based index (requirespick_index)id: select bycandidate_id(requirescandidate_id)
run_ProfileSourceMode
Section titled “run_ProfileSourceMode”How a profile interacts with the global source list:
inherit: start from global sources, apply overridesallowlist: disable all sources first, then enable only those listed in the profile’ssourcesarray
run_ApiError
Section titled “run_ApiError”Standard JSON error payload returned for validation, lookup, and persistence failures.
| Field | Type | Required | Description |
|---|---|---|---|
error | string | Yes | Human-readable error message |
code | string | Yes | Symbolic error code to branch on (for example MISSING_PROFILE_NAME). Operation-specific codes are listed under each response |
status | integer | Yes | HTTP status code of the response |
run_SelectedProfileResponse
Section titled “run_SelectedProfileResponse”| Field | Type | Required | Description |
|---|---|---|---|
selected_profile | string | Yes | Name of the active profile |