{
  "openapi": "3.1.0",
  "info": {
    "title": "Metadata Style Guidelines Distributor API",
    "version": "1.0.0",
    "description": "Validate release metadata against published DSP style-guide rules before delivery. Each finding has a severity, a suggested fix and links to the guideline it's based on. Usage is metered in tracks (rows checked) per calendar month (UTC)."
  },
  "servers": [
    {
      "url": "https://metadatastyleguidelines.pages.dev",
      "description": "Staging"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/api/v1/check": {
      "post": {
        "operationId": "checkTracks",
        "summary": "Check up to 5,000 tracks",
        "description": "Send rows as JSON or CSV. Each row counts as one track against your monthly quota. Unknown columns are ignored; missing columns are treated as empty.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "rows"
                ],
                "properties": {
                  "rows": {
                    "type": "array",
                    "maxItems": 5000,
                    "items": {
                      "$ref": "#/components/schemas/Track"
                    }
                  }
                }
              },
              "example": {
                "rows": [
                  {
                    "artist": "Nova Reyes",
                    "featured_artists": "Kai Lane",
                    "track_title": "Midnight Drive (feat. Kai Lane)",
                    "release_title": "Midnight Drive",
                    "genre": "Pop",
                    "explicit": "false",
                    "isrc": "USRC12600001",
                    "upc": "036000291452",
                    "language": "en",
                    "ai_use": "None",
                    "duration": "3:24"
                  }
                ]
              }
            },
            "text/csv": {
              "schema": {
                "type": "string",
                "description": "CSV with a header row. Columns: artist, featured_artists, track_title, version, release_title, genre, explicit, isrc, upc, language, ai_use, duration."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Findings for every row",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests allowed per minute for this key"
              },
              "X-Quota-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Tracks allowed this month"
              },
              "X-Quota-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Tracks left this month"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body (bad JSON/CSV, no rows)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Body over 5 MB or more than 5,000 rows",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (code rate_limited, with Retry-After) or monthly quota exceeded (code quota_exceeded)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/usage": {
      "get": {
        "operationId": "getUsage",
        "summary": "Current month's usage for your key",
        "responses": {
          "200": {
            "description": "Usage",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Usage"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed or revoked API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Authorization: Bearer msg_live_… (X-API-Key is also accepted)"
      }
    },
    "schemas": {
      "Track": {
        "type": "object",
        "properties": {
          "artist": {
            "type": "string"
          },
          "featured_artists": {
            "type": "string"
          },
          "track_title": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "release_title": {
            "type": "string"
          },
          "genre": {
            "type": "string"
          },
          "explicit": {
            "type": "string"
          },
          "isrc": {
            "type": "string"
          },
          "upc": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "ai_use": {
            "type": "string"
          },
          "duration": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "Finding": {
        "type": "object",
        "required": [
          "row",
          "rule",
          "severity",
          "field",
          "message"
        ],
        "properties": {
          "row": {
            "type": "integer",
            "description": "1-based row number in your input"
          },
          "rule": {
            "type": "string",
            "examples": [
              "ISRC_FORMAT"
            ]
          },
          "severity": {
            "type": "string",
            "enum": [
              "error",
              "warning",
              "info"
            ]
          },
          "status": {
            "type": "string",
            "description": "documented = stated in a published guideline; heuristic = a pattern we flag for review"
          },
          "field": {
            "type": "string"
          },
          "value": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "suggestion": {
            "type": [
              "string",
              "null"
            ]
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            }
          }
        }
      },
      "CheckResult": {
        "type": "object",
        "properties": {
          "rows": {
            "type": "integer"
          },
          "counts": {
            "type": "object",
            "properties": {
              "error": {
                "type": "integer"
              },
              "warning": {
                "type": "integer"
              },
              "info": {
                "type": "integer"
              }
            }
          },
          "findings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Finding"
            }
          },
          "usage": {
            "type": "object",
            "properties": {
              "month": {
                "type": "string"
              },
              "tracks_used": {
                "type": "integer"
              },
              "tracks_limit": {
                "type": "integer"
              }
            }
          }
        }
      },
      "Usage": {
        "type": "object",
        "properties": {
          "month": {
            "type": "string"
          },
          "plan": {
            "type": "string"
          },
          "requests": {
            "type": "integer"
          },
          "tracks_used": {
            "type": "integer"
          },
          "tracks_limit": {
            "type": "integer"
          },
          "rate_per_min": {
            "type": "integer"
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      }
    }
  }
}