The pointercrate API

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.

Errors

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 for this endpoint
409 40900 409 CONFLICT error. The resources you attempted to modify or delete has been concurrently modified by another client. Try again after re-requesting the resource
412 41200 The value provided in the If-Match header doesn’t match the current state of the object
418 41800 No If-Match header was provided, although the request needs to be conditional
500 50000 The server encountered an unexpected state and couldn’t recover
500 50001 Same as above, but we actually know what happened cause: The cause of the error
500 50003 The database unexpectedly returned an error while accessing the data required to perform the request
500 50005 Failure to connect to the database
503 50300 The requested endpoint is currently down for maintenance

In the case that you do not receive any response at all, or receive a 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.

409 versus 412

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. A 409 error is returned if the request you were making contained a valid hash of the object you were trying to access, however the same was true for another concurrent request. Which ever of the requests commits its database level transaction might now receive the CONFLICT error. A 412 error means that a modification to the object you were trying to access happen at some point prior to your current request (or the hash you sent along was invalid in the first place).

Both cases need to be handled the same way: You’ll have to re-GET the object to retrieve its updated ETag and retry the request (simply retrying after a 409 error will most likely yield a 412 error directly after)

Authentication

Basic

Some endpoints in the API require you to authenticate using HTTP Basic Authentication. Since all communication with the API is enforced to be done via HTTPS, this is OK.

Access tokens

Pointercrate requires you to have a valid access token to issue requests to most endpoints. An access token for your account can be retrieved via a successful call to the login endpoint.

Pointercrate access tokens are JSON Web Tokens and can be parsed by any standard compliant implementation.

Each access token is valid until you change your password, or is invalidated via a call to invalidate.

When an endpoint requires authentication via an access token, the Authorization header has to be set to the word Bearer followed by a space, followed by your access token.

Cookies

Theoretically, it is possible to authenticate using cookies. Any requests made from your browser through the web interface are authenticated this way. Practically, you cannot use this authentication method (attempting to do so will simply result in a 401 UNAUTHORIZED response)

Errors

These error conditions apply to any endpoint that require authentication and are thus not repeated for every one of them.

Status code Error code Description
401 40100 A generic 401 UNAUTHORIZED error, indicating that authorization failed (e.g. because of a bad username, wrong password, wrong authorization method )

Permissions

Different endpoints require different kinds of permissions to be used. Additionally, access to user objects via the sub-endpoints of /users/ is also governed by permissions. In particular, you can only access accounts of users who have permissions that you can assign (with the exception of people having MODERATOR privileges, who can access all user accounts).

If an endpoints requires special permissions to be accessed, it’s documentation will contain a notice similar to this one:

Access Restrictions:
Access to this endpoint requires at least LIST_HELPER permissions.

A user’s permissions are saved as a bitmask, and by default every user has no permissions.

Available permissions

The following permissions exist. If a permissions A implies some other permission B, then a user with permission A can do everything a user with permission B can do, without needing to explicitly having the bit for permission B set. For example, a user with only the LIST_MODERATOR bit set also has all privileges that the LIST_HELPER bit grants. Note that implication of permissions in transitive, e.g. a user with only the LIST_ADMINISTRATOR bit set still has all privileges that the LIST_HELPER bit grants, since LIST_ADMINISTRATOR implies LIST_MODERATOR, which implies LIST_HELPER.

If a permission A assigns some other permission B then a user with permission A can modify the bit for permission B via PATCH /users/user_id/ of users he has access to.

Permission Bit Description Implies Assigns
LIST_HELPER 0x2 Users that help out in managing the demonlist by reviewing records None None
LIST_MODERATOR 0x4 Users that moderate the demonlist and manage the demon placements LIST_HELPER None
LIST_ADMINISTRATOR 0x8 Users that administrate the demonlist LIST_MODERATOR LIST_HELPER, LIST_MODERATOR
MODERATOR 0x2000 Users that have access to the pointercrate user list None None
ADMINISTRATOR 0x4000 Users that can manage other users, including granting them permissions MODERATOR LIST_ADMINISTRATOR, LIST_HELPER

Errors

These error conditions can occur at any endpoint expecting requiring specific access permissions and are thus not listed specifically for each of them.

Status code Error code Description Data
403 40301 You do not have the permissions required to perform this request required: A list of permission-bitmasks that would allow you to perform the request

Pagination and Filtering

