This is the documentation for the pointercrate application programming interface (short: API). If you dont know what an API is or have no idea how you even got to this page, this link takes you back to the demonlist. If you rather want to read source code of the implementation directly, head over to the github repository instead. It also contains the markdown files these documentation pages are generated from, so if you find any error here feel free to submit a pull request!
The API can be used to retrieve data about the demonlist and is internally used to
manage it. All endpoints described here are located under
https://pointercrate.com/api/v1/ unless a different api version is
explicitly provided, in which case the v1 part of the URL needs to be amended.
Currently, there are only a few endpoints using a v2 scheme.
It is always good practice setting the Accept header in requests to
application/json (or at least give application/json a
higher preference than text/html), so that in case of errors, you
receive a JSON response instead of the HTML error page.
All HTTP traffic is automatically redirected to HTTPS. All requests to URLs without a trailing slash are automatically redirected to URLs with one.
In case of a client or server error, the API returns an error response. Errors that are specific to a given endpoint are always listed in that endpoint’s documentation. Following is an exhaustive list of errors that can occur at any endpoint in the API. Note that the errors with status code 500 INTERNAL SERVER ERROR should (obviously) not occur and are only listed for completeness sake. An complete list of all errors can be found at the bottom on this page.
| Status code | Error code | Description | Data |
|---|---|---|---|
| 400 | 40002 | A header in the request was malformed and couldn’t be processed | header: The name of the malformed header |
| 405 | 40500 | 405 METHOD NOT ALLOWED error | allowed_methods: A list of allowed HTTP methods |
| 409 | 40900 | 409 CONFLICT error | - |
| 412 | 41200 | If-Match header doesn’t match current state | - |
| 418 | 41800 | No If-Match header was provided | - |
| 500 | 50000 | Unexpected server error | - |
| 503 | 50300 | Endpoint down for maintenance | - |
In the case that you do not receive any response at all, or receive an Apache/Nginx error page you can assume that the pointercrate server crashed and couldn’t recover. If this is the case all hope is lost.
The cases in which a 409 CONFLICT error or a
412 PRECONDITION FAILED error is returned are very similar. In fact,
handling for both errors should probably be identical.
Both cases need to be handled the same way: re-GET the object to retrieve its updated ETag and retry the request.
Some endpoints in the API require HTTP Basic Authentication. Since all communication is enforced via HTTPS, this is OK.
Pointercrate requires a valid access token for most endpoints. Tokens are JSON Web Tokens and are retrieved via the login endpoint.
When required, set the Authorization header to:
Bearer <access token>.
Authentication via cookies is theoretically possible but not usable for API
access. Attempts will result in a 401 UNAUTHORIZED.
Different endpoints require different permissions. Permissions are stored as a bitmask, and higher permissions imply lower ones transitively.
| Permission | Bit | Description | Implies | Assigns |
|---|---|---|---|---|
| LIST_HELPER | 0x2 | Reviewing records | None | None |
| LIST_MODERATOR | 0x4 | Moderating the demonlist | LIST_HELPER | None |
| LIST_ADMINISTRATOR | 0x8 | Administrating the demonlist | LIST_MODERATOR | LIST_HELPER, LIST_MODERATOR |
| MODERATOR | 0x2000 | User list access | None | None |
| ADMINISTRATOR | 0x4000 | User management | MODERATOR | LIST_ADMINISTRATOR |
Some endpoints support pagination due to large result sets. Pagination is handled
via query parameters such as limit, after, and
before.
| Parameter | Description | Default |
|---|---|---|
| limit | Maximum objects to return (1–100) | 50 |
| after | ID of last object from previous page | null |
| before | ID of first object from next page | null |
?field=value__lt or __gt_contains
Example:
/api/v1/records/?after=200&limit=10&status=APPROVED&progress__lt=100
Pointercrate accepts videos from specific hosts and normalizes URLs into a single format per host.
| Host | Normalized URL |
|---|---|
| YouTube | https://www.youtube.com/watch?v={id} |
| Twitch | https://www.twitch.tv/videos/{id} |
| Everyplay | https://everyplay.com/videos/{id} |
| Vimeo | https://vimeo.com/{id} |
| Bilibili | https://www.bilibili.com/video/{id} |
The API aims to provide detailed errors wherever possible. Generic errors should be rare. Suggestions for better error communication are welcome via GitHub issues.
| Status code | Error code | Description | Data |
|---|---|---|---|
| 400 | 40000 | A generic 400 BAD REQUEST error | - |
| 400 | 40001 | Provided video or channel URL was malformed | - |
| 400 | 40002 | A header in the request was malformed and couldn’t be processed | header: The name of the malformed header |
| 401 | 40100 | A generic 401 UNAUTHORIZED error | - |
| 403 | 40300 | A generic 403 FORBIDDEN error | - |
| 403 | 40301 | You do not have the permissions required to perform this request | required: Permission bitmasks |
| 403 | 40302 | Attempt to delete your own account via administrative endpoints | - |
| 403 | 40303 | Attempt to modify your own account via administrative endpoints | - |
| 403 | 40304 | You have been banned from submitting records | - |
| 403 | 40305 | Attempt to assign non-assignable permissions | non_assignable: Permission bitmasks |
| 403 | 40306 | The claim you are trying to modify is unverified | - |
| 403 | 40307 | Attempt to geolocate through a VPN was detected | - |
| 403 | 40308 | Not authorized to submit a record for this player | - |
| 404 | 40400 | A generic 404 NOT FOUND error | - |
| 404 | 40401 | Referenced object could not be found | depends on endpoint |
| 405 | 40500 | 405 METHOD NOT ALLOWED error | allowed_methods |
| 409 | 40900 | 409 CONFLICT error | - |
| 409 | 40902 | Username already in use | - |
| 409 | 40905 | Player already registered as a creator | - |
| 409 | 40906 | Duplicate video when patching record | id: Record ID |
| 409 | 40907 | Subnation set without nation | - |
| 409 | 40908 | Conflicting verified user claims during merge | player1, player2 |
| 411 | 41100 | 411 LENGTH REQUIRED error | - |
| 412 | 41200 | 412 PRECONDITION FAILED | - |
| 413 | 41300 | 413 PAYLOAD TOO LARGE | - |
| 415 | 41500 | 415 UNSUPPORTED MEDIA TYPE | expected: application/json |
| 422 | 42200 | A generic 422 UNPROCESSABLE ENTITY error | - |
| 422 | 42202 | Username too short or not trimmed | - |
| 422 | 42204 | Password too short | - |
| 422 | 42207 | Invalid pagination limit | - |
| 422 | 42212 | Record requirement out of bounds | - |
| 422 | 42213 | Demon added out-of-bounds | maximal |
| 422 | 42215 | Invalid record progress | requirement |
| 422 | 42217 | Duplicate record submission | status, existing |
| 422 | 42218 | Record holder is banned | - |
| 422 | 42219 | Legacy demon record submitted | - |
| 422 | 42220 | Non-100% record on extended list | - |
| 422 | 42222 | Invalid URL protocol | - |
| 422 | 42223 | Authentication info in URL | - |
| 422 | 42224 | Unsupported video host | - |
| 422 | 42225 | Video URL format mismatch | expected |
| 422 | 42226 | YouTube URL expected | - |
| 422 | 42227 | Pagination after < before | - |
| 422 | 42228 | Ambiguous demon name | demons |
| 422 | 42229 | Mutually exclusive fields used | - |
| 422 | 42230 | Record note is empty | - |
| 422 | 42231 | Player already has verified claim | - |
| 422 | 42232 | Missing raw footage | - |
| 422 | 42233 | Invalid raw footage URL | - |
| 422 | 42234 | Password change not supported | - |
| 422 | 42235 | Invalid Geometry Dash level ID | - |
| 428 | 42800 | Missing If-Match header | - |
| 429 | 42900 | Rate limited | remaining |
| 500 | 50000 | Unexpected server state | - |
| 500 | 50003 | Database access error | - |
| 500 | 50004 | Database timeout | - |
| 500 | 50005 | Database connection failure | - |
| 503 | 50301 | Server in maintenance mode | - |