Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/hummatch-me:hummatch-partner-api-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.0.3
info:
title: HumMatch Partner API
description: >
A partner-facing API over HumMatch's real vocal-range and song-matching
logic: normalize a singer's vocal profile, score how well a specific
catalog song fits that profile, and find shared-range song candidates for
a small group. Every endpoint here is stateless computation over
caller-submitted data plus read-only catalog lookups -- no HumMatch user
accounts, hum sessions, or SquadMatch groups are created or touched.
version: "1.0.0"
contact:
name: HumMatch
url: https://hummatch.me/contact
servers:
- url: https://hummatch.me/api
description: Production
- url: http://localhost:3000/api
description: Local development
tags:
- name: Onboarding
description: Self-serve sandbox API key issuance.
- name: Vocal Profile
description: Normalize a singer's vocal range/hum-feature input.
- name: Song Fit
description: Score a single catalog song against a vocal profile.
- name: Group Fit
description: Find shared-range song candidates for multiple singers.
- name: Recommendations
description: Rank the whole catalog for one singer.
- name: Catalog
description: Search the song catalog and resolve slugs.
paths:
/v1/sandbox-key:
post:
operationId: createSandboxKey
tags: [Onboarding]
summary: Instantly issue a sandbox API key
description: >
Public endpoint, no API key required -- this IS the onboarding step.
Generates a new `hm_sandbox_...` key immediately, with no human
approval or email verification. Rate-limited per IP (5 keys/hour) to
prevent abuse, since it is the one endpoint that doesn't itself
require an API key.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [email]
properties:
email:
type: string
format: email
example: partner@example.com
name:
type: string
example: Acme Karaoke Co.
responses:
"200":
description: Sandbox key created. The `apiKey` value is shown exactly once.
content:
application/json:
schema:
type: object
properties:
apiKey:
type: string
description: >
The full plaintext API key. Store it now -- HumMatch
never stores or displays the plaintext value again.
example: hm_sandbox_3f9a1c2b7d8e4f5061a2b3c4d5e6f708
keyPrefix:
type: string
example: hm_sandbox_3
mode:
type: string
enum: [sandbox]
rateLimitPerMinute:
type: integer
example: 30
"400":
description: Missing or invalid email.
"429":
description: Too many sandbox keys requested from this IP; see `Retry-After` header.
/v1/vocal-profile:
post:
operationId: buildVocalProfile
tags: [Vocal Profile]
summary: Normalize a vocal range or hum-feature profile
security:
- ApiKeyAuth: []
description: >
Accepts either `{ rangeLow, rangeHigh }` (note names like "C3"/"A4"
or raw MIDI numbers) or `{ humProfile: {...} }` (audio-feature-style
input). Returns a normalized profile object that can be passed
directly into `/v1/songs/{slug}/fit` and `/v1/group-fit`. Pure
computation, no persistence.
requestBody:
required: true
content:
application/json:
schema:
oneOf:
- type: object
required: [rangeLow, rangeHigh]
properties:
rangeLow:
type: string
example: "C3"
rangeHigh:
type: string
example: "A4"
- type: object
required: [humProfile]
properties:
humProfile:
$ref: "#/components/schemas/HumProfileInput"
examples:
byRange:
summary: Note-name range
value:
rangeLow: "C3"
rangeHigh: "A4"
byHumProfile:
summary: Audio-feature hum profile
value:
humProfile:
low: "C3"
high: "A4"
confidence: 0.82
pitchStability: 0.74
brightnessScore: 58
responses:
"200":
description: Normalized vocal profile.
content:
application/json:
schema:
$ref: "#/components/schemas/VocalProfile"
example:
vocalId: "Baritone · Warm tone"
rangeLow: 48
rangeHigh: 69
voiceType: Baritone
toneLabel: Warm
humProfile:
low: 48
high: 69
center: 58.5
confidence: 0.82
pitchStability: 0.74
brightnessScore: 58
warmthScore: 42
timbreLabel: Balanced
timbreConfidence: 0.615
"400":
description: Missing/invalid rangeLow, rangeHigh, or humProfile.
"401":
description: Missing, invalid, or revoked API key.
"429":
description: Rate limit exceeded for this API key; see `Retry-After` header.
/v1/songs/{slug}/fit:
get:
operationId: getSongFit
tags: [Song Fit]
summary: Score one catalog song against a vocal profile
security:
- ApiKeyAuth: []
description: >
Looks up a single song by its catalog slug and scores it against the
supplied profile using HumMatch's real per-song scoring function.
Read-only: one row lookup plus scoring, no catalog scan and no writes.
parameters:
- name: slug
in: path
required: true
schema:
type: string
example: love-is-a-game-adele
description: The catalog song's slug (its real identifier, not a numeric id).
- name: profile
in: query
required: true
schema:
type: string
description: >
URL-encoded JSON matching the response shape of
`POST /v1/vocal-profile`, or the same `{ rangeLow, rangeHigh }` /
`{ humProfile }` shape directly -- both are accepted.
example: "%7B%22rangeLow%22%3A%22G3%22%2C%22rangeHigh%22%3A%22D5%22%7D"
responses:
"200":
description: Fit score and explanation for this song against this profile.
content:
application/json:
schema:
$ref: "#/components/schemas/SongFit"
example:
slug: love-is-a-game-adele
title: Love Is a Game
artist: Adele
matchScore: 78
vocalFitScore: 81
tessituraScore: 74
voiceTypeFitScore: 88
whyItFits: "Strong likely fit: the melody sits close to your comfortable range and the song is familiar."
reason: "Strong likely fit: the melody sits close to your comfortable range and the song is familiar."
riskWarning: ""
suggestedKey: ""
fitDetails:
rangeFitLabel: Strong fit
voiceTypeFitLabel: Strong voice lane fit
priorityTier: 2
riskLabel: No major range risk
"400":
description: Missing/invalid `profile` query parameter.
"401":
description: Missing, invalid, or revoked API key.
"404":
description: No song found for the given slug.
"429":
description: Rate limit exceeded for this API key; see `Retry-After` header.
/v1/group-fit:
post:
operationId: getGroupFit
tags: [Group Fit]
summary: Find shared-range song candidates for multiple singers
security:
- ApiKeyAuth: []
description: >
Accepts 2+ caller-submitted vocal profiles and computes their shared
vocal range plus ranked candidate songs, using the same logic
HumMatch's SquadMatch feature uses -- entirely in-memory over the
submitted profiles. No SquadMatch group, member, or match rows are
ever created. `sharedRange` is `null` when the profiles genuinely
have no overlap; it is never fabricated.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [profiles]
properties:
profiles:
type: array
minItems: 2
items:
type: object
required: [rangeLow, rangeHigh]
properties:
id:
type: string
example: singer-1
rangeLow:
type: string
example: "C3"
rangeHigh:
type: string
example: "E4"
example:
profiles:
- id: singer-1
rangeLow: "C3"
rangeHigh: "E4"
- id: singer-2
rangeLow: "A3"
rangeHigh: "G5"
responses:
"200":
description: Shared range and ranked candidate songs.
content:
application/json:
schema:
$ref: "#/components/schemas/GroupFit"
example:
sharedRange:
low: 57
high: 64
songs:
- slug: friends-in-low-places-garth-brooks
title: Friends in Low Places
artist: Garth Brooks
genre: Country
year: 1990
difficulty: Easy win
fitLabel: Group-ready
reason: Tagged as group-friendly and close to the shared comfort lane.
fitsMemberIds: [singer-1, singer-2]
"400":
description: Fewer than 2 profiles, or an invalid rangeLow/rangeHigh in one of them.
"401":
description: Missing, invalid, or revoked API key.
"429":
description: Rate limit exceeded for this API key; see `Retry-After` header.
/v1/recommendations:
post:
operationId: getRecommendations
tags: [Recommendations]
summary: Rank the catalog for one singer
security:
- ApiKeyAuth: []
description: >
The primary endpoint: one voice in, the catalog ranked for that voice
out. Accepts the same dual input shape as /v1/vocal-profile -- either
top-level rangeLow/rangeHigh (note names or MIDI numbers) or a nested
humProfile. Returns a flat ranked `matches` list plus the named buckets
HumMatch itself uses, which carry meaning a flat list loses (a "risky
pick to avoid" is not simply a low-scoring match). Read-only: scores
the catalog against what you send and creates no hum session, user, or
saved result.
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
rangeLow:
description: Note name or MIDI number.
example: "D3"
rangeHigh:
description: Note name or MIDI number.
example: "C5"
voiceType:
type: string
description: Optional hint; inferred from the range when omitted.
limit:
type: integer
default: 12
maximum: 50
humProfile:
$ref: "#/components/schemas/HumProfileInput"
example:
rangeLow: "D3"
rangeHigh: "C5"
limit: 12
responses:
"200":
description: Ranked matches plus named buckets.
content:
application/json:
schema:
type: object
properties:
vocalId: { type: string }
rangeLow: { type: integer }
rangeHigh: { type: integer }
voiceType: { type: string }
confidenceTier: { type: string }
matches:
type: array
items: { $ref: "#/components/schemas/ScoredSong" }
bestSafePicks:
type: array
items: { $ref: "#/components/schemas/ScoredSong" }
easyWins:
type: array
items: { $ref: "#/components/schemas/ScoredSong" }
popularCrowdPleasers:
type: array
items: { $ref: "#/components/schemas/ScoredSong" }
groupFriendly:
type: array
items: { $ref: "#/components/schemas/ScoredSong" }
riskyPicksToAvoid:
type: array
items: { $ref: "#/components/schemas/ScoredSong" }
"400":
description: Missing or invalid rangeLow/rangeHigh.
"401":
description: Missing, invalid, or revoked API key.
"429":
description: Rate limit exceeded for this API key; see `Retry-After` header.
/v1/songs/search:
get:
operationId: searchSongs
tags: [Catalog]
summary: Search the catalog and resolve slugs
security:
- ApiKeyAuth: []
description: >
Text search over the catalog by title or artist. Its main job is slug
resolution -- turning a song name into the `songs.slug` that
/v1/songs/{slug}/fit requires. When `profile` is supplied, every hit is
also scored against that voice and results come back ranked by fit
rather than by catalog relevance.
parameters:
- name: q
in: query
required: true
schema: { type: string }
example: someone like you adele
- name: limit
in: query
required: false
schema: { type: integer, default: 20, maximum: 50 }
- name: profile
in: query
required: false
description: URL-encoded JSON. Same shape as the /v1/vocal-profile response.
schema: { type: string }
example: '{"rangeLow":"D3","rangeHigh":"C5"}'
responses:
"200":
description: Matching songs, scored and ranked when `profile` is supplied.
content:
application/json:
schema:
type: object
properties:
query: { type: string }
count: { type: integer }
songs:
type: array
items: { $ref: "#/components/schemas/ScoredSong" }
"400":
description: Missing `q`, or `profile` was not valid JSON.
"401":
description: Missing, invalid, or revoked API key.
"429":
description: Rate limit exceeded for this API key; see `Retry-After` header.
components:
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-API-Key
schemas:
HumProfileInput:
type: object
properties:
low:
description: Note name or MIDI number.
example: "C3"
high:
description: Note name or MIDI number.
example: "A4"
confidence:
type: number
minimum: 0
maximum: 1
pitchStability:
type: number
minimum: 0
maximum: 1
brightnessScore:
type: number
minimum: 0
maximum: 100
timbreLabel:
type: string
VocalProfile:
type: object
properties:
vocalId:
type: string
rangeLow:
type: integer
rangeHigh:
type: integer
voiceType:
type: string
toneLabel:
type: string
humProfile:
type: object
properties:
low:
type: integer
high:
type: integer
center:
type: number
confidence:
type: number
pitchStability:
type: number
brightnessScore:
type: number
nullable: true
warmthScore:
type: number
nullable: true
timbreLabel:
type: string
timbreConfidence:
type: number
SongFit:
type: object
properties:
slug:
type: string
title:
type: string
artist:
type: string
matchScore:
type: integer
vocalFitScore:
type: integer
tessituraScore:
type: integer
voiceTypeFitScore:
type: integer
whyItFits:
type: string
reason:
type: string
riskWarning:
type: string
suggestedKey:
type: string
fitDetails:
type: object
GroupFit:
type: object
properties:
sharedRange:
type: object
nullable: true
properties:
low:
type: integer
high:
type: integer
songs:
type: array
items:
type: object
properties:
slug:
type: string
title:
type: string
artist:
type: string
genre:
type: string
year:
type: integer
difficulty:
type: string
fitLabel:
type: string
reason:
type: string
fitsMemberIds:
type: array
items:
type: string
ScoredSong:
type: object
description: >
A catalog song, optionally with fit scores. `lowNote`/`highNote` are
MIDI numbers for arithmetic; `lowNoteName`/`highNoteName` are the same
values as note names for display. `rangeConfidence` and `rangeSource`
state how the range was established -- a range derived from published
sources is not as certain as one measured from the recording, and
callers should present those scores as guidance rather than fact.
properties:
slug: { type: string, example: someone-like-you-adele }
title: { type: string, example: Someone Like You }
artist: { type: string, example: Adele }
lowNote: { type: integer, nullable: true, example: 52 }
highNote: { type: integer, nullable: true, example: 76 }
lowNoteName: { type: string, example: "E3" }
highNoteName: { type: string, example: "E5" }
rangeConfidence: { type: string, example: manual_research }
rangeSource: { type: string }
difficultyScore: { type: integer, nullable: true }
likelyVoiceFit: { type: string }
genre: { type: string }
year: { type: integer, nullable: true }
url: { type: string, example: https://hummatch.me/songs/someone-like-you-adele }
matchScore: { type: integer, nullable: true, example: 92 }
vocalFitScore: { type: integer, nullable: true }
tessituraScore: { type: integer, nullable: true }
voiceTypeFitScore: { type: integer, nullable: true }
whyItFits: { type: string }
riskWarning: { type: string }
suggestedKey: { type: string }