Recoup

Get started with Recoup.

API REFERENCE

Record reported listening

On this page
POST/api/players/events

Internal trusted Recoup player transport. Requires its Origin plus signed flow; browser-facing same-origin app proxy forwards to API. Provider and fan attribution come from the stored session. Event UUID makes retries idempotent, listenedMs is capped at 30 seconds and checked against elapsed server time. Recording failures do not stop music.

Authentication

This endpoint does not require authentication.

Request

cURL
curl --request POST \
  --url 'https://api.recoupable.dev/api/players/events' \
  --header 'Content-Type: application/json' \
  --data '{
  "flow": "string",
  "event": {
    "id": "YOUR_ID",
    "provider": "spotify",
    "event": "connected"
  }
}'

Try it

Fill in the fields, send the request from your browser, and read the live response. The curl below updates as you type.

cURL for this request
curl --request POST \
  --url 'https://recoup-api.vercel.app/api/players/events' \
  --header 'Content-Type: application/json' \
  --data '{
  "flow": "string",
  "event": {
    "id": "YOUR_ID",
    "provider": "spotify",
    "event": "connected"
  }
}'

Request body required

application/json

flowstringrequired

maxLength: 2048

eventobjectrequired
Properties for event
idstringrequired

format: uuid

providerstring · enumrequired

Values: "spotify", "apple_music"

eventstring · enumrequired

Values: "connected", "playing", "paused", "stopped", "track_changed", "skip", "heartbeat", "disconnected"

trackIdstring | null
positionMsinteger

Default: 0

minimum: 0 · maximum: 86400000

listenedMsinteger

Default: 0

minimum: 0 · maximum: 30000

Responses

200ListeningReceipt fields returned by the release player service.

application/json

successbooleanrequired
recordedbooleanrequired

False for an already-recorded retry.

400Invalid input

application/json

errorstringrequired
statusstring
401Missing/invalid authentication or failed provider authorization

application/json

errorstringrequired
statusstring
403Workspace, origin, or session access denied

application/json

errorstringrequired
statusstring
404Player not available

application/json

errorstringrequired
statusstring
429Request rate limit exceeded

application/json

errorstringrequired
statusstring
503Feature/configuration temporarily unavailable

application/json

errorstringrequired
statusstring

Full specification

Download the OpenAPI file for complete schemas, constraints, and examples.

Download players.json
View operation source
json
{
  "summary": "Record reported listening",
  "description": "Internal trusted Recoup player transport. Requires its Origin plus signed flow; browser-facing same-origin app proxy forwards to API. Provider and fan attribution come from the stored session. Event UUID makes retries idempotent, listenedMs is capped at 30 seconds and checked against elapsed server time. Recording failures do not stop music.",
  "security": [],
  "parameters": [],
  "responses": {
    "200": {
      "description": "ListeningReceipt fields returned by the release player service.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ListeningReceipt"
          }
        }
      }
    },
    "400": {
      "description": "Invalid input",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/PlayerError"
          }
        }
      }
    },
    "401": {
      "description": "Missing/invalid authentication or failed provider authorization",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/PlayerError"
          }
        }
      }
    },
    "403": {
      "description": "Workspace, origin, or session access denied",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/PlayerError"
          }
        }
      }
    },
    "404": {
      "description": "Player not available",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/PlayerError"
          }
        }
      }
    },
    "429": {
      "description": "Request rate limit exceeded",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/PlayerError"
          }
        }
      }
    },
    "503": {
      "description": "Feature/configuration temporarily unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/PlayerError"
          }
        }
      }
    }
  },
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "flow",
            "event"
          ],
          "properties": {
            "flow": {
              "type": "string",
              "maxLength": 2048
            },
            "event": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "id",
                "provider",
                "event"
              ],
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "provider": {
                  "type": "string",
                  "enum": [
                    "spotify",
                    "apple_music"
                  ]
                },
                "event": {
                  "type": "string",
                  "enum": [
                    "connected",
                    "playing",
                    "paused",
                    "stopped",
                    "track_changed",
                    "skip",
                    "heartbeat",
                    "disconnected"
                  ]
                },
                "trackId": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "positionMs": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 86400000,
                  "default": 0
                },
                "listenedMs": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 30000,
                  "default": 0
                }
              }
            }
          }
        }
      }
    }
  }
}