API reference

Library

6 operations. Base URL https://api.scarleta.ai. Select an operation to see its parameters, samples and errors.

Jump to an operation
GET/v1/audio/library

List the library

Free and paid accounts
  • API key required
  • Free and paid accounts
  • No token cost

Lists your files grouped into tracks, newest first by default. A track holds one file, or several versions of the same song that you grouped. Each version includes the analyses it already has, plus its tags and archive state. Only your own files are ever returned.

Page with limit and cursor: pass pagination.cursor from one response as cursor in the next while pagination.has_more is true. limit is 1 to 200. The analysis results make responses large; send include_summaries=false to receive only the category names. With summaries, an array inside a summary object that holds more than 2048 values in total (counting every number or string, also inside nested arrays, such as an embedding or a spectrogram; each record of a list of records counts as one, plus any array inside it) is left out of the list, and its path is named in the summary's omitted_large_arrays. A summary that is itself an array is returned whole. GET /v1/audio/:audioId/analyses returns the complete summary.

View mode. Send view (a saved view id) and/or q (a view definition as base64url JSON, {"version":2,"filters":{...}}) and the route reads the library through that view instead. The response then carries the standard { data, meta } envelope with an X-Request-ID header, data also has total_tracks, coverage and view, tracks have hidden_versions and group_keys, versions have values, details, starred and duration_seconds, and limit is at most 100. An unknown view is 404 view_not_found; an invalid q is 400 invalid_config; grouping by sound before building sound groups is 400 invalid_group.

Without view and q the route answers with the older body shape: success is { data } with no meta, errors for bad query values are { error, message }, and the older bodies have no request_id of their own.

Cost. Free of charge.

curl "https://api.scarleta.ai/v1/audio/library" \
  -H "Authorization: Bearer $SCARLETA_API_KEY"

Parameters

