The App Sources API lets you manage the configured package sources that Hoody queries when resolving application packages. Use these endpoints to list, create, update, delete, sync, and diagnose sources across providers like nix, pkgx, appimage, oci, registry, and system.
List all package sources
Section titled “List all package sources”GET /api/v1/run/sources
Section titled “GET /api/v1/run/sources”List every configured package source along with its type, provider, priority, enabled state, and provider-specific configuration.
This endpoint takes no parameters.
Example Request
Section titled “Example Request”curl -X GET https://api.hoody.example/api/v1/run/sources \ -H "Authorization: Bearer <token>"const sources = await client.app.sources.list();Response
Section titled “Response”[ { "source_id": "nixpkgs", "enabled": true, "priority": 100, "provider": "nix", "source_type": "nix-flake", "pin": { "url": "https://github.com/NixOS/nixpkgs" }, "config": { "flake": "nixpkgs" } }, { "source_id": "pkgx-default", "enabled": true, "priority": 80, "provider": "pkgx", "source_type": "pkgx" }]Get source diagnostics
Section titled “Get source diagnostics”GET /api/v1/run/sources/{source_id}/diagnostics
Section titled “GET /api/v1/run/sources/{source_id}/diagnostics”Return runtime-only health and observability data for a configured source, including recent search or sync failures.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
source_id | path | string | Yes | Source identifier |
Example Request
Section titled “Example Request”curl -X GET https://api.hoody.example/api/v1/run/sources/nixpkgs/diagnostics \ -H "Authorization: Bearer <token>"const diagnostics = await client.app.sources.getDiagnostics({ source_id: "nixpkgs" });Response
Section titled “Response”{ "source_id": "nixpkgs", "status": "ok", "last_success_at": "2025-01-15T10:25:00Z", "last_error_at": null, "last_error": null, "last_search_latency_ms": 142, "last_sync_job_id": "550e8400-e29b-41d4-a716-446655440000", "cache_hint": "fresh", "effective_enabled_reason": null, "provider_details": { "channel": "nixos-unstable", "rev": "abc123def456" }}{ "error": "source not found", "code": 404}Create a package source
Section titled “Create a package source”POST /api/v1/run/sources
Section titled “POST /api/v1/run/sources”Add a new package source configuration. The source is appended to the existing list and immediately available for searches if enabled.
This endpoint takes no parameters.
Request Body
Section titled “Request Body”The request body is a SourceConfig object.
| Field | Type | Required | Description |
|---|---|---|---|
source_id | string | Yes | Unique source identifier |
enabled | boolean | Yes | Whether this source is active for searches |
priority | integer | Yes | Source priority (higher values are searched first and ranked higher) |
provider | string | Yes | Provider kind: nix, pkgx, appimage, oci, registry, system, or any |
source_type | string | Yes | Implementation type: nix-pkgs, nix-flake, pkgx, app-image-pinned, app-image-git-hub-releases, app-image-catalog, oci-local-images, manifest-registry, manifest-remote-index, system-path, or trusted-list-file |
pin | object | No | Pin configuration (URL and optional integrity verification fields) |
config | object | No | Provider-specific configuration (varies by source_type) |
Example Request
Section titled “Example Request”curl -X POST https://api.hoody.example/api/v1/run/sources \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "source_id": "nixpkgs-stable", "enabled": true, "priority": 90, "provider": "nix", "source_type": "nix-flake", "pin": { "url": "https://github.com/NixOS/nixpkgs", "sha256": "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" }, "config": { "flake": "nixpkgs", "channel": "nixos-24.05" } }'const sources = await client.app.sources.create({ source_id: "nixpkgs-stable", enabled: true, priority: 90, provider: "nix", source_type: "nix-flake", pin: { url: "https://github.com/NixOS/nixpkgs", sha256: "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" }, config: { flake: "nixpkgs", channel: "nixos-24.05" }});Response
Section titled “Response”[ { "source_id": "nixpkgs", "enabled": true, "priority": 100, "provider": "nix", "source_type": "nix-flake", "pin": { "url": "https://github.com/NixOS/nixpkgs" }, "config": { "flake": "nixpkgs" } }, { "source_id": "nixpkgs-stable", "enabled": true, "priority": 90, "provider": "nix", "source_type": "nix-flake", "pin": { "url": "https://github.com/NixOS/nixpkgs", "sha256": "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" }, "config": { "flake": "nixpkgs", "channel": "nixos-24.05" } }]{ "error": "missing source_id", "code": 400}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_SOURCE_ID | Missing source identifier | The source configuration did not include a non-empty source_id | Set source_id before creating the source |
{ "error": "source already exists", "code": 409}| Error Code | Title | Description | Resolution |
|---|---|---|---|
SOURCE_ALREADY_EXISTS | Source already exists | A source with the same source_id already exists | Choose a unique source_id or update the existing source instead |
{ "error": "configuration save failed", "code": 503}| Error Code | Title | Description | Resolution |
|---|---|---|---|
CONFIG_SAVE_FAILED | Configuration save failed | The updated source configuration could not be persisted | Check storage health and retry |
Update a package source
Section titled “Update a package source”PATCH /api/v1/run/sources/{source_id}
Section titled “PATCH /api/v1/run/sources/{source_id}”Partially update a source configuration. Supports merging enabled, priority, pin, and config fields.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
source_id | path | string | Yes | Source identifier |
Request Body
Section titled “Request Body”Send a partial SourceConfig object containing only the fields you want to change. Fields not included are left unchanged. Common mergeable fields include enabled, priority, pin, and config.
Example Request
Section titled “Example Request”curl -X PATCH https://api.hoody.example/api/v1/run/sources/nixpkgs \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "enabled": false, "priority": 120 }'const updated = await client.app.sources.update({ source_id: "nixpkgs", enabled: false, priority: 120});Response
Section titled “Response”{ "source_id": "nixpkgs", "enabled": false, "priority": 120, "provider": "nix", "source_type": "nix-flake", "pin": { "url": "https://github.com/NixOS/nixpkgs" }, "config": { "flake": "nixpkgs" }}{ "error": "source not found", "code": 404}| Error Code | Title | Description | Resolution |
|---|---|---|---|
SOURCE_NOT_FOUND | Source not found | No source exists with the requested source_id | Call listSources and choose a valid source_id |
{ "error": "configuration save failed", "code": 503}| Error Code | Title | Description | Resolution |
|---|---|---|---|
CONFIG_SAVE_FAILED | Configuration save failed | The updated source configuration could not be persisted | Check storage health and retry |
Delete a package source
Section titled “Delete a package source”DELETE /api/v1/run/sources/{source_id}
Section titled “DELETE /api/v1/run/sources/{source_id}”Remove a package source by its ID. Returns 204 No Content on success.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
source_id | path | string | Yes | Source identifier |
This endpoint takes no request body.
Example Request
Section titled “Example Request”curl -X DELETE https://api.hoody.example/api/v1/run/sources/nixpkgs \ -H "Authorization: Bearer <token>"await client.app.sources.delete({ source_id: "nixpkgs" });Response
Section titled “Response”Source deleted successfully. No content returned.
{ "error": "source not found", "code": 404}| Error Code | Title | Description | Resolution |
|---|---|---|---|
SOURCE_NOT_FOUND | Source not found | No source exists with the requested source_id | Call listSources and choose a valid source_id |
{ "error": "configuration save failed", "code": 503}| Error Code | Title | Description | Resolution |
|---|---|---|---|
CONFIG_SAVE_FAILED | Configuration save failed | The updated source configuration could not be persisted | Check storage health and retry |
Sync a single source
Section titled “Sync a single source”POST /api/v1/run/sources/{source_id}/sync
Section titled “POST /api/v1/run/sources/{source_id}/sync”Trigger a sync operation for a specific source. Returns immediately with a job handle for tracking progress via the jobs endpoint.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
source_id | path | string | Yes | Source identifier |
This endpoint takes no request body.
Example Request
Section titled “Example Request”curl -X POST https://api.hoody.example/api/v1/run/sources/nixpkgs/sync \ -H "Authorization: Bearer <token>"const job = await client.app.sources.sync({ source_id: "nixpkgs" });Response
Section titled “Response”{ "job_id": "550e8400-e29b-41d4-a716-446655440000", "kind": "source-sync", "status": "queued", "created_at": "2025-01-15T10:30:00Z", "updated_at": "2025-01-15T10:30:00Z", "error": null, "result_type": null, "result": null, "progress": null}{ "error": "sync start failed", "code": 503}| Error Code | Title | Description | Resolution |
|---|---|---|---|
SYNC_START_FAILED | Sync start failed | The source sync job could not be started | Retry or inspect source/provider health |
Sync all sources
Section titled “Sync all sources”POST /api/v1/run/sources/sync
Section titled “POST /api/v1/run/sources/sync”Trigger a sync operation for all enabled sources. Returns immediately with a job handle.
Poll for completion with GET /api/v1/run/jobs/{job_id}?wait=done&timeout_ms=30000.
This endpoint takes no parameters.
This endpoint takes no request body.
Example Request
Section titled “Example Request”curl -X POST https://api.hoody.example/api/v1/run/sources/sync \ -H "Authorization: Bearer <token>"const job = await client.app.sources.syncAll();Response
Section titled “Response”{ "job_id": "550e8400-e29b-41d4-a716-446655440000", "kind": "source-sync", "status": "queued", "created_at": "2025-01-15T10:30:00Z", "updated_at": "2025-01-15T10:30:00Z", "error": null, "result_type": null, "result": null, "progress": null}{ "error": "sync start failed", "code": 503}| Error Code | Title | Description | Resolution |
|---|---|---|---|
SYNC_START_FAILED | Sync start failed | The all-sources sync job could not be started | Retry or inspect source/provider health |