Skip to main content
Find sound effects by describing the moment you’re scoring — “whoosh for a scene change”, “cash register cha-ching”, “soft notification chime” — and get back ranked SFX, each with a pre-signed download URL. It’s the same semantic search behind background music: set type=sound_effects on GET /v3/audio/sounds and describe what you want in plain language.

Search the Catalog

Send a GET request to /v3/audio/sounds with a natural-language query and type=sound_effects:
curl -X GET "https://api.heygen.com/v3/audio/sounds?query=whoosh%20for%20a%20scene%20change&type=sound_effects&limit=3" \
  -H "x-api-key: YOUR_API_KEY"
Response
{
  "data": [
    {
      "id": "7f2e91ac5b3d4e8f9a1c6d0b2e4f8a3c",
      "name": "Cinematic Whoosh: 7f2e91ac",
      "description": "Fast airy whoosh transition, ideal for scene changes and reveals.",
      "audio_url": "https://heygen-product.s3-accelerate.amazonaws.com/sound_effects/7f2e91ac...wav?X-Amz-Algorithm=...",
      "duration": 1.4,
      "score": 0.941,
      "type": "sound_effects"
    },
    {
      "id": "c4a8d2f1e6b9470a8d3e5f7c1a9b2d6e",
      "name": "Swipe Transition: c4a8d2f1",
      "description": "Quick swish swipe, light and modern, suited to UI motion and cuts.",
      "audio_url": "https://heygen-product.s3-accelerate.amazonaws.com/sound_effects/c4a8d2f1...wav?X-Amz-Algorithm=...",
      "duration": 0.9,
      "score": 0.902,
      "type": "sound_effects"
    }
  ],
  "has_more": true,
  "next_token": "eyJvZmZzZXQiOiAzLCAiX3R5cGUiOiAic291bmRfZWZmZWN0cyJ9"
}

Query Parameters

ParameterTypeDefaultDescription
querystringRequired. Natural-language description of the sound you want, e.g. cash register cha-ching. Results are ranked by semantic similarity to this text.
typestringmusicAudio content type. Set to sound_effects to search the SFX catalog; music (the default) searches background music.
limitinteger10Maximum number of results to return (1–50).
min_scorenumber0.7Minimum semantic similarity score (0–1). Effects scoring below this are omitted. Raise it for tighter matches; lower it to widen the net.
tokenstringOpaque pagination cursor. Pass the next_token from a prior response to fetch the next page.

Response Fields

FieldTypeDescription
data[].idstringStable identifier for the sound effect.
data[].namestringDisplay name of the sound effect.
data[].descriptionstringHuman-readable description of the sound and where it fits.
data[].audio_urlstringPre-signed download URL for the audio file (WAV).
data[].durationnumberLength in seconds. Most effects are short — under a few seconds.
data[].scorenumberSemantic similarity score (0–1) against your query. Results are returned highest-first.
data[].typestringsound_effects for results from the SFX catalog.
has_morebooleantrue if more results are available beyond this page.
next_tokenstringCursor for the next page. Pass it as token on your next request. Absent when has_more is false.
Each audio_url is a pre-signed link with a limited lifetime. Download the file (or hand the URL to a downstream step) soon after searching rather than caching it for later.

Paginate Through Results

When has_more is true, pass the returned next_token as the token parameter to fetch the next page:
curl -X GET "https://api.heygen.com/v3/audio/sounds?query=whoosh%20for%20a%20scene%20change&type=sound_effects&limit=3&token=eyJvZmZzZXQiOiAzLCAiX3R5cGUiOiAic291bmRfZWZmZWN0cyJ9" \
  -H "x-api-key: YOUR_API_KEY"

Full Example

import requests
from urllib.parse import urlencode

API_KEY = "YOUR_API_KEY"
BASE = "https://api.heygen.com"
HEADERS = {"x-api-key": API_KEY}

def search_sound_effects(query, limit=10, min_score=0.7):
    """Yield every matching sound effect, following pagination."""
    token = None
    while True:
        params = {
            "query": query,
            "type": "sound_effects",
            "limit": limit,
            "min_score": min_score,
        }
        if token:
            params["token"] = token
        resp = requests.get(
            f"{BASE}/v3/audio/sounds?{urlencode(params)}",
            headers=HEADERS,
        )
        page = resp.json()
        for effect in page["data"]:
            yield effect
        if not page.get("has_more"):
            break
        token = page["next_token"]

# Grab the single best-matching effect
best = next(search_sound_effects("cash register cha-ching", limit=1))
print(f"{best['name']} ({best['duration']}s, score {best['score']:.2f})")
print(f"Download: {best['audio_url']}")
If your integration validates the type field in responses against an enum, add sound_effects to it — the changelog entry for this release has the full migration note.