Some endpoints in the pointercrate API support or require pagination due to the potentially huge amount of data they can return. This mostly applies to the endpoints that return lists of objects, like GET /records/.

Objects returned by endpoints supporting pagination are totally ordered by an ID field, which is specified in the endpoint’s documentation.

If an endpoint supports pagination, it’s documentation will contain a notice similar to this one:

Pagination:
This endpoint supports pagination and filtering via query parameters. Please see the documentation on pagination for information on the additional request and response headers.

Pagination Query Parameters

Pagination is done via specific query parameters, which tell pointercrate which part of the result set to return.

Note that there is no way to get the total amount of pages, as both page bounds and size can be chosen abitrarily.

Query Parameter Description Default
limit The maximum amount of object to return. Must lie between 1 and 100 50
after The id of the last object on the previous page, thus specifying the start point of the current page null
before The id of the first object on the next page, thus specifying the end point of the current page null

Omitting before or after, which implicitly sets them to null, makes the server act like they’re set to negative/positive infinity respectively.

Pagination Response Headers

Paginatable endpoints provide the Links header to simply access to the next, previous, first and last page, using the limit set on the request. The header is set to a comma-seperated list of links in the form <[link]>; rel=[page], where page is one of next, prev, first or last.

Note that the next and prev links are only provided if there actually is a next or previous page of results respectively. The server always provides the first and last links.

Filtering

Most endpoints that support pagination also support filtering their results beyond simply using the pagination parameters.

If this is supported, the documentation specifies the filterable fields for a given endpoint. It is then possible to specify conditions in the query string, which the returned objects must meet.

There are two ways of filtering the result set:

  • Filtering by equality: The objects returned can be filtered by a specific field’s value by specifying the field and a value in the query string, i.e. /api/v1/players/?banned=true
  • Filtering by inequality: The objects returned can be filtered by whether a field is smaller/greater than a specific value by specifying the field, suffixed with either __lt or __gt, and the value to check for inequality against in the query string, i.e. /api/v1/records/?progress__gt=75. Note that this doesn’t work for all fields (since a lexicographical filtering on the record status hardly seems useful)
  • Filtering by infix: Some string-values fields support filtering objects where said string field contains a specific infix. This is done by suffixing the field’s name with _contains.

Multiple conditions can be combined, i.e. /api/v1/records/?after=200&limit=10&status=APPROVED&progress__lt=100. This request would return the first 10 approved records with a record ID greater than 200 and a progress less than 100.

Note that filtering explicitly on the ID field is not possible. You have to use the special before and after parameters for that. You also cannot use equality filtering on the ID field. Use the specific endpoint for retrieving single objects instead.

Errors:

These error conditions can occur at any endpoint supporting pagination and are thus not listed specifically for each of them.

Status code Error code Description
422 42207 The limit parameter is smaller than 1 or greater than 100
422 42227 In pagination, the after value was smaller than the before value

External Videos

Valid video formats

Pointercrate only accepts videos from a specific set of hosting services. It further normalizes all videos from a given host into one specific URL format and ensures that every video link actually leads to a valid video. All query parameters, including timestamps on youtube videos, are stripped from URLs.

If a host you want to see supported is missing or a URL format for one of the provided hosts is missing, please open an issue on the GitHub repository.

Please note that pointercrate asynchronously performs HEAD requests to any video URL submitted and discards any that don’t return a successful response.

The accepted URL formats are:

Video host URL formats
YouTube http[s]://www.youtube.com/watch?v={id}
YouTube http[s]://m.youtube.com/watch?v={id}
YouTube http[s]://youtube.com/watch?v={id}
YouTube http[s]://youtu.be/{id}
Twitch http[s]://www.twitch.tv/videos/{id}
Twitch http[s]://twitch.tv/videos/{id}
Twitch http[s]://www.twitch.tv/{name}/v/{id}
Twitch http[s]://twitch.tv/{name}/v/{id}
Everyplay http[s]://www.everyplay.com/videos/{id}
Everyplay http[s]://everyplay.com/videos/{id}
Vimeo http[s]://www.vimeo.com/{id}
Vimeo http[s]://vimeo.com/{id}
Bilibili http[s]://www.bilibili.com/video/{id}
Bilibili http[s]://bilibili.com/video/{id}

They are normalized into the following:

Video host URL format
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}

Errors

These error conditions can occur at any endpoint expecting a video URL and are thus not listed specifically for each of them.

