Oddtune
Dashboard
Developer documentationv1.1.0

Oddtune API

Create an audio verification to check for evidence of AI-generated content. Oddtune analyzes the original audio and its stems, returning detection results and downloadable PDF reports.

Base URL

https://api.oddtune.com

Authentication

X-API-Key

Your Oddtune API key.

Your first audio analysis

From an audio file to results in four steps with Python.

Manage API keys

Install Requests and set your API key in your terminal. Keep the key on your server.

bash
python3 -m pip install requests
export ODDTUNE_API_KEY="your_api_key"
Full Python example

Save this as verify.py beside song.mp3, then run python3 verify.py. Use a 55–600 second MP3 up to 128 MiB.

python
# Create a verification job
import os
import time

import requests

base_url = "https://api.oddtune.com"
headers = {"X-API-Key": os.environ["ODDTUNE_API_KEY"]}
filename = "song.mp3"
content_type = "audio/mpeg"

response = requests.post(
    f"{base_url}/v1/audio/verify",
    headers=headers,
    json={
        "source_type": "upload",
        "filename": filename,
        "content_type": content_type,
    },
    timeout=30,
)
response.raise_for_status()

verification = response.json()
verification_id = verification["verification_id"]
print("Verification ID:", verification_id)

# Upload audio
with open(filename, "rb") as audio:
    response = requests.put(
        verification["upload_url"],
        headers={"Content-Type": content_type},
        data=audio,
        timeout=300,
    )

response.raise_for_status()

# Check status
while True:
    response = requests.post(
        f"{base_url}/v1/audio/verify/results",
        headers=headers,
        json={"verification_ids": [verification_id]},
        timeout=30,
    )
    response.raise_for_status()
    result = response.json()["verifications"][0]

    if result.get("error") == "not_found":
        raise RuntimeError(f"not_found: {result['message']}")

    if result["status"] == "completed":
        print(result["components"])
        break

    if result["status"] == "failed":
        error = result["error"]
        raise RuntimeError(f"{error['code']}: {error['message']}")

    time.sleep(5)

# Get a report link
response = requests.get(
    f"{base_url}/v1/audio/verify/{verification_id}/report",
    headers=headers,
    params={"component": "original"},
    timeout=120,
)
response.raise_for_status()

for component in response.json()["reports"]:
    print(component["name"], component["report"]["url"])

1. Create a verification job

Submit the file details to get a verification ID and upload URL.

python
import os
import time

import requests

base_url = "https://api.oddtune.com"
headers = {"X-API-Key": os.environ["ODDTUNE_API_KEY"]}
filename = "song.mp3"
content_type = "audio/mpeg"

response = requests.post(
    f"{base_url}/v1/audio/verify",
    headers=headers,
    json={
        "source_type": "upload",
        "filename": filename,
        "content_type": content_type,
    },
    timeout=30,
)
response.raise_for_status()

verification = response.json()
verification_id = verification["verification_id"]
print("Verification ID:", verification_id)

Authentication

Send your API key in the X-API-Key header on every API request.

Audio and usage limits

Supported formats: MP3, WAV, FLAC, AIFF, AAC, and M4A/MP4 audio. Each file must be at most 128 MiB and between 55 and 600 seconds long. Files over the size or duration limit fail after upload with audio_too_large or audio_too_long. Shorter audio also fails after upload.

Limits are shared across your organization's API keys. Submissions have a separate rate limit from reads: submissions per second equal your plan's concurrent-analysis allowance. History, results, and report requests share a read limit of at least 10 requests per second, or your concurrent-analysis allowance if higher.

Errors and retries

HTTP errors return {"error": "...", "message": "..."}. Failed verifications return HTTP 200 with status: failed and error: {code, message}.

On 429, respect Retry-After when present. Back off on 500 or 503.

Submission, history, and results responses include X-Request-ID. Share it with support when troubleshooting; it is separate from the verification_id.

Endpoint reference

4 endpoints

4 matching endpoints

Verifications

Submit audio, check results, and browse your history.

post/v1/audio/verify

Create audio verifications

X-API-Key

Submit 1–25 uploads in songs. HTTP 200 returns an ID and upload URL or an error for each song, in input order. Check every entry for errors.

Upload each file with HTTP PUT within 15 minutes, then poll /v1/audio/verify/results. Retries do not extend the upload deadline. Each verification analyzes the original audio, vocals, drums, and other stem.

One quota unit is reserved per accepted song and charged only on success. Failed verifications and expired uploads release the reservation.

For a single upload, you can send source_type, filename, and content_type at the top level. Do not combine these fields with songs.

Parameters

Idempotency-Keystringin header

Optional; recommended for safe retries. Set IDEMPOTENCY_KEY to a new UUID for each submission; reuse the key and exact body on retries to recover the original outcomes. Rejections are retained too: use a new key after correcting songs or resolving quota errors. Keys are shared across your organization, do not expire, and accept 1–128 visible ASCII characters. Without a key, retries create new verifications and reserve quota again.

Min length: 1 · Max length: 128

Request bodyrequired

source_typeenum

Audio source type.

upload
filenamestring

Audio filename, up to 255 UTF-8 bytes. Do not include directory paths or control characters.

min length: 1

content_typeenum

MIME type of the upload. Use this same value as the Content-Type header in the PUT upload.

audio/mpegaudio/mp3audio/flacaudio/x-flacaudio/wavaudio/x-wavaudio/waveaudio/aiffaudio/x-aiffaudio/aacaudio/mp4audio/x-m4a
UploadSong[]

min items: 1 · max items: 25

Example request

