Skip to content

Latest commit

 

History

History
599 lines (364 loc) · 15.7 KB

File metadata and controls

599 lines (364 loc) · 15.7 KB

TuneForge API

Overview

The desktop backend exposes a local FastAPI API under /api/v1. It is intended for the bundled TuneForge frontend on the same machine and binds to 127.0.0.1 by default.

This document summarizes the current route surface. The generated OpenAPI schema in packages/shared-types/openapi.json remains the implementation source of truth for exact schemas and generated TypeScript types.

Conventions

  • Base path: /api/v1
  • Request and response format: JSON unless an endpoint streams a file.
  • IDs: string identifiers generated by the backend.
  • Timestamps: ISO 8601 strings in API responses.
  • Errors use a structured error object with code, message, and details.

Example error response:

{
  "error": {
    "code": "PROJECT_NOT_FOUND",
    "message": "Project not found.",
    "details": {}
  }
}

Shared Shapes

Job

Jobs represent asynchronous work such as analysis, chords, lyrics, transforms, stems, previews, and exports.

Important fields:

  • id
  • project_id
  • type
  • status
  • progress
  • source_artifact_id
  • chord_backend
  • chord_source
  • error_message
  • runtime_device
  • created_at
  • updated_at

Artifact

Artifacts represent generated or imported files associated with a project.

Important fields:

  • id
  • project_id
  • type
  • format
  • path
  • size_bytes
  • generated_by
  • can_delete
  • can_regenerate
  • metadata
  • created_at

Health

Get health

GET /api/v1/health

Returns backend name, legacy backend git ref in version, backend/frontend package versions and git refs, status, API base URL, data root, default export format, and preview format. Build git refs use the packaged build metadata when available, otherwise local development resolves them with git describe --tags --long --dirty --always.

Chord Backends

List chord backends

GET /api/v1/chord-backends

Returns available chord backends and capability metadata. Built-in chords are always expected to be available. Advanced Chords may be unavailable when optional desktop-only dependencies are not installed or the runtime platform is mobile.

Stem Models

List stem models

GET /api/v1/stem-models

Returns supported stem models and availability metadata. Labels are Default (6 stems model) for htdemucs_6s and 2 stems model for htdemucs_ft.

Sync

The sync API exposes local sync metadata, identity, and trust management for the bundled desktop app. FastAPI remains bound to loopback; LAN transport, peer discovery, QR scanning, and file transfer belong to the separate native sync layer.

device_id is the stable identity for one TuneForge install. sync_group_id identifies the sync group that trusted devices may share. Display names are editable convenience labels and must not be treated as identity.

Get local sync identity

GET /api/v1/sync/identity

Returns the local sync identity, creating it if it does not exist yet.

Response wrapper:

  • identity

Identity fields:

  • device_id
  • sync_group_id
  • display_name - nullable convenience label.
  • public_key
  • created_at - nullable when the service returns an identity DTO without persistence metadata.
  • updated_at - nullable when the service returns an identity DTO without persistence metadata.

Update local sync identity

PATCH /api/v1/sync/identity

Updates the local identity display name.

Request fields:

  • display_name

Response wrapper:

  • identity

Changing display_name does not change device_id, sync_group_id, or public identity material.

Create sync pairing offer

POST /api/v1/sync/pairing/offers

Creates a short-lived manual pairing offer for copy/paste style pairing. The endpoint does not start LAN discovery, expose FastAPI beyond loopback, or create QR UI.

Request fields:

  • endpoint_hints - optional advisory peer endpoints, default [].
  • ttl_seconds - pairing offer lifetime in seconds, default 600, maximum 3600.

Response wrapper:

  • pairing_offer

Pairing offer fields:

  • payload
  • expires_at
  • ttl_seconds

The payload is the portable value another device submits inside the payload field of POST /api/v1/sync/trusted-peers. For this backend-first slice, a peer trust request must carry the pairing_offer_id and pairing_secret from a pending local offer so this install can verify the manual exchange before storing trust. It includes:

  • protocol_version
  • pairing_offer_id
  • sync_group_id
  • device_id
  • display_name
  • public_key
  • endpoint_hints
  • pairing_secret
  • expires_at
  • signature

Pairing payloads are signed by the source device's private identity key so copied payloads are tamper-evident. Endpoint hints are advisory and do not authenticate a peer. The receiving install must still explicitly trust the payload before accepting manifests, revisions, tombstones, or artifact bytes from that device. The payload submitted to this endpoint must reference a locally issued pairing_offer_id; that local offer must still be unused, unexpired, and match the payload's pairing_secret.

List trusted peers

GET /api/v1/sync/trusted-peers

Returns active peers this install explicitly trusts. Revoked peers are not returned by this list.

Response wrapper:

  • trusted_peers

