The Sources API lets you manage the package sources Hoody uses to resolve application candidates. Use these endpoints to list, create, update, delete, sync, and diagnose individual sources. Sources can be providers like nix, pkgx, appimage, oci, registry, or system, and each source has a specific implementation type that determines how it resolves and syncs candidates.
List sources
Section titled “List sources”GET /api/v1/run/sources
Section titled “GET /api/v1/run/sources”List all configured package sources with their type, provider, priority, enabled state, and provider-specific configuration.
This endpoint takes no parameters.
curl -X GET https://api.hoody.com/api/v1/run/sources \ -H "Authorization: Bearer <token>"const sources = await client.app.sources.list();Response — 200
Section titled “Response — 200”Array of source configurations.
[ { "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 |
This endpoint accepts no request body.
curl -X GET https://api.hoody.com/api/v1/run/sources/nixpkgs/diagnostics \ -H "Authorization: Bearer <token>"const diagnostics = await client.app.sources.getDiagnostics({ source_id: "nixpkgs"});Response — 200
Section titled “Response — 200”{ "source_id": "nixpkgs", "status": "ok", "last_success_at": "2025-01-15T10:30:00Z", "last_error_at": null, "last_error": null, "last_search_latency_ms": 142, "last_sync_job_id": "550e8400-e29b-41d4-a716-446655440000", "cache_hint": "warm", "effective_enabled_reason": "configured and enabled", "provider_details": { "flake_rev": "abc123def456" }}Response — 404
Section titled “Response — 404”Source not found.
{ "error": "Source not found", "code": 404}Create a source
Section titled “Create a source”POST /api/v1/run/sources
Section titled “POST /api/v1/run/sources”Add a new package source configuration. The source will be appended to the existing list and immediately available for searches if enabled.
This endpoint takes no parameters.
Request Body
Section titled “Request Body”Source configuration object.
| Name | Type | Required | Description |
|---|---|---|---|
source_id | string | Yes | Unique source identifier (e.g. nixpkgs) |
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 | Package source provider kind. One of: nix, pkgx, appimage, oci, registry, system, any |
source_type | string | Yes | Specific source implementation type. One of: 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, trusted-list-file |
pin | object | No | Pin configuration (URL plus optional integrity fields) |
config | object | No | Provider-specific configuration (varies by source_type) |
The pin object accepts the following fields:
| Name | Type | Required | Description |
|---|---|---|---|
url | string | Yes | Pinned URL for the source |
sha256 | string | No | SHA-256 hash for integrity verification |
author_pubkey_ed25519 | string | No | Ed25519 public key of the source author (base64) |
sig_ed25519 | string | No | Ed25519 signature for provenance verification (base64) |
curl -X POST https://api.hoody.com/api/v1/run/sources \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "source_id": "nixpkgs", "enabled": true, "priority": 100, "provider": "nix", "source_type": "nix-flake", "pin": { "url": "https://github.com/NixOS/nixpkgs" }, "config": { "flake": "nixpkgs" } }'const sources = await client.app.sources.create({ source_id: "nixpkgs", enabled: true, priority: 100, provider: "nix", source_type: "nix-flake", pin: { url: "https://github.com/NixOS/nixpkgs" }, config: { flake: "nixpkgs" }});Response — 200
Section titled “Response — 200”Updated list of all sources.
[ { "source_id": "nixpkgs", "enabled": true, "priority": 100, "provider": "nix", "source_type": "nix-flake", "pin": { "url": "https://github.com/NixOS/nixpkgs" }, "config": { "flake": "nixpkgs" } }]Response — 400
Section titled “Response — 400”Missing source_id.
{ "error": "Missing source identifier", "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 |
Response — 409
Section titled “Response — 409”Source already exists.
{ "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 |
Response — 503
Section titled “Response — 503”Configuration persistence failed.
{ "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 sources
Section titled “Sync sources”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 accepts no request body.
curl -X POST https://api.hoody.com/api/v1/run/sources/nixpkgs/sync \ -H "Authorization: Bearer <token>"const job = await client.app.sources.sync({ source_id: "nixpkgs"});Response — 202
Section titled “Response — 202”Sync job accepted.
{ "job_id": "550e8400-e29b-41d4-a716-446655440000", "kind": "source-sync", "status": "running", "created_at": "2025-01-15T10:30:00Z", "updated_at": "2025-01-15T10:30:05Z"}Response — 503
Section titled “Response — 503”Sync could not be started.
{ "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 |
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. Use GET /api/v1/run/jobs/{job_id}?wait=done&timeout_ms=30000 to poll for completion.
This endpoint takes no parameters.
This endpoint accepts no request body.
curl -X POST https://api.hoody.com/api/v1/run/sources/sync \ -H "Authorization: Bearer <token>"const job = await client.app.sources.syncAll();Response — 202
Section titled “Response — 202”Sync job accepted.
{ "job_id": "550e8400-e29b-41d4-a716-446655440000", "kind": "source-sync", "status": "running", "created_at": "2025-01-15T10:30:00Z", "updated_at": "2025-01-15T10:30:05Z"}Response — 503
Section titled “Response — 503”Sync could not be started.
{ "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 |
Update a source
Section titled “Update a 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”The body is an open-ended partial source configuration object. Any fields provided are merged into the existing configuration. Common fields include enabled, priority, pin, and config.
curl -X PATCH https://api.hoody.com/api/v1/run/sources/nixpkgs \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "enabled": true, "priority": 150 }'const source = await client.app.sources.update({ source_id: "nixpkgs", data: { enabled: true, priority: 150 }});Response — 200
Section titled “Response — 200”Updated source configuration.
{ "source_id": "nixpkgs", "enabled": true, "priority": 150, "provider": "nix", "source_type": "nix-flake"}Response — 404
Section titled “Response — 404”Source not found.
{ "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 list() and choose a valid source_id |
Response — 503
Section titled “Response — 503”Configuration persistence failed.
{ "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 source
Section titled “Delete a 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 on success.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
source_id | path | string | Yes | Source identifier |
This endpoint accepts no request body.
curl -X DELETE https://api.hoody.com/api/v1/run/sources/nixpkgs \ -H "Authorization: Bearer <token>"await client.app.sources.delete({ source_id: "nixpkgs"});Response — 204
Section titled “Response — 204”Source deleted successfully. No content returned.
Response — 404
Section titled “Response — 404”Source not found.
{ "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 list() and choose a valid source_id |
Response — 503
Section titled “Response — 503”Configuration persistence failed.
{ "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 |