# Track measurements

Source: https://recoupable.dev/docs/api-reference/research/measurements

Track measurements

## GET /api/research/tracks/{id}/measurements

Full OpenAPI specification: https://recoupable.dev/docs/spec/research.json

## Authentication

The supplied specification does not declare an OpenAPI security object for this operation. Its declared headers and parameters still apply. Consult the authentication guide and the full specification before calling it.

[Authentication guide](https://recoupable.dev/docs/authentication)

## Operation and referenced schemas

```json
{
  "openapi": "3.1.0",
  "info": {
    "title": "Recoup API - Research",
    "description": "API documentation for the Recoup platform - an AI agent platform for the music industry",
    "license": {
      "name": "MIT"
    },
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://api.recoupable.dev"
    }
  ],
  "paths": {
    "/api/research/tracks/{id}/measurements": {
      "get": {
        "summary": "Track measurements",
        "description": "Time-series of a track's measured counts.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Provider-neutral track id — ISRC or Spotify track id."
          },
          {
            "name": "platform",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "spotify"
            },
            "description": "Platform to read. Currently `spotify`."
          },
          {
            "name": "metric",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "platform_displayed_play_count"
            },
            "description": "Metric to read."
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Inclusive start date (ISO) for the series."
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Inclusive end date (ISO) for the series."
          },
          {
            "name": "granularity",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "daily"
              ],
              "default": "daily"
            },
            "description": "Series granularity. `daily` returns the per-day cumulative series."
          },
          {
            "name": "aggregate",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "run_rate"
              ]
            },
            "description": "Return a derived aggregate instead of the raw series. `run_rate` returns the trailing-window annualized run-rate (a projection of the series)."
          },
          {
            "name": "window",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "365d"
            },
            "description": "Trailing window for `aggregate=run_rate` (e.g. `365d`)."
          }
        ],
        "responses": {
          "200": {
            "description": "The measurement series (or the requested aggregate).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResearchMeasurementsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error — bad identifier or query param.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResearchErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication failed — invalid or missing API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResearchErrorResponse"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResearchInsufficientCreditsResponse"
                }
              }
            }
          },
          "404": {
            "description": "No measurements for this track yet — create a `current` measurement job to capture it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResearchErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ResearchMeasurementsResponse": {
        "type": "object",
        "description": "A track's measured series, or — when `aggregate` is set — the derived projection.",
        "properties": {
          "status": {
            "type": "string",
            "example": "success"
          },
          "id": {
            "type": "string",
            "description": "The provider-neutral track id queried.",
            "example": "USQY51771120"
          },
          "platform": {
            "type": "string",
            "example": "spotify"
          },
          "metric": {
            "type": "string",
            "example": "platform_displayed_play_count"
          },
          "series": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResearchMeasurementPoint"
            },
            "description": "Present unless `aggregate` is set."
          },
          "aggregate": {
            "type": "object",
            "nullable": true,
            "description": "Present when `aggregate=run_rate`.",
            "properties": {
              "kind": {
                "type": "string",
                "example": "run_rate"
              },
              "window_days": {
                "type": "integer",
                "example": 365
              },
              "delta": {
                "type": "number",
                "example": 42000000
              },
              "run_rate_annualized": {
                "type": "number",
                "example": 42000000
              }
            }
          }
        }
      },
      "ResearchErrorResponse": {
        "type": "object",
        "required": [
          "status",
          "error"
        ],
        "description": "Error response returned by all research endpoints for validation failures (400) and authentication errors (401).",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "error"
            ],
            "example": "error"
          },
          "error": {
            "type": "string",
            "description": "Human-readable error message describing what went wrong.",
            "example": "Missing required parameter: artist"
          }
        }
      },
      "ResearchInsufficientCreditsResponse": {
        "type": "object",
        "description": "Returned (402) when the account lacks research credits. Nothing is charged and no Stripe object is created. Credits must be bought explicitly via [`POST /api/credits/sessions`](/api-reference/credits/sessions-create).",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "insufficient_credits"
            ]
          },
          "remaining_credits": {
            "type": "integer",
            "example": 0
          },
          "required_credits": {
            "type": "integer",
            "example": 5
          },
          "billingUrl": {
            "type": "string",
            "description": "Static link to the Recoup app, where a human can save a card and buy credits. It is a constant, not a freshly minted Stripe Checkout Session, so a credit-gated endpoint that keeps returning 402 creates nothing. To buy credits programmatically, call [`POST /api/credits/sessions`](/api-reference/credits/sessions-create).",
            "example": "https://app.recoupable.dev"
          }
        },
        "required": [
          "error",
          "remaining_credits",
          "required_credits",
          "billingUrl"
        ]
      },
      "ResearchMeasurementPoint": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date",
            "example": "2026-06-12"
          },
          "value": {
            "type": "number",
            "description": "Cumulative metric value as of `date`.",
            "example": 297289495
          },
          "data_source": {
            "type": "string",
            "example": "apify_spotify_playcount"
          }
        }
      }
    }
  }
}
```
