Trace
Search
Compare songs at exactly the layers you choose with a custom search, or run the comprehensive search for a fast all-round check. Both support one song against one song, one song against a dataset, and dataset against dataset.
Custom search
POST/trace/v3/searchsearch at the depths you choose
The request returns 201 with a job_id straight away; the search runs in the background. Poll the job as described in Results & Billing.
201 Created
{"job_id": "018f0000-0000-7000-8000-0000000000a2", "status": "queued"}Not sure which depths to pick? The comprehensive search and the use cases choose them for you.
Request fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| search_type | "1:1" | "1:n" | "m:n" | Yes | — | The search shape. See the Trace Overview. |
| query_file_id | string | No | — | Required for 1:1 and 1:n. The file_id of the song you are checking. |
| candidate_file_id | string | No | — | Required for 1:1. The file_id of the song to compare against. |
| candidate_dataset_name | string | No | — | Required for 1:n and m:n. The dataset to search. |
| query_dataset_name | string | No | — | Required for m:n. The dataset whose songs are the queries. |
| depth | string | string[] | No | ["track"] | The layers to compare. See Depth values below. |
| stem_types | string[] | No | ["vocals"] | Instruments to compare when depth includes stem or stem_section: vocals, bass, drums, other. |
| limit | integer | No | all matches | Maximum matches returned per query song, for 1:n and m:n. Must be 1 or more. |
| budget_tokens | integer | No | no cap | Optional cap on what this job may cost. See Results & Billing. |
| query_url | string | No | — | Legacy alternative to query_file_id: a blob_name from POST /trace/v3/upload. |
| candidate_url | string | No | — | Legacy alternative to candidate_file_id: a blob_name. |
If you send both a file ID and a blob_name for the same side, the file ID is used. Full URLs are never accepted as song inputs; upload the file with POST /v1/files and pass its file_id.
Depth values
Combine several depths in one search, for example ["track", "section", "lyrics"]. For 1:n and m:n, the datasets must have been ingested with every depth you request. A 1:1 search needs no ingestion.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| track | full mix | No | — | The whole song. The dataset needs track. |
| light_stem | vocals + accompaniment | No | — | Vocals and accompaniment, compared separately. The dataset needs light_stem. |
| stem | instruments | No | — | The instruments in stem_types, compared separately. The dataset needs stem. |
| section | structure | No | — | Matching song sections. The dataset needs section. |
| stem_section | structure per instrument | No | — | Sections within each instrument in stem_types. The dataset needs stem and section. |
| motif | melody | No | — | Melodic phrases. The dataset needs motif. |
| lyrics | text | No | — | Transcribed lyrics. The dataset needs lyrics. |
| translation | text | No | — | Lyrics after translating both songs to English. The dataset needs translation. |
| insights | tags | No | — | Genre, instrument and style tags. The dataset needs insights. |
lyrics, translation and insights need file_id inputs, because Trace looks up each song’s lyrics and tags through its file. A search with only these depths compares text and style without any audio layer.
Examples
One song against one song (1:1)
curl -X POST https://apiv2.soundverse.ai/trace/v3/search \
-H "Authorization: Bearer sksoundverse_..." \
-H "Content-Type: application/json" \
-d '{
"search_type": "1:1",
"query_file_id": "018f0000-0000-7000-8000-000000000003",
"candidate_file_id": "018f0000-0000-7000-8000-000000000001",
"depth": ["track"]
}'One song against a dataset (1:N)
{
"search_type": "1:n",
"query_file_id": "018f0000-0000-7000-8000-000000000003",
"candidate_dataset_name": "reference-catalog",
"depth": ["track", "section", "lyrics"],
"limit": 10
}Dataset against dataset (M:N)
Every song in the query dataset is compared with every song in the candidate dataset.
{
"search_type": "m:n",
"query_dataset_name": "new-releases",
"candidate_dataset_name": "reference-catalog",
"depth": ["track"]
}Choosing instruments
Compare the bass and drums separately, for example to look for a lifted groove:
{
"search_type": "1:n",
"query_file_id": "018f0000-0000-7000-8000-000000000003",
"candidate_dataset_name": "reference-catalog",
"depth": ["stem"],
"stem_types": ["bass", "drums"]
}Comprehensive search
POST/trace/v3/comprehensive1fast all-round check
GET/trace/v3/comprehensive1/jobs/{job_id}same response as /trace/v3/jobs/{job_id}
A fixed profile that compares songs on three independent signals at once, so you can judge similarity from more than one angle: the full mix, the vocals and accompaniment (each separately), and the melody in the vocals and in the other instruments. It suits screening work such as copyright checks, where one score on its own is not enough.
The request takes the same song and dataset fields as a custom search, plus limit and budget_tokens. It has no depth: the profile decides the layers.
curl -X POST https://apiv2.soundverse.ai/trace/v3/comprehensive1 \
-H "Authorization: Bearer sksoundverse_..." \
-H "Content-Type: application/json" \
-d '{
"search_type": "1:n",
"query_file_id": "018f0000-0000-7000-8000-000000000003",
"candidate_dataset_name": "reference-catalog"
}'Prepare the datasets
For 1:n and m:n, ingest the datasets with track, light_stem and motif — the default ingestion, so a dataset ingested without a depth is ready. If a layer is missing, the job still completes but results.error names what is missing.
Each match carries a summary with the three signals side by side and is ranked by the full-mix score:
{
"id": "b3ea82b7b97c8e2f733cd7850d12db41f4f334aa59c88cdd09538c3554d28326.mp3",
"score": 0.636743,
"percentage": 63.67,
"summary": {
"full_audio_hungarian_mean": 0.636743,
"full_audio_max_then_mean": 0.69,
"full_audio_max": 0.81,
"vocal_hungarian_mean": 0.58,
"vocal_max_then_mean": 0.62,
"vocal_max": 0.77,
"motif_matches_vocals_count": 2,
"motif_matches_other_count": 5
},
"full_audio_latent_scores": {},
"vocal_latent_scores": {},
"instrumental_latent_scores": {},
"motif_matches": {}
}| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| full_audio_* | number | No | — | Similarity of the full mix. |
| vocal_* | number | No | — | Similarity of the separated vocals. |
| instrumental_latent_scores | object | No | — | Similarity of the accompaniment, with per-window detail. |
| motif_matches_*_count | integer | No | — | How many melodic phrases matched in the vocals and in the other instruments. |
For a deeper check that also compares structure, every instrument, lyrics and style, use the Comprehensive – Deep use case.
Validation errors
These return 422 InvalidGenerationInput; nothing is queued or charged.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| search_type must be one of '1:1', '1:n', 'm:n' | 422 | No | — | search_type is missing or invalid. |
| a 1:1 search needs both a query and a candidate track (…) | 422 | No | — | A 1:1 search is missing one of its songs. |
| a 1:n search needs a query track and candidate_dataset_name | 422 | No | — | A 1:n search is missing the query song or the dataset. |
| an m:n search needs query_dataset_name and candidate_dataset_name | 422 | No | — | An m:n search is missing a dataset. |
| unknown depth 'x' | 422 | No | — | A depth value is not in the table above. |
| stem_types takes vocals, bass, drums and other | 422 | No | — | A stem_types value is not one of the four instruments. |
| limit must be an integer >= 1 | 422 | No | — | limit is zero, negative or not a whole number. |
| query_url takes a blob_name …, not a url | 422 | No | — | A full URL was passed as a song input. |
A search that names a dataset you do not have, or a depth the dataset was not ingested with, is accepted but finishes as failed with the reason in error, and is not charged. For authentication, balance and rate-limit errors, see Results & Billing.