NameTypeRequiredDescription
limitqueryintegerOptionalTracks per page, 1 to 200 (at most 100 in view mode).
cursorquerystringOptionalThe `pagination.cursor` of the previous page.
sort_keyquery"uploaded" | "name" | "size" | "last_activity" | "tags"OptionalWhat to sort by. Defaults to `uploaded`.
sort_dirquery"asc" | "desc"OptionalSort direction. Defaults to `desc`.
filter_tagsquerystringOptionalComma-separated tags to keep, at most 25.
filter_analysis_typequerystringOptionalKeep files that have this analysis category.
filter_date_fromquerynumberOptionalKeep files uploaded at or after this time, in milliseconds since the Unix epoch.
filter_date_toquerynumberOptionalKeep files uploaded at or before this time, in milliseconds since the Unix epoch.
filter_archivedquery"true"Optional`true` returns only archived files. Archived files are hidden otherwise.
viewquerystringOptionalId of one of your saved views. Switches the route to view mode; see the description.
qquerystringOptionalA view definition, JSON encoded as base64url. Switches the route to view mode; see the description.
include_summariesquery"true" | "false"Optional`false` leaves out the stored analysis results and keeps only the category names. Defaults to `true`.
Response fields
FieldTypeDescription
storageobject
storage.used_bytesnumberBytes your files currently use.
storage.cap_bytesnumberThe storage allowance shown for the account, in bytes.
storage.tier"free" | "paid"Whether the account is on the free or the paid tier.
storage.past_duebooleanTrue when the account has an unpaid storage overage.
storage.enforcedbooleanTrue when storage locks are actually applied.
tracksarray<object>
tracks[].idstringTrack identifier.
tracks[].namestringName of the newest version.
tracks[].versionsarray<object>Versions of the track, newest first.
tracks[].versions[].idstringIdentifier of this version of the track. Use it wherever a route asks for a file id.
tracks[].versions[].audio_idstringRegistry identifier of the file; it starts with `audio_`.
tracks[].versions[].namestringDisplay name of the file.
tracks[].versions[].labelstringShort label shown for this version.
tracks[].versions[].uploadednumber | nullWhen the file was uploaded, in milliseconds since the Unix epoch.
tracks[].versions[].file_size_bytesnumber | nullSize of the stored file in bytes, when known.
tracks[].versions[].formatstring | nullFile format, for example `wav`, when known.
tracks[].versions[].download_availablebooleanTrue when the original file is stored and can be downloaded.
tracks[].versions[].audio_urlstring | nullURL to pass as `audio_url` when running an analysis on this file. Null when the original is not stored.
tracks[].versions[].playback_urlstring | nullShort-lived URL for playing the file in a browser. Null when `audio_url` is null.
tracks[].versions[].analysesarray<object>The analyses this file already has.
tracks[].versions[].lockedbooleanTrue when the file is locked because of an unpaid storage overage. Locked files stay listed.
tracks[].versions[].pending_categoriesarray<string>Analysis categories still running on this file.
tracks[].versions[].failed_categoriesarray<string>Analysis categories that failed and have no completed result.
tracks[].versions[].tagsarray<string>Tags you added to this file.
tracks[].versions[].is_bestbooleanTrue when this version is marked as the best take of its track.
tracks[].versions[].archived_atstring | number | nullWhen the file was archived, or null.
tracks[].versions[].last_activitynumber | nullThe latest of upload time, newest analysis result and newest note, in milliseconds since the Unix epoch.
tracks[].versions[].duration_secondsnumber | nullLength of the audio. Present only when you send `view` or `q`.
tracks[].versions[].valuesobjectThe searchable values of this file (`bpm`, `key_label`, ...) with `bpm_source` and `key_source`. Present only when you send `view` or `q`.
tracks[].versions[].detailsobjectFile details such as title, artist and trash times. Present only when you send `view` or `q`.
tracks[].versions[].starredbooleanTrue when the file is starred. Present only when you send `view` or `q`.
tracks[].versions[].similaritynumber | nullSimilarity to a `sounds_like` reference. Present only with that filter.
tracks[].hidden_versionsintegerVersions the view hides. View mode only. Allowed: -9007199254740991 to 9007199254740991.
tracks[].group_keysarray<string>The group buckets of the track. View mode only.
paginationobject
pagination.limitinteger | nullThe page size used, or null when you sent no `limit`. Allowed: -9007199254740991 to 9007199254740991.
pagination.cursorstring | nullPass this as `cursor` to get the next page.
pagination.has_moreboolean
total_tracksintegerTracks the view matches. View mode only. Allowed: -9007199254740991 to 9007199254740991.
coverageobjectHow many files have each searchable value. View mode only.
coverage.total_library_sizeintegerFiles in scope before any value filter. Allowed: -9007199254740991 to 9007199254740991.
coverage.indexedobjectFor each searchable value (`bpm`, `key_label`, ...), how many files in scope have it.
viewobjectThe view that was applied. View mode only.
view.idstring | null
view.namestring | null
view.definitionobject
view.droppedarray<string>
Errors
StatusCodeDescription
401invalid_keyMissing, malformed, unknown or revoked API key.
404view_not_foundView mode: the saved view does not exist or is not yours.
429rate_limit_exceededOver the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.
503auth_unavailableTemporary platform condition; retry shortly.
Example responses
{
  "data": {
    "storage": {
      "used_bytes": 184220160,
      "cap_bytes": 1099511627776,
      "tier": "paid",
      "past_due": false,
      "enforced": true
    },
    "tracks": [
      {
        "id": "audio_3f9c1a7d2b60",
        "name": "demo-mix.wav",
        "versions": [
          {
            "id": "audio_3f9c1a7d2b60",
            "audio_id": "audio_3f9c1a7d2b60",
            "name": "demo-mix.wav",
            "label": "demo-mix.wav",
            "uploaded": 1791333870854,
            "file_size_bytes": 5290044,
            "format": "wav",
            "download_available": true,
            "audio_url": "https://api.scarleta.ai/v1/audio/media/9b2c7d1e-5a40-4f83-b6c9-0d1e2f3a4b5c.wav",
            "playback_url": null,
            "analyses": [
              {
                "category": "rhythm"
              }
            ],
            "locked": false,
            "pending_categories": [],
            "failed_categories": [],
            "tags": [
              "demo"
            ],
            "is_best": false,
            "archived_at": null,
            "last_activity": 1791333870854
          }
        ]
      }
    ],
    "pagination": {
      "limit": 25,
      "cursor": "1791333870854_audio_3f9c1a7d2b60",
      "has_more": false
    }
  }
}
  • 200 A page of tracks. Without `view` and `q` this response has no `meta`.
  • 400 A query value is not allowed: `limit` out of range, an unsupported `sort_key` or `sort_dir`, or too many `filter_tags` (body `{ error, message }`); in view mode, an invalid `q`, `view` or `group`, or a `limit` above the view cap (standard error body).
  • 401 Missing, malformed, unknown or revoked API key.
  • 404 View mode: the saved view does not exist or is not yours.
  • 429 Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.
  • 503 Temporary platform condition; retry shortly.

Try it

Sends this request from your browser to https://api.scarleta.ai with your own key. The key stays in this page only (never saved or put in the address) and is cleared when you leave. Revoke any key you have shared.

