{ "openapi": "3.0.0", "info": { "title": "Melody Auth S2S API", "version": "0.0.1" }, "components": { "securitySchemes": { "oauth2": { "type": "oauth2", "flows": { "clientCredentials": { "tokenUrl": "/oauth2/v1/token", "scopes": { "read_app": "Read access to app", "write_app": "Write access to app", "read_user": "Read access to user", "write_user": "Write access to user", "read_role": "Read access to role", "write_role": "Write access to role", "read_scope": "Read access to scope", "write_scope": "Write access to scope" } } } } }, "schemas": { "Scope": { "type": "object", "properties": { "id": { "type": "number" }, "name": { "type": "string" }, "note": { "type": "string" }, "type": { "type": "string", "enum": [ "spa", "s2s" ] }, "createdAt": { "type": "string" }, "updatedAt": { "type": "string" }, "deletedAt": { "type": "string", "nullable": true } } }, "ScopeDetail": { "allOf": [ { "$ref": "#/components/schemas/Scope" }, { "type": "object", "properties": { "locales": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "number" }, "scopeId": { "type": "number" }, "locale": { "type": "string" }, "value": { "type": "string" }, "createdAt": { "type": "string" }, "updatedAt": { "type": "string" }, "deletedAt": { "type": "string", "nullable": true } } } } } } ] }, "PutScopeReq": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 50 }, "note": { "type": "string" }, "locales": { "type": "array", "items": { "type": "object", "properties": { "locale": { "type": "string" }, "value": { "type": "string" } }, "required": [ "locale", "value" ] } } } }, "PostScopeReq": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 50 }, "type": { "type": "string", "enum": [ "spa", "s2s" ] }, "note": { "type": "string" }, "locales": { "type": "array", "items": { "type": "object", "properties": { "locale": { "type": "string" }, "value": { "type": "string" } }, "required": [ "locale", "value" ] } } }, "required": [ "name", "type" ] }, "Role": { "type": "object", "properties": { "id": { "type": "number" }, "name": { "type": "string" }, "note": { "type": "string" }, "createdAt": { "type": "string" }, "updatedAt": { "type": "string" }, "deletedAt": { "type": "string", "nullable": true } } }, "PutRoleReq": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 50 }, "note": { "type": "string" } } }, "PostRoleReq": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 50 }, "note": { "type": "string" } }, "required": [ "name" ] }, "App": { "type": "object", "properties": { "id": { "type": "number" }, "clientId": { "type": "string" }, "name": { "type": "string" }, "isActive": { "type": "boolean" }, "type": { "type": "string", "enum": [ "spa", "s2s" ] }, "secret": { "type": "string" }, "redirectUris": { "type": "array", "items": { "type": "string" } }, "createdAt": { "type": "string" }, "updatedAt": { "type": "string" }, "deletedAt": { "type": "string", "nullable": true } } }, "AppDetail": { "allOf": [ { "$ref": "#/components/schemas/App" }, { "type": "object", "properties": { "scopes": { "type": "array", "items": { "type": "string" } } } } ] }, "PostAppReq": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 50 }, "type": { "type": "string", "enum": [ "spa", "s2s" ] }, "scopes": { "type": "array", "items": { "type": "string" } }, "redirectUris": { "type": "array", "items": { "type": "string" } } }, "required": [ "name", "type", "scopes", "redirectUris" ] }, "PutAppReq": { "type": "object", "properties": { "redirectUris": { "type": "array", "items": { "type": "string" } }, "name": { "type": "string", "minLength": 1, "maxLength": 50 }, "isActive": { "type": "boolean" }, "scopes": { "type": "array", "items": { "type": "string" } } } }, "User": { "type": "object", "properties": { "id": { "type": "number" }, "authId": { "type": "string" }, "email": { "type": "string", "nullable": true }, "socialAccountId": { "type": "string", "nullable": true }, "socialAccountType": { "type": "string", "nullable": true }, "firstName": { "type": "string", "nullable": true }, "lastName": { "type": "string", "nullable": true }, "locale": { "type": "string" }, "emailVerified": { "type": "boolean" }, "otpVerified": { "type": "boolean" }, "smsPhoneNumberVerified": { "type": "boolean" }, "isActive": { "type": "boolean" }, "createdAt": { "type": "string" }, "updatedAt": { "type": "string" }, "deletedAt": { "type": "string", "nullable": true } } }, "UserDetail": { "allOf": [ { "$ref": "#/components/schemas/User" }, { "type": "object", "properties": { "roles": { "type": "array", "items": { "type": "string" }, "nullable": true } } } ] }, "UserConsentedApp": { "type": "object", "properties": { "appId": { "type": "number" }, "appName": { "type": "string" } } }, "PutUserReq": { "type": "object", "properties": { "firstName": { "type": "string" }, "lastName": { "type": "string" }, "isActive": { "type": "boolean" }, "locale": { "type": "string" }, "roles": { "type": "array", "items": { "type": "string" } } } } } }, "paths": { "/api/v1/scopes": { "get": { "summary": "Get a list of scopes", "description": "Required scope - read_scope", "tags": [ "Scopes" ], "responses": { "200": { "description": "A list of scopes", "content": { "application/json": { "schema": { "type": "object", "properties": { "scopes": { "type": "array", "items": { "$ref": "#/components/schemas/Scope" } } } } } } } } }, "post": { "summary": "Create a new scope", "description": "Required scope - write_scope", "tags": [ "Scopes" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PostScopeReq" } } } }, "responses": { "201": { "content": { "application/json": { "schema": { "type": "object", "properties": { "scope": { "$ref": "#/components/schemas/ScopeDetail" } } } } } } } } }, "/api/v1/scopes/{id}": { "get": { "summary": "Get a single scope by ID", "description": "Required scope - read_scope", "tags": [ "Scopes" ], "parameters": [ { "in": "path", "name": "id", "required": true, "schema": { "type": "number" }, "description": "The unique ID of the scope" } ], "responses": { "200": { "description": "A single scope object", "content": { "application/json": { "schema": { "type": "object", "properties": { "scope": { "$ref": "#/components/schemas/ScopeDetail" } } } } } } } }, "put": { "summary": "Update an existing scope by ID", "description": "Required scope - write_scope", "tags": [ "Scopes" ], "parameters": [ { "in": "path", "name": "id", "required": true, "schema": { "type": "number" }, "description": "The unique ID of the scope" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PutScopeReq" } } } }, "responses": { "200": { "content": { "application/json": { "schema": { "type": "object", "properties": { "scope": { "$ref": "#/components/schemas/ScopeDetail" } } } } } } } }, "delete": { "summary": "Delete an existing scope by ID", "description": "Required scope - write_scope", "tags": [ "Scopes" ], "parameters": [ { "in": "path", "name": "id", "required": true, "schema": { "type": "number" }, "description": "The unique ID of the scope" } ], "responses": { "204": { "description": "Successful operation with no content to return" } } } }, "/api/v1/roles": { "get": { "summary": "Get a list of roles", "description": "Required scope - read_role", "tags": [ "Roles" ], "responses": { "200": { "description": "A list of roles", "content": { "application/json": { "schema": { "type": "object", "properties": { "roles": { "type": "array", "items": { "$ref": "#/components/schemas/Role" } } } } } } } } }, "post": { "summary": "Create a new role", "description": "Required scope - write_role", "tags": [ "Roles" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PostRoleReq" } } } }, "responses": { "201": { "content": { "application/json": { "schema": { "type": "object", "properties": { "role": { "$ref": "#/components/schemas/Role" } } } } } } } } }, "/api/v1/roles/{id}": { "get": { "summary": "Get a single role by ID", "description": "Required scope - read_role", "tags": [ "Roles" ], "parameters": [ { "in": "path", "name": "id", "required": true, "schema": { "type": "number" }, "description": "The unique ID of the role" } ], "responses": { "200": { "description": "A single role object", "content": { "application/json": { "schema": { "type": "object", "properties": { "role": { "$ref": "#/components/schemas/Role" } } } } } } } }, "put": { "summary": "Update an existing role by ID", "description": "Required scope - write_role", "tags": [ "Roles" ], "parameters": [ { "in": "path", "name": "id", "required": true, "schema": { "type": "number" }, "description": "The unique ID of the role" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PutRoleReq" } } } }, "responses": { "200": { "content": { "application/json": { "schema": { "type": "object", "properties": { "role": { "$ref": "#/components/schemas/Role" } } } } } } } }, "delete": { "summary": "Delete an existing role by ID", "description": "Required scope - write_role", "tags": [ "Roles" ], "parameters": [ { "in": "path", "name": "id", "required": true, "schema": { "type": "number" }, "description": "The unique ID of the role" } ], "responses": { "204": { "description": "Successful operation with no content to return" } } } }, "/api/v1/apps": { "get": { "summary": "Get a list of apps", "description": "Required scope - read_app", "tags": [ "Apps" ], "responses": { "200": { "description": "A list of apps", "content": { "application/json": { "schema": { "type": "object", "properties": { "apps": { "type": "array", "items": { "$ref": "#/components/schemas/App" } } } } } } } } }, "post": { "summary": "Create a new app", "description": "Required scope - write_app", "tags": [ "Apps" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PostAppReq" } } } }, "responses": { "201": { "content": { "application/json": { "schema": { "type": "object", "properties": { "app": { "$ref": "#/components/schemas/AppDetail" } } } } } } } } }, "/api/v1/apps/{id}": { "get": { "summary": "Get a single app by ID", "description": "Required scope - read_app", "tags": [ "Apps" ], "parameters": [ { "in": "path", "name": "id", "required": true, "schema": { "type": "number" }, "description": "The unique ID of the app" } ], "responses": { "200": { "description": "A single app object", "content": { "application/json": { "schema": { "type": "object", "properties": { "app": { "$ref": "#/components/schemas/AppDetail" } } } } } } } }, "put": { "summary": "Update an existing app by ID", "description": "Required scope - write_app", "tags": [ "Apps" ], "parameters": [ { "in": "path", "name": "id", "required": true, "schema": { "type": "number" }, "description": "The unique ID of the app" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PutAppReq" } } } }, "responses": { "200": { "content": { "application/json": { "schema": { "type": "object", "properties": { "app": { "$ref": "#/components/schemas/AppDetail" } } } } } } } }, "delete": { "summary": "Delete an existing app by ID", "description": "Required scope - write_app", "tags": [ "Apps" ], "parameters": [ { "in": "path", "name": "id", "required": true, "schema": { "type": "number" }, "description": "The unique ID of the app" } ], "responses": { "204": { "description": "Successful operation with no content to return" } } } }, "/api/v1/users": { "get": { "summary": "Get a list of users", "description": "Required scope - read_user", "tags": [ "Users" ], "parameters": [ { "in": "query", "name": "page_size", "schema": { "type": "integer" }, "description": "Number of users to return per page" }, { "in": "query", "name": "page_number", "schema": { "type": "integer" }, "description": "Page number to return" }, { "in": "query", "name": "search", "schema": { "type": "string" }, "description": "Search by name or email" } ], "responses": { "200": { "description": "A list of users", "content": { "application/json": { "schema": { "type": "object", "properties": { "users": { "type": "array", "items": { "$ref": "#/components/schemas/UserDetail" } }, "count": { "type": "integer", "description": "Total number of users matching the query" } } } } } } } } }, "/api/v1/users/{authId}": { "get": { "summary": "Get a single user by authId", "description": "Required scope - read_user", "tags": [ "Users" ], "parameters": [ { "in": "path", "name": "authId", "required": true, "schema": { "type": "string" }, "description": "The authId of the user" } ], "responses": { "200": { "description": "A single user object", "content": { "application/json": { "schema": { "type": "object", "properties": { "user": { "$ref": "#/components/schemas/UserDetail" } } } } } } } }, "put": { "summary": "Update an existing user by authId", "description": "Required scope - write_user", "tags": [ "Users" ], "parameters": [ { "in": "path", "name": "authId", "required": true, "schema": { "type": "string" }, "description": "The authId of the user" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PutUserReq" } } } }, "responses": { "200": { "content": { "application/json": { "schema": { "type": "object", "properties": { "user": { "$ref": "#/components/schemas/UserDetail" } } } } } } } }, "delete": { "summary": "Delete an existing user by authId", "description": "Required scope - write_user", "tags": [ "Users" ], "parameters": [ { "in": "path", "name": "authId", "required": true, "schema": { "type": "string" }, "description": "The authId of the user" } ], "responses": { "204": { "description": "Successful operation with no content to return" } } } }, "/api/v1/users/{authId}/locked-ips": { "get": { "summary": "Get a list of locked IPs for a user", "description": "Required scope - read_user", "tags": [ "Users" ], "parameters": [ { "in": "path", "name": "authId", "required": true, "schema": { "type": "string" }, "description": "The authId of the user" } ], "responses": { "200": { "description": "A list of IPs", "content": { "application/json": { "schema": { "type": "object", "properties": { "lockedIps": { "type": "array", "items": { "type": "string" }, "description": "The list of locked IP addresses for the user" } } } } } } } }, "delete": { "summary": "Unlock all locked IP addresses for a user", "description": "Required scope - write_user", "tags": [ "Users" ], "parameters": [ { "in": "path", "name": "authId", "required": true, "schema": { "type": "string" }, "description": "The authId of the user" } ], "responses": { "204": { "description": "Successful operation with no content to return" } } } }, "/api/v1/users/{authId}/verify-email": { "post": { "summary": "Send a verification email to the user", "description": "Required scope - write_user", "tags": [ "Users" ], "parameters": [ { "in": "path", "name": "authId", "schema": { "type": "string" }, "required": true, "description": "The authId of the user who will receive the verification email" } ], "responses": { "200": { "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "example": true } } } } } } } } }, "/api/v1/users/{authId}/consented-apps": { "get": { "summary": "Get a list of apps user has consented to", "description": "Required scope - read_user", "tags": [ "Users" ], "parameters": [ { "in": "path", "name": "authId", "required": true, "schema": { "type": "string" }, "description": "The authId of the user" } ], "responses": { "200": { "description": "A list of consented apps", "content": { "application/json": { "schema": { "type": "object", "properties": { "consentedApps": { "type": "array", "items": { "$ref": "#/components/schemas/UserConsentedApp" } } } } } } } } } }, "/api/v1/users/{authId}/consented-apps/{appId}": { "delete": { "summary": "Delete an existing consent for a user by authId and appId", "description": "Required scope - write_user", "tags": [ "Users" ], "parameters": [ { "in": "path", "name": "authId", "required": true, "schema": { "type": "string" }, "description": "The authId of the user" }, { "in": "path", "name": "appId", "required": true, "schema": { "type": "number" }, "description": "The id of the app" } ], "responses": { "204": { "description": "Successful operation with no content to return" } } } }, "/api/v1/users/{authId}/email-mfa": { "post": { "summary": "enroll user for email MFA.", "description": "Required scope - write_user", "tags": [ "Users" ], "parameters": [ { "in": "path", "name": "authId", "required": true, "schema": { "type": "string" }, "description": "The authId of the user" } ], "responses": { "204": { "description": "Successful operation with no content to return" } } }, "delete": { "summary": "Unenroll user from email MFA.", "description": "Required scope - write_user", "tags": [ "Users" ], "parameters": [ { "in": "path", "name": "authId", "required": true, "schema": { "type": "string" }, "description": "The authId of the user" } ], "responses": { "204": { "description": "Successful operation with no content to return" } } } }, "/api/v1/users/{authId}/otp-mfa": { "post": { "summary": "enroll user for OTP MFA.", "description": "Required scope - write_user", "tags": [ "Users" ], "parameters": [ { "in": "path", "name": "authId", "required": true, "schema": { "type": "string" }, "description": "The authId of the user" } ], "responses": { "204": { "description": "Successful operation with no content to return" } } }, "delete": { "summary": "Remove user's current OTP MFA setup.", "description": "Required scope - write_user", "tags": [ "Users" ], "parameters": [ { "in": "path", "name": "authId", "required": true, "schema": { "type": "string" }, "description": "The authId of the user" } ], "responses": { "204": { "description": "Successful operation with no content to return" } } } }, "/api/v1/users/{authId}/sms-mfa": { "post": { "summary": "enroll user for SMS MFA.", "description": "Required scope - write_user", "tags": [ "Users" ], "parameters": [ { "in": "path", "name": "authId", "required": true, "schema": { "type": "string" }, "description": "The authId of the user" } ], "responses": { "204": { "description": "Successful operation with no content to return" } } }, "delete": { "summary": "Remove user's current SMS MFA setup.", "description": "Required scope - write_user", "tags": [ "Users" ], "parameters": [ { "in": "path", "name": "authId", "required": true, "schema": { "type": "string" }, "description": "The authId of the user" } ], "responses": { "204": { "description": "Successful operation with no content to return" } } } } }, "tags": [] }