Profiling
Persisted MusiProfile generations under /v1/profiling/profiles.
Overview
Use MusiProfile to generate an aggregate listener profile from a set of
analysed tracks, such as a playlist or a selection from your catalogue, and keep it as
organisation history. Create with POST /v1/profiling/profiles, list with
GET /v1/profiling/profiles, and retrieve one with
GET /v1/profiling/profiles/{profile_id}.
For the product behind this API, see the
MusiProfile product page.
A profile needs at least 5 distinct eligible tracks. A track is eligible when it is found and has completed MusiTag analysis with the tag data the requested profiles use. Tracks that are not found, duplicates of the same recording, and tracks without that data do not count. With fewer than 5, no profile is generated and the request returns HTTP 422.
Endpoints
POST /v1/profiling/profiles: generate and persist an aggregate profile.GET /v1/profiling/profiles: list your organisation's profile history (paginated).GET /v1/profiling/profiles/{profile_id}: retrieve one persisted profile.
Authentication
OAuth client credentials with one of these scopes. See Authentication for the token flow.
- profiling.write: create a persisted profile generation (consumes profiling credits).
- profiling.read: list and retrieve persisted profiles (reads do not consume credits).
Request
Body fields
tracks(required): array of track items, see Track identifiers.idempotency_key(required): a string you choose, at most 128 characters, unique per generation. Sending a key again returns the generation already stored under it, whatever its status, and does not consume another credit. Use a new key, for example a UUID, for each new generation.catalog_id: one of your organisation's catalogues. Required unless your OAuth client is bound to a catalogue, in which case the bound catalogue is used. List your catalogues with Catalogues.profiles(optional): profile families to compute. When omitted, all families are returned:musical,musical_abridged,ocean,mbti,enneagram,ego_equilibrium,ego_description.
Track identifiers
Each item in tracks must include exactly one of:
musimap_uid: MusiMap track UUID, theidreturned by the Workspace and MusiMap Atlas track endpoints.isrc: ISRC of the recording.outer_id: your own identifier for a track in your catalogue.
musimap_uid and isrc can reference any recording MusiMap has
analysed, so a playlist may include tracks that are not in your catalogue. Tracks in the
selected catalogue are matched first. outer_id is matched only within your
selected catalogue. Only the aggregate profile is returned; no track-level data is.
Create a persisted profile
Request
curl -X POST "https://api.musimap.com/v1/profiling/profiles" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d @- <<EOF
{
"idempotency_key": "$(uuidgen)",
"catalog_id": "$CATALOG_ID",
"profiles": ["musical", "ocean"],
"tracks": [
{ "musimap_uid": "$TRACK_ID_1" },
{ "musimap_uid": "$TRACK_ID_2" },
{ "isrc": "GBUM71904911" },
{ "isrc": "USUM71703861" },
{ "outer_id": "client-track-42" }
]
}
EOF
Response
A successful create returns HTTP 200 with the standard envelope. The
data object is the persisted generation: its id, status and the
aggregate profiles.
Response
{
"status": 200,
"message": "OK",
"data": {
"id": "<profile_id>",
"status": "completed",
"catalog_id": "<catalog_id>",
"scope_type": "catalog",
"profiles_requested": ["musical", "ocean"],
"source_track_count": 5,
"created_at": "<iso8601>",
"completed_at": "<iso8601>",
"profiles": {
"musical": { "...": "aggregate result for this profile family" },
"ocean": { "...": "aggregate result for this profile family" }
}
}
}
id: persisted generation id. It is the{profile_id}path value for retrieval.status:completedfor a successful generation;failedwhen a generation did not complete (thenerror_codeanderror_messageare present andprofilesis empty).source_track_count: number of distinct track identifiers you submitted, not the number of eligible tracks.profiles: aggregate results keyed by profile family. The inner structure is per family; the OpenAPI spec declares this map as open-ended.
Credits
Each create consumes one profiling credit. The credit is refunded when the generation fails,
including fewer than 5 eligible tracks, and when the new
profile is identical to your current one for that catalogue. Replaying an
idempotency_key does not consume a credit. See
Credits.
List profile history
Returns your organisation's generations, newest first, including failed ones.
Request
curl "https://api.musimap.com/v1/profiling/profiles?page=1&page_size=20" \ -H "Authorization: Bearer $ACCESS_TOKEN"
Response
{
"status": 200,
"message": "OK",
"data": {
"count": 1,
"page": 1,
"page_size": 20,
"total_pages": 1,
"has_next": false,
"has_previous": false,
"results": [
{
"id": "<profile_id>",
"status": "completed",
"catalog_id": "<catalog_id>",
"scope_type": "catalog",
"source_track_count": 5,
"profile_family_count": 2,
"created_at": "<iso8601>",
"completed_at": "<iso8601>",
"error_code": null,
"error_message": null
}
]
}
}
Get one profile
Request
curl "https://api.musimap.com/v1/profiling/profiles/$PROFILE_ID" \ -H "Authorization: Bearer $ACCESS_TOKEN"
Returns the same data shape as the create response. A profile that does not
exist or belongs to another organisation returns HTTP 404.
Errors
- 400
validation_error: invalid request, for example a missingidempotency_key, a track item without exactly one identifier, an unknown profile family, a missing or inaccessiblecatalog_id, or an unknown query parameter on the list call. - 401: missing or invalid bearer token.
- 402: insufficient profiling credits.
- 403: the token lacks
profiling.writeorprofiling.read, or your organisation is not entitled to profiling. - 404: profile not found.
- 422
insufficient_eligible_tracks: fewer than 5 distinct eligible tracks. - 429: rate limited.
- 503: profiling backend temporarily unavailable.
422 insufficient_eligible_tracks
No profile is generated and the credit is refunded. required_count is the
minimum; eligible_count is how many distinct eligible tracks were found. Add
analysed tracks and retry with a new idempotency_key.
Response
{
"status": 422,
"message": "Validation failed.",
"data": {
"error_code": "insufficient_eligible_tracks",
"details": "MusiProfile requires at least 5 distinct analysed tracks; 3 eligible after resolution. Unresolved, duplicate, or untagged tracks do not count.",
"required_count": 5,
"eligible_count": 3
}
}
Envelope shape and shared codes: Errors. Pagination envelope: Pagination.
Related
- Monitor remaining profiling capacity with Credits.
- Concept page: MusiProfile.