Other error codes this operation can return: db_unavailable, invalid_auth_format, invalid_config, invalid_group, invalid_key_format, invalid_limit, invalid_sort_dir, invalid_sort_key, missing_api_key, missing_auth, rate_limit_unavailable, too_many_filter_tags, unauthorized.

POST/v1/audio/library/batch

Run a recipe on a set of library files

Paid accounts onlyUses tokens
  • API key required
  • Paid accounts only
  • Uses tokens

Runs one recipe on every library file that matches a saved view (view_id) or a set of filters, as a batch. Send exactly one of the two. Batches are available on paid accounts only; a free-account key receives 403 batch_paid_only.

Send dry_run: true first: it changes nothing, charges nothing, and returns how many files matched and what the run would cost. Without dry_run the run starts and the call returns 202 with a batch_id; follow it with the batch routes. At most 500 files may match (max_items can lower that); a bigger match is refused with 422 query_result_too_large and an empty match with 422 query_result_empty. A real run is charged and rate limited exactly like a batch submit; see the Batch reference for the cost rule.

Cost. A dry run is free. A real run is charged per file when its run finishes, like a batch submit. Use `dry_run` to see the estimate first.

curl -X POST "https://api.scarleta.ai/v1/audio/library/batch" \
  -H "Authorization: Bearer $SCARLETA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "recipe_id": "rec_1005_cat_spectral",
    "filters": {
      "analyzed": [
        "rhythm"
      ],
      "name_contains": "demo"
    },
    "max_items": 20,
    "dry_run": true
  }'

Request body