Trusted peer fields:

  • device_id
  • sync_group_id
  • display_name
  • public_key
  • endpoint_hints
  • trusted_at
  • revoked_at
  • updated_at

Trust is explicit and non-transitive. Joining the same sync_group_id, discovering a device, or hearing about a peer from another trusted device does not automatically trust that peer.

Trust peer from pairing payload

POST /api/v1/sync/trusted-peers

Stores trust for one peer from a manual pairing payload.

Request fields:

  • payload - pairing payload copied from another device.
  • adopt_sync_group - whether this install should adopt the payload's sync_group_id, default false.

Response wrapper:

  • trusted_peer

Trusting a peer records its device_id, public identity, display name, endpoint hints, and sync group. The peer can later be revoked without deleting local projects or changing this install's own device_id. Standalone payloads that do not reference a local pending offer are rejected.

Revoke trusted peer

DELETE /api/v1/sync/trusted-peers/{device_id}

Revokes trust for the peer with the matching device_id.

Response wrapper:

  • trusted_peer

Revocation stops this install from accepting future sync material from that peer unless it is explicitly paired again. Revocation is local to this install and does not revoke trust transitively on any other device.

Run sync preflight

GET /api/v1/sync/preflight

Checks the local library before multi-device sync is enabled. The endpoint returns HTTP 200 for both passing and failing preflight results because failures are actionable diagnostics rather than request errors.

The response includes:

  • ok
  • project status counts
  • per-project sync identity status
  • duplicate source-hash groups
  • manual cleanup guidance

Project status values are ready, missing_source_hash, invalid_source_hash, duplicate_source_hash, and noncanonical_project_id. Canonical project IDs use proj_sha256_<full_source_sha256>, while project storage directories use a shorter derived key such as proj_<first_24_sha256_hex>. This endpoint is sync-specific; general project responses do not expose source hashes.

Get sync metadata

GET /api/v1/sync/metadata

Returns sync-safe project and artifact metadata so sync clients do not need to read the local SQLite database directly. The endpoint does not expose absolute local file paths.

Project fields:

  • project_id
  • display_name
  • source_key_override
  • source_sha256
  • duration_seconds
  • sample_rate
  • channels
  • created_at
  • updated_at

Artifact fields:

  • artifact_id
  • project_id
  • type
  • format
  • relative_path
  • content_sha256
  • size_bytes
  • generated_by
  • can_delete
  • can_regenerate
  • cache_key
  • metadata
  • created_at

relative_path is project-root relative when the artifact is stored under the backend-managed project root; otherwise it is null. Artifact metadata is sanitized recursively before returning and removes local path-bearing keys such as source_path, original_copy_path, playback_path, imported_path, and any metadata key ending in _path. Non-path metadata such as retune/transpose settings, stem_model, and source_artifact_id is preserved. Job internals such as result_artifact_ids_json are not exposed.

Export project sync manifest

GET /api/v1/sync/projects/{project_id}/manifest

Returns a single project manifest for manifest-only sync export. The response is wrapped as project_manifest and includes:

  • schema_version
  • exported_at
  • project
  • artifacts

Manifest paths are project-root relative and use portable path separators. The response does not expose absolute local source, project, artifact, or app data paths. Artifact entries include content_sha256, and the project entry includes source_sha256; receiving peers must verify staged bytes against these SHA-256 values before accepting the import. For this v1 manifest spike, a portable manifest must contain exactly one source_audio artifact, and that artifact must match the project source_sha256; normalized proxy-only source imports are not portable until original-source artifacts are modeled explicitly. The endpoint exports metadata only. File transfer and LAN peer discovery belong to the native sync layer, not the loopback FastAPI API.

Import staged project sync manifest

POST /api/v1/sync/projects/import

Imports a project from a previously exported project manifest plus files that have already been staged on disk by the sync transport.

Request fields:

  • manifest
  • staging_root

staging_root is a local directory containing the staged project files at the relative paths declared in the manifest. During import, the backend verifies source and artifact bytes with SHA-256, rewrites accepted paths into this install's backend-managed project root, and persists the project through backend services instead of copying database rows from another device.

If the local library already contains the same canonical project or source SHA-256, staged import rejects the duplicate with HTTP 409 instead of creating a second project. The response uses the normal project wrapper shape:

  • project

Staged import does not enqueue analysis, chord, lyrics, stem, or other generation jobs. Synced projects should import the durable state that was actually exported; future rebuilds are explicit user actions. This endpoint also does not expose FastAPI on the LAN. Peer communication should keep using the separate native sync layer while FastAPI remains bound to loopback.

Projects

Import project

POST /api/v1/projects/import

Creates a project from a source path and queues initial analysis and chord jobs.

