{
  "openapi": "3.1.0",
  "info": {
    "title": "OnChain Music Agent API",
    "description": "A music licensing API designed for AI agents. Search a catalog of 5,000+ independently owned, fully cleared tracks by genre, mood, BPM, and other musical attributes. License tracks autonomously with on-chain USDC payments on Base via the x402 protocol \u2014 no human in the loop.\n\n## Agentic Licensing Flow\n1. Search the catalog using /catalog/search\n2. Get full track detail using /catalog/tracks/{id}\n3. Initiate a license using /license/{track_id}/{license_type} with your paying_wallet\n4. Receive a 402 Payment Required response with payment instructions\n5. Send USDC on Base from your declared wallet to the receiving address\n6. Poll /license/verify/{payment_id} until status is license_issued\n7. Receive a signed license document and S3 download URLs\n\n## Payment\n- Chain: Base (chain_id: 8453)\n- Token: USDC (0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913)\n- Protocol: x402\n- No memo or calldata required \u2014 payment verified by wallet address",
    "version": "1.0.0",
    "contact": {
      "name": "OnChain Music Partnerships",
      "url": "https://onchainmusic.com/contact"
    }
  },
  "externalDocs": {
    "description": "OnChain Music Agent API Documentation",
    "url": "https://onchainmusic.com/api-docs"
  },	  
  "servers": [
    {
      "url": "https://onchainmusic.com/api/v1/agent",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Catalog",
      "description": "Search and browse the music catalog"
    },
    {
      "name": "Licensing",
      "description": "Initiate and verify license purchases"
    }
  ],
  "paths": {
    "/catalog/search": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "summary": "Search the music catalog",
        "description": "Search 5,000+ tracks by musical attributes. All results are confirmed available for licensing. Supports pagination.",
        "operationId": "catalogSearch",
        "parameters": [
          {
            "name": "genre",
            "in": "query",
            "description": "Genre (e.g. Rock, Electronica, Hip-Hop)",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "subgenre",
            "in": "query",
            "description": "Subgenre (e.g. Indie, Deep House)",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "additional",
            "in": "query",
            "description": "Additional genre categories",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "mood",
            "in": "query",
            "description": "Deprecated — use description= instead. Pass mood and style words directly to description= for better results.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "tempo",
            "in": "query",
            "description": "Tempo label (e.g. Medium Fast (130 - 150 BPM))",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "bpm_min",
            "in": "query",
            "description": "Minimum BPM",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 300
            }
          },
          {
            "name": "bpm_max",
            "in": "query",
            "description": "Maximum BPM",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 300
            }
          },
          {
            "name": "key",
            "in": "query",
            "description": "Musical key (e.g. C Minor, G Maj)",
            "schema": {
              "type": "string",
              "maxLength": 20
            }
          },
          {
            "name": "instrumental",
            "in": "query",
            "description": "Yes = instrumental only (no vocals), No = has vocals",
            "schema": {
              "type": "string",
              "enum": [
                "Yes",
                "No"
              ]
            }
          },
          {
            "name": "keywords",
            "in": "query",
            "description": "Keyword search",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "name": "description",
            "in": "query",
            "description": "PRIMARY search field. Pass style, mood, energy, instrumentation, or use-case words. Each word is searched individually across multiple fields. Example: 'epic orchestral trailer'",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "name": "license_type",
            "in": "query",
            "description": "Filter license pricing display by type",
            "schema": {
              "type": "string",
              "enum": [
                "social_media",
                "all_digital"
              ]
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Results per page (default 20, max 50)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Catalog search results",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogSearchResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (60 requests/minute)"
          }
        }
      }
    },
    "/catalog/tracks/{id}": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "summary": "Get a single track",
        "description": "Retrieve full metadata for a specific track including license pricing and available download formats.",
        "operationId": "catalogTrack",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Track ID from catalog search results",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Track detail",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrackDetailResponse"
                }
              }
            }
          },
          "404": {
            "description": "Track not found or not available for licensing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
	"/ai-search": {
      "post": {
        "tags": ["Catalog"],
        "summary": "Natural language music search",
        "description": "Send a plain English phrase and the API uses GPT-4o-mini to translate it into structured search parameters automatically. Returns the same response as /catalog/search plus an ai object showing the translation.",
        "operationId": "aiSearch",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["phrase"],
                "properties": {
                  "phrase": {
                    "type": "string",
                    "description": "Plain English music description",
                    "example": "I need an upbeat indie rock track for a TV commercial"
                  },
                  "per_page": {
                    "type": "integer",
                    "description": "Results per page (default 10)",
                    "default": 10
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Search results with AI translation",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {"$ref": "#/components/schemas/CatalogSearchResponse"},
                    {
                      "type": "object",
                      "properties": {
                        "ai": {
                          "type": "object",
                          "properties": {
                            "original_phrase": {"type": "string"},
                            "translated_params": {"type": "object"}
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "422": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {"$ref": "#/components/schemas/ValidationError"}
              }
            }
          }
        }
      }
    },	
    "/license/{track_id}/{license_type}": {
      "post": {
        "tags": [
          "Licensing"
        ],
        "summary": "Initiate a license purchase",
        "description": "Initiate a license purchase. Provide your paying_wallet in the request body. Returns 402 with x402 payment instructions. Send USDC on Base from your wallet, then poll /license/verify/{payment_id} for your license.",
        "operationId": "licenseInitiate",
        "parameters": [
          {
            "name": "track_id",
            "in": "path",
            "required": true,
            "description": "Track ID to license",
            "schema": {
              "type": "integer"
            }
          },
		  {
			"name": "mode",
			"in": "query",
			"description": "Use 'gpt' for ChatGPT GPT Action compatibility.",
			"schema": {
				"type": "string",
				"enum": ["gpt"],
				"default": "gpt"
			}
		  },	
          {
            "name": "license_type",
            "in": "path",
            "required": true,
            "description": "License type",
            "schema": {
              "type": "string",
              "enum": [
                "social_media",
                "all_digital"
              ]
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "paying_wallet": {
                    "type": "string",
                    "description": "Your wallet address on Base (0x...). Strongly recommended.",
                    "example": "0x6d749657EEF45aF46fA2B7c81A6a4C7636f45D64",
                    "pattern": "^0x[a-fA-F0-9]{40}$"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
			"description": "Payment instructions returned (GPT mode) — send USDC as described then poll verify_url",
			"content": {
				"application/json": {
					"schema": {"$ref": "#/components/schemas/PaymentRequiredResponse"}
				}
			}
		  },
		  "402": {
            "description": "Payment required \u2014 x402 payment challenge",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentRequiredResponse"
                }
              }
            }
          },
          "404": {
            "description": "Track not found or not available for licensing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (10 requests/minute)"
          }
        }
      }
    },
    "/license/verify/{payment_id}": {
      "get": {
        "tags": [
          "Licensing"
        ],
        "summary": "Verify payment and retrieve license",
        "description": "Poll this endpoint after sending payment. Returns 202 Accepted with retry guidance while awaiting payment confirmation, 200 OK with signed license document and download URLs once confirmed, or 410 Gone if the payment window has expired. Recommended poll interval: 5 seconds.",
        "operationId": "licenseVerify",
        "parameters": [
          {
            "name": "payment_id",
            "in": "path",
            "required": true,
            "description": "Payment ID from the 402 response",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "License issued successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LicenseIssuedResponse"
                }
              }
            }
          },
          "202": {
            "description": "Awaiting payment confirmation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AwaitingPaymentResponse"
                }
              }
            }
          },
          "404": {
            "description": "Payment ID not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "410": {
            "description": "Payment window expired",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExpiredResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Track": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "example": 417
          },
          "title": {
            "type": "string",
            "example": "Chase the Sunshine Full"
          },
          "duration": {
            "type": "string",
            "example": "3:40"
          },
          "artists": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "name": {
                  "type": "string"
                }
              }
            }
          },
          "genre": {
            "type": "string",
            "example": "Rock"
          },
          "subgenre": {
            "type": "string",
            "example": "Indie"
          },
          "additional_genres": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "mood": {
            "type": "string",
            "example": "Upbeat"
          },
          "tempo": {
            "type": "string",
            "example": "Medium (100 - 129 BPM)"
          },
          "bpm": {
            "type": "integer",
            "example": 120
          },
          "key": {
            "type": "string",
            "example": "G Maj"
          },
          "instrumental": {
            "type": "boolean",
            "description": "true = no vocals, false = has vocals"
          },
          "keywords": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string"
          },
          "artwork_url": {
            "type": "string",
            "format": "uri"
          },
          "preview_url": {
            "type": "string",
            "format": "uri",
            "description": "Link to the OnChain Music track page where the track can be previewed"
          },
          "formats_available": {
            "type": "object",
            "properties": {
              "mp3": {
                "type": "boolean"
              },
              "wav": {
                "type": "boolean"
              },
              "aif": {
                "type": "boolean"
              }
            }
          },
          "license_options": {
            "type": "object",
            "properties": {
              "social_media": {
                "$ref": "#/components/schemas/LicenseOption"
              },
              "all_digital": {
                "$ref": "#/components/schemas/LicenseOption"
              }
            }
          },
          "license_purchase_url": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "LicenseOption": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "social_media"
          },
          "name": {
            "type": "string",
            "example": "Social Media License"
          },
          "description": {
            "type": "string"
          },
          "price_usdc": {
            "type": "string",
            "example": "5.00"
          },
          "term": {
            "type": "string",
            "example": "perpetual"
          },
          "exclusivity": {
            "type": "string",
            "example": "non-exclusive"
          },
          "territories": {
            "type": "string",
            "example": "worldwide"
          },
          "permitted_uses": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "CatalogSearchResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Track"
            }
          },
          "meta": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer"
              },
              "per_page": {
                "type": "integer"
              },
              "current_page": {
                "type": "integer"
              },
              "last_page": {
                "type": "integer"
              },
			  "fallback": {
				  "type": "boolean",
				  "description": "true if search filters were relaxed to return results"
			  }	  
            }
          },
          "licensing": {
            "type": "object"
          }
        }
      },
      "TrackDetailResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Track"
          },
          "licensing": {
            "type": "object"
          }
        }
      },
      "PaymentRequiredResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "example": "payment_required"
          },
          "message": {
            "type": "string"
          },
          "payment": {
            "type": "object",
            "properties": {
              "x402_version": {
                "type": "string",
                "example": "1.0"
              },
              "payment_id": {
                "type": "string",
                "format": "uuid"
              },
              "expires_at": {
                "type": "string",
                "format": "date-time"
              },
              "payment_details": {
                "type": "object",
                "properties": {
                  "chain": {
                    "type": "string",
                    "example": "base"
                  },
                  "chain_id": {
                    "type": "integer",
                    "example": 8453
                  },
                  "token": {
                    "type": "string",
                    "example": "USDC"
                  },
                  "receiving_address": {
                    "type": "string"
                  },
                  "amount_usdc": {
                    "type": "number",
                    "example": 5.0
                  },
                  "token_contract": {
                    "type": "string"
                  },
                  "paying_wallet": {
                    "type": "string",
                    "nullable": true
                  }
                }
              },
              "track": {
                "type": "object"
              },
              "instructions": {
                "type": "object"
              },
              "verify_url": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "LicenseIssuedResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "example": "license_issued"
          },
          "payment_id": {
            "type": "string",
            "format": "uuid"
          },
          "issued_at": {
            "type": "string",
            "format": "date-time"
          },
          "license_document": {
            "type": "object",
            "properties": {
              "license_id": {
                "type": "string",
                "format": "uuid"
              },
              "issued_at": {
                "type": "string",
                "format": "date-time"
              },
              "licensor": {
                "type": "string",
                "example": "OnChain Music"
              },
              "licensor_url": {
                "type": "string",
                "format": "uri"
              },
              "track": {
                "type": "object"
              },
              "license": {
                "type": "object"
              },
              "payment": {
                "type": "object"
              },
              "payees": {
                "type": "array",
                "items": {
                  "type": "object"
                }
              },
              "signature": {
                "type": "string",
                "description": "HMAC-SHA256 signature for tamper detection"
              }
            }
          },
          "downloads": {
            "type": "object",
            "properties": {
              "mp3": {
                "type": "string",
                "format": "uri",
                "nullable": true
              },
              "wav": {
                "type": "string",
                "format": "uri",
                "nullable": true
              },
              "aif": {
                "type": "string",
                "format": "uri",
                "nullable": true
              }
            }
          },
          "track": {
            "type": "object"
          }
        }
      },
      "AwaitingPaymentResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "example": "awaiting_payment"
          },
          "payment_id": {
            "type": "string",
            "format": "uuid"
          },
          "message": {
            "type": "string"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "retry_after": {
            "type": "string",
            "example": "5 seconds"
          },
          "verify_url": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "ExpiredResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "example": "expired"
          },
          "message": {
            "type": "string"
          },
          "new_license_url": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "ValidationError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "example": "Validation failed."
          },
          "details": {
            "type": "object"
          }
        }
      }
    }
  }
}