NameTypeRequiredDescription
recipe_idbodystringRequiredThe recipe to run on every matched file. Allowed: at least 1 character.
view_idbodystringOptionalId of one of your saved views. Send this or `filters`, not both.
filtersbodyobjectOptionalWhich files to keep. Every field you send narrows the result; an empty object keeps every file. An unknown field is refused with 400 `invalid_filter`.
filters.bpmbodyobject | objectOptionalTempo range `{min, max}`, or `{near, tolerance}` (tolerance defaults to 3).
filters.bpm.minbodynumberOptional
filters.bpm.maxbodynumberOptional
filters.bpm.nearbodynumberOptional
filters.bpm.tolerancebodynumberOptional
filters.tempo_stabilitybodyobjectOptional
filters.tempo_stability.minbodynumberOptional
filters.tempo_stability.maxbodynumberOptional
filters.loudness_integratedbodyobjectOptional
filters.loudness_integrated.minbodynumberOptional
filters.loudness_integrated.maxbodynumberOptional
filters.loudness_rangebodyobjectOptional
filters.loudness_range.minbodynumberOptional
filters.loudness_range.maxbodynumberOptional
filters.true_peak_dbfsbodyobjectOptional
filters.true_peak_dbfs.minbodynumberOptional
filters.true_peak_dbfs.maxbodynumberOptional
filters.pitch_lowest_midibodyobjectOptional
filters.pitch_lowest_midi.minbodynumberOptional
filters.pitch_lowest_midi.maxbodynumberOptional
filters.pitch_highest_midibodyobjectOptional
filters.pitch_highest_midi.minbodynumberOptional
filters.pitch_highest_midi.maxbodynumberOptional
filters.notes_per_secondbodyobjectOptional
filters.notes_per_second.minbodynumberOptional
filters.notes_per_second.maxbodynumberOptional
filters.duration_secondsbodyobjectOptional
filters.duration_seconds.minbodynumberOptional
filters.duration_seconds.maxbodynumberOptional
filters.key_labelbodystring | array<string>OptionalOne key name or a list, for example `A minor`.
filters.key_rootbodystring | array<string>Optional
filters.key_modebody"major" | "minor"Optional
filters.meterbodystring | array<string>OptionalOne time signature or a list, for example `4/4`.
filters.speech_languagebodystring | array<string>Optional
filters.formatbodyarray<string>OptionalFile formats to keep, for example `["wav", "mp3"]`.
filters.transcript_containsbodystringOptionalKeep files whose transcript contains this text.
filters.sound_descriptionbodystringOptional
filters.name_containsbodystringOptionalKeep files whose name contains this text.
filters.user_tagsbodyobjectOptionalTag rules: keep files with any, with all, or with none of the listed tags.
filters.user_tags.anybodyarray<string>Optional
filters.user_tags.allbodyarray<string>Optional
filters.user_tags.nonebodyarray<string>Optional
filters.auto_tagsbodyarray<string>Optional
filters.analyzedbodyarray<string>OptionalKeep files that have results for every listed analysis category.
filters.analyzed_anybodyarray<string>OptionalKeep files that have results for at least one listed category.
filters.not_analyzedbodybooleanOptionalTrue keeps only files with no analysis results.
filters.missingbodyarray<string>OptionalKeep files that lack a value, for example `["bpm"]`.
filters.uploaded_afterbodynumberOptionalMilliseconds since the Unix epoch.
filters.uploaded_beforebodynumberOptionalMilliseconds since the Unix epoch.
filters.starredbodybooleanOptional
filters.archivedbody"hide" | "include" | "only"OptionalArchived files: hidden (default), included, or the only ones shown.
filters.include_derivedbodybooleanOptionalTrue also returns files made from other files, such as stems.
filters.sounds_likebodyobjectOptionalKeep files that sound like the given file.
filters.sounds_like.audio_idbodystringRequired
filters.sounds_like.min_scorebodynumberOptional
filters.sound_groupbodyobjectOptionalKeep the files of one sound group from a grouping job.
filters.sound_group.job_idbodystringRequired
filters.sound_group.group_idbodyintegerRequiredAllowed: -9007199254740991 to 9007199254740991.
filters.trashbody"hide" | "include" | "only"OptionalTrashed files: hidden (default), included, or the only ones shown.
filters.duplicatesbodybooleanOptionalTrue keeps only files that have an identical copy.
filters.artistbodyarray<string>Optional
filters.projectbodyarray<string>Optional
filters.albumbodyarray<string>Optional
filters.title_containsbodystringOptional
filters.credits_containsbodystringOptional
max_itemsbodyintegerOptionalRefuse the run when more files than this match. 1 to 500; defaults to 500.
dry_runbodybooleanOptionalTrue returns the estimate and starts nothing. Defaults to false.
namebodystringOptionalA label for the batch (real runs only).
webhook_urlbodystringOptionalWhere to POST the `batch_completed` event (real runs only). At most 4096 bytes.
metadatabodyobjectOptionalFree-form JSON kept with the batch (real runs only), at most 8192 bytes when serialized.
Response fields
FieldTypeDescription
matched_countintegerFiles the view or filters matched. Allowed: -9007199254740991 to 9007199254740991.
recipe_idstring
total_costnumberTokens the run would cost.
total_duration_secondsnumberAudio length the estimate covers, in seconds.
unknown_duration_countintegerFiles whose length could not be read; they add nothing to `total_cost`. Allowed: -9007199254740991 to 9007199254740991.
approximatebooleanTrue when some lengths were reported by the uploader or unknown, so the real charge can differ.
per_filearray<object>
per_file[].audio_idstring
per_file[].audio_urlstring
per_file[].duration_secondsnumber | nullLength of the file, or null when it could not be read.
per_file[].costnumberTokens this file would cost.
Errors
StatusCodeDescription
400invalid_configThe body is not a JSON object, has an unknown field, lacks `recipe_id`, names both or neither of `view_id` and `filters`, or a value such as `max_items` or `dry_run` is not valid.
401invalid_keyMissing, malformed, unknown or revoked API key.
402insufficient_balanceA real run needs a token balance or auto-recharge.
403batch_paid_onlyThe key belongs to a free account.
404view_not_foundThe saved view or the recipe does not exist or is not visible to your account.
422query_result_emptyNo file matches, or more than `max_items` files match. `error.details.matched_count` says how many matched.
429rate_limit_exceededOver the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.
503auth_unavailableTemporary platform condition; retry shortly.
Example responses
{
  "data": {
    "matched_count": 2,
    "recipe_id": "rec_1005_cat_spectral",
    "total_cost": 40,
    "total_duration_seconds": 7.2,
    "unknown_duration_count": 0,
    "approximate": false,
    "per_file": [
      {
        "audio_id": "audio_3f9c1a7d2b60",
        "audio_url": "https://api.scarleta.ai/v1/audio/media/9b2c7d1e-5a40-4f83-b6c9-0d1e2f3a4b5c.wav",
        "duration_seconds": 4,
        "cost": 20
      },
      {
        "audio_id": "audio_a81e5c40d7f2",
        "audio_url": "https://api.scarleta.ai/v1/audio/media/2c4e6a80-1b3d-4f57-8a9c-0e1d2c3b4a59.wav",
        "duration_seconds": 3.2,
        "cost": 20
      }
    ]
  },
  "meta": {
    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
  }
}
  • 200 Dry run: the estimate. Nothing was started.
  • 202 Accepted. The batch is queued.
  • 400 The body is not a JSON object, has an unknown field, lacks `recipe_id`, names both or neither of `view_id` and `filters`, or a value such as `max_items` or `dry_run` is not valid.
  • 401 Missing, malformed, unknown or revoked API key.
  • 402 A real run needs a token balance or auto-recharge.
  • 403 The key belongs to a free account.
  • 404 The saved view or the recipe does not exist or is not visible to your account.
  • 422 No file matches, or more than `max_items` files match. `error.details.matched_count` says how many matched.
  • 429 Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.
  • 503 Temporary platform condition; retry shortly.