Request fields:

  • source_path
  • copy_into_project
  • display_name

Response: ProjectResponse.

If the same source track has already been imported, the endpoint returns HTTP 409 with code DUPLICATE_PROJECT_SOURCE, message This project is already imported with name "{name}"., and details containing:

  • project_id
  • project_name

List projects

GET /api/v1/projects

Optional query:

  • search

Response: ProjectsResponse.

Get project

GET /api/v1/projects/{project_id}

Response: ProjectResponse.

Update project

PATCH /api/v1/projects/{project_id}

Supported fields:

  • display_name
  • source_key_override

Response: ProjectResponse.

Delete project

DELETE /api/v1/projects/{project_id}

Deletes the project and project-owned data.

Response: DeleteResponse.

Analysis

Start analysis

POST /api/v1/projects/{project_id}/analyze

Queues an analysis job.

Request fields:

  • include_tempo
  • force

Response: JobResponse.

Get analysis

GET /api/v1/projects/{project_id}/analysis

Returns the stored analysis result, or null if no result exists.

Analysis includes key, key confidence, reference tuning, tuning offset, tempo, analysis version, source artifact, and creation time.

Chords

Generate chords

POST /api/v1/projects/{project_id}/chords

Queues chord generation.

Request fields:

  • backend
  • backend_fallback_from
  • force
  • overwrite_user_edits

Response: JobResponse.

Get chords

GET /api/v1/projects/{project_id}/chords

Returns source segments, current timeline segments, backend, source artifact, source kind, user-edit state, metadata, and timestamps. If no chord timeline exists, the response contains an empty timeline.

Lyrics

Generate lyrics

POST /api/v1/projects/{project_id}/lyrics

Queues local lyrics generation.

Request fields:

  • force

Response: JobResponse.

Get lyrics

GET /api/v1/projects/{project_id}/lyrics

Returns source transcript segments, current edited segments, backend, source artifact, model/device metadata, language, user-edit state, and timestamps. If no lyrics exist, the response contains empty segment lists.

Update lyrics

PUT /api/v1/projects/{project_id}/lyrics

Persists edited lyric segment text.

Request fields:

  • segments

Each segment currently accepts:

  • text

Response: LyricsResponse.

Transforms and Previews

Retune

POST /api/v1/projects/{project_id}/retune

Queues a retune job.

Request fields:

  • exactly one of target_reference_hz or target_cents_offset
  • preview_only
  • output_format

Response: JobResponse.

Transpose

POST /api/v1/projects/{project_id}/transpose

Queues a transpose job.

Request fields:

  • semitones
  • preview_only
  • output_format

Response: JobResponse.

Generate preview

POST /api/v1/projects/{project_id}/preview

Queues a preview job for a retune and/or transpose transform.

Request fields:

  • retune
  • transpose
  • output_format

At least one transform must be provided.

Response: JobResponse.

Stems

Generate stems

POST /api/v1/projects/{project_id}/stems

Queues stem generation for the selected source audio or practice mix.

Request fields:

  • mode
  • stem_model
  • output_format
  • force
  • source_artifact_id
  • chord_backend
  • chord_backend_fallback_from
  • overwrite_chord_edits

Current validation allows mode: "stems" or mode: "two_stem" and output_format: "wav". If stem_model is omitted, mode: "stems" uses the backend default htdemucs_6s; mode: "two_stem" maps to htdemucs_ft for compatibility.

htdemucs_6s creates visible Vocals, Drums, Bass, Guitar, Piano, and Other artifacts. htdemucs_ft creates visible Vocals and Instrumental artifacts.

Response: JobResponse.

Project Artifacts

List project artifacts

GET /api/v1/projects/{project_id}/artifacts

Returns artifacts for a project ordered by newest first.

Response: ArtifactsResponse.

Delete project artifact

DELETE /api/v1/projects/{project_id}/artifacts/{artifact_id}

Deletes a project artifact when it belongs to the project and can be removed.

Response: DeleteResponse.

Export

Export project artifacts

POST /api/v1/projects/{project_id}/export

Queues an export job for selected project artifacts.

Request fields:

  • artifact_ids
  • mixdown_mode
  • output_format
  • destination_path

At least one artifact ID is required.

Response: JobResponse.

Jobs

List jobs

GET /api/v1/jobs

Returns all jobs ordered by most recently updated.

Response: JobsResponse.

Get job

GET /api/v1/jobs/{job_id}

Response: JobResponse.

Cancel job

POST /api/v1/jobs/{job_id}/cancel

Requests cancellation for a job.

Response: JobResponse.

Artifact Streaming

Stream artifact

GET /api/v1/artifacts/{artifact_id}/stream

Streams the artifact file as an audio response. Returns ARTIFACT_NOT_FOUND if the artifact row or file is missing.