Basic concepts¶
This page describes basic concepts and definition that you need to know to interact with pretix’ REST API, such as authentication, pagination and similar definitions.
Authentication¶
To access the API, you need to present valid authentication credentials. pretix currently supports the following authorization schemes:
Token-based authentication: This is the simplest way and recommended for server-side applications that interact with pretix without user interaction.
OAuth authentication / “Connect with pretix”: This is the recommended way to use if you write a third-party application that users can connect with their pretix account. It provides the best user experience, but requires user interaction and slightly more implementation effort.
Device authentication: This is the recommended way if you build apps or hardware devices that can connect to pretix, e.g. for processing check-ins or to sell tickets offline. It provides a way to uniquely identify devices and allows for a quick configuration flow inside your software.
Authentication using browser sessions: This is used by the pretix web interface and it is not officially supported for use by third-party applications. It might change or be removed at any time without prior notice. If you use it, you need to comply with Django’s CSRF policies.
Permissions¶
The API follows pretix team based permissions model. Each organizer can have several teams each with it’s own set of permissions. Each team can have any number of API keys attached.
To access a given endpoint the team the API key belongs to needs to have the corresponding permission for the organizer/event being accessed.
Possible permissions are:
Can create events
Can change event settings
Can change product settings
Can view orders
Can change orders
Can view vouchers
Can change vouchers
Compatibility¶
We try to avoid any breaking changes to our API to avoid hassle on your end. If possible, we’ll build new features in a way that keeps all pre-existing API usage unchanged. In some cases, this might not be possible or only possible with restrictions. In these case, any backwards-incompatible changes will be prominently noted in the “Changes to the REST API” section of our release notes. If possible, we will announce them multiple releases in advance.
We treat the following types of changes as backwards-compatible so we ask you to make sure that your clients can deal with them properly:
Support of new API endpoints
Support of new HTTP methods for a given API endpoint
Support of new query parameters for a given API endpoint
New fields contained in API responses
New possible values of enumeration-like fields
Response body structure or message texts on failed requests (
4xx
,5xx
response codes)
We treat the following types of changes as backwards-incompatible:
Type changes of fields in API responses
New required input fields for an API endpoint
New required type for input fields of an API endpoint
Removal of endpoints, API methods or fields
Pagination¶
Most lists of objects returned by pretix’ API will be paginated. The response will take the form of:
{
"count": 117,
"next": "https://pretix.eu/api/v1/organizers/?page=2",
"previous": null,
"results": […],
}
As you can see, the response contains the total number of results in the field count
.
The fields next
and previous
contain links to the next and previous page of results,
respectively, or null
if there is no such page. You can use those URLs to retrieve the
respective page.
The field results
contains a list of objects representing the first results. For most
objects, every page contains 50 results. You can specify a lower pagination size using the
page_size
query parameter, but no more than 50.
Conditional fetching¶
If you pull object lists from pretix’ APIs regularly, we ask you to implement conditional fetching to avoid unnecessary data traffic. This is not supported on all resources and we currently implement two different mechanisms for different resources, which is necessary because we can only obtain best efficiency for resources that do not support deletion operations.
Object-level conditional fetching¶
The Orders resource list contains an HTTP header called X-Page-Generated
containing the
current time on the server in ISO 8601 format. On your next request, you can pass this header
(as is, without any modifications necessary) as the modified_since
query parameter and you will receive
a list containing only objects that have changed in the time since your last request.
List-level conditional fetching¶
If modification checks are not possible with this granularity, you can instead check for the full list.
In this case, the list of objects may contain a regular HTTP header Last-Modified
with the date of the
last modification to any item of that resource. You can then pass this date back in your next request in the
If-Modified-Since
header. If the any object has changed in the meantime, you will receive back a full list
(if something it missing, this means the object has been deleted). If nothing happened, we’ll send back a
304 Not Modified
return code.
This is currently implemented on the following resources:
Errors¶
Error responses (of type 400-499) are returned in one of the following forms, depending on the type of error. General errors look like:
HTTP/1.1 405 Method Not Allowed
Content-Type: application/json
Content-Length: 42
{"detail": "Method 'DELETE' not allowed."}
Field specific input errors include the name of the offending fields as keys in the response:
HTTP/1.1 400 Bad Request
Content-Type: application/json
Content-Length: 94
{"amount": ["A valid integer is required."], "description": ["This field may not be blank."]}
If you see errors of type 429 Too Many Requests
, you should read our documentation on Rate limiting.
Data types¶
All structured API responses are returned in JSON format using standard JSON data types such
as integers, floating point numbers, strings, lists, objects and booleans. Most fields can
be null
as well.
The following table shows some data types that have no native JSON representation and how we serialize them to JSON.
Internal pretix type |
JSON representation |
Examples |
---|---|---|
Datetime |
String in ISO 8601 format with timezone (normally UTC) |
|
Date |
String in ISO 8601 format |
|
Multi-lingual string |
Object of strings |
|
Money |
String with decimal number |
|
Currency |
String with ISO 4217 code |
|
Relative datetime |
either String in ISO 8601 format or specification of a relative datetime, constructed from a number of days before the base point, a time of day, and the base point. |
|
Relative date |
either String in ISO 8601 format or specification of a relative date, constructed from a number of days before the base point and the base point. |
|
File |
URL in responses, |
|
Date range |
either two dates separated
by |
|
Query parameters¶
Most list endpoints allow a filtering of the results using query parameters. In this case, booleans should be passed
as the string values true
and false
.
If the ordering
parameter is documented for a resource, you can use it to sort the result set by one of the allowed
fields. Prepend a -
to the field name to reverse the sort order.
Idempotency¶
Our API supports an idempotency mechanism to make sure you can safely retry operations without accidentally performing them twice. This is useful if an API call experiences interruptions in transit, e.g. due to a network failure, and you do not know if it completed successfully.
To perform an idempotent request, add a X-Idempotency-Key
header with a random string value (we recommend a version
4 UUID) to your request. If we see a second request with the same X-Idempotency-Key
and the same Authorization
and Cookie
headers, we will not perform the action for a second time but return the exact same response instead.
Please note that this also goes for most error responses. For example, if we returned you a 403 Permission Denied
error and you retry with the same X-Idempotency-Key
, you will get the same error again, even if you were granted
permission in the meantime! This includes internal server errors on our side that might have been fixed in the meantime.
There are only the following exceptions to the rule:
Responses with status code
409 Conflict
are not cached. If you send the request again, it will be executed as a new request, since these responses are intended to be retried.Rate-limited responses with status code
429 Too Many Requests
are not cached and you can safely retry them.Responses with status code
500 Internal Server Error
are not cached and you can retry them. This is not guaranteed to be safe in all theoretical cases, but 500 by definition is an unforeseen situation and we need to have some way out.Responses with status code
503 Service Unavailable
are not cached and you can safely retry them.
If you send a request with an X-Idempotency-Key
header that we have seen before but that has not yet received a
response, you will receive a response with status code 409 Conflict
and are asked to retry after five seconds.
We store idempotency keys for 24 hours, so you should never retry a request after a longer time period.
All POST
, PUT
, PATCH
, or DELETE
api calls support idempotency keys. Adding an idempotency key to a
GET
, HEAD
, or OPTIONS
request has no effect.
File upload¶
In some places, the API supports working with files, for example when setting the picture of a product. In this case, you will first need to make a separate request to our file upload endpoint:
POST /api/v1/upload HTTP/1.1
Host: pretix.eu
Authorization: Token e1l6gq2ye72thbwkacj7jbri7a7tvxe614ojv8ybureain92ocub46t5gab5966k
Content-Type: image/png
Content-Disposition: attachment; filename="logo.png"
Content-Length: 1234
<raw file content>
Note that the Content-Type
and Content-Disposition
headers are required. If the upload was successful, you will
receive a JSON response with the ID of the file:
HTTP/1.1 201 Created
Content-Type: application/json
{
"id": "file:1cd99455-1ebd-4cda-b1a2-7a7d2a969ad1"
}
You can then use this file ID in the request you want to use it in. File IDs are currently valid for 24 hours and can only be used using the same authorization method and user that was used to upload them.
PATCH /api/v1/organizers/test/events/test/items/3/ HTTP/1.1
Host: pretix.eu
Content-Type: application/json
{
"picture": "file:1cd99455-1ebd-4cda-b1a2-7a7d2a969ad1"
}