Skip to content

docs: align 7 research response schemas with actual API behavior - #140

Merged
sweetmantech merged 1 commit into
mainfrom
docs/research-schema-drift-fixes
Apr 16, 2026
Merged

docs: align 7 research response schemas with actual API behavior#140
sweetmantech merged 1 commit into
mainfrom
docs/research-schema-drift-fixes

Conversation

@sweetmantech

@sweetmantech sweetmantech commented Apr 16, 2026

Copy link
Copy Markdown
Collaborator

Summary

Surfaced while comparing the merged OpenAPI spec against a full re-test of every research endpoint on recoupable/api#366's preview deployment (test comments: 1 / 2 / 3 / 4 / 5 / 6). Tested with artist "El Gran Combo de Puerto Rico" (Chartmetric id 207089) across 44 captured response bodies.

All changes are spec-only — no api behavior change.

Changes at a glance

Endpoint Change
/research/track Document cm_statistics, tempo, moods, activities
/research/playlist Drop curator_name/num_tracks (never returned) → use owner_name/num_track; add 15+ real fields
/research/charts data is an array (not object); add length
/research/profile Drop hometown/sp_followers/sp_monthly_listeners/tags (use /research/metrics for longitudinal platform metrics); add 15+ real fields
/research/metrics Replace {data: [...]} wrapper with flat per-platform time-series fields (followers/listeners/popularity/followers_to_listeners_ratio)
/research/audience Add the full audience_likers_* field family + engagement aggregates (followers, avg_likes_per_post, engagement_rate)
/research/curator Drop followers/num_playlists; add per-platform follower fields (instagram_followers, facebook_followers, etc.) + cm_statistics

Why

Every docs/actual drift item from the audit falls into one of two buckets:

  1. Spec advertises fields that never appear — e.g. /playlist advertising curator_name when the real field is owner_name, /profile advertising sp_followers when longitudinal platform metrics live behind /research/metrics. These mislead integrators into writing code against fields that never populate.
  2. Spec omits fields that always appear — e.g. the audience_likers_* family on /audience, cm_statistics on /track//profile//curator, per-platform follower fields on /curator. Not strictly wrong (additionalProperties: true lets them through), but LLM/SDK consumers won't know to use them.

Each schema now matches what the PR #366 preview actually returns, spot-checked against El Gran Combo de Puerto Rico responses.

Test plan

  • Mintlify preview renders all 7 endpoint pages without errors
  • Response-schema sections on each page show the updated field set
  • Spot-check against the JSON bodies captured in the api PR test comments (linked above)

🤖 Generated with Claude Code


Summary by cubic

Aligns the OpenAPI docs for seven research endpoints with actual API responses. Adds missing fields, removes unused ones, and fixes response shapes; no API behavior changes.

  • Schema updates
    • Corrected shapes: /research/charts uses a data array and adds length; /research/metrics returns root-level time-series arrays of {timestp, value} (link, followers, listeners, popularity, followers_to_listeners_ratio).
    • Added real fields: /research/track (cm_statistics, tempo, moods, activities); /research/playlist (owner/IDs, image/editorial/personalized, country/catalog, activity ratio, suspicion/deltas/timestamps, tags/genres/moods/activities); /research/profile (identity/geo, ranks, cm_statistics, career status, genre ranks/ordering, moods/activities, contacts, collaborators); /research/audience (likers fields, engagement aggregates, timestp, notable followers, ethnicities/interests); /research/curator (per-platform follower metrics, user_id/submithub_id, suspicion_score, tags/social URLs, cm_statistics).
    • Removed fields that never appear: /research/playlist (curator_name, num_tracksowner_name, num_track), /research/profile (sp_followers, sp_monthly_listeners, tags), /research/curator (followers, num_playlists).

Written for commit aab48da. Summary will update on new commits.

Summary by CodeRabbit

  • Documentation
    • Expanded audience response with engagement metrics, demographic breakdowns, and notable followers data
    • Enhanced curator profiles with platform follower counts, tags, and Chartmetric statistics
    • Restructured metrics response into time-series format for followers, listeners, and popularity trends
    • Enriched artist profiles with rank scores, career status, and comprehensive statistical data
    • Added comprehensive playlist metadata including genres, moods, activities, and quality indicators
    • Included tempo and mood/activity arrays in track responses
