Skip to content

Instantly share code, notes, and snippets.

@helmturner
Created May 12, 2024 23:07
Show Gist options
  • Save helmturner/2f0c98a090c8ca819b80d7a65551b189 to your computer and use it in GitHub Desktop.
Save helmturner/2f0c98a090c8ca819b80d7a65551b189 to your computer and use it in GitHub Desktop.
{
"openapi": "3.1.0",
"info": {
"title": "Tulsa WebDevs Voting Service",
"description": "API for casting votes on various topics/projects and submitting and managing proposals with a ranking and voting system.",
"version": "0.0.2"
},
"servers": [
{
"url": "http://vote.tulsawebdevs. org",
"description": "Voting Service API"
},
{
"url": "http://localhost:8080",
"description": "Local development server"
}
],
"paths": {
"/drafts": {
"summary": "Manage the current user's proposal drafts",
"parameters": [
{ "$ref": "#/components/parameters/AuthorizationRequired" }
],
"get": {
"operationId": "listDrafts",
"summary": "Get a list of the current user's drafts with pagination, filtering, and sorting",
"parameters": [
{ "$ref": "#/components/parameters/PaginationParams" },
{ "$ref": "#/components/parameters/ProposalTypeFilter" }
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/DraftIndex" }
}
}
},
"401": { "$ref": "#/components/responses/401" },
"404": { "$ref": "#/components/responses/404" },
"default": { "$ref": "#/components/responses/500" }
}
},
"post": {
"summary": "Create a new draft",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/Draft" }
}
}
},
"responses": {
"201": {
"description": "Created",
"content": {
"application/json": {
"schema": {
"allOf": [
{ "$ref": "#/components/schemas/Draft" },
{ "$ref": "#/components/schemas/DatabaseObject" }
]
}
}
}
},
"401": { "$ref": "#/components/responses/401" },
"default": { "$ref": "#/components/responses/500" }
}
},
"put": {
"summary": "Replace an existing draft",
"parameters": [{ "$ref": "#/components/parameters/RecordId" }],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/Draft" }
}
}
},
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"allOf": [
{ "$ref": "#/components/schemas/Draft" },
{ "$ref": "#/components/schemas/DatabaseObject" }
]
}
}
}
},
"401": { "$ref": "#/components/responses/401" },
"404": { "$ref": "#/components/responses/404" },
"default": { "$ref": "#/components/responses/500" }
}
},
"patch": {
"summary": "Update an existing draft",
"parameters": [{ "$ref": "#/components/parameters/RecordId" }],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/Draft" }
}
}
},
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"allOf": [
{ "$ref": "#/components/schemas/Draft" },
{ "$ref": "#/components/schemas/DatabaseObject" }
]
}
}
}
},
"401": { "$ref": "#/components/responses/401" },
"404": { "$ref": "#/components/responses/404" },
"default": { "$ref": "#/components/responses/500" }
}
},
"delete": {
"summary": "Delete a draft by ID",
"parameters": [{ "$ref": "#/components/parameters/RecordId" }],
"responses": {
"204": { "description": "No Content" },
"401": { "$ref": "#/components/responses/401" },
"404": { "$ref": "#/components/responses/404" },
"default": { "$ref": "#/components/responses/500" }
}
}
},
"/proposals": {
"summary": "Create or list proposals",
"get": {
"summary": "Get a list of the proposals with pagination, filtering, and sorting",
"parameters": [
{ "$ref": "#/components/parameters/AuthorizationOptional" },
{ "$ref": "#/components/parameters/PaginationParams" },
{ "$ref": "#/components/parameters/ProposalTypeFilter" },
{ "$ref": "#/components/parameters/ProposalStatusFilter" }
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ProposalIndex" }
}
}
},
"404": { "$ref": "#/components/responses/404" },
"default": { "$ref": "#/components/responses/500" }
}
},
"post": {
"summary": "Create a new proposal",
"parameters": [
{ "$ref": "#/components/parameters/AuthorizationRequired" }
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/Proposal" }
}
}
},
"responses": {
"201": {
"description": "Created",
"content": {
"application/json": {
"schema": {
"allOf": [
{ "$ref": "#/components/schemas/Proposal" },
{ "$ref": "#/components/schemas/ProposalState" },
{ "$ref": "#/components/schemas/DatabaseObject" }
]
}
}
}
},
"401": { "$ref": "#/components/responses/401" },
"default": { "$ref": "#/components/responses/500" }
}
}
},
"/{recordId}": {
"summary": "Manage a user's vote on a proposal",
"parameters": [
{ "$ref": "#/components/parameters/AuthorizationRequired" },
{ "$ref": "#/components/parameters/RecordId" }
],
"post": {
"summary": "Submit (or update) a vote on a proposal",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/Vote" }
}
}
},
"responses": {
"201": {
"description": "Created",
"content": {
"application/json": {
"schema": {
"allOf": [
{ "$ref": "#/components/schemas/Vote" },
{ "$ref": "#/components/schemas/DatabaseObject" }
]
}
}
}
},
"401": { "$ref": "#/components/responses/401" },
"default": { "$ref": "#/components/responses/500" }
}
},
"delete": {
"summary": "Delete a user's proposal vote",
"responses": {
"204": { "description": "No Content" },
"401": { "$ref": "#/components/responses/401" },
"404": { "$ref": "#/components/responses/404" },
"default": { "$ref": "#/components/responses/500" }
}
}
}
},
"components": {
"parameters": {
"PaginationParams": {
"name": "pagination",
"in": "query",
"required": false,
"schema": { "$ref": "#/components/schemas/Paginated" }
},
"ProposalTypeFilter": {
"name": "type",
"in": "query",
"required": false,
"schema": {
"type": "string",
"enum": ["topic", "project"]
},
"description": "Filter items by type"
},
"ProposalStatusFilter": {
"name": "status",
"in": "query",
"required": false,
"schema": {
"type": "string",
"enum": ["open", "closed"]
},
"description": "Filter items by status"
},
"AuthorizationRequired": {
"name": "Authorization",
"in": "header",
"required": true,
"schema": {
"type": "string"
}
},
"AuthorizationOptional": {
"name": "Authorization",
"in": "header",
"required": false,
"schema": {
"type": "string"
}
},
"RecordId": {
"name": "recordId",
"in": "query",
"required": true,
"description": "ID of the record to get, update, or delete",
"schema": {
"type": "integer",
"format": "int32"
}
}
},
"responses": {
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/Error" }
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/Error" }
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/Error" }
}
}
}
},
"schemas": {
"DatabaseObject": {
"type": "object",
"required": ["id", "created"],
"properties": {
"id": {
"type": "integer",
"format": "int32"
},
"created": {
"type": "string",
"format": "date-time"
},
"updated": {
"type": "string",
"format": "date-time"
}
}
},
"Draft": {
"type": "object",
"properties": {
"title": {
"type": "string",
"maxLength": 48
},
"summary": {
"type": "string",
"maxLength": 255
},
"description": {
"type": "string",
"maxLength": 2048
},
"type": {
"type": "string",
"enum": ["topic", "project"]
}
}
},
"DraftIndex": {
"allOf": [
{ "$ref": "#/components/schemas/Paginated" },
{
"type": "object",
"required": ["drafts"],
"properties": {
"drafts": {
"type": "array",
"items": {
"allOf": [
{ "$ref": "#/components/schemas/Draft" },
{ "$ref": "#/components/schemas/DatabaseObject" }
]
}
}
}
}
]
},
"Proposal": {
"allOf": [
{ "$ref": "#/components/schemas/Draft" },
{
"type": "object",
"required": ["type", "title", "summary"],
"properties": {
"title": {
"type": "string",
"minLength": 8
},
"summary": {
"type": "string",
"minLength": 30
}
}
}
]
},
"ProposalState": {
"oneOf": [
{
"type": "object",
"required": ["status", "results", "authorName"],
"properties": {
"authorName": { "type": "string" },
"status": { "type": "string", "enum": ["closed"] },
"userVote": { "$ref": "#/components/schemas/Vote" },
"results": {
"type": "array",
"items": { "$ref": "#/components/schemas/Vote" }
}
}
},
{
"type": "object",
"required": ["status", "authorName"],
"properties": {
"authorName": { "type": "string", "minLength": 4 },
"status": { "type": "string", "enum": ["open"] },
"userVote": { "$ref": "#/components/schemas/Vote" }
}
}
]
},
"ProposalIndex": {
"allOf": [
{ "$ref": "#/components/schemas/Paginated" },
{
"type": "object",
"required": ["proposals"],
"properties": {
"proposals": {
"type": "array",
"items": {
"allOf": [
{ "$ref": "#/components/schemas/Proposal" },
{ "$ref": "#/components/schemas/ProposalState" },
{ "$ref": "#/components/schemas/DatabaseObject" }
]
}
}
}
}
]
},
"Vote": {
"type": "object",
"required": ["value"],
"properties": {
"value": {
"description": "Ranking values: -2 (strong disinterest), -1 (slight disinterest), 0 (neutral), 1 (slight interest), 2 (strong interest)",
"type": "string",
"enum": ["-2", "-1", "0", "1", "2"]
},
"comment": {
"type": "string",
"maxLength": 255
}
}
},
"Expirable": {
"type": "object",
"required": ["expires"],
"properties": {
"expires": {
"type": "string",
"format": "date-time"
}
}
},
"Paginated": {
"type": "object",
"description": "Controls pagination of results",
"properties": {
"cursor": {
"description": "Cursor for paginating through a list of items",
"type": "integer",
"format": "int32"
},
"limit": {
"description": "In a request, the maximum number of items to return. In a response, the total number of items available, if known.",
"type": "integer",
"format": "int32"
}
}
},
"Error": {
"type": "object",
"required": ["message"],
"properties": {
"message": {
"type": "string"
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment