---
title: "Agent notes: the enterprise endpoint"
description: "Gotcha notes for AI agents writing AudD enterprise-endpoint code — billing, the chunked response shape, and how to compute file-absolute timestamps."
slug: "/resources/agents/enterprise"
section: "agents"
keywords: [audd, enterprise endpoint, agent, offset, limit, billing, timestamps]
---

# Agent notes: the enterprise endpoint

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=1` while 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.

```bash
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](https://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:

```json
{
  "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 usual `score`, `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_seconds` on
> the match.** Don't recompute it from `start_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`):

```python
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-fragment `start_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. `skip` is how many
  12-second chunks to skip after each scanned run; `every` is how many
  chunks to scan in a row. `skip=4, every=1` scans 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 with `use_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**

- [Controlling enterprise endpoint cost](/resources/concepts/enterprise-cost-control)
- [Standard vs. enterprise vs. streams](/resources/concepts/standard-vs-enterprise-vs-streams)
- [Result fields reference](/resources/reference/result-fields)
- [Recipe: DJ set tracklist](/resources/recipes/dj-set-tracklist)
- [Enterprise endpoint (API reference)](https://docs.audd.io/enterprise)