API Documentation

Accuracy

Important considerations:

  • This AI detector is very good at detecting pure AI songs (99.4%+ accuracy)
  • However, as soon as 3rd party mastering or processing takes place, the detection becomes a lot trickier
  • Any positive result should be examined closely before making any accusations
  • This model was last updated in September, 2026 and may struggle to successfully detect AI audio generated with software released since then

Authentication

All API requests require authentication using an API key. Include your API key in the X-API-Key header of each request.

X-API-Key: sk_your_api_key_here

Endpoints

POST/api/v1/detect

Submits an audio file for AI detection analysis. Returns results directly (typically takes 5-10 seconds).

Request Body

Provide one of audioUrl, spotifyTrackId, or isrc:

ParameterTypeRequiredDescription
audioUrlstringOne requiredURL of the audio file to analyze (MP3, WAV, M4A, MP4, or FLAC format)
spotifyTrackIdstringOne requiredSpotify track ID (e.g., "2JUDGXTQYGQZrVVUgq40Ke"). The API will automatically extract the audio from Spotify.
isrcstringOne requiredISRC code (e.g., "QT3F32442476"). The API will look up the matching track on Spotify and extract its audio.

Full-length audio vs. previews

How much audio we analyze for spotifyTrackId and isrc lookups depends on your plan:

PlanAudio analyzed
Pro, BusinessThe full-length track, lossless where available
Verified (free)The ~30 second preview clip from Spotify

Every response tells you which one you got via audio_source. Preview analysis is still accurate, but a 30 second clip carries less signal than a full track, so scores can differ between the two — don't compare them directly.

Note that audio_source reports what we actually analyzed, not what your plan entitles you to. A handful of tracks have no full-length source we can reach; on a paid plan those fall back to the preview and come back as "preview" with anotice explaining why. Read the field rather than assuming from the plan.

Two things to know about previews. Spotify does not publish a preview for every track; when it's missing you'll get a No preview audio available error rather than a result. And previews are low-bitrate lossy MP3, so heavily compressed or processed material is harder to call than it is from lossless audio.

audioUrl is unaffected — whatever you point us at is what we analyze, on every plan.

Response

{
  "result": {
    "duration": 180.5,
    "probability_ai_generated": 95.2,
    "prediction": "Pure AI",
    "confidence_score": 92.3,
    "spectral_probabilities": {
      "human": 4.8,
      "processed_ai": 15.2,
      "pure_ai": 80.0
    },
    "temporal_probabilities": {
      "human": 2.1,
      "processed_ai": 12.7,
      "pure_ai": 85.2
    },
    "most_likely_ai_type": "Suno AI",
    "treblo_probability": 99.99
  },
  "version": "v4.3",
  "response_time": 8456,
  "audio_source": "full",
  "usage": {
    "daily_remaining": 44,
    "monthly_remaining": 849
  }
}

On a free plan the same spotifyTrackId request returns the analysis of the preview clip, flagged as such:

{
  "result": { ... },
  "version": "v4.3",
  "response_time": 6120,
  "audio_source": "preview",
  "notice": "Analyzed a ~30 second Spotify preview clip, not the full track. Upgrade to Pro or Business to analyze full-length audio.",
  "usage": {
    "daily_remaining": 44,
    "monthly_remaining": 849
  }
}

Stem analysis

When the whole-mix result is uncertain, we may also split the track into vocal and instrumental stems and score each one separately to reach a firmer answer. That helps most with a human vocal over an AI instrumental (or the reverse), which a whole-mix model can misread in either direction. When the split runs, the result carries a stem_verdict:

"stem_verdict": { "vocal": 75.1, "instrumental": 29.9 }   // vocals and music
"stem_verdict": { "vocal": null, "instrumental": 52.5 }   // instrumental track
"stem_verdict": { "vocal": 65.6, "instrumental": null }   // a cappella

Each value is the probability (0-100) that the stem is AI-generated. A stem is null when the track has nothing there to judge: no singing for vocal, or no music beyond leftover residue for instrumental.

When both stems are present and one reads clearly more AI than the other, probability_ai_generated and prediction already account for it. A mid-range score can be raised, but never above 69, so stem evidence alone can't put a track in the high-confidence range. A score of 85 or above that reads as one AI stem over one human stem is lowered, since that points to a human-plus-AI collaboration rather than a fully generated track. You don't need to apply anything yourself. Tracks that aren't split don't carry the field.

Response Fields

