{ "openapi": "3.0.2", "info": { "title": "Kittens API", "version": "1.0.1", "license": { "name": "GNU GPLv3", "url": "https://www.gnu.org/licenses/gpl-3.0.en.html" }, "description": "An API to buy, sell and manage Kittens." }, "servers": [ { "url": "https://kittens.robaldo.dev/" } ], "paths": { "/api/v1/users": { "get": { "description": "List users without private information", "responses": { "200": { "description": "A list of all users", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/CompactUser" } } } } }, "500": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionServerError" } } }, "description": "Something went wrong on the server and the request could not be handled." } } } }, "/api/v1/users/register": { "post": { "description": "Create a new user", "requestBody": { "description": "The new user's details", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserRegistration" } } } }, "responses": { "202": { "description": "Registration has been accepted but has yet to be completed by the user through the appropriate email link.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserRegistrationAccepted" } } } }, "400": { "description": "Bad request. Check if your request was formatted correctly and that all the fields match", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionBadRequest" } } } }, "401": { "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string", "description": "Definition of error", "example": "User already exists", "default": "User already exists" }, "status": { "type": "integer", "description": "Status code of response", "example": 401, "default": 401 } } } } }, "description": "The given email address is already in use." }, "500": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionServerError" } } }, "description": "Something went wrong on the server and the request could not be handled." } } } }, "/api/v1/users/authenticate": { "post": { "description": "Generate a token for the given user", "requestBody": { "description": "", "content": { "application/json": { "schema": { "type": "object", "required": ["email", "password"], "properties": { "email": { "type": "string", "description": "User's email address", "example": "bob@baz.bar" }, "password": { "type": "string", "description": "User's password", "example": "password1234" }, "tfa": { "type": "integer", "description": "User's 2FA code", "example": 123456 } } } } } }, "responses": { "200": { "description": "Confirmation was successful. User is now completely registered.", "content": { "application/json": { "schema": { "type": "object", "properties": { "uid": { "type": "string", "description": "User's UID", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, "token": { "type": "string", "description": "A new token for the user.", "example": "..." }, "expiresIn": { "type": "integer", "description": "How many seconds the token will last before a renewal is required", "example": 3600 } } } } } }, "400": { "description": "Bad request. Check if your request was formatted correctly and that all the fields match", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionBadRequest" } } } }, "401": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionUnauthorized" } } }, "description": "Confirmation ID has expired. The user will have to do a new login to receive a new confirmation email." }, "500": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionServerError" } } }, "description": "Something went wrong on the server and the request could not be handled." } } } }, "/api/v1/users/{uid}": { "get": { "description": "Fetch an individual user's details.", "parameters": [ { "in": "path", "name": "uid", "description": "User UID", "required": true, "schema": { "type": "string" }, "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, { "in": "header", "name": "authorization", "description": "Bearer Token", "required": false, "schema": { "type": "string" }, "example": "bearer ........" } ], "responses": { "200": { "description": "Returns user data with contents depending on the authorization status", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/User" } } } }, "400": { "description": "The requested was badly formatted.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionBadRequest" } } } }, "403": { "description": "User is not verified. Complete account verification through email first.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionUserNotVerified" } } } }, "404": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionNotFound" } } }, "description": "The requested user could not be found." }, "500": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionServerError" } } }, "description": "Something went wrong on the server and the request could not be handled." } } }, "put": { "description": "Update your user's details. Requires authorization", "parameters": [ { "in": "path", "name": "uid", "description": "User UID", "required": true, "schema": { "type": "string" }, "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, { "in": "header", "name": "authorization", "description": "Bearer Token", "required": true, "schema": { "type": "string" }, "example": "bearer ........" } ], "requestBody": { "description": "The updated user data", "content": { "application/json": { "schema": { "properties": { "description": { "description": "User's updated description", "type": "string", "example": "I'm Bob and my best friend is Alice" }, "pronouns": { "description": "User's updated pronouns", "type": "string", "example": "her/icopter" }, "image": { "description": "Updated user image in base64", "type": "string" }, "image_mime": { "description": "Updated user image mime type", "type": "string" } } } } } }, "responses": { "200": { "description": "Returns user data with contents depending on the authorization status", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/User" } } } }, "400": { "description": "The requested was badly formatted.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionBadRequest" } } } }, "401": { "description": "Error with authenticating the request.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionUnauthorized" } } } }, "403": { "description": "User is not verified. Complete account verification through email first.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionUserNotVerified" } } } }, "404": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionNotFound" } } }, "description": "The requested user could not be found." }, "500": { "description": "Something went wrong on the server and the request could not be handled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionServerError" } } } } } }, "delete": { "description": "Delete your own user. Requires authorization.", "parameters": [ { "in": "path", "name": "uid", "description": "User UID", "required": true, "schema": { "type": "string" }, "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, { "in": "header", "name": "authorization", "description": "Bearer Token", "required": true, "schema": { "type": "string" }, "example": "bearer ........" } ], "responses": { "200": { "description": "Successfully deleted user.", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Always true as 200 represents successful operation", "example": true } } } } } }, "400": { "description": "The requested was badly formatted.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionBadRequest" } } } }, "401": { "description": "Error with authenticating the request.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionUnauthorized" } } } }, "404": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionNotFound" } } }, "description": "The requested user could not be found." }, "500": { "description": "Something went wrong on the server and the request could not be handled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionServerError" } } } } } } }, "/api/v1/users/{uid}/validate": { "post": { "description": "Validate user account with the confirmation token", "parameters": [ { "in": "path", "name": "uid", "description": "User UID received from the query parameter", "required": true, "schema": { "type": "string" }, "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" } ], "requestBody": { "description": "", "content": { "application/json": { "schema": { "type": "object", "properties": { "confirmationId": { "type": "string", "description": "The confirmation ID received by query parameter", "example": "..." } } } } } }, "responses": { "200": { "description": "Confirmation was successful. User is now completely registered.", "content": { "application/json": { "schema": { "type": "object", "properties": { "token": { "type": "string", "description": "A new token for the user.", "example": "..." }, "expiresIn": { "type": "integer", "description": "How many seconds the token will last before a renewal is required", "example": 3600 } } } } } }, "208": { "description": "Account was already confirmed.", "content": { "application/json": { "schema": { "type": "object", "properties": { "token": { "type": "string", "description": "A new token for the user.", "example": "..." }, "expiresIn": { "type": "integer", "description": "How many seconds the token will last before a renewal is required", "example": 3600 } } } } } }, "400": { "description": "Bad request. Check if your request was formatted correctly and that all the fields match", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionBadRequest" } } } }, "401": { "description": "Confirmation ID has expired. The user will have to do a new login to receive a new confirmation email.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionUnauthorized" } } } }, "500": { "description": "Something went wrong on the server and the request could not be handled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionServerError" } } } } } } }, "/api/v1/users/{uid}/validateToken": { "post": { "description": "Checks if the given user authorization token is valid.", "parameters": [ { "in": "path", "name": "uid", "description": "User UID", "required": true, "schema": { "type": "string" }, "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, { "in": "header", "name": "authorization", "description": "Bearer Token", "required": true, "schema": { "type": "string" }, "example": "bearer ........" } ], "responses": { "200": { "description": "Token is valid.", "content": { "application/json": { "schema": { "type": "object", "properties": { "expires": { "type": "integer", "description": "Time until token expiration in seconds since Jan 1st, 1970" } } } } } } } } }, "/api/v1/users/passwordReset": { "post": { "description": "Trigger password reset for user", "parameters": [], "requestBody": { }, "responses": { } }, "put": { "description": "Complete password reset for user", "parameters": [], "requestBody": { }, "responses": { } } }, "/api/v1/users/{uid}/cart": { "get": { "description": "Fetch the user's cart contents.", "parameters": [ { "in": "path", "name": "uid", "description": "User UID", "required": true, "schema": { "type": "string" }, "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, { "in": "header", "name": "authorization", "description": "Bearer Token", "required": true, "schema": { "type": "string" }, "example": "bearer ........" }, { "in": "query", "name": "fullData", "description": "Specify that you want the whole Cat object instead of a list of UIDs. When not set it defaults to a UID list", "required": false, "schema": { "type": "boolean" }, "allowEmptyValue": true }, { "in": "query", "required": false, "name": "page", "description": "The page's index if you want to recieve paged data. If not explicitly set, even with page 0, all items will be returned by default. Including items alone won't enable the paging.", "schema": { "type": "integer" }, "example": "1", "allowEmptyValue": true }, { "in": "query", "required": false, "name": "items", "description": "How many items should be on each page.", "schema": { "type": "integer" }, "example": "25", "allowEmptyValue": true } ], "responses": { "200": { "description": "Successfully fetched user's cart. Returns a list of cat UIDs.", "content": { "application/json": { "schema": { "oneOf": [ { "type": "object", "description": "Compact Cart data containing only a list of UIDs of the cats in the cart.", "properties": { "billable": { "type": "object", "description": "Cost of all items in cart", "properties": { "amount": { "type": "string", "description": "Total cost", "example": "42.00" }, "currency": { "type": "string", "description": "Currency used in transaciton. Always EUR (Euro)", "enum": [ "EUR" ], "example": "EUR" }, "vat": { "type": "string", "description": "VAT in total expense, already included in amount.", "example": "9.24" } } }, "cart": { "type": "array", "description": "The list of Cat UIDs", "items": { "type": "string", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" } } } }, { "type": "object", "description": "Cart data with complete cat information provided when query parameter `?fullData` is set.", "properties": { "billable": { "type": "object", "description": "Cost of all items in cart", "properties": { "amount": { "type": "string", "description": "Total cost", "example": "42.00" }, "currency": { "type": "string", "description": "Currency used in transaciton. Always EUR (Euro)", "enum": ["EUR"], "example": "EUR" }, "vat": { "type": "string", "description": "VAT in total expense, already included in amount.", "example": "9.24" } } }, "cart": { "type": "array", "items": { "$ref": "#/components/schemas/Cat" }, "description": "A list of the UIDs of the cats in the cart." }, "page": { "type": "integer", "description": "The current requested page relative to the amount of items per page. Not available when paging is disabled.", "example": 0 }, "viewing": { "type": "string", "description": "The range of currently shown items. Not available when paging is disabled.", "example": "0-24" }, "totalItems": { "type": "integer", "description": "The total amount of items in the cart", "example": 42 } } } ] } } } }, "401": { "description": "Token is not valid and the cart cannot be accessed. The token might be expired or not allowed to access the given user's private details.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionUnauthorized" } } } }, "404": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionNotFound" } } }, "description": "The requested user could not be found." }, "500": { "description": "Something went wrong on the server and the request could not be handled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionServerError" } } } } } }, "put": { "description": "Add a cat to the user's cart.", "parameters": [ { "in": "path", "name": "uid", "description": "User UID", "required": true, "schema": { "type": "string" }, "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, { "in": "header", "name": "authorization", "description": "Bearer Token", "required": true, "schema": { "type": "string" }, "example": "bearer ........" } ], "requestBody": { "description": "The cat's uid that will be added to the user's cart", "content": { "applicaiton/json": { "schema": { "type": "object", "properties": { "catUid": { "type": "string", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff", "description": "The cat's uid that will be added to the user's cart." } } } } } }, "responses": { "201": { "description": "Successfully added Cat to user's cart.", "content": { "application/json": { "schema": { "type": "object", "properties": { "cartItems": { "type": "integer", "description": "The amount of cats in the cart", "example": 42 }, "catUid": { "type": "string", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff", "description": "The UID of the cat that was just added." } } } } } }, "208": { "description": "The cat is already in the cart", "content": { "application/json": { "schema": { "type": "object", "properties": { "cartItems": { "type": "integer", "description": "The amount of cats in the cart", "example": 42 }, "catUid": { "type": "string", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff", "description": "The UID of the cat that was just added." } } } } } }, "400": { "description": "The request was formatted incorrectly.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionBadRequest" } } } }, "401": { "description": "Token is not valid and the cart cannot be accessed. The token might be expired or not allowed to access the given user's private details.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionUnauthorized" } } } }, "403": { "description": "The given cat is owned by another user and cannot be bought." }, "404": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionNotFound" } } }, "description": "The requested user or cat could not be found." }, "500": { "description": "Something went wrong on the server and the request could not be handled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionServerError" } } } } } }, "delete": { "description": "Delete one or more cats from the user's cart.", "parameters": [ { "in": "path", "name": "uid", "description": "User UID", "required": true, "schema": { "type": "string" }, "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, { "in": "header", "name": "authorization", "description": "Bearer Token", "required": true, "schema": { "type": "string" }, "example": "bearer ........" } ], "requestBody": { "description": "The cats to delete", "content": { "application/json": { "schema": { "type": "object", "properties": { "cats": { "type": "array", "items": { "type": "string", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" } } } } } } }, "responses": { "200": { "description": "Cat(s) deleted from cart successfully.", "content": { "application/json": { "schema": { "type": "object", "properties": { "catsRemoved": { "type": "integer", "description": "How many cats were successfully deleted" } } } } } }, "400": { "description": "The request was formatted incorrectly.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionBadRequest" } } } }, "401": { "description": "Token is not valid and the cart cannot be accessed. The token might be expired or not allowed to access the given user's private details.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionUnauthorized" } } } }, "404": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionNotFound" } } }, "description": "The requested user or cat could not be found." }, "500": { "description": "Something went wrong on the server and the request could not be handled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionServerError" } } } } } } }, "/api/v1/users/{uid}/cart/checkout": { "post": { "description": "", "requestBody": { "description": "", "content": { "application/json": { "schema": { "type": "object", "properties": { "card": { "type": "object", "description": "Payment card details", "properties": { "number": { "type": "string", "description": "Card number, can contain spaces between digits.", "example": "0123 4567 8901 2345" }, "cvv": { "type": "integer", "description": "Card security code", "example": 123 }, "cardholder": { "type": "string", "description": "Cardholder Name", "example": "Bob Bazbar" }, "expiration": { "type": "string", "description": "Card expiration date in format month/year, both two digit.", "example": "01/29" } } } } } } } }, "parameters": [ { "in": "path", "name": "uid", "description": "User UID", "required": true, "schema": { "type": "string" }, "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, { "in": "header", "name": "authorization", "description": "Bearer Token", "required": true, "schema": { "type": "string" }, "example": "bearer ........" } ], "responses": { "200": { "description": "Payment was successful and cats were added to user account", "content": { "application/json": { "schema": { "type": "object", "properties": { "billed": { "type": "object", "description": "Amount that was billed", "properties": { "amount": { "type": "string", "description": "Total cost billed", "example": "42.00" }, "currency": { "type": "string", "description": "Currency used in transaciton. Always EUR (Euro)", "enum": ["EUR"], "example": "EUR" }, "vat": { "type": "string", "description": "VAT in total expense, already included in amount.", "example": "9.24" } } }, "saleUid": { "type": "string", "description": "Sale Unique Identifier", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, "cats": { "type": "array", "description": "UID list of cats that were bought", "items": { "type": "string", "description": "Cat UID", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" } } } } } } }, "400": { "description": "Invalid request.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionBadRequest" } } } }, "401": { "description": "Token is not valid and the cart cannot be accessed. The token might be expired or not allowed to access the given user's private details.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionUnauthorized" } } } }, "402": { "description": "Payment failed." }, "404": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionNotFound" } } }, "description": "The requested user could not be found." }, "500": { "description": "Something went wrong on the server and the request could not be handled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionServerError" } } } } } } }, "/api/v1/users/{uid}/wishlist": { "get": { "description": "Fetch the user's wishlist contents.", "parameters": [ { "in": "path", "name": "uid", "description": "User UID", "required": true, "schema": { "type": "string" }, "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, { "in": "query", "required": false, "name": "page", "description": "The page's index if you want to recieve paged data. If not explicitly set, even with page 0, all items will be returned by default. Including items alone won't enable the paging.", "schema": { "type": "integer" }, "example": "1", "allowEmptyValue": true }, { "in": "query", "required": false, "name": "items", "description": "How many items should be on each page.", "schema": { "type": "integer" }, "example": "25", "allowEmptyValue": true } ], "responses": { "200": { "description": "Successfully fetched user's wishlist. Returns a list of cat UIDs.", "content": { "application/json": { "schema": { "type": "object", "properties": { "wishlist": { "type": "array", "items": { "$ref": "#/components/schemas/Uid" }, "description": "A list of the UIDs of the cats in the wishlist." }, "page": { "type": "integer", "description": "The current requested page relative to the amount of items per page. Not available when paging is disabled.", "example": 0 }, "viewing": { "type": "string", "description": "The range of currently shown items. Not available when paging is disabled.", "example": "0-24" }, "totalItems": { "type": "integer", "description": "The total amount of items in the wishlist", "example": 42 } } } } } }, "404": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionNotFound" } } }, "description": "The requested user could not be found." }, "500": { "description": "Something went wrong on the server and the request could not be handled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionServerError" } } } } } }, "put": { "description": "Add a cat to the user's wishlist.", "parameters": [ { "in": "path", "name": "uid", "description": "User UID", "required": true, "schema": { "type": "string" }, "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, { "in": "header", "name": "authorization", "description": "Bearer Token", "required": true, "schema": { "type": "string" }, "example": "bearer ........" } ], "requestBody": { "description": "The cat's uid that will be added to the user's wishlist", "content": { "applicaiton/json": { "schema": { "type": "object", "properties": { "catUid": { "type": "string", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff", "description": "The cat's uid that will be added to the user's wishlist." } } } } } }, "responses": { "201": { "description": "Successfully added Cat to user's wishlist.", "content": { "application/json": { "schema": { "type": "object", "properties": { "wishlistItems": { "type": "integer", "description": "The amount of cats in the wishlist", "example": 42 }, "catUid": { "type": "string", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff", "description": "The UID of the cat that was just added." } } } } } }, "208": { "description": "The cat is already in the wishlist", "content": { "application/json": { "schema": { "type": "object", "properties": { "wishlistItems": { "type": "integer", "description": "The amount of cats in the wishlist", "example": 42 }, "catUid": { "type": "string", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff", "description": "The UID of the cat that was just added." } } } } } }, "400": { "description": "The request was formatted incorrectly.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionBadRequest" } } } }, "401": { "description": "Token is not valid and the wishlist cannot be accessed. The token might be expired or not allowed to access the given user's private details.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionUnauthorized" } } } }, "404": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionNotFound" } } }, "description": "The requested user or cat could not be found." }, "500": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionServerError" } } }, "description": "Something went wrong on the server and the request could not be handled." } } }, "delete": { "description": "Delete one or more cats from the user's wishlist.", "parameters": [ { "in": "path", "name": "uid", "description": "User UID", "required": true, "schema": { "type": "string" }, "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, { "in": "header", "name": "authorization", "description": "Bearer Token", "required": true, "schema": { "type": "string" }, "example": "bearer ........" } ], "requestBody": { "description": "The cats to delete", "content": { "application/json": { "schema": { "type": "object", "properties": { "cats": { "type": "array", "items": { "type": "string", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" } } } } } } }, "responses": { "200": { "description": "Cat(s) deleted from wishlist successfully.", "content": { "application/json": { "schema": { "type": "object", "properties": { "catsRemoved": { "type": "integer", "description": "How many cats were successfully deleted" } } } } } }, "400": { "description": "The request was formatted incorrectly.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionBadRequest" } } } }, "401": { "description": "Token is not valid and the wishlist cannot be accessed. The token might be expired or not allowed to access the given user's private details.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionUnauthorized" } } } }, "404": { "description": "The requested user or cat could not be found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionNotFound" } } } }, "500": { "description": "Something went wrong on the server and the request could not be handled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionServerError" } } } } } } }, "/api/v1/cats": { "get": { "description": "List all cats", "responses": { "200": { "description": "A list of cats", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/Cat" } } } } }, "500": { "description": "Something went wrong on the server and the request could not be handled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionServerError" } } } } } } }, "/api/v1/cats/{uid}": { "get": { "description": "Get a cat by its UID", "parameters": [ { "in": "path", "name": "uid", "description": "Cat's UID", "schema": { "type": "string" }, "example": "ffffffff-ffff-ffff-ffff-ffffffffffff", "required": true } ], "responses": { "200": { "description": "Returns cat data with contents depending on the authorization status", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Cat" } } } }, "400": { "description": "The requested was badly formatted.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionBadRequest" } } } }, "404": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionNotFound" } } }, "description": "The requested cat could not be found." }, "500": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionServerError" } } }, "description": "Something went wrong on the server and the request could not be handled." } } }, "put": { "description": "Update your cat's details. Requires authorization", "parameters": [ { "in": "path", "name": "uid", "description": "Cat UID", "required": true, "schema": { "type": "string" }, "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, { "in": "header", "name": "authorization", "description": "Bearer Token", "required": true, "schema": { "type": "string" }, "example": "bearer ........" } ], "requestBody": { "description": "The updated cat data", "content": { "application/json": { "schema": { "type": "object", "properties": { "age": { "type": "integer", "description": "Cat's age", "example": 42 }, "description": { "type": "string", "description": "Cat's description", "example": "Lord Megatron Destroyer of Worlds, more affectionately known as Wiwi, used to be the general commander of the catworld army during the liberation of France from occupation." }, "whenLastSeen": { "type": "string", "description": "Date of where the cat, usually when stray, was last seen in format DD-MM-YYYY", "example": "27/02/1933" }, "whereLastSeen": { "type": "string", "description": "Where the cat was last seen", "example": "Platz der Republik 1, 11011 Berlin, Germany" }, "weight": { "type": "integer", "description": "The cat's weight in grams", "example": 420 }, "isStray": { "type": "boolean", "description": "If the cat is stray or not", "example": false } } } } } }, "responses": { "200": { "description": "Returns cat data with updated content", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Cat" } } } }, "400": { "description": "The requested was badly formatted.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionBadRequest" } } } }, "401": { "description": "Error with authenticating the request.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionUnauthorized" } } } }, "403": { "description": "User is not verified. Complete account verification through email first.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionUserNotVerified" } } } }, "404": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionNotFound" } } }, "description": "The requested cat could not be found." }, "500": { "description": "Something went wrong on the server and the request could not be handled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionServerError" } } } } } }, "delete": { "description": "Delete one of your cats. Requires authorization.", "parameters": [ { "in": "path", "name": "uid", "description": "Cat UID", "required": true, "schema": { "type": "string" }, "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, { "in": "header", "name": "authorization", "description": "Bearer Token", "required": true, "schema": { "type": "string" }, "example": "bearer ........" } ], "responses": { "200": { "description": "Successfully deleted Cat.", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Always true as 200 represents successful operation", "example": true } } } } } }, "400": { "description": "The requested was badly formatted.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionBadRequest" } } } }, "401": { "description": "Error with authenticating the request.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionUnauthorized" } } } }, "404": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionNotFound" } } }, "description": "The requested cat could not be found." }, "500": { "description": "Something went wrong on the server and the request could not be handled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionServerError" } } } } } } }, "/api/v1/cats/{uid}/sell": { "post": { "description": "Sell one of your cats. Requires authorization", "parameters": [ { "in": "path", "name": "uid", "description": "Cat UID", "required": true, "schema": { "type": "string" }, "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, { "in": "header", "name": "authorization", "description": "Bearer Token", "required": true, "schema": { "type": "string" }, "example": "bearer ........" } ], "requestBody": { "description": "The updated cat data", "content": { "application/json": { "schema": { "type": "object", "properties": { "price": { "type": "integer", "description": "The cat's sale price in Euro Cents. Can be zero.", "example": 4200, "minimum": 0 } } } } } }, "responses": { "200": { "description": "Cat was put up for sale successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "price": { "type": "integer", "description": "The price at which the cat was put up for sale at", "example": 4200 }, "vat": { "type": "integer", "description": "The cat's VAT percentage of the sale price.", "example": 924 } } } } } }, "400": { "description": "The requested was badly formatted.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionBadRequest" } } } }, "401": { "description": "Error with authenticating the request.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionUnauthorized" } } } }, "403": { "description": "User is not verified. Complete account verification through email first.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionUserNotVerified" } } } }, "404": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionNotFound" } } }, "description": "The requested cat could not be found." }, "500": { "description": "Something went wrong on the server and the request could not be handled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionServerError" } } } } } } }, "/api/v1/cats/create": { "post": { "description": "Create a new cat owned by your user.", "parameters": [ { "in": "header", "name": "authorization", "description": "Bearer Token", "required": true, "schema": { "type": "string" }, "example": "bearer ........" } ], "requestBody": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CatCreate" } } } }, "responses": { "200": { "description": "Successfully created cat", "content": { "application/json": { "schema": { "type": "object", "properties": { "uid": { "type": "string", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" } } } } } }, "400": { "description": "The requested was badly formatted.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionBadRequest" } } } }, "401": { "description": "Error with authenticating the request.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionUnauthorized" } } } }, "403": { "description": "User is not verified. Complete account verification through email first.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionUserNotVerified" } } } }, "500": { "description": "Something went wrong on the server and the request could not be handled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExceptionServerError" } } } } } } } }, "components": { "schemas": { "Uid": { "type": "string", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, "CatCreate": { "type": "object", "required": [ "name", "age", "isStray" ], "properties": { "name": { "type": "string", "description": "Cat's name", "example": "Lord Megatron Destroyer of Worlds" }, "age": { "type": "integer", "description": "Cat's age", "example": 42 }, "description": { "type": "string", "description": "Cat's description", "example": "Lord Megatron Destroyer of Worlds, more affectionately known as Wiwi, used to be the general commander of the catworld army during the liberation of France from occupation." }, "whenLastSeen": { "type": "string", "description": "Date of where the cat, usually when stray, was last seen in format DD-MM-YYYY", "example": "27/02/1933" }, "whereLastSeen": { "type": "string", "description": "Where the cat was last seen", "example": "Platz der Republik 1, 11011 Berlin, Germany" }, "race": { "type": "string", "description": "The cat's race", "example": "" }, "furColor": { "type": "string", "description": "The cat's fur color", "example": "White" }, "weight": { "type": "integer", "description": "The cat's weight in grams", "example": 420 }, "isStray": { "type": "boolean", "description": "If the cat is stray or not", "example": false }, "image": { "type": "string", "description": "The user's profile picture in base64 format.", "example": "data:image/...;base64,........" }, "imageMime": { "type": "string", "enum": ["image/jpeg", "image/png", "image/gif"], "description": "The user's profile picture mime type", "example": "image/gif" } } }, "Cat": { "type": "object", "properties": { "uid": { "type": "string", "description": "The user's Unique ID", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, "name": { "type": "string", "description": "Cat's name", "example": "Lord Megatron Destroyer of Worlds" }, "age": { "type": "integer", "description": "Cat's age", "example": 42 }, "description": { "type": "string", "description": "Cat's description", "example": "Lord Megatron Destroyer of Worlds, more affectionately known as Wiwi, used to be the general commander of the catworld army during the liberation of France from occupation." }, "whenLastSeen": { "type": "string", "description": "Date of where the cat, usually when stray, was last seen in format DD-MM-YYYY", "example": "27/02/1933" }, "whereLastSeen": { "type": "string", "description": "Where the cat was last seen", "example": "Platz der Republik 1, 11011 Berlin, Germany" }, "race": { "type": "string", "description": "The cat's race", "example": "" }, "furColor": { "type": "string", "description": "The cat's fur color", "example": "White" }, "weight": { "type": "integer", "description": "The cat's weight in grams", "example": 420 }, "isStray": { "type": "boolean", "description": "If the cat is stray or not", "example": false }, "price": { "type": "integer", "description": "The cat's price in cents of EUR", "example": 6942 }, "owner": { "type": "string", "description": "The owner's UID, can be null or not set", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, "image": { "type": "string", "description": "The user's profile picture in base64 format.", "example": "data:image/...;base64,........" }, "imageMime": { "type": "string", "enum": ["image/jpeg", "image/png", "image/gif"], "description": "The user's profile picture mime type", "example": "image/gif" } } }, "CompactUser": { "properties": { "uid": { "type": "string", "description": "The user's Unique ID", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, "username": { "type": "string", "description": "The user's username. ", "example": "Bob" }, "image": { "type": "string", "description": "The user's profile picture in base64 format.", "example": "base64 ........" }, "imageMime": { "type": "string", "enum": ["image/jpeg", "image/png", "image/gif"], "description": "The user's profile picture mime type", "example": "image/gif" }, "description": { "type": "string", "description": "The user's description. Can be empty", "example": "I'm bob and i love cats. I live in catworld and have 2^64 cats in my house. Their names are the fibonacci sequence. Except cat number 42 whose name is Megatron." }, "pronouns": { "type": "string", "description": "The user's pronouns, can be empty.", "example": "hee/hee" } } }, "User": { "properties": { "uid": { "type": "string", "description": "The user's Unique ID", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" }, "username": { "type": "string", "description": "The user's username. ", "example": "Bob" }, "image": { "type": "string", "description": "The user's profile picture in base64 format.", "example": "base64 ........" }, "imageMime": { "type": "string", "enum": ["image/jpeg", "image/png", "image/gif"], "description": "The user's profile picture mime type", "example": "image/gif" }, "description": { "type": "string", "description": "The user's description. Can be empty", "example": "I'm bob and i love cats. I live in catworld and have 2^64 cats in my house. Their names are the fibonacci sequence. Except cat number 42 whose name is Megatron." }, "pronouns": { "type": "string", "description": "The user's pronouns, can be empty.", "example": "hee/hee" }, "cats": { "type": "array", "description": "The user's cats' UIDs. Can be empty.", "items": { "type": "string", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" } }, "wishlist": { "type": "array", "description": "The user's wishlisted cats UIDs. Can be empty and won't contain more than 25 items, for more items check the user's wishlist endpoint.", "items": { "type": "string", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" } } } }, "UserRegistration": { "type": "object", "required": [ "email", "username", "password" ], "properties": { "email": { "type": "string", "description": "The email new user's email address.", "example": "bob@foo.bar" }, "username": { "type": "string", "description": "The username. Must be composed only by lower and uppercase letters, numbers, dashes, underscores and spaces and not be longer than 64 characters.", "example": "Bob" }, "password": { "type": "string", "description": "The user's password. Must follow the password requirements", "example": "Bob.Loves.Alice.42" }, "emailConfirmationBaseUrl": { "type": "string", "description": "Intended for the frontend, it's the URL that will handle the registration confirmation. Remember that the query parameter confirmationId and userUid will be appended. Include protocol and path. If not given an api url will be given instead with a JSON response.", "example": "https://example.com/users/confirm" }, "description": { "type": "string", "description": "The user's description. Can be empty", "example": "I'm bob and i love cats. I live in catworld and have 2^64 cats in my house. Their names are the fibonacci sequence. Except cat number 42 whose name is Megatron." }, "pronouns": { "type": "string", "description": "The user's pronouns, can be empty.", "example": "hee/hee" } } }, "UserRegistrationAccepted": { "type": "object", "properties": { "username": { "type": "string", "description": "The username", "example": "Bob" }, "email": { "type": "string", "description": "The email at which the confirmation has been sent to.", "example": "bob@foo.bar" }, "uid": { "type": "string", "description": "The new user's UID.", "example": "ffffffff-ffff-ffff-ffff-ffffffffffff" } } }, "ExceptionUserNotVerified": { "type": "object", "properties": { "error": { "type": "string", "description": "Definition of error", "default": "User account is not verified", "example": "User account is not verified" }, "status": { "type": "integer", "description": "Status code of response", "default": 403, "example": 403 } } }, "ExceptionUnauthorized": { "type": "object", "properties": { "error": { "type": "string", "description": "Definition of error", "default": "Unauthorized", "example": "Unauthorized" }, "status": { "type": "integer", "description": "Status code of response", "default": 401, "example": 401 }, "reason": { "type": "string", "enum": [ "Token expired", "No token provided", "Invalid token", "Unauthorized" ], "description": "Why you are unauthorized. Defaults to \"Unauthorized\" which is a generic reason.", "example": "Unauthorized" } } }, "ExceptionNotFound": { "type": "object", "properties": { "error": { "type": "string", "description": "Definition of error", "default": "Not found", "example": "Not found" }, "status": { "type": "integer", "description": "Status code of response", "default": 404, "example": 404 }, "reason": { "type": "string", "enum": [ "Requested cat could not be found", "Requested user could not be found", "Requested path could not be found" ], "description": "What wasn't found.", "example": "Requested path could not be found" } } }, "ExceptionBadRequest": { "type": "object", "properties": { "error": { "type": "string", "description": "Definition of error", "default": "Bad Request", "example": "Bad Request" }, "status": { "type": "integer", "description": "Status code of response", "default": 400, "example": 400 }, "field_errors": { "type": "array", "description": "A list of fields of the request that were formatted badly. An issue with an email field might also mean that the given password was wrong.", "items": { "type": "string", "example": "email" } } } }, "ExceptionMethodNotAllowed": { "type": "object", "properties": { "error": { "type": "string", "description": "Definition of error", "default": "Method not allowed", "example": "Method not allowed" }, "status": { "type": "integer", "description": "Status code of response", "default": 405, "example": 405 }, "field_errors": { "type": "string", "description": "The method that was used to make the request.", "example": "PUT" } } }, "ExceptionServerError": { "type": "object", "properties": { "error": { "type": "string", "description": "Definition of error", "default": "Server Error", "example": "Server Error" }, "status": { "type": "integer", "description": "Status code of response", "default": 500, "example": 500 }, "exception": { "type": "string", "description": "The exception message", "example": "Baz given, expected Foo or Bar" }, "trace": { "type": "string", "description": "The trace of the exception." }, "thrownIn": { "type": "string", "description": "The method where the exception was thrown", "example": "\\App\\Foo\\Bar\\Baz()" }, "file": { "type": "string", "description": "The file that threw the exception. Set only when server is in debugging mode" }, "line": { "type": "integer", "description": "The line of the file where the exception was thrown. Set only when the server is in debugging mode" }, "severity": { "type": "string", "description": "Set only in debugging mode." } } } } } }