Design your integration around complete, deliberate search requests, whether you compose them on your server or forward user input.
Supe is an AI music supervisor, not a keyword autocomplete. A new search uses a model to interpret the input and find catalog recommendations; equivalent requests may reuse cached results. Send a complete request so Supe has enough creative direction to work with. This page covers how to send Supe the kind of request it is built for, whether your backend composes the query or forwards what a user types.
What Supe expects
A search request should be a complete thought: a natural-language brief, optionally paired with scene context or reference assets. Supe is at its best on a finished description and at its weakest on half-typed fragments, because a fragment does not yet describe any music.
The mental modelSend Supe a complete thought, a phrase or a full brief, not a stream of partial inputs. It rewards a finished description and struggles with fragments.
Choose an integration pattern
Calls to Supe always go through your own backend. Client applications must not call the endpoint directly, because your API token grants privileged access to the catalog. From your backend, there are two common patterns:
- Compose the query server-side (recommended). Collect the user's intent in your interface, then build or refine the search request on your backend before calling Supe. This gives you control over the creative brief: you can enrich sparse input, add scene context, drop obvious noise, and decide when a search is worth running. Keep the user's intent intact when enriching the query.
- Forward user input (pass-through). Send the user's typed query through your backend to Supe more or less as-is. This is simpler to build, but it puts the burden of query quality on the raw input, so it needs the guardrails below.
If you forward user input, debounce
Pass-through input that reaches Supe on every keystroke sends a run of incomplete fragments. As someone types acoustic guitar, an un-debounced field fires a, ac, aco, and so on, and those fragments may not convey the intended music. This creates unnecessary requests and can show irrelevant or empty results while the user is still typing.
Apply these guardrails before a pass-through request reaches Supe:
- Debounce. Prefer an explicit search submit. If you search after typing pauses, a suggested starting delay is 400 to 600 milliseconds, not an API requirement. Tune it for your interface; a pause alone does not mean the query is complete.
- Check for useful input. Choose an interface validation rule that encourages a complete word or phrase. This is a product guardrail, not an API minimum query length; see Create a search for request validation.
- Send only the latest input. Collapse rapid edits so a single request carries the final text, not one per intermediate state.
- Ignore superseded responses. If a newer request has gone out, discard results from any older in-flight request so stale results never overwrite fresh ones.
Anti-pattern: a request per keystrokeFiring a search on each character sends requests before the user has expressed their intent. A fragment like
acois less useful thanacoustic guitar for a relaxed travel film. Neither wording guarantees a particular result; wait for a complete query before submitting.
Handle both response paths
Submit a search with POST /v1/supe/search and a callback_url, then branch on the HTTP response. See Create a search.
- HTTP 202: read the search ID from
data.idand theprocessingstatus fromdata.attributes.status. Yourcallback_urlreceives the results when the search finishes. See Webhooks. - HTTP 200: an equivalent completed search was cached. Read the full results directly from this response; no webhook is sent for the cache hit.
For example, the relevant fields in an accepted response are:
{
"data": {
"id": "<search-id>",
"type": "supe_searches",
"attributes": {
"status": "processing"
}
}
}This example shows only the fields needed to track acceptance. Completed responses also expose data.attributes.status; check it before treating an empty song list as a successful search, because a search can finish with failed status.
Do not resubmit while a search is still processing. An equivalent in-flight request returns HTTP 202 with the existing data.id, without starting new work or registering another callback. The webhook goes only to the first request's callback_url.
Equivalent completed searches are cached for 24 hours per API key. See Supe Search for how query, context, and assets determine equivalence. You can fetch a finished search again with GET /v1/supe/search/{search_id}, using the value from data.id. This endpoint returns the latest terminal execution (completed or failed) for that search ID, or HTTP 404 if none exists for your API key. Equivalent inputs reuse the same search ID: during a retry after failure or a resubmission after the result cache expires, GET may return a previous execution's result with HTTP 200 while the newer execution is still processing. Do not treat it as a processing-status endpoint or assume that a returned result belongs to the newer execution. See Retrieve a search.
Handle empty results gracefully
A search with data.attributes.status of completed can return zero songs. This can happen when the brief is unclear, the constraints are too narrow, or no suitable catalog match is found. Rather than showing a dead end, prompt the user to add detail (a mood, a genre, the use case) or to broaden their wording. For guidance you can surface to your users, see Writing Effective Queries.
Mind the rate limit and usage
Supe shares the standard enterprise rate limit of 25 requests per second per API key. Composing queries server-side and debouncing pass-through input reduce unnecessary traffic; your backend should also handle rate-limit responses. Search usage and charges follow your contract, including whether cache hits are billable. Confirm your plan's terms with your account manager.
Integration checklist
- Requests are complete queries, composed on your backend or sent on an explicit user submit.
- Pass-through input is debounced and checked for useful content, and no request goes out on a per-keystroke basis.
- Only the latest query is sent, and superseded responses are discarded.
- Both HTTP 202 acceptance and HTTP 200 cached results are handled.
- Search IDs and statuses are read from
data.idanddata.attributes.status.- You do not resubmit while a search is still processing or expect a second callback for a duplicate request.
- Empty results prompt the user to add detail instead of showing a dead end.
- Calls are made from your backend, never directly from a client application.