Try it

Sends this request from your browser to https://api.scarleta.ai with your own key. The key stays in this page only (never saved or put in the address) and is cleared when you leave. Revoke any key you have shared.

Cost. A dry run is free. A real run is charged per file when its run finishes, like a batch submit. Use `dry_run` to see the estimate first.

Other error codes this operation can return: db_unavailable, invalid_auth_format, invalid_dry_run, invalid_filter, invalid_json, invalid_key_format, invalid_max_items, missing_api_key, missing_auth, missing_recipe_id, query_result_too_large, rate_limit_unavailable, recipe_not_found, unauthorized.

GET/v1/audio/library/builtin-counts

Count files in the standard views

Free and paid accounts
  • API key required
  • Free and paid accounts
  • No token cost

Returns one count per standard library view: everything, recently added, starred, not yet analyzed, duplicates and trash. Use it for a quick header without paging through the library. Only your own files are ever returned.

Cost. Free of charge.

curl "https://api.scarleta.ai/v1/audio/library/builtin-counts" \
  -H "Authorization: Bearer $SCARLETA_API_KEY"
Response fields
FieldTypeDescription
allintegerFiles in the library, not counting trash and archive. Allowed: -9007199254740991 to 9007199254740991.
recent_30dintegerFiles added recently; the key name states the window. Allowed: -9007199254740991 to 9007199254740991.
starredintegerStarred files. Allowed: -9007199254740991 to 9007199254740991.
not_analyzedintegerFiles with no analysis results yet. Allowed: -9007199254740991 to 9007199254740991.
duplicatesintegerFiles that have an identical copy. Allowed: -9007199254740991 to 9007199254740991.
trashintegerFiles in the trash. Allowed: -9007199254740991 to 9007199254740991.
library_files_totalintegerEvery file in your library, including archived and derived ones, but not files in the trash. Allowed: -9007199254740991 to 9007199254740991.
unverified_hash_countintegerFiles whose content fingerprint has not been checked yet. Allowed: -9007199254740991 to 9007199254740991.
Errors
StatusCodeDescription
401invalid_keyMissing, malformed, unknown or revoked API key.
429rate_limit_exceededOver the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.
503auth_unavailableTemporary platform condition; retry shortly.
Example responses
{
  "data": {
    "all": 42,
    "recent_30d": 7,
    "starred": 3,
    "not_analyzed": 11,
    "duplicates": 2,
    "trash": 1,
    "library_files_total": 50,
    "unverified_hash_count": 0
  },
  "meta": {
    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
  }
}
  • 200 Success
  • 401 Missing, malformed, unknown or revoked API key.
  • 429 Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.
  • 503 Temporary platform condition; retry shortly.

Try it

Sends this request from your browser to https://api.scarleta.ai with your own key. The key stays in this page only (never saved or put in the address) and is cleared when you leave. Revoke any key you have shared.

Other error codes this operation can return: db_unavailable, invalid_auth_format, invalid_key_format, missing_api_key, missing_auth, rate_limit_unavailable, unauthorized.

GET/v1/audio/library/overview

Get a library overview

Free and paid accounts
  • API key required
  • Free and paid accounts
  • No token cost

Summarises the whole library in one call: file and track counts, how many files each analysis category covers, your most used tags, your saved views, and when sound groups were last built. Only your own files are ever returned.

Cost. Free of charge.

curl "https://api.scarleta.ai/v1/audio/library/overview" \
  -H "Authorization: Bearer $SCARLETA_API_KEY"
Response fields
FieldTypeDescription
file_countintegerFiles in the library. Allowed: -9007199254740991 to 9007199254740991.
track_countintegerTracks in the library; versions of one song count once. Allowed: -9007199254740991 to 9007199254740991.
analyzed_countintegerFiles with at least one analysis result. Allowed: -9007199254740991 to 9007199254740991.
analyzed_by_categoryobjectNumber of files with a result in each analysis category.
tagsarray<object>Your most used tags.
tags[].tagstring
tags[].countintegerAllowed: -9007199254740991 to 9007199254740991.
saved_viewsarray<object>
saved_views[].idstringSaved view id.
saved_views[].namestring
sound_groupsobject | nullThe latest sound grouping, or null when you never built one.
sound_groups.countintegerGroups found. Allowed: -9007199254740991 to 9007199254740991.
sound_groups.built_atnumberWhen the grouping finished, in milliseconds since the Unix epoch.
Errors
StatusCodeDescription
401invalid_keyMissing, malformed, unknown or revoked API key.
429rate_limit_exceededOver the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.
503auth_unavailableTemporary platform condition; retry shortly.
Example responses
{
  "data": {
    "file_count": 42,
    "track_count": 40,
    "analyzed_count": 31,
    "analyzed_by_category": {
      "rhythm": 22,
      "spectral": 18
    },
    "tags": [
      {
        "tag": "demo",
        "count": 5
      }
    ],
    "saved_views": [
      {
        "id": "7d2c9e1a-4b3f-4c68-9a5d-1e0f8b7c6a52",
        "name": "Slow tracks"
      }
    ],
    "sound_groups": null
  },
  "meta": {
    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
  }
}
  • 200 Success
  • 401 Missing, malformed, unknown or revoked API key.
  • 429 Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.
  • 503 Temporary platform condition; retry shortly.