Status code Error code Description Data
422 42222 Invalid protocol encountered while processing an URL. Only http and https are supported -
422 42223 Authentication information was discovered while processing an URL -
422 42224 An unknown/unsupported video host has been discovered while processing an URL (no, pornhub is no acceptable host, what is wrong with you people??) -
422 42225 The video URL does not match the expected format for the given host expected: The expected URL format for this host

List of Errors

In general it is the goal to have the API provide as detailed errors as possible. The generic error variants should be returned as rarely as possible. If you feel like a specific error could be communicated better, feel free to open an issue in the GitHub repository!

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, indicating that authorization failed (e.g. because of a bad username, wrong password, wrong authorization method ) -
403 40300 A generic 403 FORBIDDEN error -
403 40301 You do not have the permissions required to perform this request required: A list of permission-bitmasks that would allow you to perform the request
403 40302 Attempt to delete your own account via the administrative endpoints -
403 40303 Attempt to modify your own account via the administrative endpoints -
403 40304 You have been banned from submitting records -
403 40305 Attempt to assign someone permissions that you do not have the permissions to assign non_assignable: A list of permission bitmasks that you cannot assign
403 40306 The claim you are trying to modify is unverified -
403 40307 An attempt to geolocate through a VPN was detected -
403 40308 You are not authorized to submit a record for this player -
404 40400 A generic 404 NOT FOUND error -
404 40401 Some object referenced in the request couldn’t be found -
405 40500 405 METHOD NOT ALLOWED error allowed_methods: A list of allowed HTTP methods for this endpoint
409 40900 409 CONFLICT error. The resources you attempted to modify or delete has been concurrently modified by another client. Try again after re-requesting the resource -
409 40902 The username you chose is already in use -
409 40905 The given player is already registered as a creator -
409 40906 Duplicate video when patching record id: ID of the record already using the specified video
409 40907 Attempting to set a subnation without a nation set -
409 40908 Two players have conflicting verified user claims during merge player1: First (base) player name
player2: Second player name
411 41100 A generic 411 LENGTH REQUIRED error -
412 41200 412 PRECONDITION FAILED error. The provided If-Match header doesn’t match the current state of the object -
413 41300 413 PAYLOAD TOO LARGE error -
415 41500 415 UNSUPPORTED MEDIA TYPE error. Returned if you try to send anything that’s not a JSON request body expected: The expected media type. Currently always application/json
422 42200 A generic 422 UNPROCESSABLE ENTITY error -
422 42202 The username provided during registration is shorter than 3 characters or isn’t trimmed -
422 42204 The password provided during registration is shorter than 10 characters -
422 42207 The limit pagination parameter is smaller than 1 or greater than 100 -
422 42212 A demon was attempted to be added with a record requirement outside the interval [0, 100] -
422 42213 A demon was attempted to be added out-of-bounds maximal: The largest position it is acceptable to add a demon at
422 42215 A record with invalid progress was submitted requirement: The record requirement for the demon the record was submitted on
422 42217 A record that’s already in the database was submitted status: The status of the existing record
existing: The ID of the existing record
422 42218 The record holder of a submission is banned -
422 42219 A record for a legacy demon was submitted -
422 42220 A non-100% record was submitted for the extended list -
422 42222 Invalid protocol encountered while processing an URL. Only http and https are supported -
422 42223 Authentication information was discovered while processing an URL -
422 42224 An unknown/unsupported video host has been discovered while processing an URL (no, pornhub is no acceptable host, what is wrong with you people??) -
422 42225 The video URL does not match the expected format for the given host expected: The expected URL format for this host
422 42226 A YouTube url was expected -
422 42227 In pagination, the after value was smaller than the before value -
422 42228 A demon was specified by name, but multiple demons with the given name exist demons: A list of MinimalDemon objects sharing the given name
422 42229 Your request body tries to simultaneously use mutually exclusive fields (e.g. demon_id together with demon_name) -
422 42230 The record note is empty -
422 42231 Player already has an associated verified claim -
422 42232 A record without raw footage was submitted -
422 42233 Provided raw footage was not a valid URL -
428 42800 Missing If-Match header on a request that’s required to be conditional -
429 42900 You are being rate limited remaining: The time you have to wait before successfully making the request
500 50000 The server encountered an unexpected state and couldn’t recover -
500 50003 The database unexpectedly returned an error while accessing the data required to perform the request -
500 50005 Failure to connect to the database -
503 50301 The server is in maintenance mode and rejects all mutating requests -