Agent notes: the enterprise endpoint
Gotcha notes for AI agents writing AudD enterprise-endpoint code — billing, the chunked response shape, and how to compute file-absolute timestamps.
Terse gotchas for an agent about to write code against
POST https://enterprise.audd.io/. These are the things that bite — read
them before you generate the request, not after the bill arrives. For the
full walkthrough see the enterprise recipes; this page is the short list.
1. Always set limit in development
The enterprise endpoint bills per 12 seconds of audio processed. The default is unbounded: an enterprise call on a one-hour file ingests the whole hour, in 12-second chunks, and charges for every chunk it scans.
Set
limit=1while you build. It caps the server at one recognized chunk so a test run against a long file can’t quietly process hours of audio. Raise it only once you understand the cost of the real file.
curl -s https://enterprise.audd.io/ \
-F api_token=your-api-token \
-F url=https://audd.tech/example.mp3 \
-F limit=1
limit is the upper bound on the number of 12-second chunks the server
will recognize. The public test token does not work here — enterprise needs a real
token from dashboard.audd.io.
2. The response is an array of chunks, not a flat song list
Standard recognize returns one result object (or null). Enterprise
returns result as an array of chunks. Each chunk is one 12-second
window of the file and looks like:
{
"offset": "00:48",
"songs": [
{
"score": 100,
"artist": "Barely Alive",
"title": "Keyboard Killer",
"timecode": "00:41",
"start_offset": 1,
"end_offset": 9660,
"song_link": "https://lis.tn/KeyboardKiller"
}
]
}
offset—MM:SS, the position in your submitted file of the start of this 12-second fragment.songs[]— every match found inside that fragment. Usually one entry, but can be several when fragments overlap song boundaries or the audio is ambiguous. Each carries the usualscore,artist,title,timecode,song_link, plus the offsets below.
The same song appears across many consecutive chunks while it plays. To get a per-song tracklist you collapse runs of adjacent chunks that share the same track — don’t treat each chunk as a distinct play.
3. The SDKs flatten chunks — file positions are start_seconds / end_seconds
The typed SDKs surface enterprise results as a flat list of matches (for
example list[EnterpriseMatch] in Python) rather than the raw chunk array.
Each match carries start_seconds and end_seconds — file-absolute
positions, in seconds into the file you submitted. The SDKs request
accurate_offsets=true by default and apply the chunk offset +
start_offset / 1000 arithmetic for you, so those seconds are precise.
If you need where in the file a song played, read
start_secondson the match. Don’t recompute it fromstart_offset— that field is a within-fragment value (see below), not a file position.
The raw fragment-relative start_offset / end_offset milliseconds are
also on each match when you need them.
4. start_offset / end_offset are milliseconds inside the fragment
Do not read start_offset as a file position. Both start_offset and
end_offset are milliseconds within the 12-second fragment — they run
roughly 0–12000. In the example above start_offset: 1, end_offset: 9660
means the match occupied ~0.0s to ~9.66s of that fragment, and the
fragment itself starts at offset: "00:48" in the file.
File-absolute start time, in seconds, when you call the HTTP API directly
(the SDKs precompute this as start_seconds):
def parse_offset(mmss: str) -> int:
m, s = mmss.split(":")
return int(m) * 60 + int(s)
# chunk["offset"] = "00:48", song["start_offset"] = 1
file_start_seconds = parse_offset(chunk["offset"]) + song["start_offset"] / 1000
# 48 + 0.001 = 48.001
Three different “time” fields live on an enterprise match — keep them straight:
| Field | Unit | Means |
|---|---|---|
offset (on the chunk) | MM:SS | start of the 12s fragment in your file |
start_offset / end_offset (on the song) | milliseconds | span within that 12s fragment |
timecode (on the song) | MM:SS | position in the matched track where your audio lined up — not a file position |
The per-fragment start_offset / end_offset are only populated when the
request sets accurate_offsets=true; the SDKs set it by default.
5. accurate_offsets, every, skip, skip_first_seconds
accurate_offsets=true— populates the per-fragmentstart_offset/end_offset. Without it, don’t expect meaningful sub-fragment offsets. The SDKs send it by default.every/skip— reduce metered audio by sampling.skipis how many 12-second chunks to skip after each scanned run;everyis how many chunks to scan in a row.skip=4, every=1scans 12s then skips 48s, repeating — one recognition per 60 seconds of audio, billed for one chunk per minute instead of five.skip_first_seconds— skip the start of the file (e.g. a known intro) before recognition begins. Don’t combine withuse_timecode.
These directly lower cost; reach for them before raising limit on big
files.
6. ISRC / UPC need a plan
isrc and upc appear on enterprise matches only on the Startup plan or
higher. On lower plans the fields are simply absent — don’t write code
that assumes they’re always present, and don’t treat their absence as an
error.
7. Use enterprise, not standard, when the file is long or multi-song
Reach for enterprise — not POST https://api.audd.io/ — whenever the input
is longer than a short clip or may contain more than one song: a
full-length track, a short-form video, a podcast, a broadcast, a DJ set.
Standard recognize returns one match for one short clip and caps files at
10 MB; enterprise chunks the file server-side, returns every match, and has
no practical size cap. Picking standard for a long file is an easy
structural mistake — you’ll get one match for the whole file and miss
everything else.
Related
Reading this as an AI agent? The raw Markdown is at agents/enterprise.md, and the full index is /resources/llms.txt.