Try it

Sends this request from your browser to https://api.scarleta.ai with your own key. The key stays in this page only (never saved or put in the address) and is cleared when you leave. Revoke any key you have shared.

Other error codes this operation can return: db_unavailable, invalid_auth_format, invalid_key_format, missing_api_key, missing_auth, rate_limit_unavailable, unauthorized.

POST/v1/audio/library/query

Query the library

Free and paid accounts
  • API key required
  • Free and paid accounts
  • No token cost

Finds files by what the analyses found in them: tempo, key, loudness, tags, names, upload time and more. Send filters, optionally sort and limit, and read the matches from items. Only your own files are ever returned.

limit is 50 unless you send it, and at most 100. While has_more is true, send next_cursor back as cursor with the same filters and sort to get the next page. total_matches counts every match; coverage shows how many files have each searchable value, so you can tell "no match" from "not analyzed yet". Reading does not spend tokens.

Cost. Free of charge.

curl -X POST "https://api.scarleta.ai/v1/audio/library/query" \
  -H "Authorization: Bearer $SCARLETA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "filters": {
      "bpm": {
        "min": 90,
        "max": 130
      },
      "analyzed": [
        "rhythm"
      ]
    },
    "sort": [
      {
        "key": "uploaded",
        "dir": "desc"
      }
    ],
    "limit": 25
  }'

Request body