FieldTypeDescription
resultobjectAnalysis results from the AI detection service
result.durationnumberDuration of the audio file in seconds
result.probability_ai_generatednumberProbability (0-100) that the audio is AI-generated
result.predictionstring"Human Made", "Pure AI", or "Processed AI" based on analysis
result.confidence_scorenumberConfidence score (0-100) of the prediction
result.spectral_probabilitiesobjectBreakdown of probabilities by spectral analysis (human, processed_ai, pure_ai)
result.temporal_probabilitiesobjectBreakdown of probabilities by temporal analysis (human, processed_ai, pure_ai)
result.most_likely_ai_typestringMost likely AI generator type (field omitted when human-made, only present for AI-detected audio)
result.treblo_probabilitynumberProbability (0-100) from Treblo's own AI detector that the track is Treblo-generated. Only present when Treblo's detector is confident (above 85) — when present, it drives prediction and confidence_score
result.stem_verdictobjectPer-stem scores, present only when the track was sent for vocal/instrumental separation — see "Stem analysis" above. Omitted otherwise
result.stem_verdict.vocalnumber or nullProbability (0-100) that the isolated vocal stem is AI-generated. null when no singing was found
result.stem_verdict.instrumentalnumber or nullProbability (0-100) that the isolated instrumental stem is AI-generated. null when there's no music to judge (a cappella)
versionstringVersion of the detection model that produced this result (e.g. "v4.3")
response_timenumberTotal response time for the API request in milliseconds
audio_sourcestring"full" if the full-length track was analyzed, "preview" if a ~30 second Spotify preview clip was (only present for spotifyTrackId and isrc lookups)
noticestringExplains a limitation applied to this result (only present when audio_source is "preview")
usageobjectCurrent usage limits and remaining requests

Code Examples

# Using audio URL
curl -X POST https://shlabs.music/api/v1/detect \
  -H "X-API-Key: sk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"audioUrl": "https://example.com/audio.mp3"}'

# Using Spotify track ID
curl -X POST https://shlabs.music/api/v1/detect \
  -H "X-API-Key: sk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"spotifyTrackId": "2JUDGXTQYGQZrVVUgq40Ke"}'

# Using ISRC
curl -X POST https://shlabs.music/api/v1/detect \
  -H "X-API-Key: sk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"isrc": "QT3F32442476"}'

Error Codes

Status CodeDescription
200Success - Audio analyzed successfully
400Bad Request - Invalid request body or missing parameters
401Unauthorized - Missing or invalid API key
429Too Many Requests - Rate limit exceeded or too many concurrent requests
500Internal Server Error - AI detection service temporarily unavailable
503Service Unavailable - Spotify resolution service unreachable, or the request queue is saturated

The distinction matters if you retry automatically. A 400 means the request or the audio is the problem and will return the same error however many times you send it — audio the detector cannot use (too short, too long, silent, corrupt, unsupported encoding) is a 400, and so is an unknown track or ISRC. Do not retry those.

A 500 or 503 means something on our side failed or was briefly unreachable. Those are worth retrying with exponential backoff. A 429 is also retryable, but only after the window it names has passed.

Error Response Format

Error responses vary based on the type of error:

Spotify Resolution Errors

{
  "error": "Failed to extract audio from Spotify",
  "details": "Unable to resolve Spotify track to downloadable audio. The track may not be available or the Spotify ID may be invalid.",
  "spotifyTrackId": "4mUTfSM1IkqkGQ14k6iLV6",
  "usage": {
    "daily_remaining": 44,
    "monthly_remaining": 849
  }
}

On a free plan, tracks Spotify publishes no preview for return this instead:

{
  "error": "No preview audio available",
  "details": "Spotify does not provide a preview clip for this track, and full-length audio requires a Pro or Business plan. Upgrade your plan, or pass a direct audioUrl instead.",
  "spotifyTrackId": "4mUTfSM1IkqkGQ14k6iLV6",
  "audio_source": "preview"
}

Audio Processing Errors

{
  "error": "Request timed out",
  "details": "The audio file took too long to process. Please ensure your file is accessible and under 100MB.",
  "audioUrl": "https://example.com/audio.mp3",
  "suggestion": "Try with a different audio URL or check that your file is properly formatted and accessible.",
  "usage": {
    "daily_remaining": 44,
    "monthly_remaining": 849
  }
}

Audio that fails for a reason inherent to the file is not re-analyzed if you send it again within the hour. The repeat is answered immediately from the earlier result and marked "cached": true. The error value is identical to the first response, so it stays safe to branch on; only details gains a note explaining that nothing was re-run:

{
  "error": "Audio file is shorter than 10s.",
  "details": "This is a property of the audio itself, so retrying the same file will return the same error. Submit different audio. This repeats a failure recorded within the last hour; the audio was not re-analyzed.",
  "cached": true,
  "spotifyTrackId": "4mUTfSM1IkqkGQ14k6iLV6",
  "usage": {
    "daily_remaining": 44,
    "monthly_remaining": 849
  }
}

Transient failures — timeouts, service errors, download problems — are never cached, so a retry always gets a fresh attempt.

Error Response Fields

FieldTypeDescription
errorstringShort error message describing what went wrong
detailsstringDetailed explanation and potential solutions (when available)
spotifyTrackIdstringThe Spotify track ID that failed (only present for Spotify-related errors)
audioUrlstringThe audio URL that failed (only present for audio URL-related errors)
isrcstringThe ISRC that failed to resolve (only present for ISRC-related errors)
suggestionstringSuggested actions to resolve the error (when available)
cachedbooleanPresent and true when this audio failed recently and was not re-analyzed
usageobjectRemaining usage limits (included in most error responses)

Rate Limits

Plans differ in request volume and in how much audio we analyze — Pro and Business analyze full-length tracks for Spotify and ISRC lookups, free plans analyze the ~30 second preview. See Full-length audio vs. previews above.

PlanMonthly LimitDaily LimitPer Minute
Verified10,000 requests500 requests10 requests
Pro100,000 requests5,000 requests15 requests
Business250,000 requests10,000 requests30 requests