# Create measurement job

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

Create a current capture or enqueue historical the configured research data connection backfill.

Historical backfill requires an existing saved payment method. A missing method
returns HTTP 402 with `error: "payment_method_required"` and a neutral `message`.
The request does not create a checkout session or start card setup. Preserve the
request and stop; do not poll the denied operation or initiate a purchase.

## POST /api/research/measurement-jobs

Full OpenAPI specification: https://docs.recoupable.dev/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://docs.recoupable.dev/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/measurement-jobs": {
      "post": {
        "operationId": "postResearchMeasurementJobs",
        "summary": "Create a measurement job",
        "description": "Create a current capture or enqueue historical the configured research data connection backfill. Provide exactly one of catalog_id, album_ids or isrcs in scope; platforms supports spotify only. source=current uses the snapshot pipeline and returns an ID that can be passed to [Create catalog](/api-reference/songs/catalogs-create). source=historical requires a card on file, resolves scope recordings and returns id:null with enqueued/skipped counts; it attempts to start the existing budget-gated backfill workflow, with daily maintenance as a backstop. Enqueue success is not capture completion or evidence of complete historical coverage. Songs with any historical research measurement are skipped, including potentially partial history. Historical enqueue itself makes no credit deduction; current capture estimates and provider/account gates remain separate.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResearchMeasurementJobRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Job accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResearchMeasurementJobResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid scope/source/platform, or no recordings resolvable from the selected historical scope.",
            "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": "Historical backfill requires an existing saved payment method. If unavailable, returns a neutral entitlement error without creating a card-setup or checkout session. Preserve the job request; do not retry automatically.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "error",
                    "message"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "error"
                      ]
                    },
                    "error": {
                      "type": "string",
                      "enum": [
                        "payment_method_required"
                      ]
                    },
                    "message": {
                      "type": "string",
                      "description": "Neutral explanation that the feature is unavailable with current account entitlements."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Per-organization monthly cap reached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResearchErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal, enqueue or provider configuration error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResearchErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ResearchMeasurementJobRequest": {
        "type": "object",
        "required": [
          "scope",
          "source"
        ],
        "properties": {
          "scope": {
            "$ref": "#/components/schemas/ResearchMeasurementJobScope"
          },
          "source": {
            "type": "string",
            "enum": [
              "current",
              "historical"
            ],
            "description": "current captures present counts through the snapshot pipeline; historical enqueues the configured research data connection backfill. Historical requires a saved payment method and does not promise complete history."
          },
          "platforms": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "spotify"
              ]
            },
            "default": [
              "spotify"
            ],
            "example": [
              "spotify"
            ]
          }
        },
        "example": {
          "scope": {
            "isrcs": [
              "USQY51771120"
            ]
          },
          "source": "historical",
          "platforms": [
            "spotify"
          ]
        }
      },
      "ResearchMeasurementJobResponse": {
        "oneOf": [
          {
            "type": "object",
            "required": [
              "status",
              "source",
              "id",
              "state",
              "album_count",
              "estimated_cost_usd"
            ],
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "success"
                ]
              },
              "source": {
                "type": "string",
                "enum": [
                  "current"
                ]
              },
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Snapshot ID for current captures."
              },
              "state": {
                "type": "string",
                "description": "State returned by the snapshot pipeline; reused captures need not be queued."
              },
              "album_count": {
                "type": "integer"
              },
              "estimated_cost_usd": {
                "type": "number"
              },
              "reused": {
                "type": "boolean",
                "description": "Present when an existing capture is handed back."
              }
            }
          },
          {
            "type": "object",
            "required": [
              "status",
              "source",
              "id",
              "enqueued",
              "skipped"
            ],
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "success"
                ]
              },
              "source": {
                "type": "string",
                "enum": [
                  "historical"
                ]
              },
              "id": {
                "type": "null",
                "description": "No pollable snapshot ID is created for historical backfill."
              },
              "enqueued": {
                "type": "integer",
                "description": "Recordings submitted to the backfill queue; this does not mean history is captured."
              },
              "skipped": {
                "type": "integer",
                "description": "Recordings with any existing historical research measurement; skipping does not prove complete history."
              }
            }
          }
        ],
        "description": "Current captures return a snapshot ID; historical backfill returns queue counts and id:null."
      },
      "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"
          }
        }
      },
      "ResearchMeasurementJobScope": {
        "type": "object",
        "description": "Provide exactly one of `catalog_id`, `album_ids`, or `isrcs`.",
        "properties": {
          "catalog_id": {
            "type": "string",
            "format": "uuid"
          },
          "album_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "isrcs": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      }
    }
  }
}
```