NameTypeRequiredDescription
filtersbodyobjectOptionalWhich files to keep. Every field you send narrows the result; an empty object keeps every file. An unknown field is refused with 400 `invalid_filter`.
filters.bpmbodyobject | objectOptionalTempo range `{min, max}`, or `{near, tolerance}` (tolerance defaults to 3).
filters.bpm.minbodynumberOptional
filters.bpm.maxbodynumberOptional
filters.bpm.nearbodynumberOptional
filters.bpm.tolerancebodynumberOptional
filters.tempo_stabilitybodyobjectOptional
filters.tempo_stability.minbodynumberOptional
filters.tempo_stability.maxbodynumberOptional
filters.loudness_integratedbodyobjectOptional
filters.loudness_integrated.minbodynumberOptional
filters.loudness_integrated.maxbodynumberOptional
filters.loudness_rangebodyobjectOptional
filters.loudness_range.minbodynumberOptional
filters.loudness_range.maxbodynumberOptional
filters.true_peak_dbfsbodyobjectOptional
filters.true_peak_dbfs.minbodynumberOptional
filters.true_peak_dbfs.maxbodynumberOptional
filters.pitch_lowest_midibodyobjectOptional
filters.pitch_lowest_midi.minbodynumberOptional
filters.pitch_lowest_midi.maxbodynumberOptional
filters.pitch_highest_midibodyobjectOptional
filters.pitch_highest_midi.minbodynumberOptional
filters.pitch_highest_midi.maxbodynumberOptional
filters.notes_per_secondbodyobjectOptional
filters.notes_per_second.minbodynumberOptional
filters.notes_per_second.maxbodynumberOptional
filters.duration_secondsbodyobjectOptional
filters.duration_seconds.minbodynumberOptional
filters.duration_seconds.maxbodynumberOptional
filters.key_labelbodystring | array<string>OptionalOne key name or a list, for example `A minor`.
filters.key_rootbodystring | array<string>Optional
filters.key_modebody"major" | "minor"Optional
filters.meterbodystring | array<string>OptionalOne time signature or a list, for example `4/4`.
filters.speech_languagebodystring | array<string>Optional
filters.formatbodyarray<string>OptionalFile formats to keep, for example `["wav", "mp3"]`.
filters.transcript_containsbodystringOptionalKeep files whose transcript contains this text.
filters.sound_descriptionbodystringOptional
filters.name_containsbodystringOptionalKeep files whose name contains this text.
filters.user_tagsbodyobjectOptionalTag rules: keep files with any, with all, or with none of the listed tags.
filters.user_tags.anybodyarray<string>Optional
filters.user_tags.allbodyarray<string>Optional
filters.user_tags.nonebodyarray<string>Optional
filters.auto_tagsbodyarray<string>Optional
filters.analyzedbodyarray<string>OptionalKeep files that have results for every listed analysis category.
filters.analyzed_anybodyarray<string>OptionalKeep files that have results for at least one listed category.
filters.not_analyzedbodybooleanOptionalTrue keeps only files with no analysis results.
filters.missingbodyarray<string>OptionalKeep files that lack a value, for example `["bpm"]`.
filters.uploaded_afterbodynumberOptionalMilliseconds since the Unix epoch.
filters.uploaded_beforebodynumberOptionalMilliseconds since the Unix epoch.
filters.starredbodybooleanOptional
filters.archivedbody"hide" | "include" | "only"OptionalArchived files: hidden (default), included, or the only ones shown.
filters.include_derivedbodybooleanOptionalTrue also returns files made from other files, such as stems.
filters.sounds_likebodyobjectOptionalKeep files that sound like the given file.
filters.sounds_like.audio_idbodystringRequired
filters.sounds_like.min_scorebodynumberOptional
filters.sound_groupbodyobjectOptionalKeep the files of one sound group from a grouping job.
filters.sound_group.job_idbodystringRequired
filters.sound_group.group_idbodyintegerRequiredAllowed: -9007199254740991 to 9007199254740991.
filters.trashbody"hide" | "include" | "only"OptionalTrashed files: hidden (default), included, or the only ones shown.
filters.duplicatesbodybooleanOptionalTrue keeps only files that have an identical copy.
filters.artistbodyarray<string>Optional
filters.projectbodyarray<string>Optional
filters.albumbodyarray<string>Optional
filters.title_containsbodystringOptional
filters.credits_containsbodystringOptional
sortbody"uploaded_at_desc" | "uploaded_at_asc" | "bpm_asc" | "bpm_desc" | "loudness_asc" | "loudness_desc" | "name_asc" | array<object>OptionalEither one of the short names (`uploaded_at_desc`, `bpm_asc`, ...) or a list of `{ key, dir }`. Defaults to newest first.
limitbodyintegerOptionalMatches per page, 1 to 100. Defaults to 50.
cursorbodystringOptionalThe `next_cursor` of the previous page.
Response fields
FieldTypeDescription
itemsarray<object>The matching files.
items[].audio_idstring
items[].original_filenamestring
items[].display_namestring | null
items[].audio_urlstringURL to pass as `audio_url` when running an analysis on this file.
items[].playback_urlstring | null
items[].duration_secondsnumber | null
items[].formatstring | null
items[].uploaded_atnumberMilliseconds since the Unix epoch.
items[].starredboolean
items[].user_tagsarray<string>
items[].analyzed_categoriesarray<string>Analysis categories this file has results for.
items[].bpmnumber | null
items[].tempo_stabilitynumber | null
items[].key_labelstring | null
items[].key_rootstring | null
items[].key_modestring | null
items[].meterstring | null
items[].loudness_integratednumber | null
items[].loudness_rangenumber | null
items[].true_peak_dbfsnumber | null
items[].pitch_lowest_midinumber | null
items[].pitch_highest_midinumber | null
items[].notes_per_secondnumber | null
items[].speech_languagestring | null
items[].transcript_textstring | null
items[].sound_descriptionstring | null
items[].auto_tagsarray<string> | null
items[].bpm_sourcestring | nullWhere the tempo came from: your own value or the analysis.
items[].key_sourcestring | nullWhere the key came from: your own value or the analysis.
items[].detailsobject
items[].details.titlestring | null
items[].details.artiststring | null
items[].details.albumstring | null
items[].details.projectstring | null
items[].details.creditsstring | null
items[].details.has_coverbooleanTrue when the file has cover art.
items[].details.content_sha256string | nullFingerprint of the file content; equal values mean identical files.
items[].details.trashed_atnumber | nullWhen the file was moved to the trash, in milliseconds since the Unix epoch, or null.
items[].details.purge_atnumber | nullWhen a trashed file is removed for good, or null.
items[].similaritynumber | nullSimilarity to the `sounds_like` reference. Present only when the query uses `sounds_like`.
countintegerNumber of items in this page. Allowed: -9007199254740991 to 9007199254740991.
total_matchesintegerNumber of files that match the filters. Allowed: -9007199254740991 to 9007199254740991.
has_moreboolean
next_cursorstring | nullPass this as `cursor` to get the next page.
coverageobject
coverage.total_library_sizeintegerFiles in scope before any value filter. Allowed: -9007199254740991 to 9007199254740991.
coverage.indexedobjectFor each searchable value (`bpm`, `key_label`, ...), how many files in scope have it.
Errors
StatusCodeDescription
400invalid_filterThe body is not a JSON object, has an unknown field, or a filter, sort, `limit` or `cursor` is not valid. `error.details.field` names the field.
401invalid_keyMissing, malformed, unknown or revoked API key.
404audio_not_foundA `sounds_like` reference file does not exist in your library.
409embedding_missingThe `sounds_like` reference file has no sound fingerprint yet.
429rate_limit_exceededOver the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.
503auth_unavailableTemporary platform condition; retry shortly.
Example responses
{
  "data": {
    "items": [
      {
        "audio_id": "audio_3f9c1a7d2b60",
        "original_filename": "demo-mix.wav",
        "display_name": "Demo mix",
        "audio_url": "https://api.scarleta.ai/v1/audio/media/9b2c7d1e-5a40-4f83-b6c9-0d1e2f3a4b5c.wav",
        "playback_url": null,
        "duration_seconds": 184.2,
        "format": "wav",
        "uploaded_at": 1791333870854,
        "starred": false,
        "user_tags": [
          "demo"
        ],
        "analyzed_categories": [
          "rhythm"
        ],
        "bpm": 118.5,
        "tempo_stability": null,
        "key_label": null,
        "key_root": null,
        "key_mode": null,
        "meter": null,
        "loudness_integrated": null,
        "loudness_range": null,
        "true_peak_dbfs": null,
        "pitch_lowest_midi": null,
        "pitch_highest_midi": null,
        "notes_per_second": null,
        "speech_language": null,
        "transcript_text": null,
        "sound_description": null,
        "auto_tags": null,
        "bpm_source": "analysis",
        "key_source": null,
        "details": {
          "title": null,
          "artist": null,
          "album": null,
          "project": null,
          "credits": null,
          "has_cover": false,
          "content_sha256": null,
          "trashed_at": null,
          "purge_at": null
        }
      }
    ],
    "count": 1,
    "total_matches": 1,
    "has_more": false,
    "next_cursor": null,
    "coverage": {
      "total_library_size": 42,
      "indexed": {
        "bpm": 17,
        "key_label": 9,
        "meter": 12
      }
    }
  },
  "meta": {
    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
  }
}
  • 200 Success
  • 400 The body is not a JSON object, has an unknown field, or a filter, sort, `limit` or `cursor` is not valid. `error.details.field` names the field.
  • 401 Missing, malformed, unknown or revoked API key.
  • 404 A `sounds_like` reference file does not exist in your library.
  • 409 The `sounds_like` reference file has no sound fingerprint yet.
  • 429 Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.
  • 503 Temporary platform condition; retry shortly.

