├── .github └── workflows │ └── publish.yml ├── .gitignore ├── LICENSE ├── README.md ├── slate.sh └── source ├── fonts ├── slate.eot ├── slate.svg ├── slate.ttf ├── slate.woff └── slate.woff2 ├── images ├── favicon.ico ├── logo.png └── navbar.png ├── includes ├── _code_challenges.md ├── _errors.md ├── _users.md └── _webhooks.md ├── index.html.md ├── javascripts ├── all.js ├── all_nosearch.js ├── app │ ├── _copy.js │ ├── _lang.js │ ├── _search.js │ └── _toc.js └── lib │ ├── _energize.js │ ├── _imagesloaded.min.js │ ├── _jquery.highlight.js │ ├── _jquery.js │ └── _lunr.js ├── layouts └── layout.erb └── stylesheets ├── _icon-font.scss ├── _normalize.scss ├── _rtl.scss ├── _variables.scss ├── print.css.scss └── screen.css.scss /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | on: 3 | push: 4 | branches: 5 | - master 6 | jobs: 7 | publish: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | # Create the build directory before binding so that directory is not owned by root. 12 | - run: mkdir -p build 13 | - run: ./slate.sh 14 | - run: echo "dev.codewars.com" > ./build/CNAME 15 | - uses: peaceiris/actions-gh-pages@v3 16 | with: 17 | github_token: ${{ secrets.GITHUB_TOKEN }} 18 | publish_dir: ./build 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | coverage 6 | InstalledFiles 7 | lib/bundler/man 8 | pkg 9 | rdoc 10 | spec/reports 11 | test/tmp 12 | test/version_tmp 13 | tmp 14 | *.DS_STORE 15 | build/ 16 | .cache 17 | 18 | # YARD artifacts 19 | .yardoc 20 | _yardoc 21 | doc/ 22 | .idea/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Codewars API Docs 2 | -------------------------------------------------------------------------------- /slate.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Exit on error and error on unbound variable. 3 | set -eu 4 | 5 | function usage() { 6 | if [ -n "$1" ]; then 7 | echo -e "$1\n"; 8 | fi 9 | 10 | echo "Usage: $0 [--serve] [--port port]"; 11 | echo " -s, --serve Start dev server. Build and exit without this."; 12 | echo " -p, --port The port for the dev server. Defaults to 4567"; 13 | echo ""; 14 | echo "Examples:"; 15 | echo " $0"; 16 | echo " $0 --serve --port 8888"; 17 | exit 1; 18 | } 19 | 20 | PORT=4567 21 | while [[ "$#" > 0 ]]; do case $1 in 22 | -s|--serve) SERVE="1"; shift;; 23 | -p|--port) PORT="$2"; shift; shift;; 24 | *) usage "Unknown parameter: $1"; shift; shift;; 25 | esac; done 26 | 27 | if [ -z "${SERVE:-}" ]; then 28 | echo "Building..."; 29 | docker run \ 30 | --rm \ 31 | -v $(pwd)/build:/srv/slate/build \ 32 | -v $(pwd)/source:/srv/slate/source \ 33 | slatedocs/slate:v2.9.2 34 | else 35 | echo "Starting dev server..."; 36 | docker run \ 37 | --rm \ 38 | -v $(pwd)/build:/srv/slate/build \ 39 | -v $(pwd)/source:/srv/slate/source \ 40 | -p $PORT:4567 \ 41 | slatedocs/slate:v2.9.2 \ 42 | serve 43 | fi 44 | -------------------------------------------------------------------------------- /source/fonts/slate.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codewars/codewars-api-docs/f3478173877bd12ccc415e61e8b02afaba309ea4/source/fonts/slate.eot -------------------------------------------------------------------------------- /source/fonts/slate.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /source/fonts/slate.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codewars/codewars-api-docs/f3478173877bd12ccc415e61e8b02afaba309ea4/source/fonts/slate.ttf -------------------------------------------------------------------------------- /source/fonts/slate.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codewars/codewars-api-docs/f3478173877bd12ccc415e61e8b02afaba309ea4/source/fonts/slate.woff -------------------------------------------------------------------------------- /source/fonts/slate.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codewars/codewars-api-docs/f3478173877bd12ccc415e61e8b02afaba309ea4/source/fonts/slate.woff2 -------------------------------------------------------------------------------- /source/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codewars/codewars-api-docs/f3478173877bd12ccc415e61e8b02afaba309ea4/source/images/favicon.ico -------------------------------------------------------------------------------- /source/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codewars/codewars-api-docs/f3478173877bd12ccc415e61e8b02afaba309ea4/source/images/logo.png -------------------------------------------------------------------------------- /source/images/navbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codewars/codewars-api-docs/f3478173877bd12ccc415e61e8b02afaba309ea4/source/images/navbar.png -------------------------------------------------------------------------------- /source/includes/_code_challenges.md: -------------------------------------------------------------------------------- 1 | # Code Challenges API 2 | 3 | ## Get Code Challenge 4 | 5 | Return a code challenge information. 6 | 7 | ```bash 8 | curl https://www.codewars.com/api/v1/code-challenges/valid-braces 9 | ``` 10 | 11 | > Response 12 | 13 | ```json 14 | { 15 | "id": "5277c8a221e209d3f6000b56", 16 | "name": "Valid Braces", 17 | "slug": "valid-braces", 18 | "url": "http://www.codewars.com/kata/valid-braces", 19 | "category": "algorithms", 20 | "description": "Write a function called `validBraces` that takes a string ...", 21 | "tags": ["Algorithms", "Validation", "Logic", "Utilities"], 22 | "languages": ["javascript", "coffeescript"], 23 | "rank": { 24 | "id": -4, 25 | "name": "4 kyu", 26 | "color": "blue" 27 | }, 28 | "createdBy": { 29 | "username": "xDranik", 30 | "url": "http://www.codewars.com/users/xDranik" 31 | }, 32 | "approvedBy": { 33 | "username": "xDranik", 34 | "url": "http://www.codewars.com/users/xDranik" 35 | }, 36 | "totalAttempts": 4911, 37 | "totalCompleted": 919, 38 | "totalStars": 12, 39 | "voteScore": 512, 40 | "publishedAt": "2013-11-05T00:07:31Z", 41 | "approvedAt": "2013-12-20T14:53:06Z" 42 | } 43 | ``` 44 | 45 | 46 | ### HTTP Request 47 | 48 | `https://www.codewars.com/api/v1/code-challenges/{challenge}` 49 | 50 | ### Path Parameters 51 | 52 | | Parameter | Description | 53 | | ----------- | -------------- | 54 | | `challenge` | ID or slug | 55 | 56 | 57 | ### CodeChallenge Object 58 | 59 | | Field | Type | Description | 60 | | -------------------- | ------------- | --------------------------------------- | 61 | | `id` | `string` | ID of the kata. | 62 | | `name` | `string` | Name of the kata. | 63 | | `slug` | `string` | Slug of the kata. | 64 | | `url` | `string` | URL of the kata. | 65 | | `category` | `string` | Category of the kata. | 66 | | `description` | `string` | Description of the kata in Markdown. | 67 | | `tags` | `string[]` | Array of tags associated with the kata. | 68 | | `languages` | `string[]` | Array of language names the kata is available in. | 69 | | `rank` | `object?` | Object describing the rank of the kata if approved. | 70 | | `createdBy` | `object` | The author of the kata. | 71 | | `publishedAt` | `string` | Date and time when the kata was first published. | 72 | | `approvedBy` | `object?` | The approver of the kata. | 73 | | `approvedAt` | `string` | Date and time when the kata was approved. | 74 | | `totalCompleted` | `number` | Total number of completions. | 75 | | `totalAttempts` | `number` | Total number of attempts. | 76 | | `totalStars` | `number` | The number of bookmarks. | 77 | | `voteScore` | `number` | The sum of all votes casted. | 78 | | `contributorsWanted` | `boolean` | Whether to allow contributions. | 79 | | `unresolved` | `object` | Object with fields `issues` and `suggestions` for the number of unresolved issues and suggestions respectively. | 80 | 81 | ### User Object 82 | 83 | | Field | Type | Description | 84 | | -------------------- | ------------- | --------------------------------------- | 85 | | `username` | `string` | Username of the user. | 86 | | `url` | `string` | URL of the user's profile. | 87 | 88 | 89 | -------------------------------------------------------------------------------- /source/includes/_errors.md: -------------------------------------------------------------------------------- 1 | # Errors 2 | 3 | Codewars uses conventional HTTP response codes to indicate success or failure of an API request. 4 | In general, codes in the 2xx range indicate success, codes in the 4xx range indicate an error that resulted from 5 | the provided information (e.g. a required parameter was missing, a charge failed, etc.), and codes in the 6 | 5xx range indicate an error with Codewars' servers. 7 | 8 | 9 | Error Code | Meaning 10 | ---------- | ------- 11 | 400 | Bad Request -- Something went wrong 12 | 401 | Unauthorized -- Your API key is wrong 13 | 403 | Forbidden -- You do not have permission to access this resource 14 | 404 | Not Found -- The specified resource could not be found 15 | 405 | Method Not Allowed -- You tried to access a resource with an invalid method 16 | 406 | Not Acceptable -- You requested a format that isn't json 17 | 422 | Unprocessable Entity -- Your input failed validation. 18 | 429 | Too Many Requests -- You're making too many API requests. 19 | 500 | Internal Server Error -- We had a problem with our server. Try again later. 20 | 503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later. 21 | -------------------------------------------------------------------------------- /source/includes/_users.md: -------------------------------------------------------------------------------- 1 | # Users API 2 | 3 | ## Get User 4 | 5 | Returns a user information. 6 | 7 | ```bash 8 | curl https://www.codewars.com/api/v1/users/some_user 9 | ``` 10 | 11 | > Response 12 | 13 | ```json 14 | { 15 | "username": "some_user", 16 | "name": "Some Person", 17 | "honor": 544, 18 | "clan": "some clan", 19 | "leaderboardPosition": 134, 20 | "skills": [ 21 | "ruby", 22 | "c#", 23 | ".net", 24 | "javascript", 25 | "coffeescript", 26 | "nodejs", 27 | "rails" 28 | ], 29 | "ranks": { 30 | "overall": { 31 | "rank": -3, 32 | "name": "3 kyu", 33 | "color": "blue", 34 | "score": 2116 35 | }, 36 | "languages": { 37 | "javascript": { 38 | "rank": -3, 39 | "name": "3 kyu", 40 | "color": "blue", 41 | "score": 1819 42 | }, 43 | "ruby": { 44 | "rank": -4, 45 | "name": "4 kyu", 46 | "color": "blue", 47 | "score": 1005 48 | }, 49 | "coffeescript": { 50 | "rank": -4, 51 | "name": "4 kyu", 52 | "color": "blue", 53 | "score": 870 54 | } 55 | } 56 | }, 57 | "codeChallenges": { 58 | "totalAuthored": 3, 59 | "totalCompleted": 230 60 | } 61 | } 62 | ``` 63 | 64 | ### HTTP Request 65 | 66 | `https://www.codewars.com/api/v1/users/{user}` 67 | 68 | ### Path Parameters 69 | 70 | | Parameter | Description | 71 | | --------- | -------------- | 72 | | `user` | Username or ID | 73 | 74 | ### User Object 75 | 76 | | Field | Type | Description | 77 | | --------------------- | ---------------------- | ----------------------------------------------- | 78 | | `username` | `string` | Username of the user. | 79 | | `name` | `string` | Name of the user. | 80 | | `honor` | `number` | Total honor points earned by the user. | 81 | | `clan` | `string` | Name of the clan. | 82 | | `leaderboardPosition` | `number` | The user's position on the overall leaderboard. | 83 | | `skills` | `string[]` | Array of skills entered by the user. | 84 | | `ranks` | `object` | Ranks object with overall and language ranks. | 85 | | `codeChallenges` | `object` | Object with fields `totalAuthored` and `totalCompleted` for the number of authored and completed kata respectively. | 86 | 87 | ### Ranks Object 88 | 89 | | Field | Type | Description | 90 | | --------------------- | ---------------------- | --------------------------------------------- | 91 | | `overall` | `object` | Overall rank. | 92 | | `languages` | `object` | Ranks for each language trained. | 93 | 94 | ### Rank Object 95 | 96 | | Field | Type | Description | 97 | | --------------------- | ---------------------- | -------------------------------------------------------------- | 98 | | `rank` | `number` | Rank in integer. `[-8, -1]` maps to kyu, `[1, 8]` maps to dan. | 99 | | `name` | `string` | Either `{-rank} kyu` or `{rank} dan`. | 100 | | `color` | `string` | The color of the rank. Possible colors are `white` (7-8 kyu), `yellow` (5-6 kyu), `blue` (3-4 kyu), `purple` (1-2 kyu), `black` (1-4 dan), and `red` (5-8 dan). | 101 | | `score` | `number` | The total score earned. This is the number that determines the rank. | 102 | 103 | 104 | ## List Completed Challenges 105 | 106 | Lists challenges completed by a user, 200 items per page. Use `page` parameter (zero based) to paginate. 107 | 108 | ```bash 109 | curl http://www.codewars.com/api/v1/users/some_user/code-challenges/completed?page=0 110 | ``` 111 | 112 | > Response 113 | 114 | ```json 115 | { 116 | "totalPages": 1, 117 | "totalItems": 1, 118 | "data": [ 119 | { 120 | "id": "514b92a657cdc65150000006", 121 | "name": "Multiples of 3 and 5", 122 | "slug": "multiples-of-3-and-5", 123 | "completedAt": "2017-04-06T16:32:09Z", 124 | "completedLanguages": [ 125 | "javascript", 126 | "coffeescript", 127 | "ruby", 128 | "javascript", 129 | "ruby", 130 | "javascript", 131 | "ruby", 132 | "coffeescript", 133 | "javascript", 134 | "ruby", 135 | "coffeescript" 136 | ] 137 | } 138 | ] 139 | } 140 | ``` 141 | 142 | 143 | ### HTTP Request 144 | 145 | `https://www.codewars.com/api/v1/users/{user}/code-challenges/completed?page={page}` 146 | 147 | ### Path Parameters 148 | 149 | | Parameter | Description | 150 | | --------- | -------------- | 151 | | `user` | Username or ID | 152 | 153 | ### Query Parameters 154 | 155 | | Parameter | Description | Default | 156 | | --------- | ------------------------------------------------------ | ------- | 157 | | `page` | The page offset. Each page contains at most 200 items. | 0 | 158 | 159 | ### CompletedChallenge Object 160 | 161 | | Field | Type | Description | 162 | | -------------------- | ----------- | --------------------------------------- | 163 | | `id` | `string` | ID of the kata. | 164 | | `name` | `string` | Name of the kata. | 165 | | `slug` | `string` | Slug of the kata. | 166 | | `completedAt` | `string` | Date and time of the completion. | 167 | | `completedLanguages` | `string[]` | Array of languages a user completed in. | 168 | 169 | 170 | 171 | ## List Authored Challenges 172 | 173 | List challenges authored by the user. 174 | 175 | ```bash 176 | curl http://www.codewars.com/api/v1/users/some_user/code-challenges/authored 177 | ``` 178 | 179 | > Response 180 | 181 | ```json 182 | { 183 | "data": [ 184 | { 185 | "id": "5571d9fc11526780a000011a", 186 | "name": "The builder of things", 187 | "description": "For this kata you will be using some meta-programming ...", 188 | "rank": -3, 189 | "rankName": "3 kyu", 190 | "tags": [ 191 | "Algorithms", 192 | "Metaprogramming", 193 | "Programming Paradigms", 194 | "Advanced Language Features", 195 | "Fundamentals", 196 | "Domain Specific Languages", 197 | "Declarative Programming" 198 | ], 199 | "languages": ["ruby", "javascript", "python", "coffeescript"] 200 | }, 201 | { 202 | "id": "51ba717bb08c1cd60f00002f", 203 | "name": "Range Extraction", 204 | "description": "A format for expressing an ordered list of integers ...", 205 | "rank": -4, 206 | "rankName": "4 kyu", 207 | "tags": [ 208 | "Algorithms", 209 | "String Formatting", 210 | "Formatting", 211 | "Logic", 212 | "Strings" 213 | ], 214 | "languages": [ 215 | "javascript", 216 | "coffeescript", 217 | "ruby", 218 | "go", 219 | "python", 220 | "java", 221 | "haskell", 222 | "csharp", 223 | "cpp" 224 | ] 225 | } 226 | ] 227 | } 228 | ``` 229 | 230 | ### HTTP Request 231 | 232 | `https://www.codewars.com/api/v1/users/{user}/code-challenges/authored` 233 | 234 | ### Path Parameters 235 | 236 | | Parameter | Description | 237 | | --------- | -------------- | 238 | | `user` | Username or ID | 239 | 240 | ### AuthoredChallenge Object 241 | 242 | | Field | Type | Description | 243 | | -------------------- | ------------- | --------------------------------------- | 244 | | `id` | `string` | ID of the kata. | 245 | | `name` | `string` | Name of the kata. | 246 | | `description` | `string` | Description of the kata in Markdown. | 247 | | `rank` | `number?` | Rank of the kata if approved. | 248 | | `rankName` | `string?` | Rank name of the kata if approved. | 249 | | `tags` | `string[]` | Array of tags associated with the kata. | 250 | | `languages` | `string[]` | Array of language names the kata is available in. | 251 | 252 | -------------------------------------------------------------------------------- /source/includes/_webhooks.md: -------------------------------------------------------------------------------- 1 | # Webhooks 2 | 3 | Webhooks allows you to receive notifications when events occur. 4 | 5 | Like API v1, webhooks feature was never actively developed and poorly documented. 6 | It's not very usable at the moment. 7 | 8 | ## Structure 9 | 10 | > Sample Event (Code Challenge Created) 11 | 12 | ``` 13 | User-Agent: Codewars Hookbot 14 | Content-Type: application/json 15 | X-Webhook-Event: code_challenge 16 | X-Webhook-Secret: some-shared-secret 17 | ``` 18 | 19 | ```json 20 | { 21 | "action": "created", 22 | "code_challenge": { 23 | "id": "50654ddff44f800200000001", 24 | "created_by_id": "508f2708b3be0c0200000002" 25 | } 26 | } 27 | ``` 28 | 29 | 30 | When an event occurs in the Codewars system, any relevant webhooks will be triggered to the specified URL. Typically, 31 | events are categorized into **event** and **actions**. Typically an event references *what type of model* 32 | (i.e. `code_challenge`) and the action references what happened to it (i.e. `created`). 33 | 34 | 35 | 38 | 39 | Webhooks typically contain a very small payload (often times, it only contains the `id` of some object). You may need 40 | to query the rest of the API to get more information about a particular object. 41 | 42 | ## Register your Webhook 43 | 44 | > Webhook Ping Event 45 | 46 | ``` 47 | User-Agent: Codewars Hookbot 48 | Content-Type: application/json 49 | X-Webhook-Event: webhook 50 | ``` 51 | ```json 52 | { 53 | "action": "updated", 54 | "webhook": { 55 | "id": "53aa3f265b97485984000001" 56 | } 57 | } 58 | ``` 59 | 60 | 61 | Visit your [Codewars account page](https://www.codewars.com/users/edit) and add a webhook. A webhook takes the 62 | following input: 63 | 64 | | Input | Meaning | 65 | | ----- | ------- | 66 | | Payload URL | The server endpoint that will relieve the webhook payload (e.g, `https://example.com/my/endpoint`) | 67 | | Secret | An optional secret shared between you and our webhook service. Ensures only Codewars is sending you the webhook | 68 | 69 | Once you create or update your webhook, your endpoint will receive a webhook updated event. 70 | 71 | ## Code Challenges 72 | 73 | > Sample Webhook Payload 74 | 75 | ``` 76 | User-Agent: Codewars Hookbot 77 | Content-Type: application/json 78 | X-Webhook-Event: code_challenge 79 | ``` 80 | 81 | ```json 82 | { 83 | "action": "", 84 | "code_challenge": { 85 | "id": "53aa3f265b97485984000001", 86 | "created_by_id": "53af25145b97487568000001" 87 | } 88 | } 89 | ``` 90 | > The solution_finalized also includes the following json: 91 | 92 | ```json 93 | { 94 | "solution": { 95 | "id": "53aa3f265b97485984000001", 96 | "user_id": "53417de006654f4171000587" 97 | } 98 | } 99 | ``` 100 | 101 | The following actions are supported: 102 | 103 | | Action | Meaning | 104 | | -------------------- | ------- | 105 | | `created` | Code challenge was created | 106 | | `approved` | A code challenge was successfully approved (no longer in beta state) | 107 | | `voted` | Someone voted on the code challenge. Does not specify what type of vote. | 108 | | `solution_finalized` | Someone submitted a solution to the code challenge | 109 | 110 | 111 | ## User 112 | 113 | 114 | > Webhook Headers 115 | 116 | ``` 117 | User-Agent: Codewars Hookbot 118 | Content-Type: application/json 119 | X-Webhook-Event: user 120 | ``` 121 | 122 | > `rank_earned` Event 123 | 124 | ```json 125 | { 126 | "action": "rank_earned", 127 | "user": { 128 | "id": "53aa3f265b97485984000001", 129 | "rank": -5 130 | }, 131 | "language": null 132 | } 133 | ``` 134 | 135 | > `honor_changed` Event 136 | 137 | ```json 138 | { 139 | "action": "honor_changed", 140 | "user": { 141 | "id": "53aa3f265b97485984000001", 142 | "honor": 420, 143 | "honor_delta": 3 144 | } 145 | } 146 | ``` 147 | 148 | The following actions are supported: 149 | 150 | | Action | Meaning | 151 | | --------------- | ------- | 152 | | `rank_earned` | The user's rank has been upgraded. Could be a global rank, or a language rank | 153 | | `honor_changed` | The user's honor has changed (usually in a positive direction) | 154 | -------------------------------------------------------------------------------- /source/index.html.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Codewars API Reference 3 | 4 | language_tabs: 5 | - shell 6 | 7 | toc_footers: 8 | - codewars.com 9 | - github.com/codewars 10 | 11 | includes: 12 | - users 13 | - code_challenges 14 | - webhooks 15 | - errors 16 | 17 | search: true 18 | --- 19 | 20 | # Introduction 21 | 22 | Codewars API v1 is minimal and inconsistent. It was never actively developed. 23 | 24 | API v2 is planned, but there's no ETA at the moment. 25 | 26 | ## Authentication 27 | 28 | Not required. API v1 endpoints are all public. 29 | 30 | ## Content-Type 31 | 32 | API v1 endpoints responds with JSON (`application/json`). 33 | -------------------------------------------------------------------------------- /source/javascripts/all.js: -------------------------------------------------------------------------------- 1 | //= require ./all_nosearch 2 | //= require ./app/_search 3 | -------------------------------------------------------------------------------- /source/javascripts/all_nosearch.js: -------------------------------------------------------------------------------- 1 | //= require ./lib/_energize 2 | //= require ./app/_copy 3 | //= require ./app/_toc 4 | //= require ./app/_lang 5 | 6 | function adjustLanguageSelectorWidth() { 7 | const elem = $('.dark-box > .lang-selector'); 8 | elem.width(elem.parent().width()); 9 | } 10 | 11 | $(function() { 12 | loadToc($('#toc'), '.toc-link', '.toc-list-h2', 10); 13 | setupLanguages($('body').data('languages')); 14 | $('.content').imagesLoaded( function() { 15 | window.recacheHeights(); 16 | window.refreshToc(); 17 | }); 18 | 19 | $(window).resize(function() { 20 | adjustLanguageSelectorWidth(); 21 | }); 22 | adjustLanguageSelectorWidth(); 23 | }); 24 | 25 | window.onpopstate = function() { 26 | activateLanguage(getLanguageFromQueryString()); 27 | }; 28 | -------------------------------------------------------------------------------- /source/javascripts/app/_copy.js: -------------------------------------------------------------------------------- 1 | function copyToClipboard(container) { 2 | const el = document.createElement('textarea'); 3 | el.value = container.textContent.replace(/\n$/, ''); 4 | document.body.appendChild(el); 5 | el.select(); 6 | document.execCommand('copy'); 7 | document.body.removeChild(el); 8 | } 9 | 10 | function setupCodeCopy() { 11 | $('pre.highlight').prepend('
Copy to Clipboard
'); 12 | $('.copy-clipboard').on('click', function() { 13 | copyToClipboard(this.parentNode.children[1]); 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /source/javascripts/app/_lang.js: -------------------------------------------------------------------------------- 1 | //= require ../lib/_jquery 2 | 3 | /* 4 | Copyright 2008-2013 Concur Technologies, Inc. 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); you may 7 | not use this file except in compliance with the License. You may obtain 8 | a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15 | License for the specific language governing permissions and limitations 16 | under the License. 17 | */ 18 | ;(function () { 19 | 'use strict'; 20 | 21 | var languages = []; 22 | 23 | window.setupLanguages = setupLanguages; 24 | window.activateLanguage = activateLanguage; 25 | window.getLanguageFromQueryString = getLanguageFromQueryString; 26 | 27 | function activateLanguage(language) { 28 | if (!language) return; 29 | if (language === "") return; 30 | 31 | $(".lang-selector a").removeClass('active'); 32 | $(".lang-selector a[data-language-name='" + language + "']").addClass('active'); 33 | for (var i=0; i < languages.length; i++) { 34 | $(".highlight.tab-" + languages[i]).hide(); 35 | $(".lang-specific." + languages[i]).hide(); 36 | } 37 | $(".highlight.tab-" + language).show(); 38 | $(".lang-specific." + language).show(); 39 | 40 | window.recacheHeights(); 41 | 42 | // scroll to the new location of the position 43 | if ($(window.location.hash).get(0)) { 44 | $(window.location.hash).get(0).scrollIntoView(true); 45 | } 46 | } 47 | 48 | // parseURL and stringifyURL are from https://github.com/sindresorhus/query-string 49 | // MIT licensed 50 | // https://github.com/sindresorhus/query-string/blob/7bee64c16f2da1a326579e96977b9227bf6da9e6/license 51 | function parseURL(str) { 52 | if (typeof str !== 'string') { 53 | return {}; 54 | } 55 | 56 | str = str.trim().replace(/^(\?|#|&)/, ''); 57 | 58 | if (!str) { 59 | return {}; 60 | } 61 | 62 | return str.split('&').reduce(function (ret, param) { 63 | var parts = param.replace(/\+/g, ' ').split('='); 64 | var key = parts[0]; 65 | var val = parts[1]; 66 | 67 | key = decodeURIComponent(key); 68 | // missing `=` should be `null`: 69 | // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters 70 | val = val === undefined ? null : decodeURIComponent(val); 71 | 72 | if (!ret.hasOwnProperty(key)) { 73 | ret[key] = val; 74 | } else if (Array.isArray(ret[key])) { 75 | ret[key].push(val); 76 | } else { 77 | ret[key] = [ret[key], val]; 78 | } 79 | 80 | return ret; 81 | }, {}); 82 | }; 83 | 84 | function stringifyURL(obj) { 85 | return obj ? Object.keys(obj).sort().map(function (key) { 86 | var val = obj[key]; 87 | 88 | if (Array.isArray(val)) { 89 | return val.sort().map(function (val2) { 90 | return encodeURIComponent(key) + '=' + encodeURIComponent(val2); 91 | }).join('&'); 92 | } 93 | 94 | return encodeURIComponent(key) + '=' + encodeURIComponent(val); 95 | }).join('&') : ''; 96 | }; 97 | 98 | // gets the language set in the query string 99 | function getLanguageFromQueryString() { 100 | if (location.search.length >= 1) { 101 | var language = parseURL(location.search).language; 102 | if (language) { 103 | return language; 104 | } else if (jQuery.inArray(location.search.substr(1), languages) != -1) { 105 | return location.search.substr(1); 106 | } 107 | } 108 | 109 | return false; 110 | } 111 | 112 | // returns a new query string with the new language in it 113 | function generateNewQueryString(language) { 114 | var url = parseURL(location.search); 115 | if (url.language) { 116 | url.language = language; 117 | return stringifyURL(url); 118 | } 119 | return language; 120 | } 121 | 122 | // if a button is clicked, add the state to the history 123 | function pushURL(language) { 124 | if (!history) { return; } 125 | var hash = window.location.hash; 126 | if (hash) { 127 | hash = hash.replace(/^#+/, ''); 128 | } 129 | history.pushState({}, '', '?' + generateNewQueryString(language) + '#' + hash); 130 | 131 | // save language as next default 132 | if (localStorage) { 133 | localStorage.setItem("language", language); 134 | } 135 | } 136 | 137 | function setupLanguages(l) { 138 | var defaultLanguage = null; 139 | if (localStorage) { 140 | defaultLanguage = localStorage.getItem("language"); 141 | } 142 | 143 | languages = l; 144 | 145 | var presetLanguage = getLanguageFromQueryString(); 146 | if (presetLanguage) { 147 | // the language is in the URL, so use that language! 148 | activateLanguage(presetLanguage); 149 | 150 | if (localStorage) { 151 | localStorage.setItem("language", presetLanguage); 152 | } 153 | } else if ((defaultLanguage !== null) && (jQuery.inArray(defaultLanguage, languages) != -1)) { 154 | // the language was the last selected one saved in localstorage, so use that language! 155 | activateLanguage(defaultLanguage); 156 | } else { 157 | // no language selected, so use the default 158 | activateLanguage(languages[0]); 159 | } 160 | } 161 | 162 | // if we click on a language tab, activate that language 163 | $(function() { 164 | $(".lang-selector a").on("click", function() { 165 | var language = $(this).data("language-name"); 166 | pushURL(language); 167 | activateLanguage(language); 168 | return false; 169 | }); 170 | }); 171 | })(); 172 | -------------------------------------------------------------------------------- /source/javascripts/app/_search.js: -------------------------------------------------------------------------------- 1 | //= require ../lib/_lunr 2 | //= require ../lib/_jquery 3 | //= require ../lib/_jquery.highlight 4 | ;(function () { 5 | 'use strict'; 6 | 7 | var content, searchResults; 8 | var highlightOpts = { element: 'span', className: 'search-highlight' }; 9 | var searchDelay = 0; 10 | var timeoutHandle = 0; 11 | var index; 12 | 13 | function populate() { 14 | index = lunr(function(){ 15 | 16 | this.ref('id'); 17 | this.field('title', { boost: 10 }); 18 | this.field('body'); 19 | this.pipeline.add(lunr.trimmer, lunr.stopWordFilter); 20 | var lunrConfig = this; 21 | 22 | $('h1, h2').each(function() { 23 | var title = $(this); 24 | var body = title.nextUntil('h1, h2'); 25 | lunrConfig.add({ 26 | id: title.prop('id'), 27 | title: title.text(), 28 | body: body.text() 29 | }); 30 | }); 31 | 32 | }); 33 | determineSearchDelay(); 34 | } 35 | 36 | $(populate); 37 | $(bind); 38 | 39 | function determineSearchDelay() { 40 | if (index.tokenSet.toArray().length>5000) { 41 | searchDelay = 300; 42 | } 43 | } 44 | 45 | function bind() { 46 | content = $('.content'); 47 | searchResults = $('.search-results'); 48 | 49 | $('#input-search').on('keyup',function(e) { 50 | var wait = function() { 51 | return function(executingFunction, waitTime){ 52 | clearTimeout(timeoutHandle); 53 | timeoutHandle = setTimeout(executingFunction, waitTime); 54 | }; 55 | }(); 56 | wait(function(){ 57 | search(e); 58 | }, searchDelay); 59 | }); 60 | } 61 | 62 | function search(event) { 63 | 64 | var searchInput = $('#input-search')[0]; 65 | 66 | unhighlight(); 67 | searchResults.addClass('visible'); 68 | 69 | // ESC clears the field 70 | if (event.keyCode === 27) searchInput.value = ''; 71 | 72 | if (searchInput.value) { 73 | var results = index.search(searchInput.value).filter(function(r) { 74 | return r.score > 0.0001; 75 | }); 76 | 77 | if (results.length) { 78 | searchResults.empty(); 79 | $.each(results, function (index, result) { 80 | var elem = document.getElementById(result.ref); 81 | searchResults.append("
  • " + $(elem).text() + "
  • "); 82 | }); 83 | highlight.call(searchInput); 84 | } else { 85 | searchResults.html('
  • '); 86 | $('.search-results li').text('No Results Found for "' + searchInput.value + '"'); 87 | } 88 | } else { 89 | unhighlight(); 90 | searchResults.removeClass('visible'); 91 | } 92 | } 93 | 94 | function highlight() { 95 | if (this.value) content.highlight(this.value, highlightOpts); 96 | } 97 | 98 | function unhighlight() { 99 | content.unhighlight(highlightOpts); 100 | } 101 | })(); 102 | 103 | -------------------------------------------------------------------------------- /source/javascripts/app/_toc.js: -------------------------------------------------------------------------------- 1 | //= require ../lib/_jquery 2 | //= require ../lib/_imagesloaded.min 3 | ;(function () { 4 | 'use strict'; 5 | 6 | var htmlPattern = /<[^>]*>/g; 7 | var loaded = false; 8 | 9 | var debounce = function(func, waitTime) { 10 | var timeout = false; 11 | return function() { 12 | if (timeout === false) { 13 | setTimeout(function() { 14 | func(); 15 | timeout = false; 16 | }, waitTime); 17 | timeout = true; 18 | } 19 | }; 20 | }; 21 | 22 | var closeToc = function() { 23 | $(".toc-wrapper").removeClass('open'); 24 | $("#nav-button").removeClass('open'); 25 | }; 26 | 27 | function loadToc($toc, tocLinkSelector, tocListSelector, scrollOffset) { 28 | var headerHeights = {}; 29 | var pageHeight = 0; 30 | var windowHeight = 0; 31 | var originalTitle = document.title; 32 | 33 | var recacheHeights = function() { 34 | headerHeights = {}; 35 | pageHeight = $(document).height(); 36 | windowHeight = $(window).height(); 37 | 38 | $toc.find(tocLinkSelector).each(function() { 39 | var targetId = $(this).attr('href'); 40 | if (targetId[0] === "#") { 41 | headerHeights[targetId] = $("#" + $.escapeSelector(targetId.substring(1))).offset().top; 42 | } 43 | }); 44 | }; 45 | 46 | var refreshToc = function() { 47 | var currentTop = $(document).scrollTop() + scrollOffset; 48 | 49 | if (currentTop + windowHeight >= pageHeight) { 50 | // at bottom of page, so just select last header by making currentTop very large 51 | // this fixes the problem where the last header won't ever show as active if its content 52 | // is shorter than the window height 53 | currentTop = pageHeight + 1000; 54 | } 55 | 56 | var best = null; 57 | for (var name in headerHeights) { 58 | if ((headerHeights[name] < currentTop && headerHeights[name] > headerHeights[best]) || best === null) { 59 | best = name; 60 | } 61 | } 62 | 63 | // Catch the initial load case 64 | if (currentTop == scrollOffset && !loaded) { 65 | best = window.location.hash; 66 | loaded = true; 67 | } 68 | 69 | var $best = $toc.find("[href='" + best + "']").first(); 70 | if (!$best.hasClass("active")) { 71 | // .active is applied to the ToC link we're currently on, and its parent