diff --git a/api/auth_middleware.go b/api/auth_middleware.go index 788ee1bd..75d13cb7 100644 --- a/api/auth_middleware.go +++ b/api/auth_middleware.go @@ -114,6 +114,19 @@ func (app *ApiServer) authMiddleware(c *fiber.Ctx) error { } else { wallet = app.recoverAuthorityFromSignatureHeaders(c) myId = app.getMyId(c) + // OAuth JWT fallback: when Bearer token is not api_access_key, try as OAuth JWT (Plans app) + if wallet == "" && myId != 0 { + if authHeader := c.Get("Authorization"); authHeader != "" && strings.HasPrefix(authHeader, "Bearer ") { + token := strings.TrimSpace(strings.TrimPrefix(authHeader, "Bearer ")) + if token != "" { + if oauthWallet, jwtUserId, err := app.validateOAuthJWTTokenToWalletAndUserId(c.Context(), token); err == nil { + if int32(jwtUserId) == myId { + wallet = oauthWallet + } + } + } + } + } } c.Locals("authedWallet", wallet) diff --git a/api/frontend_auth.go b/api/frontend_auth.go deleted file mode 100644 index 6bf023b4..00000000 --- a/api/frontend_auth.go +++ /dev/null @@ -1,65 +0,0 @@ -package api - -import ( - "strings" - - "github.com/ethereum/go-ethereum/crypto" - "github.com/gofiber/fiber/v2" - "go.uber.org/zap" -) - -// requireFrontendAppAuth returns a middleware that validates Bearer token and checks -// that the given frontend app (identified by its private key secret) has a grant from the user. -// Must run after requireUserIdMiddleware. -func (app *ApiServer) requireFrontendAppAuth(secret string, appName string) fiber.Handler { - return func(c *fiber.Ctx) error { - if secret == "" { - app.logger.Error(appName+" secret not configured", zap.String("app", appName)) - return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ - "error": appName + " not configured", - }) - } - - authHeader := c.Get("Authorization") - if authHeader == "" || !strings.HasPrefix(authHeader, "Bearer ") { - return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{ - "error": "Missing or invalid Authorization header. Use Bearer ", - }) - } - token := strings.TrimPrefix(authHeader, "Bearer ") - - pathUserId := app.getUserId(c) - if pathUserId == 0 { - return fiber.NewError(fiber.StatusBadRequest, "invalid userId") - } - - jwtUserId, err := app.validateOAuthJWTTokenToUserId(c.Context(), token) - if err != nil { - return err - } - - if int32(jwtUserId) != pathUserId { - return c.Status(fiber.StatusForbidden).JSON(fiber.Map{ - "error": "Token userId does not match path userId", - }) - } - - // Derive app address from private key - privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(secret, "0x")) - if err != nil { - app.logger.Error("Invalid "+appName+" secret", zap.Error(err)) - return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ - "error": appName + " misconfigured", - }) - } - appAddress := strings.ToLower(crypto.PubkeyToAddress(privateKey.PublicKey).Hex()) - - if !app.isAuthorizedRequest(c.Context(), pathUserId, appAddress) { - return c.Status(fiber.StatusForbidden).JSON(fiber.Map{ - "error": "User has not granted the " + strings.ToLower(appName) + " write access. Log in with OAuth scope 'write'.", - }) - } - - return c.Next() - } -} diff --git a/api/server.go b/api/server.go index da0a82d1..b1c24766 100644 --- a/api/server.go +++ b/api/server.go @@ -388,6 +388,11 @@ func NewApiServer(config config.Config) *ApiServer { g.Get("/users/:userId/balance/history", app.v1UsersBalanceHistory) g.Get("/users/:userId/managers", app.v1UsersManagers) g.Get("/users/:userId/managed_users", app.v1UsersManagedUsers) + g.Post("/users/:userId/grants", app.requireAuthMiddleware, app.postV1UsersGrant) + g.Delete("/users/:userId/grants/:address", app.requireAuthMiddleware, app.deleteV1UsersGrant) + g.Post("/users/:userId/managers", app.requireAuthMiddleware, app.postV1UsersManager) + g.Delete("/users/:userId/managers/:managerUserId", app.requireAuthMiddleware, app.deleteV1UsersManager) + g.Post("/users/:userId/grants/approve", app.requireAuthMiddleware, app.postV1UsersApproveGrant) g.Get("/users/:userId/mutuals", app.v1UsersMutuals) g.Get("/users/:userId/reposts", app.v1UsersReposts) g.Get("/users/:userId/related", app.v1UsersRelated) @@ -433,12 +438,6 @@ func NewApiServer(config config.Config) *ApiServer { g.Get("/users/:userId/authorized-apps", app.v1UsersAuthorizedApps) g.Get("/users/:userId/developer_apps", app.v1UsersDeveloperApps) g.Get("/users/:userId/developer-apps", app.v1UsersDeveloperApps) - frontendAuth := app.requireFrontendAppAuth(config.AudiusApiSecret, "Plans app") - g.Post("/users/:userId/developer_apps", frontendAuth, app.postV1UsersDeveloperAppCreate) - g.Post("/users/:userId/developer-apps", frontendAuth, app.postV1UsersDeveloperAppCreate) - g.Delete("/users/:userId/developer-apps/:address", frontendAuth, app.deleteV1UsersDeveloperApp) - g.Post("/users/:userId/developer-apps/:address/access-keys/deactivate", frontendAuth, app.postV1UsersDeveloperAppAccessKeyDeactivate) - g.Post("/users/:userId/developer-apps/:address/access-keys", frontendAuth, app.postV1UsersDeveloperAppAccessKeyCreate) g.Get("/users/:userId/withdrawals/download", app.requireAuthForUserId, app.v1UsersWithdrawalsDownloadCsv) g.Get("/users/:userId/withdrawals/download/json", app.requireAuthForUserId, app.v1UsersWithdrawalsDownloadJson) g.Post("/users/:userId/follow", app.requireAuthMiddleware, app.postV1UserFollow) @@ -527,12 +526,17 @@ func NewApiServer(config config.Config) *ApiServer { g.Get("/search/full", app.v1SearchFull) g.Get("/search/tags", app.v1SearchFull) - // Developer Apps + // Developer Apps (Plans API - user_id query; indexer validates grants) g.Get("/developer_apps/:address", app.v1DeveloperApps) g.Get("/developer-apps/:address", app.v1DeveloperApps) - g.Post("/developer-apps", app.requireAuthMiddleware, app.postV1DeveloperApp) - g.Put("/developer-apps/:address", app.requireAuthMiddleware, app.putV1DeveloperApp) - g.Delete("/developer-apps/:address", app.requireAuthMiddleware, app.deleteV1DeveloperApp) + g.Post("/developer_apps", app.postV1UsersDeveloperApp) + g.Post("/developer-apps", app.postV1UsersDeveloperApp) + g.Delete("/developer_apps/:address", app.deleteV1UsersDeveloperApp) + g.Delete("/developer-apps/:address", app.deleteV1UsersDeveloperApp) + g.Post("/developer_apps/:address/access-keys/deactivate", app.postV1UsersDeveloperAppAccessKeyDeactivate) + g.Post("/developer-apps/:address/access-keys/deactivate", app.postV1UsersDeveloperAppAccessKeyDeactivate) + g.Post("/developer_apps/:address/access-keys", app.postV1UsersDeveloperAppAccessKey) + g.Post("/developer-apps/:address/access-keys", app.postV1UsersDeveloperAppAccessKey) // Rewards g.Post("/rewards/claim", app.v1ClaimRewards) diff --git a/api/swagger/swagger-v1.yaml b/api/swagger/swagger-v1.yaml index 3dd77ea5..6587013d 100644 --- a/api/swagger/swagger-v1.yaml +++ b/api/swagger/swagger-v1.yaml @@ -4,77 +4,80 @@ info: description: Audius V1 API version: "1.0" servers: -- url: /v1 + - url: /v1 tags: -- name: users - description: User related operations -- name: playlists - description: Playlist related operations -- name: tracks - description: Track related operations -- name: challenges - description: Challenge related operations -- name: tips - description: Tip related operations -- name: developer_apps - description: Developer app related operations -- name: dashboard_wallet_users - description: Protocol dashboard wallet users related operations -- name: resolve - description: Audius Cannonical URL resolver -- name: comments - description: Comment related operations -- name: events - description: Events related operations -- name: explore - description: Explore related operations -- name: rewards - description: Rewards related operations -- name: prizes - description: Prize claiming related operations + - name: users + description: User related operations + - name: playlists + description: Playlist related operations + - name: tracks + description: Track related operations + - name: challenges + description: Challenge related operations + - name: tips + description: Tip related operations + - name: developer_apps + description: Developer app related operations + - name: dashboard_wallet_users + description: Protocol dashboard wallet users related operations + - name: resolve + description: Audius Cannonical URL resolver + - name: comments + description: Comment related operations + - name: events + description: Events related operations + - name: explore + description: Explore related operations + - name: rewards + description: Rewards related operations + - name: prizes + description: Prize claiming related operations paths: /challenges/undisbursed: get: tags: - - challenges + - challenges description: Get all undisbursed challenges operationId: Get Undisbursed Challenges parameters: - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: A User ID to filter the undisbursed challenges to a particular - user - schema: - type: string - - name: completed_blocknumber - in: query - description: Starting blocknumber to retrieve completed undisbursed challenges - schema: - type: integer - - name: challenge_id - in: query - description: A challenge ID to filter the undisbursed challenges to a particular - challenge - schema: - type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: + A User ID to filter the undisbursed challenges to a particular + user + schema: + type: string + - name: completed_blocknumber + in: query + description: Starting blocknumber to retrieve completed undisbursed challenges + schema: + type: integer + - name: challenge_id + in: query + description: + A challenge ID to filter the undisbursed challenges to a particular + challenge + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/undisbursed_challenges' + $ref: "#/components/schemas/undisbursed_challenges" "400": description: Bad request content: {} @@ -84,46 +87,49 @@ paths: /challenges/undisbursed/{user_id}: get: tags: - - challenges + - challenges description: Get all undisbursed challenges for a user operationId: Get Undisbursed Challenges For User parameters: - - name: user_id - in: path - description: A User ID to filter the undisbursed challenges to a particular - user - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: completed_blocknumber - in: query - description: Starting blocknumber to retrieve completed undisbursed challenges - schema: - type: integer - - name: challenge_id - in: query - description: A challenge ID to filter the undisbursed challenges to a particular - challenge - schema: - type: string + - name: user_id + in: path + description: + A User ID to filter the undisbursed challenges to a particular + user + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: completed_blocknumber + in: query + description: Starting blocknumber to retrieve completed undisbursed challenges + schema: + type: integer + - name: challenge_id + in: query + description: + A challenge ID to filter the undisbursed challenges to a particular + challenge + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/undisbursed_challenges' + $ref: "#/components/schemas/undisbursed_challenges" "400": description: Bad request content: {} @@ -133,7 +139,7 @@ paths: /comments/unclaimed_id: get: tags: - - comments + - comments description: Gets an unclaimed blockchain comment ID operationId: Get unclaimed comment ID responses: @@ -142,40 +148,40 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/unclaimed_id_response' + $ref: "#/components/schemas/unclaimed_id_response" "500": description: Server error content: {} /comments: post: tags: - - comments + - comments description: Creates a new comment operationId: Create Comment security: - - BasicAuth: [] - - BearerAuth: [] + - BasicAuth: [] + - BearerAuth: [] parameters: - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string requestBody: x-codegen-request-body-name: metadata required: true content: application/json: schema: - $ref: '#/components/schemas/create_comment_request_body' + $ref: "#/components/schemas/create_comment_request_body" responses: "201": description: Comment created successfully content: application/json: schema: - $ref: '#/components/schemas/create_comment_response' + $ref: "#/components/schemas/create_comment_response" "400": description: Bad request content: {} @@ -188,61 +194,61 @@ paths: /comments/{comment_id}: get: tags: - - comments + - comments description: Gets a comment by ID operationId: Get Comment parameters: - - name: comment_id - in: path - description: A Comment ID - required: true - schema: - type: string + - name: comment_id + in: path + description: A Comment ID + required: true + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/comment_response' + $ref: "#/components/schemas/comment_response" "500": description: Server error content: {} put: tags: - - comments + - comments description: Updates a comment operationId: Update Comment security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: comment_id - in: path - description: A Comment ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: comment_id + in: path + description: A Comment ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string requestBody: x-codegen-request-body-name: metadata required: true content: application/json: schema: - $ref: '#/components/schemas/update_comment_request_body' + $ref: "#/components/schemas/update_comment_request_body" responses: "200": description: Comment updated successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -254,32 +260,32 @@ paths: content: {} delete: tags: - - comments + - comments description: Deletes a comment operationId: Delete Comment security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: comment_id - in: path - description: A Comment ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: comment_id + in: path + description: A Comment ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: "200": description: Comment deleted successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -292,30 +298,30 @@ paths: /comments/{comment_id}/react: post: tags: - - comments + - comments description: React to a comment operationId: React to Comment security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: comment_id - in: path - description: A Comment ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: comment_id + in: path + description: A Comment ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string requestBody: content: application/json: schema: - $ref: '#/components/schemas/react_comment_request_body' + $ref: "#/components/schemas/react_comment_request_body" required: true x-codegen-request-body-name: metadata responses: @@ -324,7 +330,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -336,30 +342,30 @@ paths: content: {} delete: tags: - - comments + - comments description: Unreact to a comment operationId: Unreact to Comment security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: comment_id - in: path - description: A Comment ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: comment_id + in: path + description: A Comment ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string requestBody: content: application/json: schema: - $ref: '#/components/schemas/react_comment_request_body' + $ref: "#/components/schemas/react_comment_request_body" required: true x-codegen-request-body-name: metadata responses: @@ -368,7 +374,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -381,30 +387,30 @@ paths: /comments/{comment_id}/pin: post: tags: - - comments + - comments description: Pin a comment operationId: Pin Comment security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: comment_id - in: path - description: A Comment ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: comment_id + in: path + description: A Comment ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string requestBody: content: application/json: schema: - $ref: '#/components/schemas/pin_comment_request_body' + $ref: "#/components/schemas/pin_comment_request_body" required: true x-codegen-request-body-name: metadata responses: @@ -413,7 +419,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -425,30 +431,30 @@ paths: content: {} delete: tags: - - comments + - comments description: Unpin a comment operationId: Unpin Comment security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: comment_id - in: path - description: A Comment ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: comment_id + in: path + description: A Comment ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string requestBody: content: application/json: schema: - $ref: '#/components/schemas/pin_comment_request_body' + $ref: "#/components/schemas/pin_comment_request_body" required: true x-codegen-request-body-name: metadata responses: @@ -457,7 +463,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -470,32 +476,32 @@ paths: /comments/{comment_id}/report: post: tags: - - comments + - comments description: Report a comment operationId: Report Comment security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: comment_id - in: path - description: A Comment ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: comment_id + in: path + description: A Comment ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: "200": description: Comment reported successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -508,39 +514,40 @@ paths: /comments/{comment_id}/replies: get: tags: - - comments + - comments description: Gets replies to a parent comment operationId: Get Comment Replies parameters: - - name: comment_id - in: path - description: A Comment ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: comment_id + in: path + description: A Comment ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/comment_replies_response' + $ref: "#/components/schemas/comment_replies_response" "400": description: Bad request content: {} @@ -550,33 +557,30 @@ paths: /developer-apps: post: tags: - - developer_apps - description: Creates a new developer app + - developer_apps + description: Create a new developer app (Plans API). Indexer validates grants. operationId: Create Developer App - security: - - BasicAuth: [] - - BearerAuth: [] parameters: - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: user_id + in: query + description: The user ID of the user creating the developer app + required: true + schema: + type: string requestBody: x-codegen-request-body-name: metadata required: true content: application/json: schema: - $ref: '#/components/schemas/create_developer_app_request_body' + $ref: "#/components/schemas/create_developer_app_request_body" responses: - "201": + "200": description: Developer app created successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/create_developer_app_response" "400": description: Bad request content: {} @@ -589,23 +593,23 @@ paths: /developer-apps/{address}: get: tags: - - developer_apps + - developer_apps description: Gets developer app matching given address (API key) operationId: Get Developer App parameters: - - name: address - in: path - description: A developer app address (API Key) - required: true - schema: - type: string + - name: address + in: path + description: A developer app address (API Key) + required: true + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/developer_app_response' + $ref: "#/components/schemas/developer_app_response" "400": description: Bad request content: {} @@ -615,86 +619,116 @@ paths: "500": description: Server error content: {} - put: + delete: tags: - - developer_apps - description: Updates an existing developer app - operationId: Update Developer App - security: - - BasicAuth: [] - - BearerAuth: [] + - developer_apps + description: Deletes a developer app (Plans API). Indexer validates grants. + operationId: Delete Developer App parameters: - - name: address - in: path - description: Developer app address - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: user_id + in: query + description: The user ID of the user who owns the developer app + required: true + schema: + type: string + - name: address + in: path + description: Developer app address (API Key) + required: true + schema: + type: string + responses: + "200": + description: Developer app deleted successfully + content: + application/json: + schema: + $ref: "#/components/schemas/write_response" + "401": + description: Unauthorized + content: {} + "404": + description: Not found + content: {} + "500": + description: Server error + content: {} + /developer-apps/{address}/access-keys/deactivate: + post: + tags: + - developer_apps + description: Deactivate a bearer token (API access key) for a developer app (Plans API). Indexer validates grants. + operationId: Deactivate Developer App Access Key + parameters: + - name: user_id + in: query + description: The user ID of the user who owns the developer app + required: true + schema: + type: string + - name: address + in: path + description: Developer app address (API Key) + required: true + schema: + type: string requestBody: x-codegen-request-body-name: metadata required: true content: application/json: schema: - $ref: '#/components/schemas/update_developer_app_request_body' + $ref: "#/components/schemas/deactivate_access_key_request_body" responses: "200": - description: Developer app updated successfully + description: Access key deactivated successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/deactivate_access_key_response" "400": - description: Bad request + description: Bad request (api_access_key required) content: {} "401": description: Unauthorized content: {} "404": - description: Not found + description: Developer app or access key not found content: {} "500": description: Server error content: {} - delete: + /developer-apps/{address}/access-keys: + post: tags: - - developer_apps - description: Deletes a developer app - operationId: Delete Developer App - security: - - BasicAuth: [] - - BearerAuth: [] + - developer_apps + description: Create a new bearer token (API access key) for a developer app (Plans API). Indexer validates grants. + operationId: Create Developer App Access Key parameters: - - name: address - in: path - description: Developer app address - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: user_id + in: query + description: The user ID of the user who owns the developer app + required: true + schema: + type: string + - name: address + in: path + description: Developer app address (API Key) + required: true + schema: + type: string responses: "200": - description: Developer app deleted successfully + description: Access key created successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/create_access_key_response" "401": description: Unauthorized content: {} "404": - description: Not found + description: Developer app not found content: {} "500": description: Server error @@ -702,27 +736,27 @@ paths: /dashboard_wallet_users: get: tags: - - dashboard_wallet_users + - dashboard_wallet_users description: Gets Audius user profiles connected to given dashboard wallet addresses operationId: Bulk get dashboard wallet users parameters: - - name: wallets - in: query - description: The wallets for which to fetch connected Audius user profiles. - required: true - style: form - explode: false - schema: - type: array - items: - type: string + - name: wallets + in: query + description: The wallets for which to fetch connected Audius user profiles. + required: true + style: form + explode: false + schema: + type: array + items: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/dashboard_wallet_users_response' + $ref: "#/components/schemas/dashboard_wallet_users_response" "400": description: Bad request content: {} @@ -735,40 +769,40 @@ paths: /events: get: tags: - - events + - events description: Get a list of events by ID operationId: Get Bulk Events parameters: - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: id - in: query - description: The ID of the event(s) to retrieve - style: form - explode: true - schema: - type: array - items: + - name: user_id + in: query + description: The user ID of the user making the request + schema: type: string - - name: event_type - in: query - description: The type of event to filter by - schema: - type: string - enum: - - remix_contest - - live_event - - new_release + - name: id + in: query + description: The ID of the event(s) to retrieve + style: form + explode: true + schema: + type: array + items: + type: string + - name: event_type + in: query + description: The type of event to filter by + schema: + type: string + enum: + - remix_contest + - live_event + - new_release responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/events_response' + $ref: "#/components/schemas/events_response" "400": description: Bad request content: {} @@ -778,52 +812,53 @@ paths: /events/all: get: tags: - - events + - events summary: Get all events description: Get all events operationId: Get All Events parameters: - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: sort_method - in: query - description: The sort method - schema: - type: string - default: newest - enum: - - newest - - timestamp - - name: event_type - in: query - description: The type of event to filter by - schema: - type: string - enum: - - remix_contest - - live_event - - new_release + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: sort_method + in: query + description: The sort method + schema: + type: string + default: newest + enum: + - newest + - timestamp + - name: event_type + in: query + description: The type of event to filter by + schema: + type: string + enum: + - remix_contest + - live_event + - new_release responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/events_response' + $ref: "#/components/schemas/events_response" "400": description: Bad request content: {} @@ -833,59 +868,60 @@ paths: /events/entity: get: tags: - - events + - events summary: Get events for a specific entity description: Get events for a specific entity operationId: Get Entity Events parameters: - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: entity_id - in: query - description: The ID of the entity to get events for - required: true - style: form - explode: true - schema: - type: array - items: - type: string - - name: entity_type - in: query - description: The type of entity to get events for - schema: - type: string - enum: - - track - - collection - - user - - name: filter_deleted - in: query - description: Whether to filter deleted events - schema: - type: boolean - default: true + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: entity_id + in: query + description: The ID of the entity to get events for + required: true + style: form + explode: true + schema: + type: array + items: + type: string + - name: entity_type + in: query + description: The type of entity to get events for + schema: + type: string + enum: + - track + - collection + - user + - name: filter_deleted + in: query + description: Whether to filter deleted events + schema: + type: boolean + default: true responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/events_response' + $ref: "#/components/schemas/events_response" "400": description: Bad request content: {} @@ -895,7 +931,7 @@ paths: /events/unclaimed_id: get: tags: - - events + - events description: Gets an unclaimed blockchain event ID operationId: Get unclaimed event ID responses: @@ -904,51 +940,52 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/unclaimed_id_response' + $ref: "#/components/schemas/unclaimed_id_response" "500": description: Server error content: {} /explore/best-selling: get: tags: - - explore + - explore summary: Get best selling tracks and/or albums description: Get best selling tracks and playlists operationId: Get Best Selling parameters: - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: type - in: query - description: The type of content to filter by - schema: - type: string - default: all - enum: - - all - - track - - album + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: type + in: query + description: The type of content to filter by + schema: + type: string + default: all + enum: + - all + - track + - album responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/best_selling_response' + $ref: "#/components/schemas/best_selling_response" "400": description: Bad request content: {} @@ -958,40 +995,40 @@ paths: /playlists: get: tags: - - playlists + - playlists description: Gets a list of playlists by ID operationId: Get Bulk Playlists parameters: - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: id - in: query - description: The ID of the playlist(s) - style: form - explode: true - schema: - type: array - items: - type: string - - name: upc - in: query - description: The UPC of the playlist(s) - style: form - explode: true - schema: - type: array - items: + - name: user_id + in: query + description: The user ID of the user making the request + schema: type: string + - name: id + in: query + description: The ID of the playlist(s) + style: form + explode: true + schema: + type: array + items: + type: string + - name: upc + in: query + description: The UPC of the playlist(s) + style: form + explode: true + schema: + type: array + items: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/playlist_response' + $ref: "#/components/schemas/playlist_response" "400": description: Bad request content: {} @@ -1000,33 +1037,33 @@ paths: content: {} post: tags: - - playlists + - playlists description: Creates a new playlist or album operationId: Create Playlist security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string requestBody: x-codegen-request-body-name: metadata required: true content: application/json: schema: - $ref: '#/components/schemas/create_playlist_request_body' + $ref: "#/components/schemas/create_playlist_request_body" responses: "201": description: Playlist created successfully content: application/json: schema: - $ref: '#/components/schemas/create_playlist_response' + $ref: "#/components/schemas/create_playlist_response" "400": description: Bad request content: {} @@ -1039,101 +1076,102 @@ paths: /playlists/by_permalink/{handle}/{slug}: get: tags: - - playlists + - playlists description: Get a playlist by handle and slug operationId: Get Playlist By Handle and Slug parameters: - - name: handle - in: path - description: playlist owner handle - required: true - schema: - type: string - - name: slug - in: path - description: playlist slug - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: handle + in: path + description: playlist owner handle + required: true + schema: + type: string + - name: slug + in: path + description: playlist slug + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/playlist_response' + $ref: "#/components/schemas/playlist_response" /playlists/search: get: tags: - - playlists + - playlists description: Search for a playlist operationId: Search Playlists parameters: - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: query - in: query - description: The search query - schema: - type: string - - name: genre - in: query - description: The genres to filter by - style: form - explode: true - schema: - type: array - items: + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: query + in: query + description: The search query + schema: type: string - - name: sort_method - in: query - description: The sort method - schema: - type: string - enum: - - relevant - - popular - - recent - - name: mood - in: query - description: The moods to filter by - style: form - explode: true - schema: - type: array - items: + - name: genre + in: query + description: The genres to filter by + style: form + explode: true + schema: + type: array + items: + type: string + - name: sort_method + in: query + description: The sort method + schema: + type: string + enum: + - relevant + - popular + - recent + - name: mood + in: query + description: The moods to filter by + style: form + explode: true + schema: + type: array + items: + type: string + - name: includePurchaseable + in: query + description: Whether or not to include purchaseable content + schema: + type: string + - name: has_downloads + in: query + description: Only include tracks that have downloads in the track results + schema: type: string - - name: includePurchaseable - in: query - description: Whether or not to include purchaseable content - schema: - type: string - - name: has_downloads - in: query - description: Only include tracks that have downloads in the track results - schema: - type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/playlist_search_result' + $ref: "#/components/schemas/playlist_search_result" "400": description: Bad request content: {} @@ -1143,58 +1181,59 @@ paths: /playlists/trending: get: tags: - - playlists + - playlists description: Gets trending playlists for a time period operationId: Get Trending Playlists parameters: - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: time - in: query - description: Calculate trending over a specified time range - schema: - type: string - enum: - - week - - month - - year - - allTime - - name: type - in: query - description: The type of content to filter by - schema: - type: string - default: playlist - enum: - - playlist - - album - - name: omit_tracks - in: query - description: Whether to omit tracks from the response - schema: - type: boolean - default: false + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: time + in: query + description: Calculate trending over a specified time range + schema: + type: string + enum: + - week + - month + - year + - allTime + - name: type + in: query + description: The type of content to filter by + schema: + type: string + default: playlist + enum: + - playlist + - album + - name: omit_tracks + in: query + description: Whether to omit tracks from the response + schema: + type: boolean + default: false responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/trending_playlists_response' + $ref: "#/components/schemas/trending_playlists_response" "400": description: Bad request content: {} @@ -1204,28 +1243,28 @@ paths: /playlists/{playlist_id}: get: tags: - - playlists + - playlists description: Get a playlist by ID operationId: Get Playlist parameters: - - name: playlist_id - in: path - description: A Playlist ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: playlist_id + in: path + description: A Playlist ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/playlist_response' + $ref: "#/components/schemas/playlist_response" "400": description: Bad request content: {} @@ -1234,39 +1273,39 @@ paths: content: {} put: tags: - - playlists + - playlists description: Updates an existing playlist or album operationId: Update Playlist security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: playlist_id - in: path - description: A Playlist ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: playlist_id + in: path + description: A Playlist ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string requestBody: x-codegen-request-body-name: metadata required: true content: application/json: schema: - $ref: '#/components/schemas/update_playlist_request_body' + $ref: "#/components/schemas/update_playlist_request_body" responses: "200": description: Playlist updated successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "400": description: Bad request content: {} @@ -1281,32 +1320,32 @@ paths: content: {} delete: tags: - - playlists + - playlists description: Deletes a playlist or album operationId: Delete Playlist security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: playlist_id - in: path - description: A Playlist ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: playlist_id + in: path + description: A Playlist ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: "200": description: Playlist deleted successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -1319,49 +1358,50 @@ paths: /playlists/{playlist_id}/access-info: get: tags: - - playlists - description: Gets the information necessary to access the playlist and what + - playlists + description: + Gets the information necessary to access the playlist and what access the given user has. operationId: Get Playlist Access Info parameters: - - name: playlist_id - in: path - description: A Playlist ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: playlist_id + in: path + description: A Playlist ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/access_info_response' + $ref: "#/components/schemas/access_info_response" /playlists/{playlist_id}/tracks: get: tags: - - playlists + - playlists description: Fetch tracks within a playlist. operationId: Get Playlist Tracks parameters: - - name: playlist_id - in: path - description: A Playlist ID - required: true - schema: - type: string + - name: playlist_id + in: path + description: A Playlist ID + required: true + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/playlist_tracks_response' + $ref: "#/components/schemas/playlist_tracks_response" "400": description: Bad request content: {} @@ -1371,32 +1411,32 @@ paths: /playlists/{playlist_id}/favorites: post: tags: - - playlists + - playlists description: Favorite a playlist operationId: Favorite Playlist security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: playlist_id - in: path - description: A Playlist ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: playlist_id + in: path + description: A Playlist ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: "200": description: Playlist favorited successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -1408,32 +1448,32 @@ paths: content: {} delete: tags: - - playlists + - playlists description: Unfavorite a playlist operationId: Unfavorite Playlist security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: playlist_id - in: path - description: A Playlist ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: playlist_id + in: path + description: A Playlist ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: "200": description: Playlist unfavorited successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -1446,32 +1486,32 @@ paths: /playlists/{playlist_id}/reposts: post: tags: - - playlists + - playlists description: Repost a playlist operationId: Repost Playlist security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: playlist_id - in: path - description: A Playlist ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: playlist_id + in: path + description: A Playlist ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: "200": description: Playlist reposted successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -1483,32 +1523,32 @@ paths: content: {} delete: tags: - - playlists + - playlists description: Unrepost a playlist operationId: Unrepost Playlist security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: playlist_id - in: path - description: A Playlist ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: playlist_id + in: path + description: A Playlist ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: "200": description: Playlist unreposted successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -1521,32 +1561,32 @@ paths: /playlists/{playlist_id}/shares: post: tags: - - playlists + - playlists description: Record a playlist share event operationId: Share Playlist security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: playlist_id - in: path - description: A Playlist ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: playlist_id + in: path + description: A Playlist ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: "200": description: Playlist share recorded successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -1559,8 +1599,9 @@ paths: /resolve: get: tags: - - resolve - summary: Resolves and redirects a provided Audius app URL to the API resource + - resolve + summary: + Resolves and redirects a provided Audius app URL to the API resource URL it represents description: |- This endpoint allows you to lookup and access API resources when you only know the @@ -1568,13 +1609,14 @@ paths: Tracks, Playlists, and Users are supported. operationId: Resolve parameters: - - name: url - in: query - description: URL to resolve. Either fully formed URL (https://audius.co) or - just the absolute path - required: true - schema: - type: string + - name: url + in: query + description: + URL to resolve. Either fully formed URL (https://audius.co) or + just the absolute path + required: true + schema: + type: string responses: "302": description: Internal redirect @@ -1582,133 +1624,136 @@ paths: /tips: get: tags: - - tips + - tips description: Gets the most recent tips on the network operationId: Get Tips parameters: - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: receiver_min_followers - in: query - description: Only include tips to recipients that have this many followers - schema: - type: integer - default: 0 - - name: receiver_is_verified - in: query - description: Only include tips to recipients that are verified - schema: - type: boolean - default: false - - name: current_user_follows - in: query - description: Only include tips involving the user's followers in the given - capacity. Requires user_id to be set. - schema: - type: string - enum: - - sender - - receiver - - sender_or_receiver - - name: unique_by - in: query - description: "Only include the most recent tip for a user was involved in\ - \ the given capacity.\n\nEg. 'sender' will ensure that each tip returned\ - \ has a unique sender, using the most recent tip sent by a user if that\ - \ user has sent multiple tips.\n " - schema: - type: string - enum: - - sender - - receiver - - name: min_slot - in: query - description: The minimum Solana slot to pull tips from - schema: - type: integer - default: 0 - - name: max_slot - in: query - description: The maximum Solana slot to pull tips from - schema: - type: integer - default: 0 - - name: tx_signatures - in: query - description: A list of transaction signatures of tips to fetch - style: form - explode: false - schema: - type: array - items: + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: receiver_min_followers + in: query + description: Only include tips to recipients that have this many followers + schema: + type: integer + default: 0 + - name: receiver_is_verified + in: query + description: Only include tips to recipients that are verified + schema: + type: boolean + default: false + - name: current_user_follows + in: query + description: + Only include tips involving the user's followers in the given + capacity. Requires user_id to be set. + schema: + type: string + enum: + - sender + - receiver + - sender_or_receiver + - name: unique_by + in: query + description: + "Only include the most recent tip for a user was involved in\ + \ the given capacity.\n\nEg. 'sender' will ensure that each tip returned\ + \ has a unique sender, using the most recent tip sent by a user if that\ + \ user has sent multiple tips.\n " + schema: type: string + enum: + - sender + - receiver + - name: min_slot + in: query + description: The minimum Solana slot to pull tips from + schema: + type: integer + default: 0 + - name: max_slot + in: query + description: The maximum Solana slot to pull tips from + schema: + type: integer + default: 0 + - name: tx_signatures + in: query + description: A list of transaction signatures of tips to fetch + style: form + explode: false + schema: + type: array + items: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/get_tips_response' + $ref: "#/components/schemas/get_tips_response" /tracks: get: tags: - - tracks + - tracks description: Gets a list of tracks using their IDs or permalinks operationId: Get Bulk Tracks parameters: - - name: permalink - in: query - description: The permalink of the track(s) - style: form - explode: true - schema: - type: array - items: - type: string - - name: id - in: query - description: The ID of the track(s) - style: form - explode: true - schema: - type: array - items: - type: string - - name: isrc - in: query - description: The ISRC of the track(s) - style: form - explode: true - schema: - type: array - items: + - name: permalink + in: query + description: The permalink of the track(s) + style: form + explode: true + schema: + type: array + items: + type: string + - name: id + in: query + description: The ID of the track(s) + style: form + explode: true + schema: + type: array + items: + type: string + - name: isrc + in: query + description: The ISRC of the track(s) + style: form + explode: true + schema: + type: array + items: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + schema: type: string - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/tracks_response' + $ref: "#/components/schemas/tracks_response" "400": description: Bad request content: {} @@ -1717,33 +1762,33 @@ paths: content: {} post: tags: - - tracks + - tracks description: Creates a new track operationId: Create Track security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string - requestBody: - x-codegen-request-body-name: metadata + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string + requestBody: + x-codegen-request-body-name: metadata required: true content: application/json: schema: - $ref: '#/components/schemas/create_track_request_body' + $ref: "#/components/schemas/create_track_request_body" responses: "201": description: Track created successfully content: application/json: schema: - $ref: '#/components/schemas/create_track_response' + $ref: "#/components/schemas/create_track_response" "400": description: Bad request content: {} @@ -1756,34 +1801,34 @@ paths: /tracks/inspect: get: tags: - - tracks + - tracks summary: Inspects the details of the files for multiple tracks description: Inspect multiple tracks operationId: Inspect Tracks parameters: - - name: id - in: query - description: List of track IDs to inspect - required: true - style: form - explode: true - schema: - type: array - items: - type: string - - name: original - in: query - description: Optional - if set to true inspects the original file quality - schema: - type: boolean - default: false + - name: id + in: query + description: List of track IDs to inspect + required: true + style: form + explode: true + schema: + type: array + items: + type: string + - name: original + in: query + description: Optional - if set to true inspects the original file quality + schema: + type: boolean + default: false responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/track_inspect_list' + $ref: "#/components/schemas/track_inspect_list" "400": description: Bad request content: {} @@ -1793,175 +1838,176 @@ paths: /tracks/recent-premium: get: tags: - - tracks + - tracks description: Gets the most recently listed premium tracks operationId: Get Recent Premium Tracks parameters: - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/tracks_response' + $ref: "#/components/schemas/tracks_response" /tracks/recommended: get: tags: - - tracks + - tracks description: Get recommended tracks operationId: Get Recommended Tracks parameters: - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: genre - in: query - description: Filter trending to a specified genre - schema: - type: string - - name: time - in: query - description: Calculate trending over a specified time range - schema: - type: string - enum: - - week - - month - - year - - allTime - - name: exclusion_list - in: query - description: List of track ids to exclude - style: form - explode: true - schema: - type: array - items: + - name: limit + in: query + description: The number of items to fetch + schema: type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: genre + in: query + description: Filter trending to a specified genre + schema: + type: string + - name: time + in: query + description: Calculate trending over a specified time range + schema: + type: string + enum: + - week + - month + - year + - allTime + - name: exclusion_list + in: query + description: List of track ids to exclude + style: form + explode: true + schema: + type: array + items: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/tracks_response' + $ref: "#/components/schemas/tracks_response" /tracks/recommended/{version}: get: tags: - - tracks + - tracks description: Get recommended tracks using the given trending strategy version operationId: Get Recommended Tracks With Version parameters: - - name: version - in: path - description: The strategy version of trending to use - required: true - schema: - type: string - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: genre - in: query - description: Filter trending to a specified genre - schema: - type: string - - name: time - in: query - description: Calculate trending over a specified time range - schema: - type: string - enum: - - week - - month - - year - - allTime - - name: exclusion_list - in: query - description: List of track ids to exclude - style: form - explode: true - schema: - type: array - items: + - name: version + in: path + description: The strategy version of trending to use + required: true + schema: + type: string + - name: limit + in: query + description: The number of items to fetch + schema: type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: genre + in: query + description: Filter trending to a specified genre + schema: + type: string + - name: time + in: query + description: Calculate trending over a specified time range + schema: + type: string + enum: + - week + - month + - year + - allTime + - name: exclusion_list + in: query + description: List of track ids to exclude + style: form + explode: true + schema: + type: array + items: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/tracks_response' + $ref: "#/components/schemas/tracks_response" /tracks/feeling-lucky: get: tags: - - tracks + - tracks description: Gets random tracks found on the "Feeling Lucky" smart playlist operationId: Get Feeling Lucky Tracks parameters: - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: limit - in: query - description: Number of tracks to fetch - schema: - type: integer - default: 10 - minimum: 1 - maximum: 100 - - name: with_users - deprecated: true - in: query - description: Boolean to include user info with tracks - schema: - type: boolean - default: false - - name: min_followers - in: query - description: Fetch tracks from users with at least this number of followers - schema: - type: integer - minimum: 1 + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: limit + in: query + description: Number of tracks to fetch + schema: + type: integer + default: 10 + minimum: 1 + maximum: 100 + - name: with_users + deprecated: true + in: query + description: Boolean to include user info with tracks + schema: + type: boolean + default: false + - name: min_followers + in: query + description: Fetch tracks from users with at least this number of followers + schema: + type: integer + minimum: 1 responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/tracks_response' + $ref: "#/components/schemas/tracks_response" "400": description: Bad request content: {} @@ -1969,86 +2015,88 @@ paths: /tracks/recent-comments: get: tags: - - tracks + - tracks description: Gets the most recent tracks with active discussion operationId: Get Tracks With Recent Comments parameters: - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: limit - in: query - description: Number of tracks to fetch - schema: - type: integer - default: 10 - minimum: 1 - maximum: 100 - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - default: 0 - minimum: 0 + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: limit + in: query + description: Number of tracks to fetch + schema: + type: integer + default: 10 + minimum: 1 + maximum: 100 + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + default: 0 + minimum: 0 responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/tracks_response' + $ref: "#/components/schemas/tracks_response" "400": description: Bad request content: {} /tracks/most-shared: get: tags: - - tracks + - tracks description: Gets the most shared tracks for a given time range operationId: Get Most Shared Tracks parameters: - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: limit - in: query - description: Number of tracks to fetch - schema: - type: integer - default: 10 - minimum: 1 - maximum: 100 - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - default: 0 - minimum: 0 - - name: time_range - in: query - description: The time range to consider - schema: - type: string - default: week - enum: - - week - - month - - allTime + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: limit + in: query + description: Number of tracks to fetch + schema: + type: integer + default: 10 + minimum: 1 + maximum: 100 + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + default: 0 + minimum: 0 + - name: time_range + in: query + description: The time range to consider + schema: + type: string + default: week + enum: + - week + - month + - allTime responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/tracks_response' + $ref: "#/components/schemas/tracks_response" "400": description: Bad request content: {} @@ -2058,48 +2106,49 @@ paths: /tracks/usdc-purchase: get: tags: - - tracks + - tracks description: Gets the top trending (most popular) USDC purchase tracks on Audius operationId: Get Trending USDC Purchase Tracks parameters: - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: genre - in: query - description: Filter trending to a specified genre - schema: - type: string - - name: time - in: query - description: Calculate trending over a specified time range - schema: - type: string - enum: - - week - - month - - year - - allTime + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: genre + in: query + description: Filter trending to a specified genre + schema: + type: string + - name: time + in: query + description: Calculate trending over a specified time range + schema: + type: string + enum: + - week + - month + - year + - allTime responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/tracks_response' + $ref: "#/components/schemas/tracks_response" "400": description: Bad request content: {} @@ -2109,151 +2158,153 @@ paths: /tracks/usdc-purchase/{version}: get: tags: - - tracks + - tracks description: Gets the top trending (most popular) USDC purchase tracks on Audius using a given trending strategy version operationId: Get Trending USDC Purchase Tracks With Version parameters: - - name: version - in: path - description: The strategy version of trending to use - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: genre - in: query - description: Filter trending to a specified genre - schema: - type: string - - name: time - in: query - description: Calculate trending over a specified time range - schema: - type: string - enum: - - week - - month - - year - - allTime + - name: version + in: path + description: The strategy version of trending to use + required: true + schema: + type: string + - name: offset + in: query + description: The number of items to skip. Useful for pagination (page number * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: genre + in: query + description: Filter trending to a specified genre + schema: + type: string + - name: time + in: query + description: Calculate trending over a specified time range + schema: + type: string + enum: + - week + - month + - year + - allTime responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/tracks_response' + $ref: "#/components/schemas/tracks_response" /tracks/search: get: tags: - - tracks + - tracks description: Search for a track or tracks operationId: Search Tracks parameters: - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: query - in: query - description: The search query - schema: - type: string - - name: genre - in: query - description: The genres to filter by - style: form - explode: true - schema: - type: array - items: + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: query + in: query + description: The search query + schema: type: string - - name: sort_method - in: query - description: The sort method - schema: - type: string - enum: - - relevant - - popular - - recent - - name: mood - in: query - description: The moods to filter by - style: form - explode: true - schema: - type: array - items: + - name: genre + in: query + description: The genres to filter by + style: form + explode: true + schema: + type: array + items: + type: string + - name: sort_method + in: query + description: The sort method + schema: type: string - - name: only_downloadable - in: query - description: Return only downloadable tracks - schema: - type: string - default: "false" - - name: includePurchaseable - in: query - description: Whether or not to include purchaseable content - schema: - type: string - - name: is_purchaseable - in: query - description: Only include purchaseable tracks and albums in the track and - album results - schema: - type: string - - name: has_downloads - in: query - description: Only include tracks that have downloads in the track results - schema: - type: string - - name: key - in: query - description: Only include tracks that match the musical key - style: form - explode: true - schema: - type: array - items: + enum: + - relevant + - popular + - recent + - name: mood + in: query + description: The moods to filter by + style: form + explode: true + schema: + type: array + items: + type: string + - name: only_downloadable + in: query + description: Return only downloadable tracks + schema: + type: string + default: "false" + - name: includePurchaseable + in: query + description: Whether or not to include purchaseable content + schema: + type: string + - name: is_purchaseable + in: query + description: + Only include purchaseable tracks and albums in the track and + album results + schema: + type: string + - name: has_downloads + in: query + description: Only include tracks that have downloads in the track results + schema: + type: string + - name: key + in: query + description: Only include tracks that match the musical key + style: form + explode: true + schema: + type: array + items: + type: string + - name: bpm_min + in: query + description: Only include tracks that have a bpm greater than or equal to + schema: + type: string + - name: bpm_max + in: query + description: Only include tracks that have a bpm less than or equal to + schema: type: string - - name: bpm_min - in: query - description: Only include tracks that have a bpm greater than or equal to - schema: - type: string - - name: bpm_max - in: query - description: Only include tracks that have a bpm less than or equal to - schema: - type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/track_search' + $ref: "#/components/schemas/track_search" "400": description: Bad request content: {} @@ -2263,48 +2314,49 @@ paths: /tracks/trending: get: tags: - - tracks + - tracks description: Gets the top 100 trending (most popular) tracks on Audius operationId: Get Trending Tracks parameters: - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: genre - in: query - description: Filter trending to a specified genre - schema: - type: string - - name: time - in: query - description: Calculate trending over a specified time range - schema: - type: string - enum: - - week - - month - - year - - allTime - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: genre + in: query + description: Filter trending to a specified genre + schema: + type: string + - name: time + in: query + description: Calculate trending over a specified time range + schema: + type: string + enum: + - week + - month + - year + - allTime + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/tracks_response' + $ref: "#/components/schemas/tracks_response" "400": description: Bad request content: {} @@ -2314,83 +2366,84 @@ paths: /tracks/trending/{version}: get: tags: - - tracks + - tracks description: Gets the top 100 trending (most popular) tracks on Audius using a given trending strategy version operationId: Get Trending Tracks With Version parameters: - - name: version - in: path - description: The strategy version of trending to use - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: genre - in: query - description: Filter trending to a specified genre - schema: - type: string - - name: time - in: query - description: Calculate trending over a specified time range - schema: - type: string - enum: - - week - - month - - year - - allTime + - name: version + in: path + description: The strategy version of trending to use + required: true + schema: + type: string + - name: offset + in: query + description: The number of items to skip. Useful for pagination (page number * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: genre + in: query + description: Filter trending to a specified genre + schema: + type: string + - name: time + in: query + description: Calculate trending over a specified time range + schema: + type: string + enum: + - week + - month + - year + - allTime responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/tracks_response' + $ref: "#/components/schemas/tracks_response" /tracks/trending/ids: get: tags: - - tracks + - tracks description: Gets the track IDs of the top trending tracks on Audius operationId: Get Trending Track IDs parameters: - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: genre - in: query - description: Filter trending to a specified genre - schema: - type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: genre + in: query + description: Filter trending to a specified genre + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/trending_ids_response' + $ref: "#/components/schemas/trending_ids_response" "400": description: Bad request content: {} @@ -2400,38 +2453,38 @@ paths: /tracks/trending/ids/{version}: get: tags: - - tracks + - tracks description: Gets the track IDs of the top trending tracks on Audius based on the given trending strategy version operationId: Get Trending Tracks IDs With Version parameters: - - name: version - in: path - description: The strategy version of trending to use - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: genre - in: query - description: Filter trending to a specified genre - schema: - type: string + - name: version + in: path + description: The strategy version of trending to use + required: true + schema: + type: string + - name: offset + in: query + description: The number of items to skip. Useful for pagination (page number * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: genre + in: query + description: Filter trending to a specified genre + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/trending_ids_response' + $ref: "#/components/schemas/trending_ids_response" "400": description: Bad request content: {} @@ -2441,93 +2494,94 @@ paths: /tracks/trending/underground: get: tags: - - tracks + - tracks description: Gets the top 100 trending underground tracks on Audius operationId: Get Underground Trending Tracks parameters: - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/tracks_response' + $ref: "#/components/schemas/tracks_response" /tracks/trending/underground/{version}: get: tags: - - tracks + - tracks description: Gets the top 100 trending underground tracks on Audius using a given trending strategy version operationId: Get Underground Trending Tracks With Version parameters: - - name: version - in: path - description: The strategy version of trending to use - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: version + in: path + description: The strategy version of trending to use + required: true + schema: + type: string + - name: offset + in: query + description: The number of items to skip. Useful for pagination (page number * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/tracks_response' + $ref: "#/components/schemas/tracks_response" /tracks/{track_id}: get: tags: - - tracks + - tracks description: Gets a track by ID operationId: Get Track parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/track_response' + $ref: "#/components/schemas/track_response" "400": description: Bad request content: {} @@ -2536,39 +2590,39 @@ paths: content: {} put: tags: - - tracks + - tracks description: Updates an existing track operationId: Update Track security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string requestBody: x-codegen-request-body-name: metadata required: true content: application/json: schema: - $ref: '#/components/schemas/update_track_request_body' + $ref: "#/components/schemas/update_track_request_body" responses: "200": description: Track updated successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "400": description: Bad request content: {} @@ -2583,32 +2637,32 @@ paths: content: {} delete: tags: - - tracks + - tracks description: Deletes a track operationId: Delete Track security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: "200": description: Track deleted successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -2621,54 +2675,55 @@ paths: /tracks/{track_id}/access-info: get: tags: - - tracks - description: Gets the information necessary to access the track and what access + - tracks + description: + Gets the information necessary to access the track and what access the given user has. operationId: Get Track Access Info parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/access_info_response' + $ref: "#/components/schemas/access_info_response" /tracks/{track_id}/comment_count: get: tags: - - tracks + - tracks description: Get the comment count for a track operationId: Get Track Comment Count parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/track_comment_count_response' + $ref: "#/components/schemas/track_comment_count_response" "400": description: Bad request content: {} @@ -2678,28 +2733,28 @@ paths: /tracks/{track_id}/comment_notification_setting: get: tags: - - tracks + - tracks description: Get the comment notification setting for a track operationId: Get Track Comment Notification Setting parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/track_comment_notification_response' + $ref: "#/components/schemas/track_comment_notification_response" "400": description: Bad request content: {} @@ -2709,49 +2764,50 @@ paths: /tracks/{track_id}/comments: get: tags: - - tracks + - tracks description: Get a list of comments for a track operationId: Get Track Comments parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: sort_method - in: query - description: The sort method - schema: - type: string - default: top - enum: - - top - - newest - - timestamp + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: sort_method + in: query + description: The sort method + schema: + type: string + default: top + enum: + - top + - newest + - timestamp responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/track_comments_response' + $ref: "#/components/schemas/track_comments_response" "400": description: Bad request content: {} @@ -2761,39 +2817,40 @@ paths: /tracks/{track_id}/favorites: get: tags: - - tracks + - tracks description: Get users that favorited a track operationId: Get Users From Favorites parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/track_favorites_response' + $ref: "#/components/schemas/track_favorites_response" "400": description: Bad request content: {} @@ -2802,32 +2859,32 @@ paths: content: {} post: tags: - - tracks + - tracks description: Favorite a track operationId: Favorite Track security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: "200": description: Track favorited successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -2839,32 +2896,32 @@ paths: content: {} delete: tags: - - tracks + - tracks description: Unfavorite a track operationId: Unfavorite Track security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: "200": description: Track unfavorited successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -2877,131 +2934,134 @@ paths: /tracks/{track_id}/remixes: get: tags: - - tracks + - tracks description: Get all tracks that remix the given track operationId: Get Track Remixes parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: sort_method - in: query - description: The sort method to use - schema: - type: string - default: recent - enum: - - likes - - plays - - recent - - name: only_cosigns - in: query - description: Only remixes cosigned by the original artist - schema: - type: boolean - - name: only_contest_entries - in: query - description: Only entries to a remix contest - schema: - type: boolean + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: sort_method + in: query + description: The sort method to use + schema: + type: string + default: recent + enum: + - likes + - plays + - recent + - name: only_cosigns + in: query + description: Only remixes cosigned by the original artist + schema: + type: boolean + - name: only_contest_entries + in: query + description: Only entries to a remix contest + schema: + type: boolean responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/remixes_response' + $ref: "#/components/schemas/remixes_response" /tracks/{track_id}/remixing: get: tags: - - tracks + - tracks description: Gets all the tracks that the given track remixes operationId: Get Track Remix Parents parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/remixing_response' + $ref: "#/components/schemas/remixing_response" /tracks/{track_id}/reposts: get: tags: - - tracks + - tracks description: Get the users that reposted a track operationId: Get Users From Reposts parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/track_reposts_response' + $ref: "#/components/schemas/track_reposts_response" "400": description: Bad request content: {} @@ -3010,32 +3070,32 @@ paths: content: {} post: tags: - - tracks + - tracks description: Repost a track operationId: Repost Track security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: "200": description: Track reposted successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -3047,32 +3107,32 @@ paths: content: {} delete: tags: - - tracks + - tracks description: Unrepost a track operationId: Unrepost Track security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: "200": description: Track unreposted successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -3085,48 +3145,50 @@ paths: /tracks/{track_id}/download: get: tags: - - tracks + - tracks summary: Download the original or MP3 file of a track description: Download an original or mp3 track operationId: Download Track parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: user_signature - in: query - description: |- - Optional - signature from the requesting user's wallet. - This is needed to authenticate the user and verify access in case the track is gated. - schema: - type: string - - name: user_data - in: query - description: Optional - data which was used to generate the optional signature - argument. - schema: - type: string - - name: nft_access_signature - in: query - description: |- - Optional - nft access signature for this track which was previously generated by a registered DN. - We perform checks on it and pass it through to CN. - schema: - type: string - - name: filename - in: query - description: "Optional - name of file to download. If not provided, defaults\ - \ to track original filename or title." - schema: - type: string + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: user_signature + in: query + description: |- + Optional - signature from the requesting user's wallet. + This is needed to authenticate the user and verify access in case the track is gated. + schema: + type: string + - name: user_data + in: query + description: + Optional - data which was used to generate the optional signature + argument. + schema: + type: string + - name: nft_access_signature + in: query + description: |- + Optional - nft access signature for this track which was previously generated by a registered DN. + We perform checks on it and pass it through to CN. + schema: + type: string + - name: filename + in: query + description: + "Optional - name of file to download. If not provided, defaults\ + \ to track original filename or title." + schema: + type: string responses: "200": description: Success @@ -3146,30 +3208,30 @@ paths: /tracks/{track_id}/inspect: get: tags: - - tracks + - tracks summary: Inspects the details of the file for a track description: Inspect a track operationId: Inspect Track parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string - - name: original - in: query - description: Optional - if set to true inspects the original file quality - schema: - type: boolean - default: false + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string + - name: original + in: query + description: Optional - if set to true inspects the original file quality + schema: + type: boolean + default: false responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/track_inspect' + $ref: "#/components/schemas/track_inspect" "400": description: Bad request content: {} @@ -3179,52 +3241,52 @@ paths: /tracks/{track_id}/stems: get: tags: - - tracks + - tracks description: Get the remixable stems of a track operationId: Get Track Stems parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/stems_response' + $ref: "#/components/schemas/stems_response" /tracks/{track_id}/shares: post: tags: - - tracks + - tracks description: Record a track share event operationId: Share Track security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string - - name: user_id - in: query - description: User ID - required: true - schema: - type: string + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string + - name: user_id + in: query + description: User ID + required: true + schema: + type: string responses: "200": description: Track share recorded successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -3237,32 +3299,32 @@ paths: /tracks/{track_id}/downloads: post: tags: - - tracks + - tracks description: Record a track download event operationId: Record Track Download security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string requestBody: x-codegen-request-body-name: location content: application/json: schema: - $ref: '#/components/schemas/track_download_request_body' + $ref: "#/components/schemas/track_download_request_body" responses: "200": description: Track download recorded successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -3275,7 +3337,7 @@ paths: /tracks/{track_id}/stream: get: tags: - - tracks + - tracks summary: Get the streamable MP3 file of a track description: |- Stream an mp3 track @@ -3283,73 +3345,76 @@ paths: https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests operationId: Stream Track parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: preview - in: query - description: Optional - true if streaming track preview - schema: - type: boolean - default: false - - name: user_signature - in: query - description: |- - Optional - signature from the requesting user's wallet. - This is needed to authenticate the user and verify access in case the track is gated. - schema: - type: string - - name: user_data - in: query - description: Optional - data which was used to generate the optional signature - argument. - schema: - type: string - - name: nft_access_signature - in: query - description: |- - Optional - gated content signature for this track which was previously generated by a registered DN. - We perform checks on it and pass it through to CN. - schema: - type: string - - name: skip_play_count - in: query - description: Optional - boolean that disables tracking of play counts. - schema: - type: boolean - default: false - - name: api_key - in: query - description: Optional - API key for third party apps. This is required for - tracks that only allow specific API keys. - schema: - type: string - - name: skip_check - in: query - description: Optional - POC to skip node 'double dip' health check - schema: - type: boolean - - name: no_redirect - in: query - description: Optional - If true will not return a 302 and instead will return - the stream url in JSON - schema: - type: boolean - responses: - "200": - description: Success - content: - application/json: + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: preview + in: query + description: Optional - true if streaming track preview + schema: + type: boolean + default: false + - name: user_signature + in: query + description: |- + Optional - signature from the requesting user's wallet. + This is needed to authenticate the user and verify access in case the track is gated. + schema: + type: string + - name: user_data + in: query + description: + Optional - data which was used to generate the optional signature + argument. + schema: + type: string + - name: nft_access_signature + in: query + description: |- + Optional - gated content signature for this track which was previously generated by a registered DN. + We perform checks on it and pass it through to CN. + schema: + type: string + - name: skip_play_count + in: query + description: Optional - boolean that disables tracking of play counts. + schema: + type: boolean + default: false + - name: api_key + in: query + description: + Optional - API key for third party apps. This is required for + tracks that only allow specific API keys. + schema: + type: string + - name: skip_check + in: query + description: Optional - POC to skip node 'double dip' health check + schema: + type: boolean + - name: no_redirect + in: query + description: + Optional - If true will not return a 302 and instead will return + the stream url in JSON + schema: + type: boolean + responses: + "200": + description: Success + content: + application/json: schema: - $ref: '#/components/schemas/stream_url_response' + $ref: "#/components/schemas/stream_url_response" "216": description: Partial content content: {} @@ -3365,39 +3430,40 @@ paths: /tracks/{track_id}/top_listeners: get: tags: - - tracks + - tracks description: Get the users that have listened to a track the most operationId: Get Track Top Listeners parameters: - - name: track_id - in: path - description: A Track ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: track_id + in: path + description: A Track ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/top_listener' + $ref: "#/components/schemas/top_listener" "400": description: Bad request content: {} @@ -3407,31 +3473,31 @@ paths: /users: get: tags: - - users + - users description: Gets a list of users by ID operationId: Get Bulk Users parameters: - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: id - in: query - description: The ID of the user(s) - style: form - explode: true - schema: - type: array - items: + - name: user_id + in: query + description: The user ID of the user making the request + schema: type: string + - name: id + in: query + description: The ID of the user(s) + style: form + explode: true + schema: + type: array + items: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/users_response' + $ref: "#/components/schemas/users_response" "400": description: Bad request content: {} @@ -3440,26 +3506,33 @@ paths: content: {} post: tags: - - users + - users description: Creates a new user operationId: Create User security: - BasicAuth: [] - BearerAuth: [] + parameters: + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string requestBody: x-codegen-request-body-name: metadata required: true content: application/json: schema: - $ref: '#/components/schemas/create_user_request_body' + $ref: "#/components/schemas/create_user_request_body" responses: "201": description: User created successfully content: application/json: schema: - $ref: '#/components/schemas/create_user_response' + $ref: "#/components/schemas/create_user_response" "400": description: Bad request content: {} @@ -3472,55 +3545,55 @@ paths: /users/address: get: tags: - - users + - users description: Gets User IDs from any Ethereum wallet address or Solana account address associated with their Audius account. operationId: Get User IDs by Addresses parameters: - - name: address - in: query - description: Wallet address - required: true - style: form - explode: true - example: - - "0x1234567890abcdef1234567890abcdef12345678" - - "E2LCbKdo2L3ikt1gK6pwp1pDLuhAfHBNf6fEQXpAqrf9" - schema: - type: array - items: - type: string + - name: address + in: query + description: Wallet address + required: true + style: form + explode: true + example: + - "0x1234567890abcdef1234567890abcdef12345678" + - "E2LCbKdo2L3ikt1gK6pwp1pDLuhAfHBNf6fEQXpAqrf9" + schema: + type: array + items: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/user_ids_addresses_response' + $ref: "#/components/schemas/user_ids_addresses_response" /users/handle/{handle}: get: tags: - - users + - users description: Gets a single user by their handle operationId: Get User by Handle parameters: - - name: handle - in: path - description: A User handle - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: handle + in: path + description: A User handle + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/user_response' + $ref: "#/components/schemas/user_response" "400": description: Bad request content: {} @@ -3530,95 +3603,96 @@ paths: /users/handle/{handle}/tracks: get: tags: - - users + - users description: Gets the tracks created by a user using the user's handle operationId: Get Tracks by User Handle parameters: - - name: handle - in: path - description: A User handle - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: sort - in: query - description: "[Deprecated] Field to sort by" - schema: - type: string - default: date - enum: - - date - - plays - - name: query - in: query - description: The filter query - schema: - type: string - - name: sort_method - in: query - description: The sort method - schema: - type: string - enum: - - title - - artist_name - - release_date - - last_listen_date - - added_date - - plays - - reposts - - saves - - most_listens_by_user - - name: sort_direction - in: query - description: The sort direction - schema: - type: string - enum: - - asc - - desc - - name: filter_tracks - in: query - description: Filter by public tracks - schema: - type: string - default: all - enum: - - all - - public - - name: Encoded-Data-Message - in: header - description: The data that was signed by the user for signature recovery - schema: - type: string - - name: Encoded-Data-Signature - in: header - description: "The signature of data, used for signature recovery" - schema: - type: string + - name: handle + in: path + description: A User handle + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: sort + in: query + description: "[Deprecated] Field to sort by" + schema: + type: string + default: date + enum: + - date + - plays + - name: query + in: query + description: The filter query + schema: + type: string + - name: sort_method + in: query + description: The sort method + schema: + type: string + enum: + - title + - artist_name + - release_date + - last_listen_date + - added_date + - plays + - reposts + - saves + - most_listens_by_user + - name: sort_direction + in: query + description: The sort direction + schema: + type: string + enum: + - asc + - desc + - name: filter_tracks + in: query + description: Filter by public tracks + schema: + type: string + default: all + enum: + - all + - public + - name: Encoded-Data-Message + in: header + description: The data that was signed by the user for signature recovery + schema: + type: string + - name: Encoded-Data-Signature + in: header + description: "The signature of data, used for signature recovery" + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/tracks_response' + $ref: "#/components/schemas/tracks_response" "400": description: Bad request content: {} @@ -3628,96 +3702,98 @@ paths: /users/handle/{handle}/tracks/ai_attributed: get: tags: - - users - description: Gets the AI generated tracks attributed to a user using the user's + - users + description: + Gets the AI generated tracks attributed to a user using the user's handle operationId: Get AI Attributed Tracks by User Handle parameters: - - name: handle - in: path - description: A User handle - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: sort - in: query - description: "[Deprecated] Field to sort by" - schema: - type: string - default: date - enum: - - date - - plays - - name: query - in: query - description: The filter query - schema: - type: string - - name: sort_method - in: query - description: The sort method - schema: - type: string - enum: - - title - - artist_name - - release_date - - last_listen_date - - added_date - - plays - - reposts - - saves - - most_listens_by_user - - name: sort_direction - in: query - description: The sort direction - schema: - type: string - enum: - - asc - - desc - - name: filter_tracks - in: query - description: Filter by public tracks - schema: - type: string - default: all - enum: - - all - - public - - name: Encoded-Data-Message - in: header - description: The data that was signed by the user for signature recovery - schema: - type: string - - name: Encoded-Data-Signature - in: header - description: "The signature of data, used for signature recovery" - schema: - type: string + - name: handle + in: path + description: A User handle + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: sort + in: query + description: "[Deprecated] Field to sort by" + schema: + type: string + default: date + enum: + - date + - plays + - name: query + in: query + description: The filter query + schema: + type: string + - name: sort_method + in: query + description: The sort method + schema: + type: string + enum: + - title + - artist_name + - release_date + - last_listen_date + - added_date + - plays + - reposts + - saves + - most_listens_by_user + - name: sort_direction + in: query + description: The sort direction + schema: + type: string + enum: + - asc + - desc + - name: filter_tracks + in: query + description: Filter by public tracks + schema: + type: string + default: all + enum: + - all + - public + - name: Encoded-Data-Message + in: header + description: The data that was signed by the user for signature recovery + schema: + type: string + - name: Encoded-Data-Signature + in: header + description: "The signature of data, used for signature recovery" + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/tracks_response' + $ref: "#/components/schemas/tracks_response" "400": description: Bad request content: {} @@ -3727,56 +3803,57 @@ paths: /users/search: get: tags: - - users + - users description: Search for users that match the given query operationId: Search Users parameters: - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: query - in: query - description: The search query - schema: - type: string - - name: genre - in: query - description: The genres to filter by - style: form - explode: true - schema: - type: array - items: + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: query + in: query + description: The search query + schema: + type: string + - name: genre + in: query + description: The genres to filter by + style: form + explode: true + schema: + type: array + items: + type: string + - name: sort_method + in: query + description: The sort method + schema: + type: string + enum: + - relevant + - popular + - recent + - name: is_verified + in: query + description: Only include verified users in the user results + schema: type: string - - name: sort_method - in: query - description: The sort method - schema: - type: string - enum: - - relevant - - popular - - recent - - name: is_verified - in: query - description: Only include verified users in the user results - schema: - type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/user_search' + $ref: "#/components/schemas/user_search" "400": description: Bad request content: {} @@ -3786,24 +3863,25 @@ paths: /users/verify_token: get: tags: - - users - description: Verify if the given jwt ID token was signed by the subject (user) + - users + description: + Verify if the given jwt ID token was signed by the subject (user) in the payload operationId: Verify ID Token parameters: - - name: token - in: query - description: JWT to verify - required: true - schema: - type: string + - name: token + in: query + description: JWT to verify + required: true + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/verify_token' + $ref: "#/components/schemas/verify_token" "400": description: Bad input content: {} @@ -3816,28 +3894,28 @@ paths: /users/{id}: get: tags: - - users + - users description: Gets a single user by their user ID operationId: Get User parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/user_response' + $ref: "#/components/schemas/user_response" "400": description: Bad request content: {} @@ -3846,38 +3924,38 @@ paths: content: {} put: tags: - - users + - users description: Updates an existing user profile operationId: Update User security: - BasicAuth: [] parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string requestBody: x-codegen-request-body-name: metadata required: true content: application/json: schema: - $ref: '#/components/schemas/update_user_request_body' + $ref: "#/components/schemas/update_user_request_body" responses: "200": description: User updated successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "400": description: Bad request content: {} @@ -3893,349 +3971,188 @@ paths: /users/{id}/albums: get: tags: - - users + - users description: Gets the albums created by a user using their user ID operationId: Get Albums by User parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: sort_method - in: query - description: The sort method - schema: - type: string - default: recent - enum: - - recent - - popular - - name: query - in: query - description: Filter albums by name - schema: - type: string - - name: Encoded-Data-Message - in: header - description: The data that was signed by the user for signature recovery - schema: - type: string - - name: Encoded-Data-Signature - in: header - description: "The signature of data, used for signature recovery" - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: sort_method + in: query + description: The sort method + schema: + type: string + default: recent + enum: + - recent + - popular + - name: query + in: query + description: Filter albums by name + schema: + type: string + - name: Encoded-Data-Message + in: header + description: The data that was signed by the user for signature recovery + schema: + type: string + - name: Encoded-Data-Signature + in: header + description: "The signature of data, used for signature recovery" + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/albums_response' + $ref: "#/components/schemas/albums_response" "400": description: Bad request content: {} "500": description: Server error content: {} - /users/{id}/authorized_apps: + /users/{id}/developer-apps: get: tags: - - users - description: Get the apps that user has authorized to write to their account - operationId: Get Authorized Apps + - developer_apps + description: Get developer apps for the user. + operationId: Get Developer Apps parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string + - name: id + in: path + description: The user ID whose developer apps to list + required: true + schema: + type: string + - name: include + in: query + description: Include metrics when set to "metrics" + schema: + type: string + enum: + - metrics responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/authorized_apps' + $ref: "#/components/schemas/developer_apps_response" "400": description: Bad request content: {} "500": description: Server error content: {} - /users/{id}/developer-apps: + /users/{id}/authorized_apps: get: tags: - - users - description: Get developer apps for the user (Plans API). Requires OAuth. - operationId: Get User Developer Apps + - users + description: Get the apps that user has authorized to write to their account + operationId: Get Authorized Apps parameters: - - name: id - in: path - description: User ID - required: true - schema: - type: string - - name: include - in: query - description: Include metrics when set to "metrics" - schema: - type: string - enum: - - metrics + - name: id + in: path + description: A User ID + required: true + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/developer_apps_response' + $ref: "#/components/schemas/authorized_apps" "400": description: Bad request content: {} "500": description: Server error content: {} - post: + /users/{id}/balance/history: + get: tags: - - users - description: Create a new developer app (Plans API). Requires OAuth Bearer token with plans app grant. - operationId: Create User Developer App - security: - - BasicAuth: [] - - BearerAuth: [] + - users + description: Get the user's historical portfolio balance data + operationId: Get User Balance History parameters: - - name: id - in: path - description: User ID - required: true - schema: - type: string - requestBody: - x-codegen-request-body-name: metadata - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/create_user_developer_app_request_body' - responses: - "200": - description: Developer app created successfully - content: - application/json: - schema: - $ref: '#/components/schemas/create_user_developer_app_response' - "400": - description: Bad request - content: {} - "401": - description: Unauthorized - content: {} - "500": - description: Server error - content: {} - /users/{id}/developer-apps/{address}: - delete: - tags: - - users - description: Delete a developer app (Plans API). Requires OAuth Bearer token with plans app grant. - operationId: Delete User Developer App - security: - - BasicAuth: [] - - BearerAuth: [] - parameters: - - name: id - in: path - description: User ID - required: true - schema: - type: string - - name: address - in: path - description: Developer app address (API Key) - required: true - schema: - type: string - responses: - "200": - description: Developer app deleted successfully - content: - application/json: - schema: - $ref: '#/components/schemas/write_response' - "401": - description: Unauthorized - content: {} - "404": - description: Developer app not found - content: {} - "500": - description: Server error - content: {} - /users/{id}/developer-apps/{address}/access-keys/deactivate: - post: - tags: - - users - description: Deactivate a bearer token (API access key) for a developer app (Plans API). Requires OAuth Bearer token with plans app grant. The deactivated token will no longer authenticate requests. - operationId: Deactivate User Developer App Access Key - security: - - BasicAuth: [] - - BearerAuth: [] - parameters: - - name: id - in: path - description: User ID - required: true - schema: - type: string - - name: address - in: path - description: Developer app address (API Key) - required: true - schema: - type: string - requestBody: - x-codegen-request-body-name: metadata - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/deactivate_access_key_request_body' - responses: - "200": - description: Access key deactivated successfully - content: - application/json: - schema: - $ref: '#/components/schemas/deactivate_access_key_response' - "400": - description: Bad request (api_access_key required) - content: {} - "401": - description: Unauthorized - content: {} - "404": - description: Developer app or access key not found - content: {} - "500": - description: Server error - content: {} - /users/{id}/developer-apps/{address}/access-keys: - post: - tags: - - users - description: Create a new bearer token (API access key) for a developer app (Plans API). Requires OAuth Bearer token with plans app grant. - operationId: Create User Developer App Access Key - security: - - BasicAuth: [] - - BearerAuth: [] - parameters: - - name: id - in: path - description: User ID - required: true - schema: - type: string - - name: address - in: path - description: Developer app address (API Key) - required: true - schema: - type: string - responses: - "200": - description: Access key created successfully - content: - application/json: - schema: - $ref: '#/components/schemas/create_access_key_response' - "401": - description: Unauthorized - content: {} - "404": - description: Developer app not found - content: {} - "500": - description: Server error - content: {} - /users/{id}/balance/history: - get: - tags: - - users - description: Get the user's historical portfolio balance data - operationId: Get User Balance History - parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: start_time - in: query - description: Start time for the balance history query (ISO 8601 format). Defaults to 7 days ago. - required: false - schema: - type: string - format: date-time - - name: end_time - in: query - description: End time for the balance history query (ISO 8601 format). Defaults to now. - required: false - schema: - type: string - format: date-time - - name: granularity - in: query - description: Data granularity. 'hourly' returns hourly data points, 'daily' returns daily aggregated data. Defaults to 'hourly'. - required: false - schema: - type: string - enum: - - hourly - - daily - default: hourly - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: Encoded-Data-Message - in: header - description: The data that was signed by the user for signature recovery - schema: - type: string - - name: Encoded-Data-Signature - in: header - description: "The signature of data, used for signature recovery" - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: start_time + in: query + description: Start time for the balance history query (ISO 8601 format). Defaults to 7 days ago. + required: false + schema: + type: string + format: date-time + - name: end_time + in: query + description: End time for the balance history query (ISO 8601 format). Defaults to now. + required: false + schema: + type: string + format: date-time + - name: granularity + in: query + description: Data granularity. 'hourly' returns hourly data points, 'daily' returns daily aggregated data. Defaults to 'hourly'. + required: false + schema: + type: string + enum: + - hourly + - daily + default: hourly + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: Encoded-Data-Message + in: header + description: The data that was signed by the user for signature recovery + schema: + type: string + - name: Encoded-Data-Signature + in: header + description: "The signature of data, used for signature recovery" + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/balance_history_response' + $ref: "#/components/schemas/balance_history_response" "400": description: Bad request content: {} @@ -4251,29 +4168,29 @@ paths: /users/{id}/challenges: get: tags: - - users + - users description: Gets all challenges for the given user operationId: Get User Challenges parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: show_historical - in: query - description: Whether to show challenges that are inactive but completed - schema: - type: boolean - default: false + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: show_historical + in: query + description: Whether to show challenges that are inactive but completed + schema: + type: boolean + default: false responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/get_challenges' + $ref: "#/components/schemas/get_challenges" "400": description: Bad request content: {} @@ -4284,123 +4201,125 @@ paths: /users/{id}/coins: get: tags: - - users - description: 'Gets a list of the coins owned by the user and their balances' + - users + description: "Gets a list of the coins owned by the user and their balances" parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - default: 0 - minimum: 0 - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - default: 50 - minimum: 1 - maximum: 100 + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + default: 0 + minimum: 0 + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + default: 50 + minimum: 1 + maximum: 100 operationId: Get User Coins responses: - '200': + "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/user_coins_response' + $ref: "#/components/schemas/user_coins_response" /users/{id}/coins/{mint}: get: tags: - - users - description: 'Gets information about a specific coin owned by the user and their wallets' + - users + description: "Gets information about a specific coin owned by the user and their wallets" parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: mint - in: path - description: The mint address of the coin - required: true - schema: - type: string - example: "Dez1g5f3h4j5k6l7m8n9o0p1q2r3s4t5u6v7w8x9y0z" + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: mint + in: path + description: The mint address of the coin + required: true + schema: + type: string + example: "Dez1g5f3h4j5k6l7m8n9o0p1q2r3s4t5u6v7w8x9y0z" operationId: Get User Coin responses: - '200': + "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/user_coin_response' + $ref: "#/components/schemas/user_coin_response" /wallet/{walletId}/coins: get: tags: - - wallet - description: 'Gets a list of the coins held by a wallet address and their balances' + - wallet + description: "Gets a list of the coins held by a wallet address and their balances" parameters: - - name: walletId - in: path - description: A Solana wallet address - required: true - schema: - type: string - example: "Dez1g5f3h4j5k6l7m8n9o0p1q2r3s4t5u6v7w8x9y0z" - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - default: 0 - minimum: 0 - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - default: 50 - minimum: 1 - maximum: 100 + - name: walletId + in: path + description: A Solana wallet address + required: true + schema: + type: string + example: "Dez1g5f3h4j5k6l7m8n9o0p1q2r3s4t5u6v7w8x9y0z" + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + default: 0 + minimum: 0 + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + default: 50 + minimum: 1 + maximum: 100 operationId: Get Wallet Coins responses: - '200': + "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/user_coins_response' + $ref: "#/components/schemas/user_coins_response" /users/{id}/collectibles: get: tags: - - users + - users description: Get the User's indexed collectibles data operationId: Get User Collectibles parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/collectibles_response' + $ref: "#/components/schemas/collectibles_response" "400": description: Bad request content: {} @@ -4410,39 +4329,40 @@ paths: /users/{id}/comments: get: tags: - - users + - users description: Get user comment history operationId: Get User Comments parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/user_comments_response' + $ref: "#/components/schemas/user_comments_response" "400": description: Bad request content: {} @@ -4452,23 +4372,23 @@ paths: /users/{id}/connected_wallets: get: tags: - - users + - users description: Get the User's ERC and SPL connected wallets operationId: Get connected wallets parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/connected_wallets_response' + $ref: "#/components/schemas/connected_wallets_response" "400": description: Bad request content: {} @@ -4478,23 +4398,23 @@ paths: /users/{id}/favorites: get: tags: - - users + - users description: Gets a user's favorite tracks operationId: Get Favorites parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/favorites_response' + $ref: "#/components/schemas/favorites_response" "400": description: Bad request content: {} @@ -4504,39 +4424,40 @@ paths: /users/{id}/followers: get: tags: - - users + - users description: All users that follow the provided user operationId: Get Followers parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/followers_response' + $ref: "#/components/schemas/followers_response" "400": description: Bad request content: {} @@ -4546,32 +4467,32 @@ paths: /users/{id}/follow: post: tags: - - users + - users description: Follow a user operationId: Follow User security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: "200": description: User followed successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -4583,32 +4504,32 @@ paths: content: {} delete: tags: - - users + - users description: Unfollow a user operationId: Unfollow User security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: "200": description: User unfollowed successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -4618,42 +4539,248 @@ paths: "500": description: Server error content: {} + /users/{id}/grants: + post: + tags: + - users + description: Create a grant (authorize an app to act on the user's behalf) + operationId: Create Grant + security: + - BasicAuth: [] + - BearerAuth: [] + parameters: + - name: id + in: path + description: The user ID (grantor) + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/create_grant_request_body" + responses: + "200": + description: Grant created successfully + content: + application/json: + schema: + $ref: "#/components/schemas/write_response" + "400": + description: Bad request + content: {} + "401": + description: Unauthorized + content: {} + "403": + description: Forbidden (user ID does not match) + content: {} + "500": + description: Server error + content: {} + /users/{id}/grants/{address}: + delete: + tags: + - users + description: Revoke a grant (remove app authorization) + operationId: Revoke Grant + security: + - BasicAuth: [] + - BearerAuth: [] + parameters: + - name: id + in: path + description: The user ID (grantor) + required: true + schema: + type: string + - name: address + in: path + description: The app API key (grantee address) to revoke + required: true + schema: + type: string + responses: + "200": + description: Grant revoked successfully + content: + application/json: + schema: + $ref: "#/components/schemas/write_response" + "400": + description: Bad request + content: {} + "401": + description: Unauthorized + content: {} + "403": + description: Forbidden + content: {} + "500": + description: Server error + content: {} + /users/{id}/grants/approve: + post: + tags: + - users + description: Approve a manager request (manager approves being added by the child user) + operationId: Approve Grant + security: + - BasicAuth: [] + - BearerAuth: [] + parameters: + - name: id + in: path + description: The user ID of the manager (grantee) approving the request + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/approve_grant_request_body" + responses: + "200": + description: Grant approved successfully + content: + application/json: + schema: + $ref: "#/components/schemas/write_response" + "400": + description: Bad request + content: {} + "401": + description: Unauthorized + content: {} + "403": + description: Forbidden + content: {} + "500": + description: Server error + content: {} + /users/{id}/managers: + post: + tags: + - users + description: Add a manager (authorize another user to act on your behalf) + operationId: Add Manager + security: + - BasicAuth: [] + - BearerAuth: [] + parameters: + - name: id + in: path + description: The user ID (child user adding the manager) + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/add_manager_request_body" + responses: + "200": + description: Manager added successfully + content: + application/json: + schema: + $ref: "#/components/schemas/write_response" + "400": + description: Bad request + content: {} + "401": + description: Unauthorized + content: {} + "403": + description: Forbidden + content: {} + "500": + description: Server error + content: {} + /users/{id}/managers/{managerUserId}: + delete: + tags: + - users + description: Remove a manager (revoke user-to-user grant). Can be called by the child user or the manager. + operationId: Remove Manager + security: + - BasicAuth: [] + - BearerAuth: [] + parameters: + - name: id + in: path + description: The user ID (child user whose manager is being removed) + required: true + schema: + type: string + - name: managerUserId + in: path + description: The user ID of the manager to remove + required: true + schema: + type: string + responses: + "200": + description: Manager removed successfully + content: + application/json: + schema: + $ref: "#/components/schemas/write_response" + "400": + description: Bad request + content: {} + "401": + description: Unauthorized + content: {} + "403": + description: Forbidden + content: {} + "500": + description: Server error + content: {} /users/{id}/following: get: tags: - - users + - users description: All users that the provided user follows operationId: Get Following parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/following_response' + $ref: "#/components/schemas/following_response" "400": description: Bad request content: {} @@ -4662,78 +4789,79 @@ paths: content: {} /users/{id}/history/tracks: get: - tags: - - users - description: Get the tracks the user recently listened to. - operationId: Get User's Track History - parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: query - in: query - description: The filter query - schema: - type: string - - name: sort_method - in: query - description: The sort method - schema: - type: string - enum: - - title - - artist_name - - release_date - - last_listen_date - - added_date - - plays - - reposts - - saves - - most_listens_by_user - - name: sort_direction - in: query - description: The sort direction - schema: - type: string - enum: - - asc - - desc - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: Encoded-Data-Message - in: header - description: The data that was signed by the user for signature recovery - schema: - type: string - - name: Encoded-Data-Signature - in: header - description: "The signature of data, used for signature recovery" - schema: - type: string + tags: + - users + description: Get the tracks the user recently listened to. + operationId: Get User's Track History + parameters: + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: query + in: query + description: The filter query + schema: + type: string + - name: sort_method + in: query + description: The sort method + schema: + type: string + enum: + - title + - artist_name + - release_date + - last_listen_date + - added_date + - plays + - reposts + - saves + - most_listens_by_user + - name: sort_direction + in: query + description: The sort direction + schema: + type: string + enum: + - asc + - desc + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: Encoded-Data-Message + in: header + description: The data that was signed by the user for signature recovery + schema: + type: string + - name: Encoded-Data-Signature + in: header + description: "The signature of data, used for signature recovery" + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/history_response' + $ref: "#/components/schemas/history_response" "400": description: Bad request content: {} @@ -4749,38 +4877,41 @@ paths: /users/{id}/listen_counts_monthly: get: tags: - - users - description: Gets the listen data for a user by month and track within a given + - users + description: + Gets the listen data for a user by month and track within a given time frame. operationId: Get User Monthly Track Listens parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: start_time - in: query - description: Start time from which to start results for user listen count - data (inclusive). - required: true - schema: - type: string - - name: end_time - in: query - description: End time until which to cut off results of listen count data - (not inclusive). - required: true - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: start_time + in: query + description: + Start time from which to start results for user listen count + data (inclusive). + required: true + schema: + type: string + - name: end_time + in: query + description: + End time until which to cut off results of listen count data + (not inclusive). + required: true + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/user_track_listen_counts_response' + $ref: "#/components/schemas/user_track_listen_counts_response" "400": description: Bad request content: {} @@ -4790,61 +4921,61 @@ paths: /users/{id}/muted: get: tags: - - users + - users description: Gets users muted by the given user operationId: Get Muted Users parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: Encoded-Data-Message - in: header - description: The data that was signed by the user for signature recovery - schema: - type: string - - name: Encoded-Data-Signature - in: header - description: "The signature of data, used for signature recovery" - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: Encoded-Data-Message + in: header + description: The data that was signed by the user for signature recovery + schema: + type: string + - name: Encoded-Data-Signature + in: header + description: "The signature of data, used for signature recovery" + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/users_response' + $ref: "#/components/schemas/users_response" post: tags: - - users + - users description: Mute a user operationId: Mute User security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: "200": description: User muted successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -4856,32 +4987,32 @@ paths: content: {} delete: tags: - - users + - users description: Unmute a user operationId: Unmute User security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: "200": description: User unmuted successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -4894,40 +5025,42 @@ paths: /users/{id}/mutuals: get: tags: - - users - description: Get intersection of users that follow followeeUserId and users + - users + description: + Get intersection of users that follow followeeUserId and users that are followed by followerUserId operationId: Get Mutual Followers parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/mutual_followers_response' + $ref: "#/components/schemas/mutual_followers_response" "400": description: Bad request content: {} @@ -4937,63 +5070,64 @@ paths: /users/{id}/playlists: get: tags: - - users + - users description: Gets the playlists created by a user using their user ID operationId: Get Playlists by User parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: sort_method - in: query - description: The sort method - schema: - type: string - default: recent - enum: - - recent - - popular - - name: query - in: query - description: Filter playlists by name - schema: - type: string - - name: Encoded-Data-Message - in: header - description: The data that was signed by the user for signature recovery - schema: - type: string - - name: Encoded-Data-Signature - in: header - description: "The signature of data, used for signature recovery" - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: sort_method + in: query + description: The sort method + schema: + type: string + default: recent + enum: + - recent + - popular + - name: query + in: query + description: Filter playlists by name + schema: + type: string + - name: Encoded-Data-Message + in: header + description: The data that was signed by the user for signature recovery + schema: + type: string + - name: Encoded-Data-Signature + in: header + description: "The signature of data, used for signature recovery" + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/playlists_response' + $ref: "#/components/schemas/playlists_response" "400": description: Bad request content: {} @@ -5003,51 +5137,54 @@ paths: /users/{id}/purchasers: get: tags: - - users - description: Gets the list of unique users who have purchased content by the + - users + description: + Gets the list of unique users who have purchased content by the given user operationId: Get purchasers parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: content_type - in: query - description: Type of content to filter by (track or album) - schema: - type: string - - name: content_id - in: query - description: Filters for users who have purchased the given track or album - ID - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: content_type + in: query + description: Type of content to filter by (track or album) + schema: + type: string + - name: content_id + in: query + description: + Filters for users who have purchased the given track or album + ID + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/purchasers_response' + $ref: "#/components/schemas/purchasers_response" "400": description: Bad request content: {} @@ -5057,31 +5194,31 @@ paths: /users/{id}/purchases/download: get: tags: - - users + - users description: Downloads the purchases the user has made as a CSV file operationId: Download Purchases as CSV parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: Encoded-Data-Message - in: header - description: The data that was signed by the user for signature recovery - schema: - type: string - - name: Encoded-Data-Signature - in: header - description: "The signature of data, used for signature recovery" - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: Encoded-Data-Message + in: header + description: The data that was signed by the user for signature recovery + schema: + type: string + - name: Encoded-Data-Signature + in: header + description: "The signature of data, used for signature recovery" + schema: + type: string responses: "200": description: Success @@ -5089,49 +5226,50 @@ paths: /users/{id}/recommended-tracks: get: tags: - - users + - users description: Gets the recommended tracks for the user operationId: Get User Recommended Tracks parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: time_range - in: query - description: The time range for the recommended tracks - schema: - type: string - default: week - enum: - - week - - month - - allTime + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: time_range + in: query + description: The time range for the recommended tracks + schema: + type: string + default: week + enum: + - week + - month + - allTime responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/tracks_response' + $ref: "#/components/schemas/tracks_response" "400": description: Bad request content: {} @@ -5141,46 +5279,48 @@ paths: /users/{id}/related: get: tags: - - users - description: Gets a list of users that might be of interest to followers of + - users + description: + Gets a list of users that might be of interest to followers of this user. operationId: Get Related Users parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: filter_followed - in: query - description: "If true, filters out artists that the current user already follows" - schema: - type: boolean - default: false + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: filter_followed + in: query + description: "If true, filters out artists that the current user already follows" + schema: + type: boolean + default: false responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/related_artist_response' + $ref: "#/components/schemas/related_artist_response" "400": description: Bad request content: {} @@ -5190,45 +5330,47 @@ paths: /users/{id}/remixers: get: tags: - - users - description: "Gets the list of unique users who have remixed tracks by the given\ + - users + description: + "Gets the list of unique users who have remixed tracks by the given\ \ user, or a specific track by that user if provided" operationId: Get remixers parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: track_id - in: query - description: Filters for remixers who have remixed the given track ID - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: track_id + in: query + description: Filters for remixers who have remixed the given track ID + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/remixers_response' + $ref: "#/components/schemas/remixers_response" "400": description: Bad request content: {} @@ -5238,39 +5380,40 @@ paths: /users/{id}/reposts: get: tags: - - users + - users description: Gets the given user's reposts operationId: Get Reposts parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/reposts' + $ref: "#/components/schemas/reposts" "400": description: Bad request content: {} @@ -5280,77 +5423,78 @@ paths: /users/{id}/sales/aggregate: get: tags: - - users + - users description: Gets the aggregated sales data for the user operationId: Get Sales Aggregate parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: Encoded-Data-Message - in: header - description: The data that was signed by the user for signature recovery - schema: - type: string - - name: Encoded-Data-Signature - in: header - description: "The signature of data, used for signature recovery" - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: Encoded-Data-Message + in: header + description: The data that was signed by the user for signature recovery + schema: + type: string + - name: Encoded-Data-Signature + in: header + description: "The signature of data, used for signature recovery" + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/sales_aggregate_response' + $ref: "#/components/schemas/sales_aggregate_response" /users/{id}/sales/download: get: tags: - - users + - users description: Downloads the sales the user has made as a CSV file operationId: Download Sales as CSV parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: Encoded-Data-Message - in: header - description: The data that was signed by the user for signature recovery - schema: - type: string - - name: Encoded-Data-Signature - in: header - description: "The signature of data, used for signature recovery" - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: Encoded-Data-Message + in: header + description: The data that was signed by the user for signature recovery + schema: + type: string + - name: Encoded-Data-Signature + in: header + description: "The signature of data, used for signature recovery" + schema: + type: string responses: "200": description: Success @@ -5358,79 +5502,80 @@ paths: /users/{id}/sales/download/json: get: tags: - - users + - users description: Gets the sales data for the user in JSON format - operationId: Download Sales as JSON - parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: grantee_user_id - in: query - description: Optional receiving user ID for email decryption - schema: - type: string - - name: Encoded-Data-Message - in: header - description: The data that was signed by the user for signature recovery - schema: - type: string - - name: Encoded-Data-Signature - in: header - description: "The signature of data, used for signature recovery" - schema: - type: string + operationId: Download Sales as JSON + parameters: + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: grantee_user_id + in: query + description: Optional receiving user ID for email decryption + schema: + type: string + - name: Encoded-Data-Message + in: header + description: The data that was signed by the user for signature recovery + schema: + type: string + - name: Encoded-Data-Signature + in: header + description: "The signature of data, used for signature recovery" + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/sales_json_response' + $ref: "#/components/schemas/sales_json_response" /users/{id}/subscribers: get: tags: - - users + - users description: All users that subscribe to the provided user operationId: Get Subscribers parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/subscribers_response' + $ref: "#/components/schemas/subscribers_response" "400": description: Bad request content: {} @@ -5439,32 +5584,32 @@ paths: content: {} post: tags: - - users + - users description: Subscribe to a user operationId: Subscribe to User security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: "200": description: Subscribed successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -5476,32 +5621,32 @@ paths: content: {} delete: tags: - - users + - users description: Unsubscribe from a user operationId: Unsubscribe from User security: - BasicAuth: [] - BearerAuth: [] parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: "200": description: Unsubscribed successfully content: application/json: schema: - $ref: '#/components/schemas/write_response' + $ref: "#/components/schemas/write_response" "401": description: Unauthorized content: {} @@ -5514,106 +5659,108 @@ paths: /users/{id}/supporters: get: tags: - - users + - users description: Gets the supporters of the given user operationId: Get Supporters parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/get_supporters' + $ref: "#/components/schemas/get_supporters" /users/{id}/supporting: get: tags: - - users + - users description: Gets the users that the given user supports operationId: Get Supported Users parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/get_supported_users' + $ref: "#/components/schemas/get_supported_users" /users/{id}/tags: get: tags: - - users + - users summary: Fetch most used tags in a user's tracks description: Gets the most used track tags by a user. operationId: Get Top Track Tags parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/tags_response' + $ref: "#/components/schemas/tags_response" "400": description: Bad request content: {} @@ -5623,111 +5770,112 @@ paths: /users/{id}/tracks: get: tags: - - users + - users description: Gets the tracks created by a user using their user ID operationId: Get Tracks by User parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: sort - in: query - description: "[Deprecated] Field to sort by" - schema: - type: string - default: date - enum: - - date - - plays - - name: query - in: query - description: The filter query - schema: - type: string - - name: sort_method - in: query - description: The sort method - schema: - type: string - enum: - - title - - artist_name - - release_date - - last_listen_date - - added_date - - plays - - reposts - - saves - - most_listens_by_user - - name: sort_direction - in: query - description: The sort direction - schema: - type: string - enum: - - asc - - desc - - name: filter_tracks - in: query - description: Filter by public tracks - schema: - type: string - default: all - enum: - - all - - public - - name: gate_condition - in: query - description: Filter tracks by gate condition type. Multiple values can be provided to filter by multiple gate types (OR logic) - style: form - explode: true - schema: - type: array - items: + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: sort + in: query + description: "[Deprecated] Field to sort by" + schema: type: string + default: date enum: - - ungated - - usdc_purchase - - follow - - tip - - nft - - token - - name: Encoded-Data-Message - in: header - description: The data that was signed by the user for signature recovery - schema: - type: string - - name: Encoded-Data-Signature - in: header - description: "The signature of data, used for signature recovery" - schema: - type: string + - date + - plays + - name: query + in: query + description: The filter query + schema: + type: string + - name: sort_method + in: query + description: The sort method + schema: + type: string + enum: + - title + - artist_name + - release_date + - last_listen_date + - added_date + - plays + - reposts + - saves + - most_listens_by_user + - name: sort_direction + in: query + description: The sort direction + schema: + type: string + enum: + - asc + - desc + - name: filter_tracks + in: query + description: Filter by public tracks + schema: + type: string + default: all + enum: + - all + - public + - name: gate_condition + in: query + description: Filter tracks by gate condition type. Multiple values can be provided to filter by multiple gate types (OR logic) + style: form + explode: true + schema: + type: array + items: + type: string + enum: + - ungated + - usdc_purchase + - follow + - tip + - nft + - token + - name: Encoded-Data-Message + in: header + description: The data that was signed by the user for signature recovery + schema: + type: string + - name: Encoded-Data-Signature + in: header + description: "The signature of data, used for signature recovery" + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/tracks_response' + $ref: "#/components/schemas/tracks_response" "400": description: Bad request content: {} @@ -5737,63 +5885,63 @@ paths: /users/{id}/tracks/count: get: tags: - - users + - users description: Gets the count of tracks created by a user operationId: Get Tracks Count by User parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: filter_tracks - in: query - description: Filter by public tracks - schema: - type: string - default: all - enum: - - all - - public - - name: gate_condition - in: query - description: Filter by gate conditions (can be repeated) - style: form - explode: true - schema: - type: array - items: + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + schema: type: string + - name: filter_tracks + in: query + description: Filter by public tracks + schema: + type: string + default: all enum: - - ungated - - usdc_purchase - - follow - - tip - - nft - - token - - name: Encoded-Data-Message - in: header - description: The data that was signed by the user for signature recovery - schema: - type: string - - name: Encoded-Data-Signature - in: header - description: "The signature of data, used for signature recovery" - schema: - type: string + - all + - public + - name: gate_condition + in: query + description: Filter by gate conditions (can be repeated) + style: form + explode: true + schema: + type: array + items: + type: string + enum: + - ungated + - usdc_purchase + - follow + - tip + - nft + - token + - name: Encoded-Data-Message + in: header + description: The data that was signed by the user for signature recovery + schema: + type: string + - name: Encoded-Data-Signature + in: header + description: "The signature of data, used for signature recovery" + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/tracks_count_response' + $ref: "#/components/schemas/tracks_count_response" "400": description: Bad request content: {} @@ -5803,45 +5951,47 @@ paths: /users/{id}/tracks/remixed: get: tags: - - users - description: Gets tracks owned by the user which have been remixed by another + - users + description: + Gets tracks owned by the user which have been remixed by another track operationId: Get User Tracks Remixed parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - default: 0 - type: integer - minimum: 0 - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - default: 10 - minimum: 1 - maximum: 100 - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + default: 0 + type: integer + minimum: 0 + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + default: 10 + minimum: 1 + maximum: 100 + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/user_tracks_remixed_response' + $ref: "#/components/schemas/user_tracks_remixed_response" "400": description: Bad request content: {} @@ -5851,31 +6001,31 @@ paths: /users/{id}/withdrawals/download: get: tags: - - users + - users description: Downloads the USDC withdrawals the user has made as a CSV file operationId: Download USDC Withdrawals as CSV parameters: - - name: id - in: path - description: A User ID - required: true - schema: - type: string - - name: user_id - in: query - description: The user ID of the user making the request - schema: - type: string - - name: Encoded-Data-Message - in: header - description: The data that was signed by the user for signature recovery - schema: - type: string - - name: Encoded-Data-Signature - in: header - description: "The signature of data, used for signature recovery" - schema: - type: string + - name: id + in: path + description: A User ID + required: true + schema: + type: string + - name: user_id + in: query + description: The user ID of the user making the request + schema: + type: string + - name: Encoded-Data-Message + in: header + description: The data that was signed by the user for signature recovery + schema: + type: string + - name: Encoded-Data-Signature + in: header + description: "The signature of data, used for signature recovery" + schema: + type: string responses: "200": description: Success @@ -5883,30 +6033,31 @@ paths: /users/{receiving_user_id}/emails/{grantor_user_id}/key: get: tags: - - users - description: Gets the encrypted key for email access between the receiving user + - users + description: + Gets the encrypted key for email access between the receiving user and granting user. operationId: Get User Email Key parameters: - - name: receiving_user_id - in: path - description: ID of user receiving email access - required: true - schema: - type: string - - name: grantor_user_id - in: path - description: ID of user granting email access - required: true - schema: - type: string + - name: receiving_user_id + in: path + description: ID of user receiving email access + required: true + schema: + type: string + - name: grantor_user_id + in: path + description: ID of user granting email access + required: true + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/email_access_response' + $ref: "#/components/schemas/email_access_response" "400": description: Bad request content: {} @@ -5918,118 +6069,119 @@ paths: tags: - coins operationId: Get Coins - description: 'Gets information about coins' - parameters: - - name: mint - in: query - description: The mint addresses of the coins - style: form - explode: true - schema: - type: array - items: + description: "Gets information about coins" + parameters: + - name: mint + in: query + description: The mint addresses of the coins + style: form + explode: true + schema: + type: array + items: + type: string + - name: owner_id + in: query + description: The user IDs of artists with minted coins + style: form + explode: true + schema: + type: array + items: + type: string + - name: ticker + in: query + description: The tickers of the coins + style: form + explode: true + schema: + type: array + items: + type: string + - name: query + in: query + description: Search by the coin name or ticker + schema: type: string - - name: owner_id - in: query - description: The user IDs of artists with minted coins - style: form - explode: true - schema: - type: array - items: + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + default: 0 + minimum: 0 + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + default: 50 + minimum: 1 + maximum: 100 + - name: sort_method + in: query + description: Field to use for sorting the results + schema: type: string - - name: ticker - in: query - description: The tickers of the coins - style: form - explode: true - schema: - type: array - items: + default: market_cap + enum: + - market_cap + - volume + - price + - created_at + - holder + - name: sort_direction + in: query + description: The sort direction + schema: type: string - - name: query - in: query - description: Search by the coin name or ticker - schema: - type: string - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - default: 0 - minimum: 0 - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - default: 50 - minimum: 1 - maximum: 100 - - name: sort_method - in: query - description: Field to use for sorting the results - schema: - type: string - default: market_cap - enum: - - market_cap - - volume - - price - - created_at - - holder - - name: sort_direction - in: query - description: The sort direction - schema: - type: string - default: desc - enum: - - asc - - desc + default: desc + enum: + - asc + - desc responses: - '200': + "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/coins_response' + $ref: "#/components/schemas/coins_response" post: tags: - coins operationId: Create Coin - description: 'Creates a new artist coin' + description: "Creates a new artist coin" parameters: - - name: user_id - in: query - description: The user ID to create a coin - required: true - schema: - type: string - example: "7eP5n" + - name: user_id + in: query + description: The user ID to create a coin + required: true + schema: + type: string + example: "7eP5n" requestBody: x-codegen-request-body-name: metadata required: true content: application/json: schema: - $ref: '#/components/schemas/create_coin_request_body' + $ref: "#/components/schemas/create_coin_request_body" responses: - '201': + "201": description: Success - Coin created content: application/json: schema: - $ref: '#/components/schemas/create_coin_response' - '400': + $ref: "#/components/schemas/create_coin_response" + "400": description: Bad request - Invalid parameters content: {} - '401': + "401": description: Unauthorized - User not authenticated content: {} - '500': + "500": description: Server error content: {} /coins/{mint}: @@ -6037,66 +6189,66 @@ paths: tags: - coins operationId: Get Coin - description: 'Gets information about a specific coin by its mint address' + description: "Gets information about a specific coin by its mint address" parameters: - - name: mint - in: path - description: The mint address of the coin - required: true - schema: - type: string - example: 9LzCMqDgTKYz9Drzqnpgee3SGa89up3a247ypMj2xrqM + - name: mint + in: path + description: The mint address of the coin + required: true + schema: + type: string + example: 9LzCMqDgTKYz9Drzqnpgee3SGa89up3a247ypMj2xrqM responses: - '200': + "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/coin_response' + $ref: "#/components/schemas/coin_response" post: tags: - coins operationId: Update Coin - description: 'Updates information about a specific coin by its mint address' - parameters: - - name: mint - in: path - description: The mint address of the coin - required: true - schema: - type: string - example: bearR26zyyB3fNQm5wWv1ZfN8MPQDUMwaAuoG79b1Yj - - name: user_id - in: query - description: The user ID making the update (must be the coin owner) - required: true - schema: - type: string - example: "7eP5n" + description: "Updates information about a specific coin by its mint address" + parameters: + - name: mint + in: path + description: The mint address of the coin + required: true + schema: + type: string + example: bearR26zyyB3fNQm5wWv1ZfN8MPQDUMwaAuoG79b1Yj + - name: user_id + in: query + description: The user ID making the update (must be the coin owner) + required: true + schema: + type: string + example: "7eP5n" requestBody: x-codegen-request-body-name: metadata required: true content: application/json: schema: - $ref: '#/components/schemas/update_coin_request_body' + $ref: "#/components/schemas/update_coin_request_body" responses: - '200': + "200": description: Success - Coin updated content: application/json: schema: - $ref: '#/components/schemas/update_coin_response' - '400': + $ref: "#/components/schemas/update_coin_response" + "400": description: Bad request - Invalid parameters or no fields provided content: {} - '403': + "403": description: Forbidden - User does not own the coin content: {} - '404': + "404": description: Not found - Coin does not exist content: {} - '500': + "500": description: Server error content: {} /coins/ticker/{ticker}: @@ -6104,26 +6256,26 @@ paths: tags: - coins operationId: Get Coin By Ticker - description: 'Gets information about a specific coin by its ticker' + description: "Gets information about a specific coin by its ticker" parameters: - - name: ticker - in: path - description: The ticker of the coin - required: true - schema: - type: string - example: $AUDIO + - name: ticker + in: path + description: The ticker of the coin + required: true + schema: + type: string + example: $AUDIO responses: - '200': + "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/coin_response' - '400': + $ref: "#/components/schemas/coin_response" + "400": description: Bad request content: {} - '500': + "500": description: Server error content: {} /coins/{mint}/insights: @@ -6131,190 +6283,192 @@ paths: tags: - coins operationId: Get Coin Insights - description: 'Gets insights about a specific coin by its mint address' + description: "Gets insights about a specific coin by its mint address" parameters: - - name: mint - in: path - description: The mint address of the coin - required: true - schema: - type: string - example: 9LzCMqDgTKYz9Drzqnpgee3SGa89up3a247ypMj2xrqM + - name: mint + in: path + description: The mint address of the coin + required: true + schema: + type: string + example: 9LzCMqDgTKYz9Drzqnpgee3SGa89up3a247ypMj2xrqM responses: - '200': + "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/coin_insights_response' + $ref: "#/components/schemas/coin_insights_response" /coins/{mint}/members: get: tags: - coins operationId: Get Coin Members - description: 'Gets a list of Audius users with a non-zero balance of a specific coin' + description: "Gets a list of Audius users with a non-zero balance of a specific coin" parameters: - - name: mint - in: path - description: The mint address of the coin - required: true - schema: - type: string - example: 9LzCMqDgTKYz9Drzqnpgee3SGa89up3a247ypMj2xrqM - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - default: 0 - minimum: 0 - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - default: 10 - minimum: 1 - maximum: 100 - - name: sort_direction - in: query - description: The sort direction for the results - schema: - type: string - enum: - - asc - - desc - default: desc + - name: mint + in: path + description: The mint address of the coin + required: true + schema: + type: string + example: 9LzCMqDgTKYz9Drzqnpgee3SGa89up3a247ypMj2xrqM + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + default: 0 + minimum: 0 + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + default: 10 + minimum: 1 + maximum: 100 + - name: sort_direction + in: query + description: The sort direction for the results + schema: + type: string + enum: + - asc + - desc + default: desc responses: - '200': + "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/coin_members_response' + $ref: "#/components/schemas/coin_members_response" /coins/{mint}/members/count: get: tags: - coins operationId: Get Coin Members Count - description: 'Gets the total number of Audius users with a non-zero balance of a specific coin' + description: "Gets the total number of Audius users with a non-zero balance of a specific coin" parameters: - - name: mint - in: path - description: The mint address of the coin - required: true - schema: - type: string - example: 9LzCMqDgTKYz9Drzqnpgee3SGa89up3a247ypMj2xrqM + - name: mint + in: path + description: The mint address of the coin + required: true + schema: + type: string + example: 9LzCMqDgTKYz9Drzqnpgee3SGa89up3a247ypMj2xrqM responses: - '200': + "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/coin_members_count_response' + $ref: "#/components/schemas/coin_members_count_response" /coins/volume-leaders: get: tags: - coins operationId: Get Volume Leaders - description: 'Gets top coin<>AUDIO trading addresses by volume' - parameters: - - name: from - in: query - description: Beginning of time range to query over (RFC3339 format) - schema: - type: string - example: '2006-01-02T15:04:05Z' - default: '(most recent midnight UTC)' - - name: to - in: query - description: End of time range to query over (RFC3339 format) - schema: - type: string - example: '2006-01-02T15:04:05Z' - default: '(most recent midnight UTC + 24hrs)' - - name: offset - in: query - description: The number of items to skip. Useful for pagination (page number - * limit) - schema: - type: integer - default: 0 - minimum: 0 - maximum: 500 - - name: limit - in: query - description: The number of items to fetch - schema: - type: integer - default: 20 - minimum: 1 - maximum: 100 + description: "Gets top coin<>AUDIO trading addresses by volume" + parameters: + - name: from + in: query + description: Beginning of time range to query over (RFC3339 format) + schema: + type: string + example: "2006-01-02T15:04:05Z" + default: "(most recent midnight UTC)" + - name: to + in: query + description: End of time range to query over (RFC3339 format) + schema: + type: string + example: "2006-01-02T15:04:05Z" + default: "(most recent midnight UTC + 24hrs)" + - name: offset + in: query + description: + The number of items to skip. Useful for pagination (page number + * limit) + schema: + type: integer + default: 0 + minimum: 0 + maximum: 500 + - name: limit + in: query + description: The number of items to fetch + schema: + type: integer + default: 20 + minimum: 1 + maximum: 100 responses: - '200': + "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/coins_volume_leaders_response' - '400': + $ref: "#/components/schemas/coins_volume_leaders_response" + "400": description: Bad Request /coins/{mint}/redeem: get: tags: - coins operationId: Get Coin Redeem Amount - description: 'Gets the availability indicator for reward codes for a specific coin' + description: "Gets the availability indicator for reward codes for a specific coin" parameters: - - name: mint - in: path - description: The mint address of the coin - required: true - schema: - type: string - example: 9LzCMqDgTKYz9Drzqnpgee3SGa89up3a247ypMj2xrqM + - name: mint + in: path + description: The mint address of the coin + required: true + schema: + type: string + example: 9LzCMqDgTKYz9Drzqnpgee3SGa89up3a247ypMj2xrqM responses: - '200': + "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/redeem_amount_response' + $ref: "#/components/schemas/redeem_amount_response" post: tags: - coins operationId: Claim Coin Reward - description: 'Claims a coin reward for a given mint' + description: "Claims a coin reward for a given mint" parameters: - - name: mint - in: path - description: The mint address of the coin - required: true - schema: - type: string - example: 9LzCMqDgTKYz9Drzqnpgee3SGa89up3a247ypMj2xrqM - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: mint + in: path + description: The mint address of the coin + required: true + schema: + type: string + example: 9LzCMqDgTKYz9Drzqnpgee3SGa89up3a247ypMj2xrqM + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: - '200': + "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/claim_rewards_response' - '400': + $ref: "#/components/schemas/claim_rewards_response" + "400": description: Bad request - No coin reward available or already claimed content: application/json: schema: - $ref: '#/components/schemas/reward_code_error_response' - '500': + $ref: "#/components/schemas/reward_code_error_response" + "500": description: Server error content: {} /coins/{mint}/redeem/{code}: @@ -6322,81 +6476,81 @@ paths: tags: - coins operationId: Get Reward Code - description: 'Gets information about a specific reward code for a coin' + description: "Gets information about a specific reward code for a coin" parameters: - - name: mint - in: path - description: The mint address of the coin - required: true - schema: - type: string - example: 9LzCMqDgTKYz9Drzqnpgee3SGa89up3a247ypMj2xrqM - - name: code - in: path - description: The reward code to retrieve - required: true - schema: - type: string - example: XYZ123 + - name: mint + in: path + description: The mint address of the coin + required: true + schema: + type: string + example: 9LzCMqDgTKYz9Drzqnpgee3SGa89up3a247ypMj2xrqM + - name: code + in: path + description: The reward code to retrieve + required: true + schema: + type: string + example: XYZ123 responses: - '200': + "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/reward_code_response' - '400': + $ref: "#/components/schemas/reward_code_response" + "400": description: Bad request - Code is invalid or already used content: application/json: schema: - $ref: '#/components/schemas/reward_code_error_response' + $ref: "#/components/schemas/reward_code_error_response" post: tags: - coins operationId: Claim Coin Reward Code - description: 'Claims a coin reward using a given code' + description: "Claims a coin reward using a given code" parameters: - - name: mint - in: path - description: The mint address of the coin - required: true - schema: - type: string - example: 9LzCMqDgTKYz9Drzqnpgee3SGa89up3a247ypMj2xrqM - - name: code - in: path - description: The reward code to claim - required: true - schema: - type: string - example: XYZ123 - - name: user_id - in: query - description: The user ID of the user making the request - required: true - schema: - type: string + - name: mint + in: path + description: The mint address of the coin + required: true + schema: + type: string + example: 9LzCMqDgTKYz9Drzqnpgee3SGa89up3a247ypMj2xrqM + - name: code + in: path + description: The reward code to claim + required: true + schema: + type: string + example: XYZ123 + - name: user_id + in: query + description: The user ID of the user making the request + required: true + schema: + type: string responses: - '200': + "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/claim_rewards_response' - '400': + $ref: "#/components/schemas/claim_rewards_response" + "400": description: Bad request - Code is invalid or already used content: application/json: schema: - $ref: '#/components/schemas/reward_code_error_response' - '500': + $ref: "#/components/schemas/reward_code_error_response" + "500": description: Server error content: {} /rewards/claim: post: tags: - - rewards + - rewards description: Claims all the filtered undisbursed rewards for a user operationId: Claim Rewards requestBody: @@ -6405,14 +6559,14 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/claim_rewards_request_body' + $ref: "#/components/schemas/claim_rewards_request_body" responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/claim_rewards_response' + $ref: "#/components/schemas/claim_rewards_response" "400": description: Bad request - No rewards to claim or invalid parameters content: {} @@ -6422,7 +6576,7 @@ paths: /rewards/code: post: tags: - - rewards + - rewards description: Creates a new reward code with Solana signature verification operationId: Create Reward Code requestBody: @@ -6430,14 +6584,14 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/create_reward_code_request_body' + $ref: "#/components/schemas/create_reward_code_request_body" responses: "201": description: Created - Reward code successfully created content: application/json: schema: - $ref: '#/components/schemas/create_reward_code_response' + $ref: "#/components/schemas/create_reward_code_response" "400": description: Bad request - Invalid signature format or missing required fields content: {} @@ -6452,14 +6606,14 @@ paths: tags: - prizes operationId: Get Prizes - description: 'Gets a list of active prizes available for claiming. Excludes sensitive information like download URLs.' + description: "Gets a list of active prizes available for claiming. Excludes sensitive information like download URLs." responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/prizes_response' + $ref: "#/components/schemas/prizes_response" "500": description: Server error content: {} @@ -6468,21 +6622,21 @@ paths: tags: - prizes operationId: Claim Prize - description: 'Claims a prize by verifying a Solana transaction. User must send exactly 2 YAK to the prize receiver address. Returns the prize won and any redeem codes/URLs.' + description: "Claims a prize by verifying a Solana transaction. User must send exactly 2 YAK to the prize receiver address. Returns the prize won and any redeem codes/URLs." requestBody: x-codegen-request-body-name: claim required: true content: application/json: schema: - $ref: '#/components/schemas/prize_claim_request_body' + $ref: "#/components/schemas/prize_claim_request_body" responses: "200": description: Success - Prize claimed content: application/json: schema: - $ref: '#/components/schemas/prize_claim_response' + $ref: "#/components/schemas/prize_claim_response" "400": description: Bad request - Transaction not found, invalid, or signature already used content: {} @@ -6494,7 +6648,7 @@ paths: tags: - prizes operationId: Get Wallet Prizes - description: 'Gets all claimed prizes for a wallet. Public endpoint - no authentication required. Excludes sensitive action_data for security.' + description: "Gets all claimed prizes for a wallet. Public endpoint - no authentication required. Excludes sensitive action_data for security." parameters: - name: wallet in: path @@ -6509,7 +6663,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/claimed_prizes_response' + $ref: "#/components/schemas/claimed_prizes_response" "400": description: Bad request - Missing wallet parameter content: {} @@ -6523,31 +6677,31 @@ components: type: object properties: data: - $ref: '#/components/schemas/user' + $ref: "#/components/schemas/user" user: required: - - album_count - - erc_wallet - - followee_count - - follower_count - - handle - - id - - is_available - - is_deactivated - - is_verified - - name - - playlist_count - - repost_count - - spl_wallet - - spl_usdc_wallet - - supporter_count - - supporting_count - - total_audio_balance - - track_count - - verified_with_instagram - - verified_with_tiktok - - verified_with_twitter - - wallet + - album_count + - erc_wallet + - followee_count + - follower_count + - handle + - id + - is_available + - is_deactivated + - is_verified + - name + - playlist_count + - repost_count + - spl_wallet + - spl_usdc_wallet + - supporter_count + - supporting_count + - total_audio_balance + - track_count + - verified_with_instagram + - verified_with_tiktok + - verified_with_twitter + - wallet type: object properties: album_count: @@ -6557,7 +6711,7 @@ components: bio: type: string cover_photo: - $ref: '#/components/schemas/cover_photo' + $ref: "#/components/schemas/cover_photo" followee_count: type: integer follower_count: @@ -6591,7 +6745,7 @@ components: playlist_count: type: integer profile_picture: - $ref: '#/components/schemas/profile_picture' + $ref: "#/components/schemas/profile_picture" repost_count: type: integer track_count: @@ -6697,16 +6851,16 @@ components: data: type: array items: - $ref: '#/components/schemas/user' + $ref: "#/components/schemas/user" user_track_listen_counts_response: type: object properties: data: - $ref: '#/components/schemas/wild_month_model' + $ref: "#/components/schemas/wild_month_model" wild_month_model: type: object additionalProperties: - $ref: '#/components/schemas/monthly_aggregate_play' + $ref: "#/components/schemas/monthly_aggregate_play" monthly_aggregate_play: type: object properties: @@ -6719,7 +6873,7 @@ components: listenCounts: type: array items: - $ref: '#/components/schemas/listen_count' + $ref: "#/components/schemas/listen_count" listen_count: type: object properties: @@ -6735,26 +6889,26 @@ components: data: type: array items: - $ref: '#/components/schemas/Track' + $ref: "#/components/schemas/Track" Track: required: - - artwork - - comment_count - - duration - - favorite_count - - genre - - id - - is_downloadable - - is_original_available - - permalink - - play_count - - repost_count - - title - - user + - artwork + - comment_count + - duration + - favorite_count + - genre + - id + - is_downloadable + - is_original_available + - permalink + - play_count + - repost_count + - title + - user type: object properties: artwork: - $ref: '#/components/schemas/track_artwork' + $ref: "#/components/schemas/track_artwork" description: type: string genre: @@ -6779,7 +6933,7 @@ components: isrc: type: string remix_of: - $ref: '#/components/schemas/remix_parent' + $ref: "#/components/schemas/remix_parent" repost_count: type: integer favorite_count: @@ -6791,7 +6945,7 @@ components: title: type: string user: - $ref: '#/components/schemas/user' + $ref: "#/components/schemas/user" duration: type: integer is_downloadable: @@ -6811,9 +6965,9 @@ components: pinned_comment_id: type: integer album_backlink: - $ref: '#/components/schemas/album_backlink' + $ref: "#/components/schemas/album_backlink" access: - $ref: '#/components/schemas/track_access_info' + $ref: "#/components/schemas/track_access_info" ai_attribution_user_id: type: integer allowed_api_keys: @@ -6852,9 +7006,9 @@ components: ddex_release_ids: type: object download: - $ref: '#/components/schemas/media_link' + $ref: "#/components/schemas/media_link" download_conditions: - $ref: '#/components/schemas/access_gate' + $ref: "#/components/schemas/access_gate" field_visibility: type: object followee_favorites: @@ -6900,7 +7054,7 @@ components: playlists_previously_containing_track: type: object preview: - $ref: '#/components/schemas/media_link' + $ref: "#/components/schemas/media_link" preview_start_seconds: type: number producer_copyright_line: @@ -6916,9 +7070,9 @@ components: items: type: object stream: - $ref: '#/components/schemas/media_link' + $ref: "#/components/schemas/media_link" stream_conditions: - $ref: '#/components/schemas/access_gate' + $ref: "#/components/schemas/access_gate" track_id: type: integer track_segments: @@ -6941,35 +7095,35 @@ components: tracks: type: array items: - $ref: '#/components/schemas/track_element' + $ref: "#/components/schemas/track_element" remix_parent_write: type: object required: - - tracks + - tracks properties: tracks: type: array items: - $ref: '#/components/schemas/track_element_write' + $ref: "#/components/schemas/track_element_write" track_element: required: - - parent_track_id + - parent_track_id type: object properties: parent_track_id: type: string track_element_write: required: - - parent_track_id + - parent_track_id type: object properties: parent_track_id: type: integer album_backlink: required: - - permalink - - playlist_id - - playlist_name + - permalink + - playlist_id + - playlist_name type: object properties: playlist_id: @@ -6984,28 +7138,28 @@ components: data: type: array items: - $ref: '#/components/schemas/activity' + $ref: "#/components/schemas/activity" track_activity: allOf: - - $ref: '#/components/schemas/activity' - - required: - - item - - item_type - type: object - properties: - item_type: - type: string - example: track - enum: - - track - item: - $ref: '#/components/schemas/Track' + - $ref: "#/components/schemas/activity" + - required: + - item + - item_type + type: object + properties: + item_type: + type: string + example: track + enum: + - track + item: + $ref: "#/components/schemas/Track" activity: required: - - class - - item - - item_type - - timestamp + - class + - item + - item_type + - timestamp type: object properties: timestamp: @@ -7014,8 +7168,8 @@ components: type: string example: track enum: - - track - - playlist + - track + - playlist item: type: object properties: {} @@ -7025,52 +7179,52 @@ components: propertyName: class collection_activity: allOf: - - $ref: '#/components/schemas/activity' - - required: - - item - - item_type - type: object - properties: - timestamp: - type: string - item_type: - type: string - example: playlist - enum: - - playlist - item: - $ref: '#/components/schemas/playlist' + - $ref: "#/components/schemas/activity" + - required: + - item + - item_type + type: object + properties: + timestamp: + type: string + item_type: + type: string + example: playlist + enum: + - playlist + item: + $ref: "#/components/schemas/playlist" playlist: required: - - access - - added_timestamps - - blocknumber - - created_at - - favorite_count - - followee_favorites - - followee_reposts - - has_current_user_reposted - - has_current_user_saved - - id - - is_album - - is_delete - - is_image_autogenerated - - is_private - - is_scheduled_release - - is_stream_gated - - permalink - - playlist_contents - - playlist_name - - repost_count - - total_play_count - - track_count - - updated_at - - user - - user_id + - access + - added_timestamps + - blocknumber + - created_at + - favorite_count + - followee_favorites + - followee_reposts + - has_current_user_reposted + - has_current_user_saved + - id + - is_album + - is_delete + - is_image_autogenerated + - is_private + - is_scheduled_release + - is_stream_gated + - permalink + - playlist_contents + - playlist_name + - repost_count + - total_play_count + - track_count + - updated_at + - user + - user_id type: object properties: artwork: - $ref: '#/components/schemas/playlist_artwork' + $ref: "#/components/schemas/playlist_artwork" description: type: string permalink: @@ -7086,7 +7240,7 @@ components: playlist_contents: type: array items: - $ref: '#/components/schemas/playlist_added_timestamp' + $ref: "#/components/schemas/playlist_added_timestamp" repost_count: type: integer favorite_count: @@ -7094,11 +7248,11 @@ components: total_play_count: type: integer user: - $ref: '#/components/schemas/user' + $ref: "#/components/schemas/user" ddex_app: type: string access: - $ref: '#/components/schemas/access' + $ref: "#/components/schemas/access" upc: type: string track_count: @@ -7110,11 +7264,11 @@ components: followee_reposts: type: array items: - $ref: '#/components/schemas/repost' + $ref: "#/components/schemas/repost" followee_favorites: type: array items: - $ref: '#/components/schemas/favorite' + $ref: "#/components/schemas/favorite" has_current_user_reposted: type: boolean has_current_user_saved: @@ -7129,26 +7283,26 @@ components: type: array description: DEPRECATED. Use playlist_contents instead. items: - $ref: '#/components/schemas/playlist_added_timestamp' + $ref: "#/components/schemas/playlist_added_timestamp" user_id: type: string tracks: type: array items: - $ref: '#/components/schemas/Track' + $ref: "#/components/schemas/Track" cover_art: type: string cover_art_sizes: type: string cover_art_cids: - $ref: '#/components/schemas/playlist_artwork' + $ref: "#/components/schemas/playlist_artwork" is_stream_gated: type: boolean stream_conditions: type: object description: How to unlock stream access to the track allOf: - - $ref: '#/components/schemas/access_gate' + - $ref: "#/components/schemas/access_gate" is_scheduled_release: type: boolean release_date: @@ -7181,8 +7335,8 @@ components: type: string playlist_added_timestamp: required: - - track_id - - timestamp + - track_id + - timestamp type: object properties: track_id: @@ -7200,8 +7354,8 @@ components: minimum: 0 access: required: - - download - - stream + - download + - stream type: object properties: stream: @@ -7221,12 +7375,12 @@ components: data: type: array items: - $ref: '#/components/schemas/favorite' + $ref: "#/components/schemas/favorite" repost: required: - - repost_item_id - - repost_type - - user_id + - repost_item_id + - repost_type + - user_id type: object properties: repost_item_id: @@ -7237,10 +7391,10 @@ components: type: string favorite: required: - - created_at - - favorite_item_id - - favorite_type - - user_id + - created_at + - favorite_item_id + - favorite_type + - user_id type: object properties: favorite_item_id: @@ -7257,75 +7411,75 @@ components: data: type: array items: - $ref: '#/components/schemas/playlist' + $ref: "#/components/schemas/playlist" albums_response: type: object properties: data: type: array items: - $ref: '#/components/schemas/playlist' + $ref: "#/components/schemas/playlist" user_search: type: object properties: data: type: array items: - $ref: '#/components/schemas/user' + $ref: "#/components/schemas/user" history_response: type: object properties: data: type: array items: - $ref: '#/components/schemas/track_activity' + $ref: "#/components/schemas/track_activity" subscribers_response: type: object properties: data: type: array items: - $ref: '#/components/schemas/user' + $ref: "#/components/schemas/user" followers_response: type: object properties: data: type: array items: - $ref: '#/components/schemas/user' + $ref: "#/components/schemas/user" following_response: type: object properties: data: type: array items: - $ref: '#/components/schemas/user' + $ref: "#/components/schemas/user" mutual_followers_response: type: object properties: data: type: array items: - $ref: '#/components/schemas/user' + $ref: "#/components/schemas/user" related_artist_response: type: object properties: data: type: array items: - $ref: '#/components/schemas/user' + $ref: "#/components/schemas/user" user_ids_addresses_response: type: object properties: data: type: array items: - $ref: '#/components/schemas/user_id_address' + $ref: "#/components/schemas/user_id_address" user_id_address: type: object required: - - user_id - - address + - user_id + - address properties: user_id: type: string @@ -7335,11 +7489,11 @@ components: type: object properties: data: - $ref: '#/components/schemas/connected_wallets' + $ref: "#/components/schemas/connected_wallets" connected_wallets: required: - - erc_wallets - - spl_wallets + - erc_wallets + - spl_wallets type: object properties: erc_wallets: @@ -7354,7 +7508,7 @@ components: type: object properties: data: - $ref: '#/components/schemas/collectibles' + $ref: "#/components/schemas/collectibles" collectibles: type: object properties: @@ -7368,18 +7522,18 @@ components: data: type: array items: - $ref: '#/components/schemas/challenge_response' + $ref: "#/components/schemas/challenge_response" challenge_response: required: - - amount - - challenge_id - - challenge_type - - disbursed_amount - - is_active - - is_complete - - is_disbursed - - metadata - - user_id + - amount + - challenge_id + - challenge_type + - disbursed_amount + - is_active + - is_complete + - is_disbursed + - metadata + - user_id type: object properties: challenge_id: @@ -7415,12 +7569,12 @@ components: data: type: array items: - $ref: '#/components/schemas/supporter' + $ref: "#/components/schemas/supporter" supporter: required: - - amount - - rank - - sender + - amount + - rank + - sender type: object properties: rank: @@ -7428,19 +7582,19 @@ components: amount: type: string sender: - $ref: '#/components/schemas/user' + $ref: "#/components/schemas/user" get_supported_users: type: object properties: data: type: array items: - $ref: '#/components/schemas/supporting' + $ref: "#/components/schemas/supporting" supporting: required: - - amount - - rank - - receiver + - amount + - rank + - receiver type: object properties: rank: @@ -7448,22 +7602,22 @@ components: amount: type: string receiver: - $ref: '#/components/schemas/user' + $ref: "#/components/schemas/user" verify_token: type: object properties: data: - $ref: '#/components/schemas/decoded_user_token' + $ref: "#/components/schemas/decoded_user_token" decoded_user_token: required: - - apiKey - - email - - handle - - iat - - name - - sub - - userId - - verified + - apiKey + - email + - handle + - iat + - name + - sub + - userId + - verified type: object properties: apiKey: @@ -7479,7 +7633,7 @@ components: verified: type: boolean profilePicture: - $ref: '#/components/schemas/profilePicture' + $ref: "#/components/schemas/profilePicture" sub: type: string iat: @@ -7495,9 +7649,9 @@ components: type: string developer_app: required: - - address - - name - - user_id + - address + - name + - user_id type: object properties: address: @@ -7516,14 +7670,14 @@ components: data: type: array items: - $ref: '#/components/schemas/authorized_app' + $ref: "#/components/schemas/authorized_app" authorized_app: required: - - address - - grant_created_at - - grant_updated_at - - grantor_user_id - - name + - address + - grant_created_at + - grant_updated_at + - grantor_user_id + - name type: object properties: address: @@ -7546,12 +7700,12 @@ components: data: type: array items: - $ref: '#/components/schemas/sales_aggregate' + $ref: "#/components/schemas/sales_aggregate" sales_aggregate: required: - - content_id - - content_type - - purchase_count + - content_id + - content_type + - purchase_count type: object properties: content_type: @@ -7564,14 +7718,14 @@ components: type: object properties: data: - $ref: '#/components/schemas/sales_json_content' + $ref: "#/components/schemas/sales_json_content" sales_json_content: type: object properties: sales: type: array items: - $ref: '#/components/schemas/sale_json' + $ref: "#/components/schemas/sale_json" sale_json: type: object properties: @@ -7623,26 +7777,26 @@ components: data: type: array items: - $ref: '#/components/schemas/user' + $ref: "#/components/schemas/user" purchasers_response: type: object properties: data: type: array items: - $ref: '#/components/schemas/user' + $ref: "#/components/schemas/user" user_tracks_remixed_response: type: object properties: data: type: array items: - $ref: '#/components/schemas/remixed_track_aggregate' + $ref: "#/components/schemas/remixed_track_aggregate" remixed_track_aggregate: required: - - remix_count - - title - - track_id + - remix_count + - title + - track_id type: object properties: track_id: @@ -7655,17 +7809,17 @@ components: type: object properties: data: - $ref: '#/components/schemas/email_access' + $ref: "#/components/schemas/email_access" email_access: required: - - created_at - - email_owner_user_id - - encrypted_key - - grantor_user_id - - id - - is_initial - - receiving_user_id - - updated_at + - created_at + - email_owner_user_id + - encrypted_key + - grantor_user_id + - id + - is_initial + - receiving_user_id + - updated_at type: object properties: id: @@ -7690,17 +7844,17 @@ components: data: type: array items: - $ref: '#/components/schemas/comment' + $ref: "#/components/schemas/comment" comment: required: - - created_at - - entity_id - - entity_type - - id - - is_edited - - message - - react_count - - reply_count + - created_at + - entity_id + - entity_type + - id + - is_edited + - message + - react_count + - reply_count type: object properties: id: @@ -7708,7 +7862,7 @@ components: entity_id: type: string entity_type: - $ref: '#/components/schemas/comment_entity_type' + $ref: "#/components/schemas/comment_entity_type" user_id: type: string message: @@ -7716,7 +7870,7 @@ components: mentions: type: array items: - $ref: '#/components/schemas/comment_mention' + $ref: "#/components/schemas/comment_mention" track_timestamp_s: type: integer react_count: @@ -7740,13 +7894,13 @@ components: replies: type: array items: - $ref: '#/components/schemas/reply_comment' + $ref: "#/components/schemas/reply_comment" parent_comment_id: type: integer comment_mention: required: - - handle - - user_id + - handle + - user_id type: object properties: user_id: @@ -7755,14 +7909,14 @@ components: type: string reply_comment: required: - - created_at - - entity_id - - entity_type - - id - - is_edited - - message - - react_count - - user_id + - created_at + - entity_id + - entity_type + - id + - is_edited + - message + - react_count + - user_id type: object properties: id: @@ -7770,7 +7924,7 @@ components: entity_id: type: string entity_type: - $ref: '#/components/schemas/comment_entity_type' + $ref: "#/components/schemas/comment_entity_type" user_id: type: string message: @@ -7778,7 +7932,7 @@ components: mentions: type: array items: - $ref: '#/components/schemas/comment_mention' + $ref: "#/components/schemas/comment_mention" track_timestamp_s: type: integer react_count: @@ -7801,44 +7955,44 @@ components: data: type: array items: - $ref: '#/components/schemas/playlist' + $ref: "#/components/schemas/playlist" playlist_tracks_response: type: object properties: data: type: array items: - $ref: '#/components/schemas/Track' + $ref: "#/components/schemas/Track" playlist_search_result: type: object properties: data: type: array items: - $ref: '#/components/schemas/playlist' + $ref: "#/components/schemas/playlist" trending_playlists_response: type: object properties: data: type: array items: - $ref: '#/components/schemas/playlist' + $ref: "#/components/schemas/playlist" access_info_response: type: object properties: data: - $ref: '#/components/schemas/track_access_info' + $ref: "#/components/schemas/track_access_info" track_access_info: required: - - blocknumber - - user_id + - blocknumber + - user_id type: object properties: access: type: object description: Describes what access the given user has allOf: - - $ref: '#/components/schemas/access' + - $ref: "#/components/schemas/access" user_id: type: string description: The user ID of the owner of this track @@ -7847,31 +8001,33 @@ components: description: The blocknumber this track was last updated is_stream_gated: type: boolean - description: Whether or not the owner has restricted streaming behind an + description: + Whether or not the owner has restricted streaming behind an access gate stream_conditions: type: object description: How to unlock stream access to the track allOf: - - $ref: '#/components/schemas/extended_access_gate' + - $ref: "#/components/schemas/extended_access_gate" is_download_gated: type: boolean - description: Whether or not the owner has restricted downloading behind + description: + Whether or not the owner has restricted downloading behind an access gate download_conditions: type: object description: How to unlock the track download allOf: - - $ref: '#/components/schemas/extended_access_gate' + - $ref: "#/components/schemas/extended_access_gate" extended_access_gate: oneOf: - - $ref: '#/components/schemas/tip_gate' - - $ref: '#/components/schemas/follow_gate' - - $ref: '#/components/schemas/extended_purchase_gate' - - $ref: '#/components/schemas/token_gate' + - $ref: "#/components/schemas/tip_gate" + - $ref: "#/components/schemas/follow_gate" + - $ref: "#/components/schemas/extended_purchase_gate" + - $ref: "#/components/schemas/token_gate" tip_gate: required: - - tip_user_id + - tip_user_id type: object properties: tip_user_id: @@ -7879,7 +8035,7 @@ components: description: Must tip the given user ID to unlock follow_gate: required: - - follow_user_id + - follow_user_id type: object properties: follow_user_id: @@ -7887,18 +8043,18 @@ components: description: Must follow the given user ID to unlock token_gate: required: - - token_gate + - token_gate type: object properties: token_gate: type: object description: Must hold an NFT of the given collection to unlock allOf: - - $ref: '#/components/schemas/extended_token_gate' + - $ref: "#/components/schemas/extended_token_gate" extended_token_gate: required: - - token_mint - - token_amount + - token_mint + - token_amount type: object properties: token_mint: @@ -7909,19 +8065,20 @@ components: description: The amount of the token needed to unlock extended_purchase_gate: required: - - usdc_purchase + - usdc_purchase type: object properties: usdc_purchase: type: object - description: Must pay the total price and split to the given addresses to + description: + Must pay the total price and split to the given addresses to unlock allOf: - - $ref: '#/components/schemas/extended_usdc_gate' + - $ref: "#/components/schemas/extended_usdc_gate" extended_usdc_gate: required: - - price - - splits + - price + - splits type: object properties: price: @@ -7929,12 +8086,12 @@ components: splits: type: array items: - $ref: '#/components/schemas/extended_payment_split' + $ref: "#/components/schemas/extended_payment_split" extended_payment_split: required: - - amount - - payout_wallet - - percentage + - amount + - payout_wallet + - percentage type: object properties: user_id: @@ -7958,24 +8115,24 @@ components: type: string access_gate: oneOf: - - $ref: '#/components/schemas/tip_gate' - - $ref: '#/components/schemas/follow_gate' - - $ref: '#/components/schemas/extended_purchase_gate' - - $ref: '#/components/schemas/token_gate' + - $ref: "#/components/schemas/tip_gate" + - $ref: "#/components/schemas/follow_gate" + - $ref: "#/components/schemas/extended_purchase_gate" + - $ref: "#/components/schemas/token_gate" track_response: type: object properties: data: - $ref: '#/components/schemas/Track' + $ref: "#/components/schemas/Track" track_inspect: type: object properties: data: - $ref: '#/components/schemas/blob_info' + $ref: "#/components/schemas/blob_info" blob_info: required: - - content_type - - size + - content_type + - size type: object properties: size: @@ -7988,37 +8145,37 @@ components: data: type: array items: - $ref: '#/components/schemas/blob_info' + $ref: "#/components/schemas/blob_info" track_comments_response: type: object properties: data: type: array items: - $ref: '#/components/schemas/comment' + $ref: "#/components/schemas/comment" trending_ids_response: type: object properties: data: - $ref: '#/components/schemas/trending_times_ids' + $ref: "#/components/schemas/trending_times_ids" trending_times_ids: type: object properties: week: type: array items: - $ref: '#/components/schemas/track_id' + $ref: "#/components/schemas/track_id" month: type: array items: - $ref: '#/components/schemas/track_id' + $ref: "#/components/schemas/track_id" year: type: array items: - $ref: '#/components/schemas/track_id' + $ref: "#/components/schemas/track_id" track_id: required: - - id + - id type: object properties: id: @@ -8029,17 +8186,17 @@ components: data: type: array items: - $ref: '#/components/schemas/user' + $ref: "#/components/schemas/user" track_reposts_response: type: object properties: data: type: array items: - $ref: '#/components/schemas/user' + $ref: "#/components/schemas/user" remixes_response: required: - - count + - count type: object properties: count: @@ -8047,14 +8204,14 @@ components: tracks: type: array items: - $ref: '#/components/schemas/Track' + $ref: "#/components/schemas/Track" remixing_response: type: object properties: data: type: array items: - $ref: '#/components/schemas/Track' + $ref: "#/components/schemas/Track" tracks_count_response: type: object properties: @@ -8069,17 +8226,17 @@ components: type: object properties: data: - $ref: '#/components/schemas/comment_notification_setting' + $ref: "#/components/schemas/comment_notification_setting" comment_notification_setting: required: - - is_muted + - is_muted type: object properties: is_muted: type: boolean stream_url_response: required: - - data + - data type: object properties: data: @@ -8090,30 +8247,30 @@ components: data: type: array items: - $ref: '#/components/schemas/Track' + $ref: "#/components/schemas/Track" top_listener: type: object properties: data: type: array items: - $ref: '#/components/schemas/top_listener' + $ref: "#/components/schemas/top_listener" stems_response: type: object properties: data: type: array items: - $ref: '#/components/schemas/stem' + $ref: "#/components/schemas/stem" stem: required: - - blocknumber - - category - - cid - - id - - orig_filename - - parent_id - - user_id + - blocknumber + - category + - cid + - id + - orig_filename + - parent_id + - user_id type: object properties: id: @@ -8147,12 +8304,12 @@ components: - OTHER stem_parent: required: - - category - - parent_track_id + - category + - parent_track_id type: object properties: category: - $ref: '#/components/schemas/stem_category' + $ref: "#/components/schemas/stem_category" parent_track_id: type: integer undisbursed_challenges: @@ -8161,18 +8318,18 @@ components: data: type: array items: - $ref: '#/components/schemas/undisbursed_challenge' + $ref: "#/components/schemas/undisbursed_challenge" undisbursed_challenge: required: - - amount - - challenge_id - - completed_at - - completed_blocknumber - - created_at - - handle - - specifier - - user_id - - wallet + - amount + - challenge_id + - completed_at + - completed_blocknumber + - created_at + - handle + - specifier + - user_id + - wallet type: object properties: challenge_id: @@ -8201,57 +8358,57 @@ components: data: type: array items: - $ref: '#/components/schemas/tip' + $ref: "#/components/schemas/tip" tip: required: - - amount - - created_at + - amount + - created_at type: object properties: amount: type: string sender: - $ref: '#/components/schemas/user' + $ref: "#/components/schemas/user" receiver: - $ref: '#/components/schemas/user' + $ref: "#/components/schemas/user" created_at: type: string developer_app_response: type: object properties: data: - $ref: '#/components/schemas/developer_app' + $ref: "#/components/schemas/developer_app" dashboard_wallet_users_response: type: object properties: data: type: array items: - $ref: '#/components/schemas/dashboard_wallet_user' + $ref: "#/components/schemas/dashboard_wallet_user" dashboard_wallet_user: required: - - user - - wallet + - user + - wallet type: object properties: wallet: type: string user: - $ref: '#/components/schemas/user' + $ref: "#/components/schemas/user" comment_response: type: object properties: data: type: array items: - $ref: '#/components/schemas/comment' + $ref: "#/components/schemas/comment" comment_replies_response: type: object properties: data: type: array items: - $ref: '#/components/schemas/reply_comment' + $ref: "#/components/schemas/reply_comment" unclaimed_id_response: type: object properties: @@ -8263,15 +8420,15 @@ components: data: type: array items: - $ref: '#/components/schemas/event' + $ref: "#/components/schemas/event" event: required: - - created_at - - event_data - - event_id - - event_type - - updated_at - - user_id + - created_at + - event_data + - event_id + - event_type + - updated_at + - user_id type: object properties: event_id: @@ -8280,18 +8437,18 @@ components: type: string example: remix_contest enum: - - remix_contest - - live_event - - new_release + - remix_contest + - live_event + - new_release user_id: type: string entity_type: type: string example: track enum: - - track - - collection - - user + - track + - collection + - user entity_id: type: string end_date: @@ -8311,12 +8468,12 @@ components: data: type: array items: - $ref: '#/components/schemas/best_selling_item' + $ref: "#/components/schemas/best_selling_item" best_selling_item: required: - - content_id - - owner_id - - title + - content_id + - owner_id + - title type: object properties: content_id: @@ -8325,8 +8482,8 @@ components: type: string example: track enum: - - track - - album + - track + - album title: type: string owner_id: @@ -8757,7 +8914,7 @@ components: type: object properties: data: - $ref: '#/components/schemas/coin' + $ref: "#/components/schemas/coin" coins_response: type: object required: @@ -8766,7 +8923,7 @@ components: data: type: array items: - $ref: '#/components/schemas/coin' + $ref: "#/components/schemas/coin" create_coin_request_body: type: object required: @@ -9257,7 +9414,7 @@ components: type: object properties: data: - $ref: '#/components/schemas/coin_insights' + $ref: "#/components/schemas/coin_insights" coin_member: type: object required: @@ -9280,7 +9437,7 @@ components: data: type: array items: - $ref: '#/components/schemas/coin_member' + $ref: "#/components/schemas/coin_member" coin_members_count_response: type: object required: @@ -9308,7 +9465,7 @@ components: volume: type: number user: - $ref: '#/components/schemas/user' + $ref: "#/components/schemas/user" user_coin: required: - mint @@ -9366,7 +9523,7 @@ components: data: type: array items: - $ref: '#/components/schemas/user_coin' + $ref: "#/components/schemas/user_coin" user_coin_with_accounts: type: object required: @@ -9405,7 +9562,7 @@ components: accounts: type: array items: - $ref: '#/components/schemas/user_coin_account' + $ref: "#/components/schemas/user_coin_account" user_coin_account: type: object required: @@ -9439,7 +9596,7 @@ components: type: object properties: data: - $ref: '#/components/schemas/user_coin_with_accounts' + $ref: "#/components/schemas/user_coin_with_accounts" balance_history_response: type: object required: @@ -9448,7 +9605,7 @@ components: data: type: array items: - $ref: '#/components/schemas/balance_history_data_point' + $ref: "#/components/schemas/balance_history_data_point" balance_history_data_point: type: object required: @@ -9495,7 +9652,10 @@ components: items: type: string description: Transaction signatures - example: ["5j7s1QjmRKFuDbCWMRVRNibSV2VAAEcNKP6HWU7GwPdXkBZvhz8n4vQl7bBq8tN4Rz9x1Kj3mP5wQ8rT2Y6zA"] + example: + [ + "5j7s1QjmRKFuDbCWMRVRNibSV2VAAEcNKP6HWU7GwPdXkBZvhz8n4vQl7bBq8tN4Rz9x1Kj3mP5wQ8rT2Y6zA", + ] error: type: string description: Error message if claim failed @@ -9676,7 +9836,7 @@ components: data: type: array items: - $ref: '#/components/schemas/prize_public' + $ref: "#/components/schemas/prize_public" description: List of active prizes available for claiming claimed_prize: type: object @@ -9735,7 +9895,7 @@ components: data: type: array items: - $ref: '#/components/schemas/claimed_prize' + $ref: "#/components/schemas/claimed_prize" description: List of claimed prizes for the wallet (action_data excluded for security) write_response: type: object @@ -9810,13 +9970,13 @@ components: description: Track title example: "My New Track" genre: - $ref: '#/components/schemas/genre' + $ref: "#/components/schemas/genre" description: type: string description: Track description maxLength: 1000 mood: - $ref: '#/components/schemas/mood' + $ref: "#/components/schemas/mood" bpm: type: number description: Beats per minute (tempo) @@ -9874,18 +10034,18 @@ components: type: boolean description: Whether the track is unlisted stream_conditions: - $ref: '#/components/schemas/access_gate' + $ref: "#/components/schemas/access_gate" download_conditions: - $ref: '#/components/schemas/access_gate' + $ref: "#/components/schemas/access_gate" field_visibility: - $ref: '#/components/schemas/field_visibility' + $ref: "#/components/schemas/field_visibility" placement_hosts: type: string description: Placement hosts for the track stem_of: - $ref: '#/components/schemas/stem_parent' + $ref: "#/components/schemas/stem_parent" remix_of: - $ref: '#/components/schemas/remix_parent_write' + $ref: "#/components/schemas/remix_parent_write" ddex_app: type: string description: DDEX application identifier @@ -9900,7 +10060,7 @@ components: type: string description: Track title genre: - $ref: '#/components/schemas/genre' + $ref: "#/components/schemas/genre" description: type: string nullable: true @@ -9909,7 +10069,7 @@ components: mood: nullable: true allOf: - - $ref: '#/components/schemas/mood' + - $ref: "#/components/schemas/mood" bpm: type: number nullable: true @@ -9975,20 +10135,20 @@ components: stream_conditions: nullable: true allOf: - - $ref: '#/components/schemas/access_gate' + - $ref: "#/components/schemas/access_gate" download_conditions: nullable: true allOf: - - $ref: '#/components/schemas/access_gate' + - $ref: "#/components/schemas/access_gate" field_visibility: - $ref: '#/components/schemas/field_visibility' + $ref: "#/components/schemas/field_visibility" placement_hosts: type: string description: Placement hosts for the track stem_of: - $ref: '#/components/schemas/stem_parent' + $ref: "#/components/schemas/stem_parent" remix_of: - $ref: '#/components/schemas/remix_parent_write' + $ref: "#/components/schemas/remix_parent_write" ddex_app: type: string nullable: true @@ -10021,9 +10181,9 @@ components: type: boolean description: Whether this is an album genre: - $ref: '#/components/schemas/genre' + $ref: "#/components/schemas/genre" mood: - $ref: '#/components/schemas/mood' + $ref: "#/components/schemas/mood" tags: type: string description: Comma-separated tags @@ -10044,7 +10204,7 @@ components: type: array description: Array of tracks in the playlist items: - $ref: '#/components/schemas/playlist_added_timestamp' + $ref: "#/components/schemas/playlist_added_timestamp" ddex_app: type: string description: DDEX application identifier @@ -10069,9 +10229,9 @@ components: type: boolean description: Whether the playlist is private genre: - $ref: '#/components/schemas/genre' + $ref: "#/components/schemas/genre" mood: - $ref: '#/components/schemas/mood' + $ref: "#/components/schemas/mood" tags: type: string description: Comma-separated tags @@ -10086,7 +10246,7 @@ components: type: array description: Array of track IDs to include in the playlist items: - $ref: '#/components/schemas/playlist_added_timestamp' + $ref: "#/components/schemas/playlist_added_timestamp" cover_art_cid: type: string description: IPFS CID for cover art @@ -10172,9 +10332,9 @@ components: description: Array of folders and playlist identifiers items: oneOf: - - $ref: '#/components/schemas/playlist_library_folder' - - $ref: '#/components/schemas/playlist_library_playlist_identifier' - - $ref: '#/components/schemas/playlist_library_explore_playlist_identifier' + - $ref: "#/components/schemas/playlist_library_folder" + - $ref: "#/components/schemas/playlist_library_playlist_identifier" + - $ref: "#/components/schemas/playlist_library_explore_playlist_identifier" events: type: object description: User events for tracking referrals and mobile users @@ -10258,9 +10418,9 @@ components: description: Array of folders and playlist identifiers items: oneOf: - - $ref: '#/components/schemas/playlist_library_folder' - - $ref: '#/components/schemas/playlist_library_playlist_identifier' - - $ref: '#/components/schemas/playlist_library_explore_playlist_identifier' + - $ref: "#/components/schemas/playlist_library_folder" + - $ref: "#/components/schemas/playlist_library_playlist_identifier" + - $ref: "#/components/schemas/playlist_library_explore_playlist_identifier" events: type: object description: User events for tracking referrals and mobile users @@ -10281,7 +10441,7 @@ components: properties: entityType: allOf: - - $ref: '#/components/schemas/comment_entity_type' + - $ref: "#/components/schemas/comment_entity_type" example: "Track" entityId: type: integer @@ -10308,7 +10468,7 @@ components: properties: entityType: allOf: - - $ref: '#/components/schemas/comment_entity_type' + - $ref: "#/components/schemas/comment_entity_type" example: "Track" entityId: type: integer @@ -10347,7 +10507,7 @@ components: properties: entityType: allOf: - - $ref: '#/components/schemas/comment_entity_type' + - $ref: "#/components/schemas/comment_entity_type" example: "Track" entityId: type: integer @@ -10362,49 +10522,71 @@ components: properties: entityType: allOf: - - $ref: '#/components/schemas/comment_entity_type' + - $ref: "#/components/schemas/comment_entity_type" example: "Track" entityId: type: integer description: ID of the entity (track or playlist) the comment is on minimum: 1 example: 12345 + create_grant_request_body: + type: object + required: + - app_api_key + properties: + app_api_key: + type: string + description: The developer app address (API key) to grant authorization to + add_manager_request_body: + type: object + required: + - manager_user_id + properties: + manager_user_id: + type: string + description: The user ID of the user to add as manager + approve_grant_request_body: + type: object + required: + - grantor_user_id + properties: + grantor_user_id: + type: string + description: The user ID of the child user who proposed the manager (grantor) create_developer_app_request_body: type: object required: - name - - description - - imageUrl - - appSignature properties: name: type: string description: Developer app name - example: "My Music App" + example: "My API Key" description: type: string description: App description imageUrl: type: string - description: App logo/image URL (camelCase) - appSignature: - type: object - required: - - message - - signature - properties: - message: - type: string - description: Signed message - signature: - type: string - description: Signature + description: App logo/image URL + create_developer_app_response: + type: object + properties: + api_key: + type: string + description: The API key (address) for the developer app + api_secret: + type: string + description: The private key for the developer app (for signing) + bearer_token: + type: string + description: The bearer token for API authentication (use in Authorization header) + transaction_hash: + type: string + description: Transaction hash of the creation update_developer_app_request_body: type: object required: - name - - description - - imageUrl properties: name: type: string @@ -10458,7 +10640,7 @@ components: data: type: array items: - $ref: '#/components/schemas/developer_app' + $ref: "#/components/schemas/developer_app" create_user_developer_app_response: type: object properties: @@ -10467,7 +10649,10 @@ components: description: The API key (address) for the developer app api_secret: type: string - description: The API secret (access key) for the developer app + description: The private key for the developer app (for signing) + bearer_token: + type: string + description: The bearer token for API authentication (use in Authorization header) transaction_hash: type: string description: Transaction hash of the creation @@ -10500,9 +10685,9 @@ components: description: Nested folders and playlist identifiers items: oneOf: - - $ref: '#/components/schemas/playlist_library_folder' - - $ref: '#/components/schemas/playlist_library_playlist_identifier' - - $ref: '#/components/schemas/playlist_library_explore_playlist_identifier' + - $ref: "#/components/schemas/playlist_library_folder" + - $ref: "#/components/schemas/playlist_library_playlist_identifier" + - $ref: "#/components/schemas/playlist_library_explore_playlist_identifier" playlist_library_playlist_identifier: type: object description: Reference to a playlist @@ -10644,29 +10829,29 @@ components: scheme: basic description: | HTTP Basic Authentication with Ethereum private key for write operations. - + **Authentication** - + Use HTTP Basic Authentication where the password field contains your Ethereum private key: ``` Authorization: Basic ``` - + The username can be any value. The password must be your Ethereum private key in hex format (with or without 0x prefix). - + Example: ``` Authorization: Basic dXNlcm5hbWU6MHgxMjM0NTY3ODkwYWJjZGVmLi4u ``` - + **How it works:** 1. The API decodes the Basic Auth credentials 2. Extracts the private key from the password field 3. Derives the Ethereum address from the private key 4. Uses this address for authorization checks - + **Authorization** - + The derived wallet address must be either: - The wallet of the user being acted upon (direct ownership) - A wallet with an approved, non-revoked grant for the user (manager mode) diff --git a/api/v1_developer_apps.go b/api/v1_developer_apps.go index 60703026..1df54b6e 100644 --- a/api/v1_developer_apps.go +++ b/api/v1_developer_apps.go @@ -1,35 +1,12 @@ package api import ( - "encoding/json" - "strconv" "strings" - "time" "api.audius.co/api/dbv1" - "api.audius.co/indexer" - corev1 "github.com/OpenAudio/go-openaudio/pkg/api/core/v1" - "github.com/ethereum/go-ethereum/common" "github.com/gofiber/fiber/v2" - "go.uber.org/zap" ) -type CreateDeveloperAppRequest struct { - Name string `json:"name"` - Description string `json:"description"` - ImageUrl string `json:"imageUrl"` - AppSignature struct { - Message string `json:"message"` - Signature string `json:"signature"` - } `json:"appSignature"` -} - -type UpdateDeveloperAppRequest struct { - Name string `json:"name"` - Description string `json:"description"` - ImageUrl string `json:"imageUrl"` -} - func (app *ApiServer) v1DeveloperApps(c *fiber.Ctx) error { address := c.Params("address") if address == "" { @@ -55,147 +32,4 @@ func (app *ApiServer) v1DeveloperApps(c *fiber.Ctx) error { return c.JSON(fiber.Map{ "data": developerApps[0], }) - -} - -func (app *ApiServer) postV1DeveloperApp(c *fiber.Ctx) error { - userID := app.getMyId(c) - - var req CreateDeveloperAppRequest - if err := c.BodyParser(&req); err != nil { - return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ - "error": "Invalid request body", - }) - } - - signer, err := app.getApiSigner(c) - if err != nil { - return err - } - - nonce := time.Now().UnixNano() - - metadataObj := map[string]interface{}{ - "name": req.Name, - "description": req.Description, - "image_url": req.ImageUrl, - "app_signature": map[string]interface{}{ - "message": req.AppSignature.Message, - "signature": req.AppSignature.Signature, - }, - } - metadataBytes, _ := json.Marshal(metadataObj) - - manageEntityTx := &corev1.ManageEntityLegacy{ - Signer: common.HexToAddress(signer.Address).String(), - UserId: int64(userID), - EntityId: 0, // Contract requires uint, but we don't actually need this field for this action - Action: indexer.Action_Create, - EntityType: indexer.Entity_DeveloperApp, - Nonce: strconv.FormatInt(nonce, 10), - Metadata: string(metadataBytes), - } - - response, err := app.sendTransactionWithSigner(manageEntityTx, signer.PrivateKey) - if err != nil { - app.logger.Error("Failed to send developer app create transaction", zap.Error(err)) - return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ - "error": "Failed to create developer app", - }) - } - - return c.JSON(fiber.Map{ - "success": true, - "transaction_hash": response.Msg.GetTransaction().GetHash(), - }) -} - -func (app *ApiServer) putV1DeveloperApp(c *fiber.Ctx) error { - userID := app.getMyId(c) - address := c.Params("address") - - var req UpdateDeveloperAppRequest - if err := c.BodyParser(&req); err != nil { - return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ - "error": "Invalid request body", - }) - } - - signer, err := app.getApiSigner(c) - if err != nil { - return err - } - - nonce := time.Now().UnixNano() - - metadataObj := map[string]interface{}{ - "address": address, - "name": req.Name, - "description": req.Description, - "image_url": req.ImageUrl, - } - metadataBytes, _ := json.Marshal(metadataObj) - - manageEntityTx := &corev1.ManageEntityLegacy{ - Signer: common.HexToAddress(signer.Address).String(), - UserId: int64(userID), - EntityId: 0, // Contract requires uint, but we don't actually need this field for this action - Action: indexer.Action_Update, - EntityType: indexer.Entity_DeveloperApp, - Nonce: strconv.FormatInt(nonce, 10), - Metadata: string(metadataBytes), - } - - response, err := app.sendTransactionWithSigner(manageEntityTx, signer.PrivateKey) - if err != nil { - app.logger.Error("Failed to send developer app update transaction", zap.Error(err)) - return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ - "error": "Failed to update developer app", - }) - } - - return c.JSON(fiber.Map{ - "success": true, - "transaction_hash": response.Msg.GetTransaction().GetHash(), - }) -} - -func (app *ApiServer) deleteV1DeveloperApp(c *fiber.Ctx) error { - userID := app.getMyId(c) - address := c.Params("address") - - signer, err := app.getApiSigner(c) - if err != nil { - return err - } - - nonce := time.Now().UnixNano() - - metadataObj := map[string]interface{}{ - "address": address, - } - metadataBytes, _ := json.Marshal(metadataObj) - - manageEntityTx := &corev1.ManageEntityLegacy{ - Signer: common.HexToAddress(signer.Address).String(), - UserId: int64(userID), - EntityId: 0, // Contract requires uint, but we don't actually need this field for this action - Action: indexer.Action_Delete, - EntityType: indexer.Entity_DeveloperApp, - Nonce: strconv.FormatInt(nonce, 10), - Metadata: string(metadataBytes), - } - - response, err := app.sendTransactionWithSigner(manageEntityTx, signer.PrivateKey) - if err != nil { - app.logger.Error("Failed to send developer app delete transaction", zap.Error(err)) - return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ - "error": "Failed to delete developer app", - }) - } - - return c.JSON(fiber.Map{ - "success": true, - "transaction_hash": response.Msg.GetTransaction().GetHash(), - }) } diff --git a/api/v1_grants.go b/api/v1_grants.go new file mode 100644 index 00000000..99f46b4f --- /dev/null +++ b/api/v1_grants.go @@ -0,0 +1,353 @@ +package api + +import ( + "encoding/json" + "strconv" + "strings" + "time" + + "api.audius.co/api/dbv1" + "api.audius.co/indexer" + "api.audius.co/trashid" + corev1 "github.com/OpenAudio/go-openaudio/pkg/api/core/v1" + "github.com/ethereum/go-ethereum/common" + "github.com/gofiber/fiber/v2" + "go.uber.org/zap" +) + +type createGrantBody struct { + AppApiKey string `json:"app_api_key"` +} + +type addManagerBody struct { + ManagerUserId string `json:"manager_user_id"` +} + +type approveGrantBody struct { + GrantorUserId string `json:"grantor_user_id"` +} + +// postV1UsersGrant creates a grant from the user to an app (user authorizes app to act on their behalf) +func (app *ApiServer) postV1UsersGrant(c *fiber.Ctx) error { + userID := app.getMyId(c) + pathUserID, err := trashid.DecodeHashId(c.Params("userId")) + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, "Invalid user ID") + } + if int32(pathUserID) != userID { + return fiber.NewError(fiber.StatusForbidden, "User ID does not match authenticated user") + } + + var body createGrantBody + if err := c.BodyParser(&body); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "Invalid request body", + }) + } + appApiKey := strings.TrimSpace(body.AppApiKey) + if appApiKey == "" { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "app_api_key is required", + }) + } + if !strings.HasPrefix(strings.ToLower(appApiKey), "0x") { + appApiKey = "0x" + appApiKey + } + appApiKey = strings.ToLower(appApiKey) + + signer, err := app.getApiSigner(c) + if err != nil { + return err + } + + nonce := time.Now().UnixNano() + metadata := map[string]string{"grantee_address": appApiKey} + metadataBytes, _ := json.Marshal(metadata) + + manageEntityTx := &corev1.ManageEntityLegacy{ + Signer: common.HexToAddress(signer.Address).String(), + UserId: int64(userID), + EntityId: 0, + Action: indexer.Action_Create, + EntityType: indexer.Entity_Grant, + Nonce: strconv.FormatInt(nonce, 10), + Metadata: string(metadataBytes), + } + + response, err := app.sendTransactionWithSigner(manageEntityTx, signer.PrivateKey) + if err != nil { + app.logger.Error("Failed to send create grant transaction", zap.Error(err)) + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "error": "Failed to create grant", + }) + } + + return c.JSON(fiber.Map{ + "success": true, + "transaction_hash": response.Msg.GetTransaction().GetHash(), + }) +} + +// deleteV1UsersGrant revokes a grant from the user to an app +func (app *ApiServer) deleteV1UsersGrant(c *fiber.Ctx) error { + userID := app.getMyId(c) + pathUserID, err := trashid.DecodeHashId(c.Params("userId")) + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, "Invalid user ID") + } + if int32(pathUserID) != userID { + return fiber.NewError(fiber.StatusForbidden, "User ID does not match authenticated user") + } + + appApiKey := c.Params("address") + if appApiKey == "" { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "address (app API key) is required", + }) + } + if !strings.HasPrefix(strings.ToLower(appApiKey), "0x") { + appApiKey = "0x" + appApiKey + } + appApiKey = strings.ToLower(appApiKey) + + signer, err := app.getApiSigner(c) + if err != nil { + return err + } + + nonce := time.Now().UnixNano() + metadata := map[string]string{"grantee_address": appApiKey} + metadataBytes, _ := json.Marshal(metadata) + + manageEntityTx := &corev1.ManageEntityLegacy{ + Signer: common.HexToAddress(signer.Address).String(), + UserId: int64(userID), + EntityId: 0, + Action: indexer.Action_Delete, + EntityType: indexer.Entity_Grant, + Nonce: strconv.FormatInt(nonce, 10), + Metadata: string(metadataBytes), + } + + response, err := app.sendTransactionWithSigner(manageEntityTx, signer.PrivateKey) + if err != nil { + app.logger.Error("Failed to send revoke grant transaction", zap.Error(err)) + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "error": "Failed to revoke grant", + }) + } + + return c.JSON(fiber.Map{ + "success": true, + "transaction_hash": response.Msg.GetTransaction().GetHash(), + }) +} + +// postV1UsersManager adds a manager (user-to-user grant). The child user adds another user as manager. +func (app *ApiServer) postV1UsersManager(c *fiber.Ctx) error { + userID := app.getMyId(c) + pathUserID, err := trashid.DecodeHashId(c.Params("userId")) + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, "Invalid user ID") + } + if int32(pathUserID) != userID { + return fiber.NewError(fiber.StatusForbidden, "User ID does not match authenticated user") + } + + var body addManagerBody + if err := c.BodyParser(&body); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "Invalid request body", + }) + } + managerUserID, err := trashid.DecodeHashId(body.ManagerUserId) + if err != nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "Invalid manager_user_id", + }) + } + + // Get manager's wallet (grantee_address) + users, err := app.queries.Users(c.Context(), dbv1.GetUsersParams{ + MyID: 0, + Ids: []int32{int32(managerUserID)}, + }) + if err != nil || len(users) == 0 { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "manager_user_id is invalid", + }) + } + managerWallet := users[0].Wallet + if !managerWallet.Valid || managerWallet.String == "" { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "Manager user has no wallet", + }) + } + granteeAddress := strings.ToLower(managerWallet.String) + if !strings.HasPrefix(granteeAddress, "0x") { + granteeAddress = "0x" + granteeAddress + } + + signer, err := app.getApiSigner(c) + if err != nil { + return err + } + + nonce := time.Now().UnixNano() + metadata := map[string]string{"grantee_address": granteeAddress} + metadataBytes, _ := json.Marshal(metadata) + + manageEntityTx := &corev1.ManageEntityLegacy{ + Signer: common.HexToAddress(signer.Address).String(), + UserId: int64(userID), + EntityId: 0, + Action: indexer.Action_Create, + EntityType: indexer.Entity_Grant, + Nonce: strconv.FormatInt(nonce, 10), + Metadata: string(metadataBytes), + } + + response, err := app.sendTransactionWithSigner(manageEntityTx, signer.PrivateKey) + if err != nil { + app.logger.Error("Failed to send add manager transaction", zap.Error(err)) + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "error": "Failed to add manager", + }) + } + + return c.JSON(fiber.Map{ + "success": true, + "transaction_hash": response.Msg.GetTransaction().GetHash(), + }) +} + +// deleteV1UsersManager removes a manager. Can be called by the child user or the manager. +func (app *ApiServer) deleteV1UsersManager(c *fiber.Ctx) error { + userID := app.getMyId(c) + pathUserID, err := trashid.DecodeHashId(c.Params("userId")) + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, "Invalid user ID") + } + managerUserID, err := trashid.DecodeHashId(c.Params("managerUserId")) + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, "Invalid manager user ID") + } + + // Either the child user (userId) or the manager (managerUserId) can remove + if int32(pathUserID) != userID && int32(managerUserID) != userID { + return fiber.NewError(fiber.StatusForbidden, "Only the user or manager can remove this grant") + } + + // Get manager's wallet + users, err := app.queries.Users(c.Context(), dbv1.GetUsersParams{ + MyID: 0, + Ids: []int32{int32(managerUserID)}, + }) + if err != nil || len(users) == 0 { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "manager_user_id is invalid", + }) + } + managerWallet := users[0].Wallet + if !managerWallet.Valid || managerWallet.String == "" { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "Manager user has no wallet", + }) + } + granteeAddress := strings.ToLower(managerWallet.String) + if !strings.HasPrefix(granteeAddress, "0x") { + granteeAddress = "0x" + granteeAddress + } + + // The grantor is the child user (path userId) + grantorUserID := int32(pathUserID) + + signer, err := app.getApiSigner(c) + if err != nil { + return err + } + + nonce := time.Now().UnixNano() + metadata := map[string]string{"grantee_address": granteeAddress} + metadataBytes, _ := json.Marshal(metadata) + + manageEntityTx := &corev1.ManageEntityLegacy{ + Signer: common.HexToAddress(signer.Address).String(), + UserId: int64(grantorUserID), + EntityId: 0, + Action: indexer.Action_Delete, + EntityType: indexer.Entity_Grant, + Nonce: strconv.FormatInt(nonce, 10), + Metadata: string(metadataBytes), + } + + response, err := app.sendTransactionWithSigner(manageEntityTx, signer.PrivateKey) + if err != nil { + app.logger.Error("Failed to send remove manager transaction", zap.Error(err)) + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "error": "Failed to remove manager", + }) + } + + return c.JSON(fiber.Map{ + "success": true, + "transaction_hash": response.Msg.GetTransaction().GetHash(), + }) +} + +// postV1UsersApproveGrant approves a manager request. The manager (grantee) approves being added by the child (grantor). +func (app *ApiServer) postV1UsersApproveGrant(c *fiber.Ctx) error { + userID := app.getMyId(c) + pathUserID, err := trashid.DecodeHashId(c.Params("userId")) + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, "Invalid user ID") + } + if int32(pathUserID) != userID { + return fiber.NewError(fiber.StatusForbidden, "User ID does not match authenticated user") + } + + var body approveGrantBody + if err := c.BodyParser(&body); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "Invalid request body", + }) + } + grantorUserID, err := trashid.DecodeHashId(body.GrantorUserId) + if err != nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "Invalid grantor_user_id", + }) + } + + signer, err := app.getApiSigner(c) + if err != nil { + return err + } + + nonce := time.Now().UnixNano() + metadata := map[string]interface{}{"grantor_user_id": int64(grantorUserID)} + metadataBytes, _ := json.Marshal(metadata) + + manageEntityTx := &corev1.ManageEntityLegacy{ + Signer: common.HexToAddress(signer.Address).String(), + UserId: int64(userID), + EntityId: 0, + Action: indexer.Action_Approve, + EntityType: indexer.Entity_Grant, + Nonce: strconv.FormatInt(nonce, 10), + Metadata: string(metadataBytes), + } + + response, err := app.sendTransactionWithSigner(manageEntityTx, signer.PrivateKey) + if err != nil { + app.logger.Error("Failed to send approve grant transaction", zap.Error(err)) + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "error": "Failed to approve grant", + }) + } + + return c.JSON(fiber.Map{ + "success": true, + "transaction_hash": response.Msg.GetTransaction().GetHash(), + }) +} diff --git a/api/v1_users_developer_apps.go b/api/v1_users_developer_apps.go index d68c5b86..536f2d8b 100644 --- a/api/v1_users_developer_apps.go +++ b/api/v1_users_developer_apps.go @@ -42,27 +42,12 @@ type DeveloperAppWithMetrics struct { APIAccessKeys json.RawMessage `json:"api_access_keys" db:"api_access_keys"` } -// registerDeveloperAppRoutes adds developer app routes to the given router. -// The secret and appName identify the frontend app that must have OAuth write grant from the user -// to access the mutating endpoints (create, delete, manage access keys). -func (app *ApiServer) registerDeveloperAppRoutes(g fiber.Router, secret string, appName string) { - auth := app.requireFrontendAppAuth(secret, appName) - - g.Get("/users/:userId/developer_apps", app.v1UsersDeveloperApps) - g.Get("/users/:userId/developer-apps", app.v1UsersDeveloperApps) - g.Post("/users/:userId/developer_apps", auth, app.postV1UsersDeveloperAppCreate) - g.Post("/users/:userId/developer-apps", auth, app.postV1UsersDeveloperAppCreate) - g.Delete("/users/:userId/developer-apps/:address", auth, app.deleteV1UsersDeveloperApp) - g.Post("/users/:userId/developer-apps/:address/access-keys/deactivate", auth, app.postV1UsersDeveloperAppAccessKeyDeactivate) - g.Post("/users/:userId/developer-apps/:address/access-keys", auth, app.postV1UsersDeveloperAppAccessKeyCreate) -} - func (app *ApiServer) v1UsersDeveloperApps(c *fiber.Ctx) error { - userId := app.getUserId(c) + userID := app.getUserId(c) includeMetrics := c.Query("include") == "metrics" if includeMetrics { - return app.v1UsersDeveloperAppsWithMetrics(c, userId) + return app.v1UsersDeveloperAppsWithMetrics(c, userID) } sql := ` @@ -74,7 +59,7 @@ func (app *ApiServer) v1UsersDeveloperApps(c *fiber.Ctx) error { ` rows, err := app.pool.Query(c.Context(), sql, pgx.NamedArgs{ - "userId": userId, + "userId": userID, }) if err != nil { return err @@ -222,12 +207,57 @@ func (app *ApiServer) validateOAuthJWTTokenToUserId(ctx context.Context, token s return trashid.HashId(jwtUserId), nil } +// validateOAuthJWTTokenToWalletAndUserId validates the OAuth JWT and returns (wallet, userId). +// Used by auth middleware when Bearer token is not an api_access_key. +func (app *ApiServer) validateOAuthJWTTokenToWalletAndUserId(ctx context.Context, token string) (wallet string, userId int32, err error) { + id, err := app.validateOAuthJWTTokenToUserId(ctx, token) + if err != nil { + return "", 0, err + } + tokenParts := strings.Split(token, ".") + if len(tokenParts) != 3 { + return "", 0, fiber.NewError(fiber.StatusBadRequest, "Invalid JWT token format") + } + base64Payload, base64Signature := tokenParts[1], tokenParts[2] + paddedSignature := base64Signature + if len(paddedSignature)%4 != 0 { + paddedSignature += strings.Repeat("=", 4-len(paddedSignature)%4) + } + signatureDecoded, err := base64.URLEncoding.DecodeString(paddedSignature) + if err != nil { + return "", 0, fiber.NewError(fiber.StatusBadRequest, "The JWT signature could not be decoded") + } + signatureBytes := common.FromHex(string(signatureDecoded)) + if len(signatureBytes) != 65 { + return "", 0, fiber.NewError(fiber.StatusBadRequest, "The JWT signature was incorrectly signed") + } + if signatureBytes[64] >= 27 { + signatureBytes[64] -= 27 + } + message := fmt.Sprintf("%s.%s", tokenParts[0], base64Payload) + prefixedMessage := []byte(fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", len(message), message)) + finalHash := crypto.Keccak256Hash(prefixedMessage) + publicKey, err := crypto.SigToPub(finalHash.Bytes(), signatureBytes) + if err != nil { + return "", 0, fiber.NewError(fiber.StatusUnauthorized, "The JWT signature is invalid") + } + recoveredAddr := crypto.PubkeyToAddress(*publicKey) + return strings.ToLower(recoveredAddr.Hex()), int32(id), nil +} + type createDeveloperAppBody struct { - Name string `json:"name"` + Name string `json:"name"` + Description *string `json:"description"` + ImageUrl *string `json:"image_url"` } -func (app *ApiServer) postV1UsersDeveloperAppCreate(c *fiber.Ctx) error { - userID := app.getUserId(c) +func (app *ApiServer) postV1UsersDeveloperApp(c *fiber.Ctx) error { + userID := app.getMyId(c) + if userID == 0 { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "user_id query parameter is required", + }) + } var body createDeveloperAppBody if err := c.BodyParser(&body); err != nil { @@ -290,8 +320,8 @@ func (app *ApiServer) postV1UsersDeveloperAppCreate(c *fiber.Ctx) error { metadataObj := map[string]interface{}{ "address": strings.ToLower(address), "name": name, - "description": "", - "image_url": "", + "description": body.Description, + "image_url": body.ImageUrl, "app_signature": map[string]interface{}{ "message": message, "signature": signatureHex, @@ -360,13 +390,19 @@ func (app *ApiServer) postV1UsersDeveloperAppCreate(c *fiber.Ctx) error { return c.JSON(fiber.Map{ "api_key": address, - "api_secret": apiAccessKey, + "api_secret": apiSecretHex, + "bearer_token": apiAccessKey, "transaction_hash": response.Msg.GetTransaction().GetHash(), }) } func (app *ApiServer) deleteV1UsersDeveloperApp(c *fiber.Ctx) error { - userID := app.getUserId(c) + userID := app.getMyId(c) + if userID == 0 { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "user_id query parameter is required", + }) + } address := c.Params("address") if address == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ @@ -464,7 +500,12 @@ type deactivateAccessKeyBody struct { } func (app *ApiServer) postV1UsersDeveloperAppAccessKeyDeactivate(c *fiber.Ctx) error { - userID := app.getUserId(c) + userID := app.getMyId(c) + if userID == 0 { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "user_id query parameter is required", + }) + } address := c.Params("address") if address == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ @@ -528,8 +569,13 @@ func (app *ApiServer) postV1UsersDeveloperAppAccessKeyDeactivate(c *fiber.Ctx) e return c.JSON(fiber.Map{"success": true}) } -func (app *ApiServer) postV1UsersDeveloperAppAccessKeyCreate(c *fiber.Ctx) error { - userID := app.getUserId(c) +func (app *ApiServer) postV1UsersDeveloperAppAccessKey(c *fiber.Ctx) error { + userID := app.getMyId(c) + if userID == 0 { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "user_id query parameter is required", + }) + } address := c.Params("address") if address == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ diff --git a/static/plans/src/App.tsx b/static/plans/src/App.tsx index b9e0c281..b2546084 100644 --- a/static/plans/src/App.tsx +++ b/static/plans/src/App.tsx @@ -800,7 +800,14 @@ export default function App() { if (!oauthUser?.userId) return; try { const appsRes = await fetch( - `${API_BASE}/v1/users/${encodeURIComponent(oauthUser.userId)}/developer-apps?include=metrics`, + `${API_BASE}/v1/users/${oauthUser.userId}/developer-apps?include=metrics`, + { + headers: { + ...(sessionStorage.getItem(OAUTH_TOKEN_KEY) + ? { Authorization: `Bearer ${sessionStorage.getItem(OAUTH_TOKEN_KEY)}` } + : {}), + }, + }, ); if (appsRes.ok) { const { data } = (await appsRes.json()) as { data: DeveloperApp[] }; @@ -828,17 +835,14 @@ export default function App() { async (name: string) => { if (!oauthUser?.userId) throw new Error("Not logged in"); const token = sessionStorage.getItem(OAUTH_TOKEN_KEY); - const res = await fetch( - `${API_BASE}/v1/users/${encodeURIComponent(oauthUser.userId)}/developer-apps`, - { - method: "POST", - headers: { - "Content-Type": "application/json", - ...(token ? { Authorization: `Bearer ${token}` } : {}), - }, - body: JSON.stringify({ name }), + const res = await fetch(`${API_BASE}/v1/developer-apps?user_id=${oauthUser.userId}`, { + method: "POST", + headers: { + "Content-Type": "application/json", + ...(token ? { Authorization: `Bearer ${token}` } : {}), }, - ); + body: JSON.stringify({ name }), + }); if (!res.ok) { const err = await res.json().catch(() => ({})); throw new Error( @@ -848,10 +852,12 @@ export default function App() { const result = (await res.json()) as { api_key?: string; api_secret?: string; + bearer_token?: string; + transaction_hash?: string; }; - if (result.api_key != null && result.api_secret != null) { + if (result.api_key != null && result.bearer_token != null) { navigator.clipboard.writeText( - `API Key: ${result.api_key}\nAPI Bearer Token: ${result.api_secret}`, + `API Key: ${result.api_key}\nBearer Token: ${result.bearer_token}`, ); } // Optimistically add new app and reload; merge ensures it stays visible if indexer hasn't processed yet @@ -865,8 +871,8 @@ export default function App() { request_count_all_time: 0, is_legacy: false, api_access_keys: - result.api_secret != null - ? [{ api_access_key: result.api_secret, is_active: true }] + result.bearer_token != null + ? [{ api_access_key: result.bearer_token, is_active: true }] : [], }; await loadDeveloperApps(optimisticApp); @@ -881,7 +887,7 @@ export default function App() { if (oauthUser?.userId == null) throw new Error("Not logged in"); const token = sessionStorage.getItem(OAUTH_TOKEN_KEY); const res = await fetch( - `${API_BASE}/v1/users/${encodeURIComponent(oauthUser.userId)}/developer-apps/${encodeURIComponent(app.address)}/access-keys/deactivate`, + `${API_BASE}/v1/developer-apps/${encodeURIComponent(app.address)}/access-keys/deactivate?user_id=${oauthUser.userId}`, { method: "POST", headers: { @@ -916,7 +922,7 @@ export default function App() { if (oauthUser?.userId == null) throw new Error("Not logged in"); const token = sessionStorage.getItem(OAUTH_TOKEN_KEY); const res = await fetch( - `${API_BASE}/v1/users/${encodeURIComponent(oauthUser.userId)}/developer-apps/${encodeURIComponent(app.address)}/access-keys`, + `${API_BASE}/v1/developer-apps/${encodeURIComponent(app.address)}/access-keys?user_id=${oauthUser.userId}`, { method: "POST", headers: { @@ -956,7 +962,7 @@ export default function App() { if (oauthUser?.userId == null) throw new Error("Not logged in"); const token = sessionStorage.getItem(OAUTH_TOKEN_KEY); const res = await fetch( - `${API_BASE}/v1/users/${encodeURIComponent(oauthUser.userId)}/developer-apps/${encodeURIComponent(app.address)}`, + `${API_BASE}/v1/developer-apps/${encodeURIComponent(app.address)}?user_id=${oauthUser.userId}`, { method: "DELETE", headers: { @@ -986,11 +992,14 @@ export default function App() { const load = async () => { try { + const token = sessionStorage.getItem(OAUTH_TOKEN_KEY); const [userRes, appsRes] = await Promise.all([ fetch(`${API_BASE}/v1/users/${encodeURIComponent(oauthUser.userId)}`), - fetch( - `${API_BASE}/v1/users/${encodeURIComponent(oauthUser.userId)}/developer-apps?include=metrics`, - ), + fetch(`${API_BASE}/v1/users/${oauthUser.userId}/developer-apps?include=metrics`, { + headers: token + ? { Authorization: `Bearer ${token}` } + : undefined, + }), ]); const userData = userRes.ok ? (