Try it

Sends this request from your browser to https://api.scarleta.ai with your own key. The key stays in this page only (never saved or put in the address) and is cleared when you leave. Revoke any key you have shared.

Other error codes this operation can return: cluster_job_not_found, db_unavailable, invalid_auth_format, invalid_config, invalid_cursor, invalid_json, invalid_key_format, invalid_limit, invalid_sort, missing_api_key, missing_auth, rate_limit_unavailable, unauthorized.

GET/v1/audio/library/view-counts

Count tracks in each saved view

Free and paid accounts
  • API key required
  • Free and paid accounts
  • No token cost

Returns an object that maps the id of each of your saved views to the number of tracks it currently matches. The object is empty when you have no saved views. Only your own files are ever returned.

Cost. Free of charge.

curl "https://api.scarleta.ai/v1/audio/library/view-counts" \
  -H "Authorization: Bearer $SCARLETA_API_KEY"
Errors
StatusCodeDescription
401invalid_keyMissing, malformed, unknown or revoked API key.
429rate_limit_exceededOver the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.
503auth_unavailableTemporary platform condition; retry shortly.
Example responses
{
  "data": {
    "7d2c9e1a-4b3f-4c68-9a5d-1e0f8b7c6a52": 12
  },
  "meta": {
    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
  }
}
  • 200 Success
  • 401 Missing, malformed, unknown or revoked API key.
  • 429 Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.
  • 503 Temporary platform condition; retry shortly.

Try it

Sends this request from your browser to https://api.scarleta.ai with your own key. The key stays in this page only (never saved or put in the address) and is cleared when you leave. Revoke any key you have shared.

Other error codes this operation can return: db_unavailable, invalid_auth_format, invalid_key_format, missing_api_key, missing_auth, rate_limit_unavailable, unauthorized.