bash
curl -X POST "https://api.oddtune.com/v1/audio/verify" \
  -H "X-API-Key: $ODDTUNE_API_KEY" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "songs": [
    {
      "source_type": "upload",
      "filename": "song.mp3",
      "content_type": "audio/mpeg"
    },
    {
      "source_type": "upload",
      "filename": "another-song.mp3",
      "content_type": "audio/mpeg"
    }
  ]
}'

Responses

For songs arrays, returns per-song outcomes in input order, including errors. Single-song requests return one verification object.

VerificationSubmissionResponse
json
{
  "verifications": [
    {
      "verification_id": "550e8400-e29b-41d4-a716-446655440000",
      "upload_url": "https://example.com/upload/song.mp3?signature=example",
      "expires_in": 900,
      "units": 1
    },
    {
      "error": "quota_exceeded",
      "message": "Quota exceeded"
    }
  ]
}

Example values. Optional fields may be omitted.

post/v1/audio/verify/results

Get verification results

X-API-Key

Check 1–100 distinct verification IDs. Results are returned in input order, with detection results when completed. Missing or inaccessible IDs return a per-ID not_found error. One ID also returns a verifications array. Poll until completed or failed; failed verifications include error.code and error.message. Organization identity comes from your API key.

Request bodyrequired

verification_idsstring[]required

min items: 1 · max items: 100

Example request

bash
curl -X POST "https://api.oddtune.com/v1/audio/verify/results" \
  -H "X-API-Key: $ODDTUNE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "verification_ids": [
    "550e8400-e29b-41d4-a716-446655440000"
  ]
}'

Responses

Verification outcomes in input order

VerificationResultsResponse
json
{
  "verifications": [
    {
      "verification_id": "550e8400-e29b-41d4-a716-446655440000",
      "status": "completed",
      "created_at": "2026-04-03T12:34:56Z",
      "updated_at": "2026-04-03T12:35:30Z",
      "filename": "song.mp3",
      "units": 1,
      "components": [
        {
          "type": "original",
          "name": "original",
          "detection": {
            "contains_generated": true,
            "origin": "suno",
            "evidence_strength": 0.87
          }
        },
        {
          "type": "stem",
          "name": "vocals",
          "detection": {
            "contains_generated": true,
            "origin": "suno",
            "evidence_strength": 0.85
          }
        },
        {
          "type": "stem",
          "name": "drums",
          "detection": {
            "contains_generated": false,
            "origin": null
          }
        },
        {
          "type": "stem",
          "name": "other",
          "detection": {
            "contains_generated": true,
            "origin": "suno",
            "evidence_strength": 0.82
          }
        }
      ]
    }
  ]
}

Example values. Optional fields may be omitted.

get/v1/audio/verify/history

List verification history

X-API-Key

Returns your organization's verifications, newest first. To continue, pass next_cursor as cursor with the same search and status filters. Stop when next_cursor is null, even if a page contains fewer than limit items.

Parameters

limitintegerin querydefault: 25

Maximum verifications per page.

Minimum: 1 · Maximum: 100

querystringin query

Case-insensitive search of verification IDs, filenames, audio metadata, sources, results, and submitters.

Min length: 1 · Max length: 200

statusstringin query

Return only verifications with this status.

pendingprocessingcompletedfailed

cursorstringin query

The unchanged next_cursor from the previous page.

Example request

bash
curl -X GET "https://api.oddtune.com/v1/audio/verify/history?limit=25" \
  -H "X-API-Key: $ODDTUNE_API_KEY"

Responses

A page of verifications.

VerificationListResponse
json
{
  "items": [
    {
      "verification_id": "550e8400-e29b-41d4-a716-446655440000",
      "status": "completed",
      "created_at": "2026-04-03T12:34:56Z",
      "updated_at": "2026-04-03T12:35:30Z",
      "filename": "song.mp3",
      "units": 1,
      "components": [
        {
          "type": "original",
          "name": "original",
          "detection": {
            "contains_generated": true,
            "origin": "suno",
            "evidence_strength": 0.87
          }
        },
        {
          "type": "stem",
          "name": "vocals",
          "detection": {
            "contains_generated": true,
            "origin": "suno",
            "evidence_strength": 0.85
          }
        },
        {
          "type": "stem",
          "name": "drums",
          "detection": {
            "contains_generated": false,
            "origin": null
          }
        },
        {
          "type": "stem",
          "name": "other",
          "detection": {
            "contains_generated": true,
            "origin": "suno",
            "evidence_strength": 0.82
          }
        }
      ]
    }
  ],
  "next_cursor": "string"
}

Example values. Optional fields may be omitted.

Reports

Download PDF reports for completed verifications.

get/v1/audio/verify/{verification_id}/report

Download PDF reports

X-API-Key

Returns PDF download links for a completed verification. Pass component to retrieve one component's report; omit it to return all reports, ordered as the original followed by its stems. Requesting one component at a time is recommended when reports have not yet been generated.

Links expire after one hour; call this endpoint again for new links. Download the links directly without sending your API key. Downloads use application/pdf and .pdf filenames; this endpoint returns JSON. Report generation consumes no additional analysis units.

Parameters

verification_idstringin pathrequired

Verification ID returned when creating the verification.

componentstringin query

Exact component name from the completed verification, such as original or vocals. Returns one entry in reports. Omit for all components.

Min length: 1

Example request

bash
curl -X GET "https://api.oddtune.com/v1/audio/verify/{verification_id}/report?component=original" \
  -H "X-API-Key: $ODDTUNE_API_KEY"

Responses

Temporary download links for the PDF reports.

ReportResponse
json
{
  "verification_id": "550e8400-e29b-41d4-a716-446655440000",
  "reports": [
    {
      "type": "original",
      "name": "original",
      "report": {
        "url": "https://example.com/report.pdf?signature=example",
        "expires_in": 3600
      }
    }
  ]
}

Example values. Optional fields may be omitted.