2018-04-25 05:02:41 +00:00
import Widget from require "lapis.html"
2018-04-25 05:34:47 +00:00
import domain from require("lapis.config").get!
if domain == "localhost"
domain = "http://localhost"
else
domain = "https://#{domain}"
2018-04-25 05:02:41 +00:00
class Docs_1 extends Widget
content: =>
task_list = ->
ul ->
li ->
2018-04-25 05:34:47 +00:00
a href: "#new", "/new"
2018-04-25 05:02:41 +00:00
text " { content: string }"
li ->
2018-04-25 05:34:47 +00:00
a href: "#get", "/get"
2018-04-25 05:02:41 +00:00
text " { id: integer, content: string }"
li ->
2018-04-25 05:34:47 +00:00
a href: "#do", "/do"
2018-04-25 05:02:41 +00:00
text " { id: integer, content: string }"
li ->
2018-04-25 05:34:47 +00:00
a href: "#undo", "/undo"
2018-04-25 05:02:41 +00:00
text " { id: integer, content: string }"
li ->
2018-04-25 05:34:47 +00:00
a href: "#delete", "/delete"
2018-04-25 05:02:41 +00:00
text " { id: integer, content: string }"
li ->
2018-04-25 05:34:47 +00:00
a href: "#list", "/list"
2018-04-25 05:02:41 +00:00
text " { count: integer, done: boolean, page: integer, order: 'asc'/'desc' }"
li ->
2018-04-25 05:34:47 +00:00
a href: "#random", "/random"
2018-04-25 05:02:41 +00:00
text " { count: integer, done: boolean }"
2018-04-25 06:19:42 +00:00
style -> raw "
h3 { font-family: monospace; }
.top { font-size: 1.33rem; }
2018-04-25 06:23:58 +00:00
blockquote > code { white-space: normal; }
2018-04-25 06:19:42 +00:00
"
2018-04-25 05:02:41 +00:00
2018-04-25 05:59:07 +00:00
a name: "top"
2018-04-25 05:02:41 +00:00
ol style: "font-family: monospace;", ->
2018-04-25 05:34:47 +00:00
li ->
a href: "#endpoints", "Endpoints"
2018-04-25 05:02:41 +00:00
li ->
a href: "#auth", "Authorization"
li ->
a href: "#tasks", "Tasks"
task_list!
li ->
a href: "#keys", "API Keys"
ul ->
li ->
2018-04-25 05:34:47 +00:00
a href: "#new-key", "/key/new"
2018-04-25 05:02:41 +00:00
li ->
2018-04-25 05:34:47 +00:00
a href: "#delete-key", "/key/delete"
2018-04-25 05:02:41 +00:00
text " { id: integer, key: string }"
2018-04-25 05:34:47 +00:00
li ->
a href: "#errors", "Errors"
li ->
a href: "#rate-limit", "Rate Limiting"
2018-04-25 15:25:54 +00:00
li ->
a href: "#changes", "Changes"
2018-04-25 15:30:16 +00:00
li ->
a href: "#next", "Coming Next"
2018-04-25 05:34:47 +00:00
a name: "endpoints"
h2 "Endpoints"
p ->
text "All endpoints are at "
2018-04-25 05:36:27 +00:00
code "#{domain}/v1"
2018-04-25 05:34:47 +00:00
text ", so for example, to get an existing task, send a POST request to "
2018-04-25 05:36:27 +00:00
code "#{domain}/v1/get"
2018-04-25 05:34:47 +00:00
text " with the appropriate JSON and authorization (listed below)."
p ->
text "All endpoints return a JSON object with a "
code "success"
text " boolean set to "
code "true"
text " and additional object data depending on the endpoint, or an "
code "errors"
text " array stating any errors in usage or encountered during processing. See "
a href: "#errors", "Errors"
text " below for more info on that."
2018-04-25 05:02:41 +00:00
2018-04-25 06:19:42 +00:00
a class: ".top", href: "#top", "back to top"
2018-04-25 05:02:41 +00:00
a name: "auth"
h2 "Authorization"
p "Authorization is done using a session cookie on the web interface, or an API key sent along with API requests."
p ->
text "API keys can be sent in an Authorization header or as an "
code "api_key"
text " field in JSON."
blockquote ->
code "Authorization: JDJiJDEyJFRPaG0wOW16VXhoUTd3dElB"
blockquote ->
code '{ "api_key": "JDJiJDEyJFRPaG0wOW16VXhoUTd3dElB" }'
p ->
text "Grab an API key from "
a href: @url_for("index"), "the web interface"
text " to get started. You can also delete existing API keys there."
2018-04-25 06:19:42 +00:00
a class: ".top", href: "#top", "back to top"
2018-04-25 05:02:41 +00:00
a name: "tasks"
h2 "Tasks"
p ->
text "Version 1 of this API is extremely simple. POST "
code '{ "content": "this is a todo item" }'
text " with valid authorization to "
2018-04-25 05:34:47 +00:00
code "/new"
2018-04-25 05:02:41 +00:00
text " to add tasks. The next four endpoints ("
2018-04-25 05:34:47 +00:00
code "/get"
2018-04-25 05:02:41 +00:00
text ","
2018-04-25 05:34:47 +00:00
code "/do"
2018-04-25 05:02:41 +00:00
text ","
2018-04-25 05:34:47 +00:00
code "/undo"
2018-04-25 05:02:41 +00:00
text ","
2018-04-25 05:34:47 +00:00
code "/delete"
2018-04-25 05:02:41 +00:00
text ") all use the same input to complete their operations (an "
code "id"
text " integer or "
code "content"
text " boolean)."
p ->
2018-04-25 05:34:47 +00:00
code "/list"
2018-04-25 05:02:41 +00:00
text " and "
2018-04-25 05:34:47 +00:00
code "/random"
2018-04-25 05:02:41 +00:00
text " are a little more complex, and explained further below."
task_list!
2018-04-25 06:19:42 +00:00
a class: ".top", href: "#top", "back to top"
2018-04-25 05:02:41 +00:00
a name: "new"
2018-04-25 05:34:47 +00:00
h3 "/new"
2018-04-25 05:20:16 +00:00
p ->
2018-04-25 05:34:47 +00:00
text "As stated above, to create a new task, just POST a "
2018-04-25 05:20:16 +00:00
code "content"
2018-04-25 05:34:47 +00:00
text " string with valid authorization and a new task item will be returned. Here's an example response:"
2018-04-25 05:20:16 +00:00
blockquote ->
2018-04-25 06:23:58 +00:00
code '{ "success": true, "task": { "id": 4, "user_id": 2, "content": "Get a new API key.", "done": false, "created_at": "2018-04-25 04:27:47", "updated_at": "2018-04-25 04:27:47" } }'
2018-04-25 05:20:16 +00:00
2018-04-25 05:34:47 +00:00
p ->
text "This same format is used to return any task, whether it is as a response to these simple queries, or as part of an array returned by "
code "/list"
text " or "
code "/random"
text "."
2018-04-25 05:02:41 +00:00
2018-04-25 06:19:42 +00:00
a class: ".top", href: "#top", "back to top"
2018-04-25 05:02:41 +00:00
a name: "get"
2018-04-25 05:34:47 +00:00
h3 "/get"
2018-04-25 05:02:41 +00:00
2018-04-25 05:59:07 +00:00
p ->
text "Select a task by its "
code "id"
text " (an integer), or its "
code "content"
text " (a string). Example request:"
blockquote ->
code '{ "id": 5 }'
p ->
text "See "
a href: "#new", "/new"
text " for an example response."
2018-04-25 06:19:42 +00:00
a class: ".top", href: "#top", "back to top"
2018-04-25 05:02:41 +00:00
a name: "do"
2018-04-25 05:34:47 +00:00
h3 "/do"
2018-04-25 05:02:41 +00:00
2018-04-25 05:59:07 +00:00
p "Marks a task as done. Returns success even if the task was already marked done. Example request:"
blockquote ->
code '{ "content": "that one thing you need to remember to do" }'
p ->
text "See "
a href: "#new", "/new"
text " for an example response."
2018-04-25 06:19:42 +00:00
a class: ".top", href: "#top", "back to top"
2018-04-25 05:02:41 +00:00
a name: "undo"
2018-04-25 05:34:47 +00:00
h3 "/undo"
2018-04-25 05:02:41 +00:00
2018-04-25 05:59:07 +00:00
p ->
text "Marks a task as not done. Returns success even if the task was already marked not done. See "
a href: "#new", "/new"
text " for an example response."
2018-04-25 06:19:42 +00:00
a class: ".top", href: "#top", "back to top"
2018-04-25 05:02:41 +00:00
a name: "delete"
2018-04-25 05:34:47 +00:00
h3 "/delete"
2018-04-25 05:02:41 +00:00
2018-04-25 05:59:07 +00:00
p ->
text "Deletes a task. Just returns "
code '{ "success": true }'
text " if successful."
2018-04-25 06:19:42 +00:00
a class: ".top", href: "#top", "back to top"
2018-04-25 05:02:41 +00:00
a name: "list"
2018-04-25 05:34:47 +00:00
h3 "/list"
2018-04-25 05:02:41 +00:00
2018-04-25 05:59:07 +00:00
p ->
text "Returns an array of task objects (see "
a href: "#new", "/new"
text " for an example task object). All arguments are optional:"
element "table", ->
thead ->
tr ->
th "Argument"
th "Type"
th "Default"
tbody ->
tr ->
td -> code "count"
td "integer"
td 50
tr ->
td -> code "done"
td "boolean"
td "returns ALL tasks if not set"
tr ->
td -> code "page"
td "integer"
td 1
tr ->
td -> code "order"
td "'asc'/'desc'"
td "'asc' (oldest first)"
p ->
text "If you request a page beyond the number of pages available, the last page will be returned. "
code "page"
text " is specified in the response, so you will know if you have received a different page than requested. Additionally, "
code "pages"
text " is defined in all requests to "
code "/list"
text ". Example response (with tasks trimmed out):"
blockquote ->
code '{ "success": true, page: 5, pages: 10, tasks: [ /* task list omitted */ ] }'
2018-04-25 06:19:42 +00:00
a class: ".top", href: "#top", "back to top"
2018-04-25 05:02:41 +00:00
a name: "random"
2018-04-25 05:34:47 +00:00
h3 "/random"
2018-04-25 05:02:41 +00:00
2018-04-25 06:19:42 +00:00
p "This is the only endpoint not currently implemented. This documentation will be updated once it is finished."
-- TODO /random { count: #, done: bool } (both args optional, defaults count 1, done false)
a class: ".top", href: "#top", "back to top"
2018-04-25 05:02:41 +00:00
a name: "keys"
h2 "API Keys"
2018-04-25 06:19:42 +00:00
p "The API can be used to request new API keys and delete API keys, but cannot be used to look up API keys, or perform any other actions with API keys."
a class: ".top", href: "#top", "back to top"
2018-04-25 05:02:41 +00:00
a name: "new-key"
2018-04-25 05:34:47 +00:00
h3 "/key/new"
2018-04-25 05:02:41 +00:00
2018-04-25 06:19:42 +00:00
p "Send an empty request. Receive the following:"
blockquote ->
code '{ "success": true, "api_key": { "id": 4, "user_id": 1, "key": "<key text omitted>", "created_at": "2018-04-25 06:05:53", "updated_at": "2018-04-25 06:05:53" } }'
p "NOTE: For some reason, API key IDs are not being returned with API keys currently."
a class: ".top", href: "#top", "back to top"
2018-04-25 05:02:41 +00:00
a name: "delete-key"
2018-04-25 05:34:47 +00:00
h3 "/key/delete"
2018-04-25 06:19:42 +00:00
p ->
text "Send a POST request with "
code "id"
text " or "
code "key"
text " defined to delete an API key. Note: You can delete the API key you are currently using with this endpoint, so be careful!"
p ->
text "Returns just the "
code '{ "success": true }'
text " JSON if successful."
a class: ".top", href: "#top", "back to top"
2018-04-25 05:34:47 +00:00
a name: "errors"
h2 "Errors"
2018-04-25 06:19:42 +00:00
p "In addition to an array of errors (usually only consisting of one error message), the HTTP status returned will indicate errors:"
ul ->
li "400: Bad Request. This means something on the client-side did not call the API correctly."
li "404: Not Found. This means the requested item doesn't exist."
li "500: Internal Server Error. Something went wrong with the server while processing your request."
li ->
text "501: Not Implemented. This error should only exist for the next few hours/days as I finish implementing "
code "/random"
text ", the only part of the API not already implemented."
p "Right now, please report any 500 errors you encounter. In the future, these will be logged automatically."
a class: ".top", href: "#top", "back to top"
2018-04-25 05:34:47 +00:00
a name: "rate-limit"
h2 "Rate Limiting"
p "At this time there is no rate limiting. This will be developed when needed, and the API documentation updated to reflect that, with at least 2 months' warning."
2018-04-25 05:02:41 +00:00
2018-04-25 06:19:42 +00:00
a class: ".top", href: "#top", "back to top"
2018-04-25 15:25:54 +00:00
a name: "changes"
h2 "Changes"
p "I intend to keep support for v1 of the API indefinitely. If new features require backwards-incompatible API changes, those will be released under a new version of the API, and v1 will remain accessible for at least 6 months before switching."
p "All new features that do not require modifications to existing API calls will be added to v1 as they are introduced. The next version of the API will only exist if backwards-incompatible changes are introduced."
a class: ".top", href: "#top", "back to top"
a name: "next"
h2 "Coming Next"
p "Until I implement an a tracking system for features/bugs, here is a brief list of features to be added 'soon', and a few known bugs:"
ul ->
li ->
text "Implementing "
code "/random"
text " endpoint."
li ->
code "/edit"
text " endpoint for modifying the "
code "content"
text " of a task. The web interface will also be updated to utilize this."
li ->
code "/search"
text " endpoint. The web interface will also be updated to utilize this."
li "Lists (including the ability to have lists of lists). The API and web interface will receive several updates for this."
li ->
code "/duplicate"
text " endpoint for duplicating a task or list (with optional inclusion of any sub-tasks/sub-lists). The web interface will be updated to utilize this."
li "CLI program for interacting with the API."
2018-04-25 15:29:09 +00:00
li ->
span class: "error", "BUG"
text ": IDs are not returned with requests to "
2018-04-25 15:25:54 +00:00
code "/key/new"
text " endpoint."
li "Twitter integration."
li "Data export. (Note: Initially will be a large JSON dump, but you can contact me if you have special needs for data export and I will develop these upon request.)"
p "And this is a list of ideas that may or may not be coming a bit later on, still being thought about:"
ul ->
li "Email integration."
li "Reminders."
li "Recurring tasks."
li "Shared tasks."
li "Customization of web interface. (e.g. select between current interface and a kanban-style board)"
li "Reordering tasks/lists. (This one requires some research on my part of how to implement this efficiently.)"
li "Tagging system (for tasks/lists)."
li "Due dates/times."
li "Webhooks."
li "OAuth2 support."
li "Import from other todo/task management software."
p "Finally, this is a list of a few site-related things I need to get set up:"
ul ->
li "A homepage for non-users showing features / enticing sign-up. Of course. :P"
li "A dynamically updated page showing project status, both in terms of budget (income/expenses) and features/bugs. (This will also allow users to vote for features/bugs to be prioritized.)"
li "A page for accepting payments. At this stage, this is optional and I will be relying purely on people wanting to see this system succeed. In the future, more advanced API features may be behind a subscription model (intended to be $1.50/year)."
a class: ".top", href: "#top", "back to top"