Surfaced while comparing the merged docs to a full re-test of the
research endpoints on the recoupable/api#366 preview (see
recoupable/api#366 (comment)
through #issuecomment-4263097490). Each of the schemas below either
advertised fields that never appear in responses or omitted fields
that always do.

All changes are spec-only — no api behavior change.

/research/track response
- Document `cm_statistics` (nested platform stats blob)
- Document tempo / moods / activities (common nullable fields)

/research/playlist response
- Drop `curator_name` (never returned) → surface as `owner_name`
- Drop `num_tracks` (never returned) → real field is `num_track`
- Add playlist_id (platform-native), owner_id, user_id, image_url,
  editorial, personalized, catalog, code2, active_ratio,
  suspicion_score, fdiff_week/month, last_updated, sys_last_updated,
  genres/moods/activities + their smart-ordered counterparts, tags

/research/charts response
- `data` is an array, not an object (50 entries in practice)
- Document `length` (total entry count)

/research/profile response
- Drop `hometown`, `sp_followers`, `sp_monthly_listeners`, `tags` —
  none are returned (longitudinal platform metrics live behind
  /research/metrics; use `hometown_city`/`current_city` for geography)
- Add: band/band_members, gender fields, code2, isni,
  cover_url, hometown_city, current_city(_id),
  cm_artist_rank/cm_artist_score, cm_statistics, career_status,
  genreRank/subGenreRank1/2, genre_smart_ordered, moods, activities,
  booking_agent, press_contact, general_manager, topSongwriterCollaborators

/research/metrics response
- Replace documented `{data: [...]}` wrapper with flat per-platform
  time-series fields. For Spotify: `link`, `followers`, `listeners`,
  `popularity`, `followers_to_listeners_ratio` — each an array of
  `{timestp, value}` points.

/research/audience response
- Add the likers/engagement field family: audience_likers_genders
  (+per_age), audience_likers_ethnicities, audience_likers_interests,
  audience_likers_brand_affinities, likers_top_countries,
  likers_top_cities, notable_followers, followers,
  avg_likes_per_post, avg_commments_per_post (sic — upstream typo),
  engagement_rate, timestp
- Add audience_ethnicities, audience_interests

/research/curator response
- Drop `followers` / `num_playlists` (neither returned)
- Add per-platform follower fields: instagram_followers,
  facebook_followers/fans, twitter_followers/retweets,
  youtube_subscribers/views, soundcloud_followers,
  tiktok_followers/likes (all nullable)
- Add user_id, submithub_id, last_updated, suspicion_score, tags,
  tag_ids, tag_names, spotifySocialUrls, cm_statistics

/research/extract response
- No change. Prior audit flagged errors as drift, but the field is
  already correctly optional (not in `required`) with a description
  noting conditional presence.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Apr 16, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Updated OpenAPI schemas for six Research API responses to document expanded Chartmetric payloads, adding audience engagement metrics, platform follower counts, identity fields, curator/playlist metadata, time-series structures for metrics, and track analysis data across multiple schema definitions.

Changes

Cohort / File(s) Summary
Audience & Engagement Metrics
api-reference/openapi/research.jsonResearchAudienceResponse
Added audience snapshot timestamp, follower counts, engagement aggregates, likers demographic breakdowns (countries, cities, ethnicities, interests, brand affinities), and notable followers array.
Data Structure Conversions
api-reference/openapi/research.jsonResearchChartsResponse, ResearchMetricsResponse
Transformed ResearchChartsResponse.data from single object to typed-array with length field; restructured ResearchMetricsResponse as root-level time-series envelope with separate arrays for followers, listeners, popularity, and computed ratios.
Creator & Profile Enrichment
api-reference/openapi/research.jsonResearchCuratorResponse, ResearchProfileResponse
Expanded curator schema with identity, tag, platform follower counts, and statistics fields; significantly enhanced profile schema with identity/geography, Chartmetric rank/score, career status, converted genres to object structure, added smart-ordered genre/mood/activity arrays, and personnel contact fields.
Playlist Metadata
api-reference/openapi/research.jsonResearchPlaylistResponse
Added ownership, editorial/personalized flags, catalog/country fields, suspicion/active-ratio scores, temporal deltas, renamed num_tracks to num_track, and introduced genre/mood/activity/tag smart-ordered arrays.
Track Analysis
api-reference/openapi/research.jsonResearchTrackResponse
Added Chartmetric statistics, tempo, and moods/activities arrays to track response schema.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 Schemas bloom with richer tales,
New fields dance down audit trails—
Audiences, charts, and metrics bright,
Curators gleaming in the light,
Our API now tells stories right! 🌟

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: updating OpenAPI schemas for seven research endpoints to match actual API behavior, which is the primary purpose of this documentation-only pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/research-schema-drift-fixes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@api-reference/openapi/research.json`:
- Around line 4893-4912: Add explicit type declarations for the two permissive
schema entries: for band_members, change the schema to declare its type as
["array","null"] and ensure the array items are typed as objects (e.g., items: {
type: "object", additionalProperties: true }) while retaining nullable
semantics; for hometown_city, declare its type as ["object","null"] and add
additionalProperties: true to represent the Chartmetric hometown-city object.
Update the definitions that currently only have "nullable": true and
"description" so they include these explicit "type" and "additionalProperties"
(and "items" for band_members) entries.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c5399f2a-cf9b-4128-b42e-739a913deacf

📥 Commits

Reviewing files that changed from the base of the PR and between e6281b9 and aab48da.

📒 Files selected for processing (1)
  • api-reference/openapi/research.json
Comment on lines +4893 to +4912
"band_members": {
"nullable": true,
"description": "Band-member objects when known."
},
"gender": {
"type": "string",
"nullable": true
},
"gender_title": {
"type": "string",
"nullable": true
},
"pronoun_title": {
"type": "string",
"nullable": true
},
"hometown_city": {
"nullable": true,
"description": "Chartmetric hometown-city object (null when unknown)."
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, examine the actual file to confirm the current state
head -n 4920 api-reference/openapi/research.json | tail -n 50

Repository: recoupable/docs

Length of output: 1463


🏁 Script executed:

# Search for test fixtures or example API responses containing band_members
rg "band_members" --type json -A 3 -B 3

Repository: recoupable/docs

Length of output: 574


🏁 Script executed:

# Search for test fixtures or example API responses containing hometown_city
rg "hometown_city" --type json -A 3 -B 3

Repository: recoupable/docs

Length of output: 537


🏁 Script executed:

# Look for other properties in the file that also lack explicit `type` but have `nullable`
rg '"nullable"\s*:\s*true' api-reference/openapi/research.json | head -20

Repository: recoupable/docs

Length of output: 644


🏁 Script executed:

# Check the OpenAPI spec version and overall schema structure
head -n 20 api-reference/openapi/research.json

Repository: recoupable/docs

Length of output: 834


🏁 Script executed:

# Search for test fixtures or example data files
find . -type f \( -name "*fixture*" -o -name "*example*" -o -name "*mock*" \) -name "*.json" | head -20

Repository: recoupable/docs

Length of output: 41


🏁 Script executed:

# Search for any TypeScript/JS type definitions or interface files that might document these fields
rg "band_members|hometown_city" --type ts --type tsx --type js -B 2 -A 2

Repository: recoupable/docs

Length of output: 86


🏁 Script executed:

# Look for any documentation or comments about the structure of these fields
rg "Band-member|hometown" -i --type md

Repository: recoupable/docs

Length of output: 41


🏁 Script executed:

# Check if there are git changes that show what this looked like before
git log --oneline -20 -- api-reference/openapi/research.json

Repository: recoupable/docs

Length of output: 131


🏁 Script executed:

# Examine the recent commit that changed the research.json
git show aab48da --stat | head -30

Repository: recoupable/docs

Length of output: 1452


🏁 Script executed:

# Look at the diff for the specific properties we're concerned with
git show aab48da -- api-reference/openapi/research.json | grep -A 10 -B 10 "band_members\|hometown_city" | head -80

Repository: recoupable/docs

Length of output: 2359


🏁 Script executed:

# Check if there's any backend code or API implementation in the repo
find . -type f \( -name "*.ts" -o -name "*.js" -o -name "*.py" \) | grep -E "(research|api)" | head -20

Repository: recoupable/docs

Length of output: 41


Add explicit type declarations for band_members and hometown_city.

Both properties declare only nullable: true + description with no type, making the schema permissive to any value. Based on the descriptions and OpenAPI 3.1.0 semantics, these should declare explicit types:

  • band_members: "Band-member objects when known" → likely "type": ["array", "null"] with array items typed as objects
  • hometown_city: "Chartmetric hometown-city object" → likely "type": ["object", "null"]

For consistency with the surrounding nullable: true style, add type alongside additionalProperties: true:

Suggested changes
          "band_members": {
+           "type": "array",
            "nullable": true,
+           "items": { "type": "object", "additionalProperties": true },
            "description": "Band-member objects when known."
          },
          "hometown_city": {
+           "type": "object",
            "nullable": true,
+           "additionalProperties": true,
            "description": "Chartmetric hometown-city object (null when unknown)."
          },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"band_members": {
"nullable": true,
"description": "Band-member objects when known."
},
"gender": {
"type": "string",
"nullable": true
},
"gender_title": {
"type": "string",
"nullable": true
},
"pronoun_title": {
"type": "string",
"nullable": true
},
"hometown_city": {
"nullable": true,
"description": "Chartmetric hometown-city object (null when unknown)."
},
"band_members": {
"type": "array",
"nullable": true,
"items": { "type": "object", "additionalProperties": true },
"description": "Band-member objects when known."
},
"gender": {
"type": "string",
"nullable": true
},
"gender_title": {
"type": "string",
"nullable": true
},
"pronoun_title": {
"type": "string",
"nullable": true
},
"hometown_city": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "Chartmetric hometown-city object (null when unknown)."
},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api-reference/openapi/research.json` around lines 4893 - 4912, Add explicit
type declarations for the two permissive schema entries: for band_members,
change the schema to declare its type as ["array","null"] and ensure the array
items are typed as objects (e.g., items: { type: "object", additionalProperties:
true }) while retaining nullable semantics; for hometown_city, declare its type
as ["object","null"] and add additionalProperties: true to represent the
Chartmetric hometown-city object. Update the definitions that currently only
have "nullable": true and "description" so they include these explicit "type"
and "additionalProperties" (and "items" for band_members) entries.
@sweetmantech
sweetmantech merged commit 4f9824d into main Apr 16, 2026
3 checks passed
@sweetmantech
sweetmantech deleted the docs/research-schema-drift-fixes branch April 16, 2026 21:17
recoupableorg pushed a commit that referenced this pull request Apr 20, 2026
Combine the design/narrative overhaul (new 8-tab IA, deprecation notices,
rebuilt Agent Onboarding, achromatic design system) with all API doc updates
shipped to main since the branch diverged:

- 8 research PRs (#132-#140): schema hardening, /research/track id-proxy,
  /research/curator Chartmetric contract, /research/track/playlists, error
  responses aligned with handler enforcement
- Artist surface rename: /api/artist/socials -> /api/artists/{id}/socials
- New endpoints: artists/pin, artists/unpin, admins/agent-signups
- Removed dead surfaces: artist/segments, chat/segment, segment/fans
- Caption length default -> none

Conflict resolutions:
- docs.json: kept design IA (Overview/Chat/Research/Artists/Catalog/Content/
  Automation/Accounts), spliced in all new endpoints from main, removed
  stale nav refs to deleted surfaces
- index.mdx, quickstart.mdx: kept design copy (richer, superseded main's
  verbose endpoint listing with card-based IA)
- openapi/content.json: auto-merge preserved design's deprecation of
  /api/content/create alongside main's untouched body

research.json, accounts.json, releases.json are byte-identical to main.
131 API mdx files / 131 nav entries / 0 orphans / 0 broken intra-doc links.

Made-with: Cursor
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant