Compare commits

..

1 Commits

Author SHA1 Message Date
Raphael Michel
3b62737d4c Widget: Support for inline seating plan 2022-12-22 13:24:42 +01:00
1129 changed files with 302831 additions and 926278 deletions

View File

@@ -6,13 +6,11 @@
version: 2
updates:
- package-ecosystem: "pip"
directory: "/"
directory: "/src"
schedule:
interval: "daily"
versioning-strategy: increase
open-pull-requests-limit: 10
- package-ecosystem: "npm"
directory: "/src/pretix/static/npm_dir"
schedule:
interval: "monthly"
open-pull-requests-limit: 5

View File

@@ -1,49 +0,0 @@
name: Build
on:
push:
branches: [ master ]
paths-ignore:
- 'doc/**'
- 'src/pretix/locale/**'
pull_request:
branches: [ master ]
paths-ignore:
- 'doc/**'
- 'src/pretix/locale/**'
permissions:
contents: read # to fetch code (actions/checkout)
env:
FORCE_COLOR: 1
jobs:
test:
runs-on: ubuntu-22.04
name: Packaging
strategy:
matrix:
python-version: ["3.11"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install system dependencies
run: sudo apt update && sudo apt install -y gettext unzip
- name: Install Python dependencies
run: pip3 install -U setuptools build pip check-manifest
- name: Run check-manifest
run: check-manifest
- name: Run build
run: python -m build
- name: Check files
run: unzip -l dist/pretix*whl | grep node_modules || exit 1

View File

@@ -25,19 +25,19 @@ jobs:
name: Spellcheck
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
- uses: actions/checkout@v2
- name: Set up Python 3.9
uses: actions/setup-python@v1
with:
python-version: 3.11
- uses: actions/cache@v4
python-version: 3.9
- uses: actions/cache@v1
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install system packages
run: sudo apt update && sudo apt install -y enchant-2 hunspell aspell-en
run: sudo apt update && sudo apt install enchant-2 hunspell aspell-en
- name: Install Dependencies
run: pip3 install -Ur requirements.txt
working-directory: ./doc

View File

@@ -23,21 +23,22 @@ jobs:
runs-on: ubuntu-22.04
name: Check gettext syntax
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
- uses: actions/checkout@v2
- name: Set up Python 3.9
uses: actions/setup-python@v1
with:
python-version: 3.11
- uses: actions/cache@v4
python-version: 3.9
- uses: actions/cache@v1
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install system packages
run: sudo apt update && sudo apt -y install gettext
run: sudo apt update && sudo apt install gettext
- name: Install Dependencies
run: pip3 install uv && uv pip install --system -e ".[dev]"
run: pip3 install -e ".[dev]"
working-directory: ./src
- name: Compile messages
run: python manage.py compilemessages
working-directory: ./src
@@ -48,12 +49,12 @@ jobs:
runs-on: ubuntu-22.04
name: Spellcheck
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
- uses: actions/checkout@v2
- name: Set up Python 3.9
uses: actions/setup-python@v1
with:
python-version: 3.11
- uses: actions/cache@v4
python-version: 3.9
- uses: actions/cache@v1
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
@@ -62,7 +63,8 @@ jobs:
- name: Install system packages
run: sudo apt update && sudo apt install enchant-2 hunspell hunspell-de-de aspell-en aspell-de
- name: Install Dependencies
run: pip3 install uv && uv pip install --system -e ".[dev]"
run: pip3 install -e ".[dev]"
working-directory: ./src
- name: Spellcheck translations
run: potypo
working-directory: ./src

View File

@@ -23,19 +23,20 @@ jobs:
name: isort
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
- uses: actions/checkout@v2
- name: Set up Python 3.9
uses: actions/setup-python@v1
with:
python-version: 3.11
- uses: actions/cache@v4
python-version: 3.9
- uses: actions/cache@v1
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install Dependencies
run: pip3 install uv && uv pip install --system -e ".[dev]" psycopg2-binary
run: pip3 install -e ".[dev]" mysqlclient psycopg2-binary
working-directory: ./src
- name: Run isort
run: isort -c .
working-directory: ./src
@@ -43,19 +44,20 @@ jobs:
name: flake8
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
- uses: actions/checkout@v2
- name: Set up Python 3.9
uses: actions/setup-python@v1
with:
python-version: 3.11
- uses: actions/cache@v4
python-version: 3.9
- uses: actions/cache@v1
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install Dependencies
run: pip3 install uv && uv pip install --system -e ".[dev]" psycopg2-binary
run: pip3 install -e ".[dev]" mysqlclient psycopg2-binary
working-directory: ./src
- name: Run flake8
run: flake8 .
working-directory: ./src
@@ -63,11 +65,11 @@ jobs:
name: licenseheaders
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
- uses: actions/checkout@v2
- name: Set up Python 3.9
uses: actions/setup-python@v1
with:
python-version: 3.11
python-version: 3.9
- name: Install Dependencies
run: pip3 install licenseheaders
- name: Run licenseheaders

View File

@@ -5,6 +5,7 @@ on:
branches: [ master ]
paths-ignore:
- 'doc/**'
- 'src/pretix/locale/**'
pull_request:
branches: [ master ]
paths-ignore:
@@ -23,42 +24,47 @@ jobs:
name: Tests
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11"]
database: [sqlite, postgres]
python-version: ["3.7", "3.9", "3.10"]
database: [sqlite, postgres, mysql]
exclude:
- database: sqlite
- database: mysql
python-version: "3.10"
- database: mysql
python-version: "3.9"
- database: sqlite
python-version: "3.7"
- database: sqlite
python-version: "3.10"
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: pretix
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
- uses: getong/mariadb-action@v1.1
with:
mariadb version: '10.4'
mysql database: 'pretix'
mysql root password: ''
if: matrix.database == 'mysql'
- uses: harmon758/postgresql-action@v1
with:
postgresql version: '11'
postgresql db: 'pretix'
postgresql user: 'postgres'
postgresql password: 'postgres'
if: matrix.database == 'postgres'
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- uses: actions/cache@v4
- uses: actions/cache@v1
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install system dependencies
run: sudo apt update && sudo apt install -y gettext
run: sudo apt update && sudo apt install gettext mariadb-client
- name: Install Python dependencies
run: pip3 install uv && uv pip install --system -e ".[dev]" psycopg2-binary
run: pip3 install --ignore-requires-python -e ".[dev]" mysqlclient psycopg2-binary # We ignore that flake8 needs newer python as we don't run flake8 during tests
working-directory: ./src
- name: Run checks
run: python manage.py check
working-directory: ./src
@@ -70,15 +76,10 @@ jobs:
run: make all compress
- name: Run tests
working-directory: ./src
run: PRETIX_CONFIG_FILE=tests/ci_${{ matrix.database }}.cfg py.test -n 3 -p no:sugar --cov=./ --cov-report=xml --reruns 3 tests --maxfail=100
- name: Run concurrency tests
working-directory: ./src
run: PRETIX_CONFIG_FILE=tests/ci_${{ matrix.database }}.cfg py.test tests/concurrency_tests/ --reruns 0 --reuse-db
if: matrix.database == 'postgres'
run: PRETIX_CONFIG_FILE=tests/travis_${{ matrix.database }}.cfg py.test -n 3 -p no:sugar --cov=./ --cov-report=xml --reruns 3 tests --maxfail=100
- name: Upload coverage
uses: codecov/codecov-action@v1
with:
file: src/coverage.xml
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: false
if: matrix.database == 'postgres' && matrix.python-version == '3.11'
fail_ci_if_error: true
if: matrix.database == 'postgres' && matrix.python-version == '3.10'

2
.gitignore vendored
View File

@@ -1,6 +1,4 @@
env/
build/
dist/
.coverage
htmlcov/
.ropeproject

View File

@@ -1,45 +1,44 @@
before_script:
tests:
image:
name: pretix/ci-image
stage: test
before_script:
- pip install -U pip uv
- uv pip install --system -U wheel setuptools
script:
- uv pip install --system -e ".[dev]"
- virtualenv env
- source env/bin/activate
- pip install -U pip wheel setuptools
- cd src
- XDG_CACHE_HOME=/cache pip3 install -e ".[dev]"
- python manage.py check
- make all compress
- PRETIX_CONFIG_FILE=tests/ci_sqlite.cfg py.test --reruns 3 -n 3 tests --maxfail=100
- py.test --reruns 3 -n 3 tests
tags:
- python3
except:
- pypi
pypi:
stage: release
image:
name: pretix/ci-image
before_script:
- cat $PYPIRC > ~/.pypirc
- pip install -U pip uv
- uv pip install --system -U wheel setuptools twine build pretix-plugin-build check-manifest
script:
- uv pip install --system -e ".[dev]"
- cp /keys/.pypirc ~/.pypirc
- virtualenv env
- source env/bin/activate
- pip install -U pip wheel setuptools check-manifest twine
- cd src
- XDG_CACHE_HOME=/cache pip3 install -e ".[dev]"
- python setup.py sdist
- uv pip install --system dist/pretix-*.tar.gz
- pip install dist/pretix-*.tar.gz
- python -m pretix migrate
- python -m pretix check
- cd src
- make npminstall
- cd ..
- check-manifest
- python -m build
- make npminstall
- python setup.py sdist bdist_wheel
- twine check dist/*
- twine upload dist/*
tags:
- python3
only:
- pypi
artifacts:
paths:
- src/dist/
stages:
- test
- build

View File

@@ -1 +0,0 @@
17

View File

@@ -1,8 +1,9 @@
FROM python:3.11-bookworm
FROM python:3.9-bullseye
RUN apt-get update && \
apt-get install -y --no-install-recommends \
build-essential \
libmariadb-dev \
gettext \
git \
libffi-dev \
@@ -18,27 +19,38 @@ RUN apt-get update && \
python3-dev \
sudo \
supervisor \
libmaxminddb0 \
libmaxminddb-dev \
zlib1g-dev \
nodejs \
npm && \
zlib1g-dev && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* && \
dpkg-reconfigure locales && \
locale-gen C.UTF-8 && \
/usr/sbin/update-locale LANG=C.UTF-8 && \
dpkg-reconfigure locales && \
locale-gen C.UTF-8 && \
/usr/sbin/update-locale LANG=C.UTF-8 && \
mkdir /etc/pretix && \
mkdir /data && \
useradd -ms /bin/bash -d /pretix -u 15371 pretixuser && \
echo 'pretixuser ALL=(ALL) NOPASSWD:SETENV: /usr/bin/supervisord' >> /etc/sudoers && \
mkdir /static && \
mkdir /etc/supervisord
mkdir /etc/supervisord && \
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash - && \
apt-get install -y nodejs && \
curl -qL https://www.npmjs.com/install.sh | sh
ENV LC_ALL=C.UTF-8 \
DJANGO_SETTINGS_MODULE=production_settings
# To copy only the requirements files needed to install from PIP
COPY src/setup.py /pretix/src/setup.py
RUN pip3 install -U \
pip \
setuptools \
wheel && \
cd /pretix/src && \
PRETIX_DOCKER_BUILD=TRUE pip3 install \
-e ".[memcached,mysql]" \
gunicorn django-extensions ipython && \
rm -rf ~/.cache/pip
COPY deployment/docker/pretix.bash /usr/local/bin/pretix
COPY deployment/docker/supervisord /etc/supervisord
COPY deployment/docker/supervisord.all.conf /etc/supervisord.all.conf
@@ -46,27 +58,17 @@ COPY deployment/docker/supervisord.web.conf /etc/supervisord.web.conf
COPY deployment/docker/nginx.conf /etc/nginx/nginx.conf
COPY deployment/docker/nginx-max-body-size.conf /etc/nginx/conf.d/nginx-max-body-size.conf
COPY deployment/docker/production_settings.py /pretix/src/production_settings.py
COPY pyproject.toml /pretix/pyproject.toml
COPY _build /pretix/_build
COPY src /pretix/src
RUN pip3 install -U \
pip \
setuptools \
wheel && \
cd /pretix && \
PRETIX_DOCKER_BUILD=TRUE pip3 install \
-e ".[memcached]" \
gunicorn django-extensions ipython && \
rm -rf ~/.cache/pip
RUN cd /pretix/src && python setup.py install
RUN chmod +x /usr/local/bin/pretix && \
rm /etc/nginx/sites-enabled/default && \
cd /pretix/src && \
rm -f pretix.cfg && \
mkdir -p data && \
chown -R pretixuser:pretixuser /pretix /data data && \
sudo -u pretixuser make production
rm -f pretix.cfg && \
mkdir -p data && \
chown -R pretixuser:pretixuser /pretix /data data && \
sudo -u pretixuser make production
USER pretixuser
VOLUME ["/etc/pretix", "/data"]

View File

@@ -1,50 +0,0 @@
include LICENSE
include README.rst
include src/Makefile
include _build/backend.py
global-include *.proto
recursive-include src/pretix/static *
recursive-include src/pretix/static.dist *
recursive-include src/pretix/locale *
recursive-include src/pretix/helpers/locale *
recursive-include src/pretix/base/templates *
recursive-include src/pretix/control/templates *
recursive-include src/pretix/presale/templates *
recursive-include src/pretix/plugins/autocheckin/templates *
recursive-include src/pretix/plugins/autocheckin/static *
recursive-include src/pretix/plugins/banktransfer/templates *
recursive-include src/pretix/plugins/banktransfer/static *
recursive-include src/pretix/plugins/manualpayment/templates *
recursive-include src/pretix/plugins/manualpayment/static *
recursive-include src/pretix/plugins/paypal/templates *
recursive-include src/pretix/plugins/paypal/static *
recursive-include src/pretix/plugins/paypal2/templates *
recursive-include src/pretix/plugins/paypal2/static *
recursive-include src/pretix/plugins/src/pretixdroid/templates *
recursive-include src/pretix/plugins/src/pretixdroid/static *
recursive-include src/pretix/plugins/sendmail/templates *
recursive-include src/pretix/plugins/statistics/templates *
recursive-include src/pretix/plugins/statistics/static *
recursive-include src/pretix/plugins/stripe/templates *
recursive-include src/pretix/plugins/stripe/static *
recursive-include src/pretix/plugins/ticketoutputpdf/templates *
recursive-include src/pretix/plugins/ticketoutputpdf/static *
recursive-include src/pretix/plugins/badges/templates *
recursive-include src/pretix/plugins/badges/static *
recursive-include src/pretix/plugins/returnurl/templates *
recursive-include src/pretix/plugins/returnurl/static *
recursive-include src/pretix/plugins/webcheckin/templates *
recursive-include src/pretix/plugins/webcheckin/static *
recursive-include src *.cfg
recursive-include src *.csv
recursive-include src *.gitkeep
recursive-include src *.jpg
recursive-include src *.json
recursive-include src *.py
recursive-include src *.svg
recursive-include src *.txt
recursive-include src Makefile
recursive-exclude doc *
recursive-exclude deployment *
recursive-exclude res *

View File

@@ -1,12 +0,0 @@
import tomli
from setuptools import build_meta as _orig
from setuptools.build_meta import *
def get_requires_for_build_wheel(config_settings=None):
with open("pyproject.toml", "rb") as f:
p = tomli.load(f)
return [
*_orig.get_requires_for_build_wheel(config_settings),
*p['project']['dependencies']
]

View File

@@ -5,7 +5,7 @@ export DATA_DIR=/data/
export HOME=/pretix
AUTOMIGRATE=${AUTOMIGRATE:-yes}
NUM_WORKERS_DEFAULT=$((2 * $(nproc)))
NUM_WORKERS_DEFAULT=$((2 * $(nproc --all)))
export NUM_WORKERS=${NUM_WORKERS:-$NUM_WORKERS_DEFAULT}
if [ ! -d /data/logs ]; then
@@ -47,7 +47,7 @@ if [ "$1" == "taskworker" ]; then
fi
if [ "$1" == "upgrade" ]; then
exec python3 -m pretix updateassets
exec python3 -m pretix updatestyles
fi
exec python3 -m pretix "$@"

View File

@@ -1,4 +1,4 @@
from pretix.settings import *
LOGGING['handlers']['mail_admins']['include_html'] = True
STORAGES["staticfiles"]["BACKEND"] = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'

View File

@@ -18,82 +18,67 @@
<title>{{ title|striptags|e }}{{ titlesuffix }}</title>
{% endblock %}
{#- CSS #}
{%- for css in css_files %}
{%- if css|attr("rel") %}
<link rel="{{ css.rel }}" href="{{ pathto(css.filename, 1) }}" type="text/css"{% if css.title is not none %} title="{{ css.title }}"{% endif %} />
{%- else %}
<link rel="stylesheet" href="{{ pathto(css, 1) }}" type="text/css" />
{%- endif %}
{%- endfor %}
{%- for cssfile in extra_css_files %}
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
{%- endfor -%}
{#- FAVICON
favicon_url is the only context var necessary since Sphinx 4.
In Sphinx<4, we use favicon but need to prepend path info.
#}
{%- set _favicon_url = favicon_url | default(pathto('_static/' + (favicon or ""), 1)) %}
{%- if favicon_url or favicon %}
<link rel="shortcut icon" href="{{ _favicon_url }}"/>
{%- endif %}
{#- CANONICAL URL (deprecated) #}
{%- if theme_canonical_url and not pageurl %}
{# FAVICON #}
{% if favicon %}
<link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/>
{% endif %}
{# CANONICAL URL #}
{% if theme_canonical_url %}
<link rel="canonical" href="{{ theme_canonical_url }}{{ pagename }}.html"/>
{%- endif -%}
{% endif %}
{#- CANONICAL URL #}
{%- if pageurl %}
<link rel="canonical" href="{{ pageurl|e }}" />
{%- endif -%}
{# CSS #}
{#- JAVASCRIPTS #}
{%- block scripts %}
<!--[if lt IE 9]>
<script src="{{ pathto('_static/js/html5shiv.min.js', 1) }}"></script>
<![endif]-->
{%- if not embedded %}
{# XXX Sphinx 1.8.0 made this an external js-file, quick fix until we refactor the template to inherert more blocks directly from sphinx #}
{%- for scriptfile in script_files %}
{{ js_tag(scriptfile) }}
{%- endfor %}
<script src="{{ pathto('_static/js/theme.js', 1) }}"></script>
{# OPENSEARCH #}
{% if not embedded %}
{% if use_opensearch %}
<link rel="search" type="application/opensearchdescription+xml" title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}" href="{{ pathto('_static/opensearch.xml', 1) }}"/>
{% endif %}
{#- OPENSEARCH #}
{%- if use_opensearch %}
<link rel="search" type="application/opensearchdescription+xml"
title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}"
href="{{ pathto('_static/opensearch.xml', 1) }}"/>
{%- endif %}
{%- endif %}
{%- endblock %}
{% endif %}
{# RTD hosts this file, so just load on non RTD builds #}
<link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
{% for cssfile in css_files %}
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
{% endfor %}
{% for cssfile in extra_css_files %}
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
{% endfor %}
{%- block linktags %}
{%- if hasdoc('about') %}
<link rel="author" title="{{ _('About these documents') }}" href="{{ pathto('about') }}" />
<link rel="author" title="{{ _('About these documents') }}"
href="{{ pathto('about') }}"/>
{%- endif %}
{%- if hasdoc('genindex') %}
<link rel="index" title="{{ _('Index') }}" href="{{ pathto('genindex') }}" />
<link rel="index" title="{{ _('Index') }}"
href="{{ pathto('genindex') }}"/>
{%- endif %}
{%- if hasdoc('search') %}
<link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}" />
<link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}"/>
{%- endif %}
{%- if hasdoc('copyright') %}
<link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}" />
<link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}"/>
{%- endif %}
<link rel="top" title="{{ docstitle|e }}" href="{{ pathto('index') }}"/>
{%- if parents %}
<link rel="up" title="{{ parents[-1].title|striptags|e }}" href="{{ parents[-1].link|e }}"/>
{%- endif %}
{%- if next %}
<link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}" />
<link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}"/>
{%- endif %}
{%- if prev %}
<link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}" />
<link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}"/>
{%- endif %}
{%- endblock %}
{%- block extrahead %} {% endblock %}
{# Keep modernizr in head - http://modernizr.com/docs/#installing #}
<script src="{{ pathto('_static/js/modernizr.min.js', 1) }}"></script>
</head>
<body class="wy-body-for-nav" role="document">
@@ -107,14 +92,16 @@
<div class="wy-side-nav-search">
{% block sidebartitle %}
{# the logo helper function was removed in Sphinx 6 and deprecated since Sphinx 4 #}
{# the master_doc variable was renamed to root_doc in Sphinx 4 (master_doc still exists in later Sphinx versions) #}
{%- set _logo_url = logo_url|default(pathto('_static/' + (logo or ""), 1)) %}
{%- set _root_doc = root_doc|default(master_doc) %}
<a href="{{ pathto(_root_doc) }}"{% if not theme_logo_only %} class="icon icon-home"{% endif %}>
{%- if logo or logo_url %}
<img src="{{ _logo_url }}" class="logo" alt="{{ _('Logo') }}"/>
{%- endif %}
{% if logo and theme_logo_only %}
<a href="{{ pathto('index') }}">
{% else %}
<a href="{{ pathto('index') }}" class="icon icon-home"> {{ project }}
{% endif %}
{% if logo %}
{# Not strictly valid HTML, but it's the only way to display/scale it properly, without weird scripting or heaps of work #}
<img src="{{ pathto('_static/' + logo, 1) }}" class="logo" />
{% endif %}
</a>
{% include "searchbox.html" %}

View File

@@ -5,37 +5,31 @@
Template for the search page.
:copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see https://github.com/sphinx-doc/sphinx/blob/master/LICENSE for details.
:license: BSD, see LICENSE for details.
#}
{%- extends "layout.html" %}
{% set title = _('Search') %}
{% set display_vcs_links = False %}
{%- block scripts %}
{{ super() }}
<script src="{{ pathto('_static/searchtools.js', 1) }}"></script>
<script src="{{ pathto('_static/language_data.js', 1) }}"></script>
{%- endblock %}
{% set script_files = script_files + ['_static/searchtools.js'] %}
{% block footer %}
<script>
<script type="text/javascript">
jQuery(function() { Search.loadIndex("{{ pathto('searchindex.js', 1) }}"); });
</script>
{# this is used when loading the search index using $.ajax fails,
such as on Chrome for documents on localhost #}
<script id="searchindexloader"></script>
<script type="text/javascript" id="searchindexloader"></script>
{{ super() }}
{% endblock %}
{% block body %}
<noscript>
<div id="fallback" class="admonition warning">
<p class="last">
{% trans trimmed %}Please activate JavaScript to enable the search
{% trans %}Please activate JavaScript to enable the search
functionality.{% endtrans %}
</p>
</div>
</noscript>
{% if search_performed %}
{# Translators: Search is a noun, not a verb #}
<h2>{{ _('Search Results') }}</h2>
{% if not search_results %}
<p>{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}</p>
@@ -53,4 +47,4 @@
</ul>
{% endif %}
</div>
{% endblock %}
{% endblock %}

View File

@@ -2,7 +2,7 @@
.. _`config`:
.. spelling:word-list:: Galera
.. spelling:: Galera
Configuration file
==================
@@ -42,6 +42,7 @@ Example::
currency=EUR
datadir=/data
plugins_default=pretix.plugins.sendmail,pretix.plugins.statistics
cookie_domain=.pretix.de
``instance_name``
The name of this installation. Default: ``pretix.de``
@@ -52,18 +53,10 @@ Example::
``currency``
The default currency as a three-letter code. Defaults to ``EUR``.
``cachedir``
The local path to a directory where temporary files will be stored.
Defaults to the ``cache`` directory below the ``datadir``.
``datadir``
The local path to a data directory that will be used for storing user uploads and similar
data. Defaults to the value of the environment variable ``DATA_DIR`` or ``data``.
``logdir``
The local path to a directory where log files will be stored.
Defaults to the ``logs`` directory below the ``datadir``.
``plugins_default``
A comma-separated list of plugins that are enabled by default for all new events.
Defaults to ``pretix.plugins.sendmail,pretix.plugins.statistics``.
@@ -78,8 +71,11 @@ Example::
``auth_backends``
A comma-separated list of available auth backends. Defaults to ``pretix.base.auth.NativeAuthBackend``.
``cookie_domain``
The cookie domain to be set. Defaults to ``None``.
``registration``
Enables or disables the registration of new admin users. Defaults to ``off``.
Enables or disables the registration of new admin users. Defaults to ``on``.
``password_reset``
Enables or disables password reset. Defaults to ``on``.
@@ -88,7 +84,7 @@ Example::
Enables or disables the "keep me logged in" button. Defaults to ``on``.
``ecb_rates``
By default, pretix periodically downloads currency rates from the European Central Bank as well as other authorities
By default, pretix periodically downloads a XML file from the European Central Bank to retrieve exchange rates
that are used to print tax amounts in the customer currency on invoices for some currencies. Set to ``off`` to
disable this feature. Defaults to ``on``.
@@ -97,9 +93,8 @@ Example::
Defaults to ``off``.
``obligatory_2fa``
Enables or disables obligatory usage of two-factor authentication for users of the pretix backend.
Can be ``True`` to make two-factor authentication obligatory for all users or ``staff`` to make it only
obligatory to users with admin permissions. Defaults to ``False``.
Enables or disables obligatory usage of Two-Factor Authentication for users of the pretix backend.
Defaults to ``False``
``trust_x_forwarded_for``
Specifies whether the ``X-Forwarded-For`` header can be trusted. Only set to ``on`` if you have a reverse
@@ -111,11 +106,6 @@ Example::
proxy that actively removes and re-adds the header to make sure the correct value is set.
Defaults to ``off``.
``trust_x_forwarded_host``
Specifies whether the ``X-Forwarded-Host`` header can be trusted. Only set to ``on`` if you have a reverse
proxy that actively removes and re-adds the header to make sure the correct value is set.
Defaults to ``off``.
``csp_log``
Log violations of the Content Security Policy (CSP). Defaults to ``on``.
@@ -151,44 +141,30 @@ Database settings
Example::
[database]
backend=postgresql
backend=mysql
name=pretix
user=pretix
password=abcd
host=localhost
port=3306
advisory_lock_index=1
disable_server_side_cursors=0
sslmode=require
sslrootcert=/etc/pretix/postgresql-ca.crt
sslcert=/etc/pretix/postgresql-client-crt.crt
sslkey=/etc/pretix/postgresql-client-key.key
``backend``
One of ``sqlite3`` and ``postgresql``.
One of ``mysql``, ``sqlite3``, ``oracle`` and ``postgresql``.
Default: ``sqlite3``.
If you use MySQL, be sure to create your database using
``CREATE DATABASE <dbname> CHARACTER SET utf8;``. Otherwise, Unicode
support will not properly work.
``name``
The database's name. Default: ``db.sqlite3``.
``user``, ``password``, ``host``, ``port``
Connection details for the database connection. Empty by default.
``advisory_lock_index``
On PostgreSQL, pretix uses the "advisory lock" feature. However, advisory locks use a server-wide name space and
and are not scoped to a specific database. If you run multiple pretix applications with the same PostgreSQL server,
you should set separate values for this setting (integers up to 256).
``disable_server_side_cursors``
On PostgreSQL pretix might use server side cursors for certain operations. This is generally fine but will break in
specific circumstances, for example when connecting to PostgreSQL through a PGBouncer configured with a transaction
pool mode. Off by default (i.e. by default server side cursors will be used).
``sslmode``, ``sslrootcert``
Connection TLS details for the PostgreSQL database connection. Possible values of ``sslmode`` are ``disable``, ``allow``, ``prefer``, ``require``, ``verify-ca``, and ``verify-full``. ``sslrootcert`` should be the accessible path of the ca certificate. Both values are empty by default.
``sslcert``, ``sslkey``
Connection mTLS details for the PostgreSQL database connection. It's also necessary to specify ``sslmode`` and ``sslrootcert`` parameters, please check the correct values from the TLS part. ``sslcert`` should be the accessible path of the client certificate. ``sslkey`` should be the accessible path of the client key. All values are empty by default.
``galera``
Indicates if the database backend is a MySQL/MariaDB Galera cluster and
turns on some optimizations/special case handlers. Default: ``False``
.. _`config-replica`:
@@ -218,7 +194,7 @@ Example::
[urls]
media=/media/
static=/static/
static=/media/
``media``
The URL to be used to serve user-uploaded content. You should not need to modify
@@ -294,10 +270,6 @@ Example::
setting is not provided, pretix will generate a random secret on the first start
and will store it in the filesystem for later usage.
``secret_fallback0`` ... ``secret_fallback9``
Prior versions of the secret to be used by Django for signing and verification purposes that will still
be accepted but no longer be used for new signing.
``debug``
Whether or not to run in debug mode. Default is ``False``.
@@ -355,16 +327,12 @@ to speed up various operations::
["sentinel_host_3", 26379]
]
password=password
ssl_cert_reqs=required
ssl_ca_certs=/etc/pretix/redis-ca.pem
ssl_keyfile=/etc/pretix/redis-client-crt.pem
ssl_certfile=/etc/pretix/redis-client-key.key
``location``
The location of redis, as a URL of the form ``redis://[:password]@localhost:6379/0``
or ``unix://[:password]@/path/to/socket.sock?db=0``
``sessions``
``session``
When this is set to ``True``, redis will be used as the session storage.
``sentinels``
@@ -382,22 +350,6 @@ to speed up various operations::
If your redis setup doesn't require a password or you already specified it in the location you can omit this option.
If this is set it will be passed to redis as the connection option PASSWORD.
``ssl_cert_reqs``
If this is set it will be passed to redis as the connection option ``SSL_CERT_REQS``.
Possible values are ``none``, ``optional``, and ``required``.
``ssl_ca_certs``
If your redis setup doesn't require TLS you can omit this option.
If this is set it will be passed to redis as the connection option ``SSL_CA_CERTS``. Possible value is the ca path.
``ssl_keyfile``
If your redis setup doesn't require mTLS you can omit this option.
If this is set it will be passed to redis as the connection option ``SSL_KEYFILE``. Possible value is the keyfile path.
``ssl_certfile``
If your redis setup doesn't require mTLS you can omit this option.
If this is set it will be passed to redis as the connection option ``SSL_CERTFILE``. Possible value is the certfile path.
If redis is not configured, pretix will store sessions and locks in the database. If memcached
is configured, memcached will be used for caching instead of redis.
@@ -447,8 +399,6 @@ The two ``transport_options`` entries can be omitted in most cases.
If they are present they need to be a valid JSON dictionary.
For possible entries in that dictionary see the `Celery documentation`_.
It is possible the use Redis with TLS/mTLS for the broker or the backend. To do so, it is necessary to specify the TLS identifier ``rediss``, the ssl mode ``ssl_cert_reqs`` and optionally specify the CA (TLS) ``ssl_ca_certs``, cert ``ssl_certfile`` and key ``ssl_keyfile`` (mTLS) path as encoded string. the following uri describes the format and possible parameters ``rediss://0.0.0.0:6379/1?ssl_cert_reqs=required&ssl_ca_certs=%2Fetc%2Fpretix%2Fredis-ca.pem&ssl_certfile=%2Fetc%2Fpretix%2Fredis-client-crt.pem&ssl_keyfile=%2Fetc%2Fpretix%2Fredis-client-key.key``
To use redis with sentinels set the broker or backend to ``sentinel://sentinel_host_1:26379;sentinel_host_2:26379/0``
and the respective transport_options to ``{"master_name":"mymaster"}``.
If your redis instances behind the sentinel have a password use ``sentinel://:my_password@sentinel_host_1:26379;sentinel_host_2:26379/0``.
@@ -526,18 +476,3 @@ You can configure the maximum file size for uploading various files::
; Max upload size for other files in MiB, defaults to 10 MiB
; This includes all file upload type order questions
max_size_other = 100
GeoIP
-----
pretix can optionally make use of a GeoIP database for some features. It needs a file in ``mmdb`` format, for example
`GeoLite2`_ or `GeoAcumen`_::
[geoip]
path=/var/geoipdata/
filename_country=GeoLite2-Country.mmdb
.. _GeoAcumen: https://github.com/geoacumen/geoacumen-country
.. _GeoLite2: https://dev.maxmind.com/geoip/geolite2-free-geolocation-data

View File

@@ -14,5 +14,4 @@ This documentation is for everyone who wants to install pretix on a server.
maintainance
scaling
errors
mysql2postgres
indexes

View File

@@ -45,8 +45,8 @@ Here is the currently recommended set of commands::
CREATE INDEX CONCURRENTLY pretix_addidx_order_comment
ON pretixbase_order
USING gin (upper("comment") gin_trgm_ops);
CREATE INDEX CONCURRENTLY pretix_addidx_order_event_date_id
ON public.pretixbase_order (event_id, datetime, id);
CREATE INDEX CONCURRENTLY pretix_addidx_order_event_date
ON public.pretixbase_order (event_id, datetime);
CREATE INDEX CONCURRENTLY pretix_addidx_orderpos_name
ON pretixbase_orderposition
USING gin (upper("attendee_name_cached") gin_trgm_ops);
@@ -66,10 +66,10 @@ Here is the currently recommended set of commands::
ON public.pretixbase_orderposition (upper((attendee_email)::text));
CREATE INDEX CONCURRENTLY pretix_addidx_voucher_code_upper
ON public.pretixbase_voucher (upper((code)::text));
CREATE INDEX CONCURRENTLY pretix_addidx_logentry_event_date_id
ON public.pretixbase_logentry (event_id, datetime, id);
CREATE INDEX CONCURRENTLY pretix_addidx_logentry_event_cid_date_id
ON public.pretixbase_logentry (event_id, content_type_id, datetime, id);
CREATE INDEX CONCURRENTLY pretix_addidx_logentry_event_date
ON public.pretixbase_logentry (event_id, datetime);
CREATE INDEX CONCURRENTLY pretix_addidx_logentry_event_cid_date
ON public.pretixbase_logentry (event_id, content_type_id, datetime);
Also, if you use our ``pretix-shipping`` plugin::

View File

@@ -1,18 +0,0 @@
.. highlight:: none
.. _`community`:
Community install guides
========================
.. warning:: The guides are maintained by the community and not by the pretix core team. If you encounter any issues with the guides, please report them to the maintainers of the guides. The pretix core team can not provide support for installs using these guides.
Kubernetes
----------
- Helm Chart by techwolf12 - A Helm chart for deploying pretix on Kubernetes. The chart documentation is available on `ArtifactHub <https://artifacthub.io/packages/helm/techwolf12/pretix>`_ and the source code is available on `GitHub <https://github.com/Techwolf12/charts/tree/main/pretix-helm>`_.
Docker
------
- `docker compose setup <https://github.com/ZPascal/pretix-docker-compose>`_ by ZPascal

View File

@@ -16,10 +16,10 @@ Manual installation
You can use ``pip`` to update pretix directly to the development branch. Then, upgrade as usual::
$ source /var/pretix/venv/bin/activate
(venv)$ pip3 install -U "git+https://github.com/pretix/pretix.git#egg=pretix"
(venv)$ pip3 install -U "git+https://github.com/pretix/pretix.git#egg=pretix&subdirectory=src"
(venv)$ python -m pretix migrate
(venv)$ python -m pretix rebuild
(venv)$ python -m pretix updateassets
(venv)$ python -m pretix updatestyles
# systemctl restart pretix-web pretix-worker
Docker installation

View File

@@ -14,7 +14,7 @@ This has some trade-offs in terms of performance and isolation but allows a rath
get it right. If you're not feeling comfortable managing a Linux server, check out our hosting and service
offers at `pretix.eu`_.
We tested this guide on the Linux distribution **Debian 11.0** but it should work very similar on other
We tested this guide on the Linux distribution **Debian 8.0** but it should work very similar on other
modern distributions, especially on all systemd-based ones.
Requirements
@@ -26,7 +26,7 @@ installation guides):
* `Docker`_
* A SMTP server to send out mails, e.g. `Postfix`_ on your machine or some third-party server you have credentials for
* A HTTP reverse proxy, e.g. `nginx`_ or Apache to allow HTTPS connections
* A `PostgreSQL`_ 12+ database server
* A `PostgreSQL`_ 9.6+, `MySQL`_ 5.7+, or MariaDB 10.2.7+ database server
* A `redis`_ server
We also recommend that you use a firewall, although this is not a pretix-specific recommendation. If you're new to
@@ -58,6 +58,9 @@ directory writable to the user that runs pretix inside the docker container::
Database
--------
.. warning:: **Please use PostgreSQL for all new installations**. If you need to go for MySQL, make sure you run
**MySQL 5.7 or newer** or **MariaDB 10.2.7 or newer**.
Next, we need a database and a database user. We can create these with any kind of database managing tool or directly on
our database's shell. Please make sure that UTF8 is used as encoding for the best compatibility. You can check this with
the following command::
@@ -83,6 +86,13 @@ Restart PostgreSQL after you changed these files::
If you have a firewall running, you should also make sure that port 5432 is reachable from the ``172.17.0.1/16`` subnet.
For MySQL, you can either also use network-based connections or mount the ``/var/run/mysqld/mysqld.sock`` socket into the docker container.
When using MySQL, make sure you set the character set of the database to ``utf8mb4``, e.g. like this::
mysql > CREATE DATABASE pretix DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
You will also need to make sure that ``sql_mode`` in your ``my.cnf`` file does **not** include ``ONLY_FULL_GROUP_BY``.
Redis
-----
@@ -142,13 +152,15 @@ Fill the configuration file ``/etc/pretix/pretix.cfg`` with the following conten
trust_x_forwarded_proto=on
[database]
; Replace postgresql with mysql for MySQL
backend=postgresql
name=pretix
user=pretix
; Replace with the password you chose above
password=*********
; In most docker setups, 172.17.0.1 is the address of the docker host. Adjust
; this to wherever your database is running, e.g. the name of a linked container.
; this to wherever your database is running, e.g. the name of a linked container
; or of a mounted MySQL socket.
host=172.17.0.1
[mail]
@@ -200,6 +212,8 @@ named ``/etc/systemd/system/pretix.service`` with the following content::
[Install]
WantedBy=multi-user.target
When using MySQL and socket mounting, you'll need the additional flag ``-v /var/run/mysqld:/var/run/mysqld`` in the command.
You can now run the following commands
to enable and start the service::
@@ -276,8 +290,7 @@ Restarting the service can take a few seconds, especially if the update requires
Replace ``stable`` above with a specific version number like ``1.0`` or with ``latest`` for the development
version, if you want to.
Make sure to also read :ref:`update_notes` and the release notes of the version you are updating to. Pay special
attention to the "Runtime and server environment" section of all release notes between your current and new version.
Make sure to also read :ref:`update_notes` and the release notes of the version you are updating to.
.. _`docker_plugininstall`:
@@ -322,11 +335,12 @@ workers, e.g. ``docker run … taskworker -Q notifications --concurrency 32``.
.. _Docker: https://docs.docker.com/engine/installation/linux/debian/
.. _Postfix: https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-as-a-send-only-smtp-server-on-ubuntu-22-04
.. _Postfix: https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-as-a-send-only-smtp-server-on-ubuntu-16-04
.. _nginx: https://botleg.com/stories/https-with-lets-encrypt-and-nginx/
.. _Let's Encrypt: https://letsencrypt.org/
.. _pretix.eu: https://pretix.eu/
.. _PostgreSQL: https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-22-04
.. _MySQL: https://dev.mysql.com/doc/refman/5.7/en/linux-installation-apt-repo.html
.. _PostgreSQL: https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-20-04
.. _redis: https://blog.programster.org/debian-8-install-redis-server/
.. _ufw: https://en.wikipedia.org/wiki/Uncomplicated_Firewall
.. _redis website: https://redis.io/topics/security

View File

@@ -68,7 +68,7 @@ generated key and installs the plugin from the URL we told you::
mkdir -p /etc/ssh && \
ssh-keyscan -t rsa -p 10022 code.rami.io >> /root/.ssh/known_hosts && \
echo StrictHostKeyChecking=no >> /root/.ssh/config && \
DJANGO_SETTINGS_MODULE= pip3 install -U "git+ssh://git@code.rami.io:10022/pretix/pretix-slack.git@stable#egg=pretix-slack" && \
DJANGO_SETTINGS_MODULE=pretix.settings pip3 install -U "git+ssh://git@code.rami.io:10022/pretix/pretix-slack.git@stable#egg=pretix-slack" && \
cd /pretix/src && \
sudo -u pretixuser make production
USER pretixuser

View File

@@ -1,6 +1,6 @@
.. highlight:: ini
.. spelling:word-list:: SQL
.. spelling:: SQL
General remarks
===============
@@ -16,11 +16,14 @@ To use pretix, you will need the following things:
* A periodic task runner, e.g. ``cron``
* **A database**. This needs to be a SQL-based that is supported by Django. We highly recommend to either
go for **PostgreSQL**. If you do not provide one, pretix will run on SQLite, which is useful
go for **PostgreSQL** or **MySQL/MariaDB**. If you do not provide one, pretix will run on SQLite, which is useful
for evaluation and development purposes.
.. warning:: Do not ever use SQLite in production. It will break.
.. warning:: We recommend **PostgreSQL**. If you go for MySQL, make sure you run **MySQL 5.7 or newer** or
**MariaDB 10.2.7 or newer**.
* A **reverse proxy**. pretix needs to deliver some static content to your users (e.g. CSS, images, ...). While pretix
is capable of doing this, having this handled by a proper web server like **nginx** or **Apache** will be much
faster. Also, you need a proxying web server in front to provide SSL encryption.

View File

@@ -14,4 +14,3 @@ for your needs.
manual_smallscale
dev_version
enterprise
community

View File

@@ -12,7 +12,7 @@ solution with many things readily set-up, look at :ref:`dockersmallscale`.
get it right. If you're not feeling comfortable managing a Linux server, check out our hosting and service
offers at `pretix.eu`_.
We tested this guide on the Linux distribution **Debian 12** but it should work very similar on other
We tested this guide on the Linux distribution **Debian 10.0** but it should work very similar on other
modern distributions, especially on all systemd-based ones.
Requirements
@@ -21,10 +21,9 @@ Requirements
Please set up the following systems beforehand, we'll not explain them here in detail (but see these links for external
installation guides):
* A python 3.9+ installation
* A SMTP server to send out mails, e.g. `Postfix`_ on your machine or some third-party server you have credentials for
* A HTTP reverse proxy, e.g. `nginx`_ or Apache to allow HTTPS connections
* A `PostgreSQL`_ 12+ database server
* A `PostgreSQL`_ 9.6+, `MySQL`_ 5.7+, or MariaDB 10.2.7+ database server
* A `redis`_ server
* A `nodejs`_ installation
@@ -48,6 +47,9 @@ In this guide, all code lines prepended with a ``#`` symbol are commands that yo
Database
--------
.. warning:: **Please use PostgreSQL for all new installations**. If you need to go for MySQL, make sure you run
**MySQL 5.7 or newer** or **MariaDB 10.2.7 or newer**.
Having the database server installed, we still need a database and a database user. We can create these with any kind
of database managing tool or directly on our database's shell. Please make sure that UTF8 is used as encoding for the
best compatibility. You can check this with the following command::
@@ -59,14 +61,20 @@ For PostgreSQL database creation, we would do::
# sudo -u postgres createuser pretix
# sudo -u postgres createdb -O pretix pretix
When using MySQL, make sure you set the character set of the database to ``utf8mb4``, e.g. like this::
mysql > CREATE DATABASE pretix DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
You will also need to make sure that ``sql_mode`` in your ``my.cnf`` file does **not** include ``ONLY_FULL_GROUP_BY``.
Package dependencies
--------------------
To build and run pretix, you will need the following debian packages::
# apt-get install git build-essential python3-dev python3-venv python3 python3-pip \
libxml2-dev libxslt1-dev libffi-dev zlib1g-dev libssl-dev \
gettext libpq-dev libjpeg-dev libopenjp2-7-dev
# apt-get install git build-essential python-dev python3-venv python3 python3-pip \
python3-dev libxml2-dev libxslt1-dev libffi-dev zlib1g-dev libssl-dev \
gettext libpq-dev libmariadb-dev libjpeg-dev libopenjp2-7-dev
Config file
-----------
@@ -89,12 +97,16 @@ Fill the configuration file ``/etc/pretix/pretix.cfg`` with the following conten
trust_x_forwarded_proto=on
[database]
; For MySQL, replace with "mysql"
backend=postgresql
name=pretix
user=pretix
; For PostgreSQL on the same host, we don't need a password because we can use
; peer authentication if our PostgreSQL user matches our unix user.
; For MySQL, enter the user password. For PostgreSQL on the same host,
; we don't need one because we can use peer authentification if our
; PostgreSQL user matches our unix user.
password=
; For MySQL, use local socket, e.g. /var/run/mysqld/mysqld.sock
; For a remote host, supply an IP address
; For local postgres authentication, you can leave it empty
host=
@@ -120,7 +132,6 @@ Now we will install pretix itself. The following steps are to be executed as the
actually install pretix, we will create a virtual environment to isolate the python packages from your global
python installation::
# sudo -u pretix -s
$ python3 -m venv /var/pretix/venv
$ source /var/pretix/venv/bin/activate
(venv)$ pip3 install -U pip setuptools wheel
@@ -129,12 +140,15 @@ We now install pretix, its direct dependencies and gunicorn::
(venv)$ pip3 install pretix gunicorn
Note that you need Python 3.9 or newer. You can find out your Python version using ``python -V``.
If you're running MySQL, also install the client library::
We also need to create a data directory and allow your webserver to traverse to the root directory::
(venv)$ pip3 install mysqlclient
Note that you need Python 3.7 or newer. You can find out your Python version using ``python -V``.
We also need to create a data directory::
(venv)$ mkdir -p /var/pretix/data/media
(venv)$ chmod +x /var/pretix
Finally, we compile static files and translation data and create the database structure::
@@ -250,14 +264,14 @@ The following snippet is an example on how to configure a nginx proxy for pretix
}
location /static/ {
alias /var/pretix/venv/lib/python3.11/site-packages/pretix/static.dist/;
alias /var/pretix/venv/lib/python3.10/site-packages/pretix/static.dist/;
access_log off;
expires 365d;
add_header Cache-Control "public";
}
}
.. note:: Remember to replace the ``python3.11`` in the ``/static/`` path in the config
.. note:: Remember to replace the ``python3.10`` in the ``/static/`` path in the config
above with your python version.
We recommend reading about setting `strong encryption settings`_ for your web server.
@@ -280,16 +294,14 @@ Updates
To upgrade to a new pretix release, pull the latest code changes and run the following commands::
# sudo -u pretix -s
$ source /var/pretix/venv/bin/activate
(venv)$ pip3 install -U --upgrade-strategy eager pretix gunicorn
(venv)$ python -m pretix migrate
(venv)$ python -m pretix rebuild
(venv)$ python -m pretix updateassets
(venv)$ python -m pretix updatestyles
# systemctl restart pretix-web pretix-worker
Make sure to also read :ref:`update_notes` and the release notes of the version you are updating to. Pay special
attention to the "Runtime and server environment" section of all release notes between your current and new version.
Make sure to also read :ref:`update_notes` and the release notes of the version you are updating to.
.. _`manual_plugininstall`:
@@ -325,14 +337,15 @@ Then, proceed like after any plugin installation::
(venv)$ python -m pretix migrate
(venv)$ python -m pretix rebuild
(venv)$ python -m pretix updateassets
(venv)$ python -m pretix updatestyles
# systemctl restart pretix-web pretix-worker
.. _Postfix: https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-as-a-send-only-smtp-server-on-ubuntu-22-04
.. _Postfix: https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-as-a-send-only-smtp-server-on-ubuntu-16-04
.. _nginx: https://botleg.com/stories/https-with-lets-encrypt-and-nginx/
.. _Let's Encrypt: https://letsencrypt.org/
.. _pretix.eu: https://pretix.eu/
.. _PostgreSQL: https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-22-04
.. _MySQL: https://dev.mysql.com/doc/refman/5.7/en/linux-installation-apt-repo.html
.. _PostgreSQL: https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-20-04
.. _redis: https://blog.programster.org/debian-8-install-redis-server/
.. _ufw: https://en.wikipedia.org/wiki/Uncomplicated_Firewall
.. _strong encryption settings: https://mozilla.github.io/server-side-tls/ssl-config-generator/

View File

@@ -17,11 +17,11 @@ Backups
There are essentially two things which you should create backups of:
Database
Your SQL database. This is critical and you should **absolutely always create automatic
backups of your database**. There are tons of tutorials on the internet on how to do this,
and the exact process depends on the choice of your database. For PostgreSQL, see the
``pg_dump`` tool. You probably want to create a cronjob that does the backups for you on a
regular schedule.
Your SQL database (MySQL or PostgreSQL). This is critical and you should **absolutely
always create automatic backups of your database**. There are tons of tutorials on the
internet on how to do this, and the exact process depends on the choice of your database.
For MySQL, see ``mysqldump`` and for PostgreSQL, see the ``pg_dump`` tool. You probably
want to create a cronjob that does the backups for you on a regular schedule.
Data directory
The data directory of your pretix configuration might contain some things that you should
@@ -103,12 +103,6 @@ pretix_celery_tasks_queued_count
pretix_celery_tasks_queued_age_seconds
The age of the longest-waiting in the worker queue in seconds, labeled with ``queue``.
pretix_logins_successful
Counter. The number of successful backend logins.
pretix_logins_failed
Counter. The number of failed backend logins, labeled with ``reason``.
.. _metric types: https://prometheus.io/docs/concepts/metric_types/
.. _Prometheus: https://prometheus.io/
.. _cProfile: https://docs.python.org/3/library/profile.html

View File

@@ -1,261 +0,0 @@
.. highlight:: none
Migrating from MySQL/MariaDB to PostgreSQL
==========================================
Our recommended database for all production installations is PostgreSQL. Support for MySQL/MariaDB has been removed
in newer pretix releases.
In order to follow this guide, your pretix installation needs to be a version that fully supports MySQL/MariaDB. If you
already upgraded to pretix 5.0 or later, downgrade back to the last 4.x release using ``pip``.
.. note:: We have tested this guide carefully, but we can't assume any liability for its correctness. The data loss
risk should be low as long as pretix is not running while you do the migration. If you are a pretix Enterprise
customer, feel free to reach out in advance if you want us to support you along the way.
Update database schema
----------------------
Before you start, make sure your database schema is up to date. With a local installation::
# sudo -u pretix -s
$ source /var/pretix/venv/bin/activate
(venv)$ python -m pretix migrate
With a docker installation::
docker exec -it pretix.service pretix migrate
Install PostgreSQL
------------------
Now, install and set up a PostgreSQL server. For a local installation on Debian or Ubuntu, use::
# apt install postgresql
Having the database server installed, we still need a database and a database user. We can create these with any kind
of database managing tool or directly on our database's shell. Please make sure that UTF8 is used as encoding for the
best compatibility. You can check this with the following command::
# sudo -u postgres psql -c 'SHOW SERVER_ENCODING'
Without Docker
""""""""""""""
For our standard manual installation, create the database and user like this::
# sudo -u postgres createuser pretix
# sudo -u postgres createdb -O pretix pretix
With Docker
"""""""""""
For our standard docker installation, create the database and user like this::
# sudo -u postgres createuser -P pretix
# sudo -u postgres createdb -O pretix pretix
Make sure that your database listens on the network. If PostgreSQL on the same same host as docker, but not inside a docker container, we recommend that you listen on the Docker interface by changing the following line in ``/etc/postgresql/<version>/main/postgresql.conf``::
listen_addresses = 'localhost,172.17.0.1'
You also need to add a new line to ``/etc/postgresql/<version>/main/pg_hba.conf`` to allow network connections to this user and database::
host pretix pretix 172.17.0.1/16 md5
Restart PostgreSQL after you changed these files::
# systemctl restart postgresql
If you have a firewall running, you should also make sure that port 5432 is reachable from the ``172.17.0.1/16`` subnet.
Of course, instead of all this you can also run a PostgreSQL docker container and link it to the pretix container.
Stop pretix
-----------
To prevent any more changes to your data, stop pretix from running. With a local installation::
# systemctl stop pretix-web pretix-worker
With docker::
# systemctl stop pretix
Change configuration
--------------------
Change the database configuration in your ``/etc/pretix/pretix.cfg`` file::
[database]
backend=postgresql
name=pretix
user=pretix
password= ; only required for docker or remote database, can be kept empty for local auth
host= ; set to 172.17.0.1 in docker setup, keep empty for local auth
Create database schema
-----------------------
To create the schema in your new PostgreSQL database, use the following commands. With a local installation::
# sudo -u pretix -s
$ source /var/pretix/venv/bin/activate
(venv)$ python -m pretix migrate
With docker::
# docker run --rm -v /var/pretix-data:/data -v /etc/pretix:/etc/pretix -v /var/run/redis:/var/run/redis pretix/standalone:stable migrate
Migrate your data
-----------------
Install ``pgloader``::
# apt install pgloader
.. note::
If you are using Ubuntu 20.04, the ``pgloader`` version from the repositories seems to be incompatible with PostgreSQL
12+. You can install ``pgloader`` from the `PostgreSQL repositories`_ instead.
See also `this discussion <https://github.com/pretix/pretix/issues/3090>`_.
Create a new file ``/tmp/pretix.load``, replacing the MySQL and PostgreSQL connection strings with the correct user names, passwords, and/or database names::
LOAD DATABASE
FROM mysql://pretix:password@localhost/pretix -- replace with mysql://username:password@hostname/dbname
INTO postgresql:///pretix -- replace with dbname
WITH data only, include no drop, truncate, disable triggers,
create no indexes, drop indexes, reset sequences
ALTER SCHEMA 'pretix' RENAME TO 'public' -- replace pretix with the name of the MySQL database
ALTER TABLE NAMES MATCHING ~/.*/
SET SCHEMA 'public'
SET timezone TO '+00:00'
SET PostgreSQL PARAMETERS
maintenance_work_mem to '128MB',
work_mem to '12MB';
Then, run::
# sudo -u postgres pgloader /tmp/pretix.load
The output should end with a table summarizing the results for every table. You can ignore warnings about type casts
and missing constraints.
Afterwards, delete the file again::
# rm -rf /tmp/pretix.load
Start pretix
------------
Stop your MySQL server as a verification step that you are no longer using it::
# systemctl stop mariadb
Then, restart pretix. With a local installation::
# systemctl start pretix-web pretix-worker
With a docker installation::
# systemctl start pretix
And you're done! After you've verified everything has been copied correctly, you can delete the old MySQL database.
.. note:: Don't forget to update your backup process to back up your PostgreSQL database instead of your MySQL database now.
Troubleshooting
---------------
Peer authentication failed
""""""""""""""""""""""""""
Sometimes you might see an error message like this::
django.db.utils.OperationalError: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: Peer authentication failed for user "pretix"
It is important to understand that PostgreSQL by default offers two types of authentication:
- **Peer authentication**, which works automatically based on the Linux user you are working as. This requires that
the connection is made through a local socket (empty ``host=`` in ``pretix.cfg``) and the name of the PostgreSQL user
and the Linux user are identical.
- Typically, you might run into this error if you accidentally execute ``python -m pretix`` commands as root instead
of the ``pretix`` user.
- **Password authentication**, which requires a username and password and works over network connections. To force
password authentication instead of peer authentication, set ``host=127.0.0.1`` in ``pretix.cfg``.
- You can alter the password on a PostgreSQL shell using the command ``ALTER USER pretix WITH PASSWORD '***';``.
When creating a user with the ``createuser`` command, pass option ``-P`` to set a new password.
- Even with password authentication, PostgreSQL by default only allows local connections. To allow remote connections,
you need to adjust both the ``listen_address`` configuration parameter as well as the ``pg_hba.conf`` file (see above
for an example with the docker networking setup).
Database error: relation does not exist
"""""""""""""""""""""""""""""""""""""""
If you see an error like this::
2023-04-17T19:20:47.744023Z ERROR Database error 42P01: relation "public.pretix_foobar" does not exist
QUERY: ALTER TABLE public.pretix_foobar DROP CONSTRAINT IF EXISTS pretix_foobar_order_id_57e2cb41_fk_pretixbas CASCADE;
2023-04-17T19:20:47.744023Z FATAL Failed to create the schema, see above.
The reason is most likely that in the past, you installed a pretix plugin that you no longer have installed. However,
the database still contains tables of that plugin. If you want to keep the data, reinstall the plugin and re-run the
``migrate`` step from above. If you want to get rid of the data, manually drop the table mentioned in the error message
from your MySQL database::
# mysql -u root pretix
mysql> DROP TABLE pretix_foobar;
Then, retry. You might see a new error message with a new table, which you can handle the same way.
Cleaning out a failed attempt
"""""""""""""""""""""""""""""
You might want to clean your PostgreSQL database before you try again after an error. You can do so like this::
# sudo -u postgres psql pretix
pretix=# DROP SCHEMA public CASCADE;
pretix=# CREATE SCHEMA public;
pretix=# ALTER SCHEMA public OWNER TO pretix;
``pgloader`` crashes with heap exhaustion error
"""""""""""""""""""""""""""""""""""""""""""""""
On some larger databases, we've seen ``pgloader`` crash with error messages similar to this::
Heap exhausted during garbage collection: 16 bytes available, 48 requested.
Or this::
2021-01-04T21:31:17.367000Z ERROR A SB-KERNEL::HEAP-EXHAUSTED-ERROR condition without bindings for heap statistics. (If
you did not expect to see this message, please report it.
2021-01-04T21:31:17.382000Z ERROR The value
NIL
is not of type
NUMBER
when binding SB-KERNEL::X
The ``pgloader`` version distributed for Debian and Ubuntu is compiled with the ``SBCL`` compiler. If compiled with
``CCL``, these bugs go away. Unfortunately, it is pretty hard to compile ``pgloader`` manually with ``CCL``. If you
run into this, we therefore recommend using the docker container provided by the ``pgloader`` maintainers::
sudo docker run --rm -v /tmp:/tmp --network host -it dimitri/pgloader:ccl.latest pgloader /tmp/pretix.load
As peer authentication is not available from inside the container, this requires you to use password-based authentication
in PostgreSQL (see above).
.. _PostgreSQL repositories: https://wiki.postgresql.org/wiki/Apt

View File

@@ -25,7 +25,7 @@ and what you should think of.
Scaling reasons
---------------
There are two main reasons for scaling up a pretix installation beyond a single server:
There's mainly two reasons to scale up a pretix installation beyond a single server:
* **Availability:** Distributing pretix over multiple servers can allow you to survive failure of one or more single machines, leading to a higher uptime and reliability of your system.
@@ -42,7 +42,7 @@ A pretix installation usually consists of the following components which run per
* ``pretix-worker`` is a Celery-based application that processes tasks that should be run asynchronously outside of the web application process.
* A **PostgreSQL database** keeps all the important data and processes the actual transactions.
* A **SQL database** keeps all the important data and processes the actual transactions. We recommend using PostgreSQL, but MySQL/MariaDB works as well.
* A **web server** that terminates TLS and HTTP connections and forwards them to ``pretix-web``. In some cases, e.g. when serving static files, the web servers might return a response directly. We recommend using ``nginx``.
@@ -74,7 +74,7 @@ We recommend reading up on tuning your web server for high concurrency. For ngin
processes and the number of connections each worker process accepts. Double-check that TLS session caching works, because TLS
handshakes can get really expensive.
During a traffic peak, your web server will be able to make use of more CPU resources, while memory usage will stay comparatively low,
During a traffic peak, your web server will be able to make us of more CPU resources, while memory usage will stay comparatively low,
so if you invest in more hardware here, invest in more and faster CPU cores.
Make sure that pretix' static files (such as CSS and JavaScript assets) as well as user-uploaded media files (event logos, etc)
@@ -92,7 +92,7 @@ them from a different URL <config-urls>`.
pretix-web
""""""""""
The ``pretix-web`` process does not carry any internal state and can be easily started on as many machines as you like, and you can
The ``pretix-web`` process does not carry any internal state can be easily started on as many machines as you like, and you can
use the load balancing features of your frontend web server to redirect to all of them.
You can adjust the number of processes in the ``gunicorn`` command line, and we recommend choosing roughly two times the number
@@ -154,7 +154,7 @@ files, otherwise you **will** run into errors with the user interface.
The easiest solution for this is probably to store them on a NFS server that you mount
on each of the other servers.
Since we use Django's file storage mechanism internally, you can in theory also use an object-storage solution like Amazon S3, Ceph, or Minio to store these files, although we currently do not expose this through pretix' configuration file and this would require you to ship your own variant of ``pretix/settings.py`` and reference it through the ``DJANGO_SETTINGS_MODULE`` environment variable.
Since we use Django's file storage mechanism internally, you can in theory also use a object-storage solution like Amazon S3, Ceph, or Minio to store these files, although we currently do not expose this through pretix' configuration file and this would require you to ship your own variant of ``pretix/settings.py`` and reference it through the ``DJANGO_SETTINGS_MODULE`` environment variable.
At pretix.eu, we use a custom-built `object storage cluster`_.
@@ -171,12 +171,12 @@ you configure, so make sure to set this memory usage as high as you can afford.
memory available allows your database to make more use of caching, which is usually good.
Scaling your database to multiple machines needs to be treated with great caution. It's a
good idea to have a replica of your database for availability reasons. In case your primary
good to have a replica of your database for availability reasons. In case your primary
database server fails, you can easily switch over to the replica and continue working.
However, using database replicas for performance gain is much more complicated. When using
However, using database replicas for performance gains is much more complicated. When using
replicated database systems, you are always trading in consistency or availability to get
additional performance and the consequences of this can be subtle. It is important
additional performance and the consequences of this can be subtle and it is important
that you have a deep understanding of the semantics of your replication mechanism.
.. warning::
@@ -187,7 +187,7 @@ that you have a deep understanding of the semantics of your replication mechanis
As an example, if you buy a ticket, pretix first needs to calculate how many tickets
are left to sell. If this calculation is done on a database replica that lags behind
even for fractions of a second, the decision to allow selling the ticket will be made
on stale data and you can end up with more tickets sold than configured. Similarly,
on out-of-data data and you can end up with more tickets sold than configured. Similarly,
you could imagine situations leading to double payments etc.
If you do have a replica, you *can* tell pretix about it :ref:`in your configuration <config-replica>`.
@@ -204,9 +204,9 @@ redis
While redis is a very important part that glues together some of the components, it isn't used
heavily and can usually handle a fairly large pretix installation easily on a single modern
CPU core.
Having some memory available is good, e.g. if lots of tasks queue up during a traffic peak, but we wouldn't expect ever needing more than a gigabyte of it.
Having some memory available is good in case of e.g. lots of tasks queuing up during a traffic peak, but we wouldn't expect ever needing more than a gigabyte of it.
Feel free to set up a redis cluster for availability but you probably won't need it for performance.
Feel free to set up a redis cluster for availability but you won't need it for performance in a long time.
The limitations
---------------
@@ -228,9 +228,9 @@ if you add more hardware.
If you have an unlimited number of tickets, we can apply fewer locking and we've reached **approx.
1500 orders per minute per event** in benchmarks, although even more should be possible.
We're working on reducing the number of cases in which this is relevant and thereby improve the possible
We're working to reduce the number of cases in which this is relevant and thereby improve the possible
throughput. If you want to use pretix for an event with 10,000+ tickets that are likely to be sold out
within minutes, please get in touch to discuss possible solutions. We'll work something out for you!
.. _object storage cluster: https://behind.pretix.eu/2018/03/20/high-available-cdn/
.. _object storage cluster: https://behind.pretix.eu/2018/03/20/high-available-cdn/

View File

@@ -47,37 +47,5 @@ Or, with a docker installation::
$ docker exec -it pretix.service pretix create_order_transactions
Upgrade to 2023.6.0 or newer
""""""""""""""""""""""""""""
MariaDB and MySQL are no longer supported.
Upgrade to 2023.8.0 or newer
""""""""""""""""""""""""""""
PostgreSQL 11 is now required.
Upgrade to 2023.9.0 or newer
""""""""""""""""""""""""""""
This release includes a migration that changes the `id` column of all core database tables from `integer`
to `bigint`. If you have a large database, the migration step of the upgrade might take significantly longer than
usual, so plan the update accordingly.
The default value for the `registration` setting in `pretix.cfg` has changed to `false`.
Upgrade to 2023.10.0 or newer
"""""""""""""""""""""""""""""
This release includes a migration that changes retroactively fills an `organizer` column in the table
`pretixbase_logentry`. If you have a large database, the migration step of the upgrade might take significantly
longer than usual, so plan the update accordingly.
Upgrade to 2024.7.0 or newer
"""""""""""""""""""""""""""""
This release includes a migration that changes how sales channels are referred on orders.
If you have a large database, the migration step of the upgrade might take significantly longer than usual, so plan
the update accordingly.
.. _blog: https://pretix.eu/about/en/blog/

View File

@@ -32,16 +32,10 @@ as well as the type of underlying hardware. Example:
"token": "kpp4jn8g2ynzonp6",
"hardware_brand": "Samsung",
"hardware_model": "Galaxy S",
"os_name": "Android",
"os_version": "2.3.6",
"software_brand": "pretixdroid",
"software_version": "4.0.0",
"rsa_pubkey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqh…nswIDAQAB\n-----END PUBLIC KEY-----\n"
"software_version": "4.0.0"
}
The ``rsa_pubkey`` is optional any only required for certain fatures such as working with reusable
media and NFC cryptography.
Every initialization token can only be used once. On success, you will receive a response containing
information on your device as well as your API token:
@@ -104,8 +98,6 @@ following endpoint:
{
"hardware_brand": "Samsung",
"hardware_model": "Galaxy S",
"os_name": "Android",
"os_version": "2.3.6",
"software_brand": "pretixdroid",
"software_version": "4.1.0",
"info": {"arbitrary": "data"}
@@ -141,29 +133,9 @@ The response will look like this:
"id": 3,
"name": "South entrance"
}
},
"server": {
"version": {
"pretix": "3.6.0.dev0",
"pretix_numeric": 30060001000
}
},
"medium_key_sets": [
{
"public_id": 3456349,
"organizer": "foo",
"active": true,
"media_type": "nfc_mf0aes",
"uid_key": "base64-encoded-encrypted-key",
"diversification_key": "base64-encoded-encrypted-key",
}
]
}
}
``"medium_key_sets`` will always be empty if you did not set an ``rsa_pubkey``.
The individual keys in the key sets are encrypted with the device's ``rsa_pubkey``
using ``RSA/ECB/PKCS1Padding``.
Creating a new API key
----------------------
@@ -249,10 +221,8 @@ You can get three response codes:
Content-Type: application/json
{
"event": {
"name": "Demo Conference",
"slug": "democon"
},
"event": "democon",
"subevent": 23,
"checkinlist": 5
}

View File

@@ -192,9 +192,6 @@ Relative date *either* String in ISO 8601 ``"2017-12-27"``,
File URL in responses, ``file:`` ``"https://…"``, ``"file:…"``
specifiers in requests
(see below).
Date range *either* two dates separated ``2022-03-18/2022-03-23``, ``2022-03-18/``,
by ``/`` *or* the name of a ``/2022-03-23``, ``week_this``, ``week_next``,
defined range. ``month_this``
===================== ============================ ===================================
Query parameters

View File

@@ -94,9 +94,7 @@ If you want the user to return to your application after the payment is complete
"Plugins". Enable the plugin "Redirection from order page". Then, go to the new page "Settings", then "Redirection".
Enter the base URL of your web application. This will allow you to redirect to pages under this base URL later on.
For example, if you want users to be redirected to ``https://example.org/order/return?tx_id=1234``, you could now
either enter ``https://example.org/order/`` or ``https://example.org/``.
Please note that in the latter case the trailing slash is required, ``https://example.org`` is not allowed to prevent.
Only base URLs with a secure (``https://``) or local (``http://localhost``) origin are permitted.
either enter ``https://example.org`` or ``https://example.org/order/``.
The user will be redirected back to your page instead of pretix' order confirmation page after the payment,
**regardless of whether it was successful or not**. We will append an ``error=…`` query parameter with an error

View File

@@ -107,9 +107,9 @@ You can supply a valid access token as a ``Bearer``-type token in the ``Authoriz
.. sourcecode:: http
:emphasize-lines: 3
GET /api/v1/organizers/ HTTP/1.1
Host: pretix.eu
Authorization: Bearer i3ytqTSRWsKp16fqjekHXa4tdM4qNC
GET /api/v1/organizers/ HTTP/1.1
Host: pretix.eu
Authorization: Bearer i3ytqTSRWsKp16fqjekHXa4tdM4qNC
Refreshing an access token
--------------------------

View File

@@ -1,259 +0,0 @@
.. _rest-autocheckinrules:
Auto check-in rules
===================
This feature requires the bundled ``pretix.plugins.autocheckin`` plugin to be active for the event in order to work properly.
Resource description
--------------------
Auto check-in rules specify that tickets should under specific conditions automatically be considered checked in after
they have been purchased.
.. rst-class:: rest-resource-table
===================================== ========================== =======================================================
Field Type Description
===================================== ========================== =======================================================
id integer Internal ID of the rule
list integer ID of the check-in list to check the ticket in on. If
``None``, the system will select all matching check-in lists.
mode string ``"placed"`` if the rule should be evaluated right after
an order has been created, ``"paid"`` if the rule should
be evaluated after the order has been fully paid.
all_sales_channels boolean If ``true`` (default), the rule applies to tickets sold on all sales channels.
limit_sales_channels list of strings List of sales channel identifiers the rule should apply to
if ``all_sales_channels`` is ``false``.
all_products boolean If ``true`` (default), the rule affects all products and variations.
limit_products list of integers List of item IDs, if ``all_products`` is not set. If the
product listed here has variations, all variations will be matched.
limit_variations list of integers List of product variation IDs, if ``all_products`` is not set.
The parent product does not need to be part of ``limit_products``.
all_payment_methods boolean If ``true`` (default), the rule applies to tickets paid with all payment methods.
limit_payment_methods list of strings List of payment method identifiers the rule should apply to
if ``all_payment_methods`` is ``false``.
===================================== ========================== =======================================================
.. versionadded:: 2024.7
Endpoints
---------
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/auto_checkin_rules/
Returns a list of all rules configured for an event.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/events/sampleconf/auto_checkin_rules/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"list": 12345,
"mode": "placed",
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"all_products": False,
"limit_products": [2, 3],
"limit_variations": [456],
"all_payment_methods": true,
"limit_payment_methods": []
}
]
}
:query page: The page number in case of a multi-page result set, default is 1
:param organizer: The ``slug`` field of a valid organizer
:param event: The ``slug`` field of the event to fetch
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to view it.
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/auto_checkin_rules/(id)/
Returns information on one rule, identified by its ID.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/events/sampleconf/auto_checkin_rules/1/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"id": 1,
"list": 12345,
"mode": "placed",
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"all_products": False,
"limit_products": [2, 3],
"limit_variations": [456],
"all_payment_methods": true,
"limit_payment_methods": []
}
:param organizer: The ``slug`` field of the organizer to fetch
:param event: The ``slug`` field of the event to fetch
:param id: The ``id`` field of the rule to fetch
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event/rule does not exist **or** you have no permission to view it.
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/auto_checkin_rules/
Create a new rule.
**Example request**:
.. sourcecode:: http
POST /api/v1/organizers/bigevents/events/sampleconf/auto_checkin_rules/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
Content-Type: application/json
Content-Length: 166
{
"list": 12345,
"mode": "placed",
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"all_products": False,
"limit_products": [2, 3],
"limit_variations": [456],
"all_payment_methods": true,
"limit_payment_methods": []
}
**Example response**:
.. sourcecode:: http
HTTP/1.1 201 Created
Vary: Accept
Content-Type: application/json
{
"id": 1,
"list": 12345,
"mode": "placed",
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"all_products": False,
"limit_products": [2, 3],
"limit_variations": [456],
"all_payment_methods": true,
"limit_payment_methods": []
}
:param organizer: The ``slug`` field of the organizer to create a rule for
:param event: The ``slug`` field of the event to create a rule for
:statuscode 201: no error
:statuscode 400: The rule could not be created due to invalid submitted data.
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create rules.
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/auto_checkin_rules/(id)/
Update a rule. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
want to change.
**Example request**:
.. sourcecode:: http
PATCH /api/v1/organizers/bigevents/events/sampleconf/auto_checkin_rules/1/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
Content-Type: application/json
Content-Length: 34
{
"mode": "paid",
}
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript
{
"id": 1,
"list": 12345,
"mode": "placed",
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"all_products": False,
"limit_products": [2, 3],
"limit_variations": [456],
"all_payment_methods": true,
"limit_payment_methods": []
}
:param organizer: The ``slug`` field of the organizer to modify
:param event: The ``slug`` field of the event to modify
:param id: The ``id`` field of the rule to modify
:statuscode 200: no error
:statuscode 400: The rule could not be modified due to invalid submitted data.
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event/rule does not exist **or** you have no permission to change it.
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/auto_checkin_rules/(id)/
Delete a rule.
**Example request**:
.. sourcecode:: http
DELETE /api/v1/organizers/bigevents/events/sampleconf/auto_checkin_rules/1/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 204 No Content
Vary: Accept
:param organizer: The ``slug`` field of the organizer to modify
:param event: The ``slug`` field of the event to modify
:param id: The ``id`` field of the rule to delete
:statuscode 204: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event/rule does not exist **or** you have no permission to change it **or** this rule cannot be deleted since it is currently in use.

View File

@@ -40,11 +40,6 @@ answers list of objects Answers to user
seat objects The assigned seat (or ``null``)
├ id integer Internal ID of the seat instance
├ name string Human-readable seat name
├ zone_name string Name of the zone the seat is in
├ row_name string Name/number of the row the seat is in
├ row_label string Additional label of the row (or ``null``)
├ seat_number string Number of the seat within the row
├ seat_label string Additional label of the seat (or ``null``)
└ seat_guid string Identifier of the seat within the seating plan
===================================== ========================== =======================================================

View File

@@ -23,22 +23,6 @@ position integer An integer, use
is_addon boolean If ``true``, items within this category are not on sale
on their own but the category provides a source for
defining add-ons for other products.
cross_selling_mode string If ``null``, cross-selling is disabled for this category.
If ``"only"``, it is only visible in the cross-selling
step.
If ``"both"``, it is visible on the normal index page
as well.
Only available if ``is_addon`` is ``false``.
cross_selling_condition string Only relevant if ``cross_selling_mode`` is not ``null``.
If ``"always"``, always show in cross-selling step.
If ``"products"``, only show if the cart contains one of
the products listed in ``cross_selling_match_products``.
If ``"discounts"``, only show products that qualify for
a discount according to discount rules.
cross_selling_match_products list of integer Only relevant if ``cross_selling_condition`` is
``"products"``. Internal ID of the items of which at
least one needs to be in the cart for this category to
be shown.
===================================== ========================== =======================================================
@@ -76,10 +60,7 @@ Endpoints
"internal_name": "",
"description": {"en": "Tickets are what you need to get in."},
"position": 1,
"is_addon": false,
"cross_selling_mode": null,
"cross_selling_condition": null,
"cross_selling_match_products": []
"is_addon": false
}
]
}
@@ -121,10 +102,7 @@ Endpoints
"internal_name": "",
"description": {"en": "Tickets are what you need to get in."},
"position": 1,
"is_addon": false,
"cross_selling_mode": null,
"cross_selling_condition": null,
"cross_selling_match_products": []
"is_addon": false
}
:param organizer: The ``slug`` field of the organizer to fetch
@@ -152,10 +130,7 @@ Endpoints
"internal_name": "",
"description": {"en": "Tickets are what you need to get in."},
"position": 1,
"is_addon": false,
"cross_selling_mode": null,
"cross_selling_condition": null,
"cross_selling_match_products": []
"is_addon": false
}
**Example response**:
@@ -172,10 +147,7 @@ Endpoints
"internal_name": "",
"description": {"en": "Tickets are what you need to get in."},
"position": 1,
"is_addon": false,
"cross_selling_mode": null,
"cross_selling_condition": null,
"cross_selling_match_products": []
"is_addon": false
}
:param organizer: The ``slug`` field of the organizer of the event to create a category for
@@ -221,10 +193,7 @@ Endpoints
"internal_name": "",
"description": {"en": "Tickets are what you need to get in."},
"position": 1,
"is_addon": true,
"cross_selling_mode": null,
"cross_selling_condition": null,
"cross_selling_match_products": []
"is_addon": true
}
:param organizer: The ``slug`` field of the organizer to modify

View File

@@ -1,4 +1,4 @@
.. spelling:word-list:: checkin
.. spelling:: checkin
.. _rest-checkin:
@@ -13,10 +13,6 @@ failed scans.
The endpoints listed on this page have been added.
.. versionchanged:: 4.18
The ``source_type`` parameter has been added.
.. _`rest-checkin-redeem`:
Checking a ticket in
@@ -31,9 +27,7 @@ Checking a ticket in
This endpoint supports passing multiple check-in lists to perform a multi-event scan. However, each check-in list
passed needs to be from a distinct event.
:query string expand: Expand a field inside the ``position`` object into a full object. Currently ``subevent``, ``item``, ``variation``, and ``answers.question`` are supported. Can be passed multiple times.
:<json string secret: Scanned QR code corresponding to the ``secret`` attribute of a ticket.
:<json string source_type: Type of source the ``secret`` was obtained form. Defaults to ``"barcode"``.
:<json array lists: List of check-in list IDs to search on. No two check-in lists may be from the same event.
:<json string type: Send ``"exit"`` for an exit and ``"entry"`` (default) for an entry.
:<json datetime datetime: Specifies the datetime of the check-in. If not supplied, the current time will be used.
@@ -64,7 +58,6 @@ Checking a ticket in
``checkin_attention`` flag set. (3) If ``attendee_name`` is empty, it may automatically fall
back to values from a parent product or from invoice addresses.
:>json boolean require_attention: Whether or not the ``require_attention`` flag is set on the item or order.
:>json list checkin_texts: List of additional texts to show to the user.
:>json object list: Excerpt of information about the matching :ref:`check-in list <rest-checkinlists>` (if any was found),
including the attributes ``id``, ``name``, ``event``, ``subevent``, and ``include_pending``.
:>json object questions: List of questions to be answered for check-in, only set on status ``"incomplete"``.
@@ -79,7 +72,6 @@ Checking a ticket in
{
"secret": "M5BO19XmFwAjLd4nDYUAL9ISjhti0e9q",
"source_type": "barcode",
"lists": [1],
"force": false,
"ignore_unpaid": false,
@@ -105,7 +97,6 @@ Checking a ticket in
},
"require_attention": false,
"checkin_texts": [],
"list": {
"id": 1,
"name": "Default check-in list",
@@ -128,7 +119,6 @@ Checking a ticket in
},
"require_attention": false,
"checkin_texts": [],
"list": {
"id": 1,
"name": "Default check-in list",
@@ -146,7 +136,6 @@ Checking a ticket in
"position": 1,
"identifier": "WY3TP9SL",
"ask_during_checkin": true,
"show_during_checkin": true,
"options": [
{
"id": 1,
@@ -183,8 +172,7 @@ Checking a ticket in
"status": "error",
"reason": "invalid",
"reason_explanation": null,
"require_attention": false,
"checkin_texts": []
"require_attention": false
}
**Example error response (known, but invalid ticket)**:
@@ -199,7 +187,6 @@ Checking a ticket in
"reason": "unpaid",
"reason_explanation": null,
"require_attention": false,
"checkin_texts": [],
"list": {
"id": 1,
"name": "Default check-in list",
@@ -216,19 +203,16 @@ Checking a ticket in
* ``invalid`` - Ticket is not known.
* ``unpaid`` - Ticket is not paid for.
* ``blocked`` - Ticket has been blocked.
* ``invalid_time`` - Ticket is not valid at this time.
* ``canceled`` Ticket is canceled or expired.
* ``already_redeemed`` - Ticket already has been redeemed.
* ``product`` - Tickets with this product may not be scanned at this device.
* ``rules`` - Check-in prevented by a user-defined rule.
* ``ambiguous`` - Multiple tickets match scan, rejected.
* ``revoked`` - Ticket code has been revoked.
* ``unapproved`` - Order has not yet been approved.
* ``error`` - Internal error.
In case of reason ``rules`` and ``invalid_time``, there might be an additional response field ``reason_explanation``
with a human-readable description of the violated rules. However, that field can also be missing or be ``null``.
In case of reason ``rules``, there might be an additional response field ``reason_explanation`` with a human-readable
description of the violated rules. However, that field can also be missing or be ``null``.
:param organizer: The ``slug`` field of the organizer to fetch
:statuscode 201: no error

View File

@@ -1,4 +1,4 @@
.. spelling:word-list:: checkin
.. spelling:: checkin
.. _rest-checkinlists:
@@ -32,24 +32,17 @@ position_count integer Number of ticke
checkin_count integer Number of check-ins performed on this list (read-only).
include_pending boolean If ``true``, the check-in list also contains tickets from orders in pending state.
auto_checkin_sales_channels list of strings All items on the check-in list will be automatically marked as checked-in when purchased through any of the listed sales channels.
**Deprecated, will be removed in pretix 2024.10.** Use :ref:`rest-autocheckinrules`: instead.
allow_multiple_entries boolean If ``true``, subsequent scans of a ticket on this list should not show a warning but instead be stored as an additional check-in.
allow_entry_after_exit boolean If ``true``, subsequent scans of a ticket on this list are valid if the last scan of the ticket was an exit scan.
rules object Custom check-in logic. The contents of this field are currently not considered a stable API and modifications through the API are highly discouraged.
exit_all_at datetime Automatically check out (i.e. perform an exit scan) at this point in time. After this happened, this property will automatically be set exactly one day into the future. Note that this field is considered "internal configuration" and if you pull the list with ``If-Modified-Since``, the daily change in this field will not trigger a response.
addon_match boolean If ``true``, tickets on this list can be redeemed by scanning their parent ticket if this still leads to an unambiguous match.
ignore_in_statistics boolean If ``true``, check-ins on this list will be ignored in most reporting features.
consider_tickets_used boolean If ``true`` (default), tickets checked in on this list will be considered "used" by other functionality, i.e. when checking if they can still be canceled.
===================================== ========================== =======================================================
.. versionchanged:: 4.12
The ``addon_match`` attribute has been added.
.. versionchanged:: 2023.9
The ``ignore_in_statistics`` and ``consider_tickets_used`` attributes have been added.
Endpoints
---------
@@ -105,8 +98,6 @@ Endpoints
:query string ends_after: Exclude all check-in lists attached to a sub-event that is already in the past at the given time.
:query string expand: Expand a field into a full object. Currently only ``subevent`` is supported. Can be passed multiple times.
:query string exclude: Exclude a field from the output, e.g. ``checkin_count``. Can be used as a performance optimization. Can be passed multiple times.
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``id``, ``name``, and ``subevent__date_from``,
Default: ``subevent__date_from,name``
:param organizer: The ``slug`` field of the organizer to fetch
:param event: The ``slug`` field of the event to fetch
:statuscode 200: no error
@@ -371,7 +362,7 @@ Endpoints
Stores a failed check-in. Only necessary for statistical purposes if you perform scan validation offline.
:<json boolean error_reason: One of ``canceled``, ``invalid``, ``unpaid``, ``product``, ``rules``, ``revoked``,
``incomplete``, ``already_redeemed``, ``blocked``, ``invalid_time``, or ``error``. Required.
``incomplete``, ``already_redeemed``, or ``error``. Required.
:<json raw_barcode: The raw barcode you scanned. Required.
:<json datetime: Date and time of the scan. Optional.
:<json type: Type of scan, defaults to ``"entry"``.
@@ -499,7 +490,7 @@ Order position endpoints
``attendee_name,positionid``
:query string order: Only return positions of the order with the given order code
:query string search: Fuzzy search matching the attendee name, order code, invoice address name as well as to the beginning of the secret.
:query string expand: Expand a field into a full object. Currently ``subevent``, ``item``, ``variation``, and ``answers.question`` are supported. Can be passed multiple times.
:query string expand: Expand a field into a full object. Currently only ``subevent``, ``item``, and ``variation`` are supported. Can be passed multiple times.
:query integer item: Only return positions with the purchased item matching the given ID.
:query integer item__in: Only return positions with the purchased item matching one of the given comma-separated IDs.
:query integer variation: Only return positions with the purchased item variation matching the given ID.
@@ -633,8 +624,7 @@ Order position endpoints
set this to ``false``. In that case, questions will just be ignored. Defaults
to ``true``.
:<json boolean canceled_supported: When this parameter is set to ``true``, the response code ``canceled`` may be
returned. Otherwise, canceled orders will return ``unpaid``. (**Deprecated**, in
the future, this will be ignored and ``canceled`` may always be returned.)
returned. Otherwise, canceled orders will return ``unpaid``.
:<json datetime datetime: Specifies the datetime of the check-in. If not supplied, the current time will be used.
:<json boolean force: Specifies that the check-in should succeed regardless of revoked barcode, previous check-ins or required
questions that have not been filled. This is usually used to upload offline scans that already happened,
@@ -708,7 +698,6 @@ Order position endpoints
"position": 1,
"identifier": "WY3TP9SL",
"ask_during_checkin": true,
"show_during_checkin": true,
"options": [
{
"id": 1,
@@ -752,8 +741,6 @@ Order position endpoints
* ``invalid`` - Ticket code not known.
* ``unpaid`` - Ticket is not paid for.
* ``blocked`` - Ticket has been blocked.
* ``invalid_time`` - Ticket is not valid at this time.
* ``canceled`` Ticket is canceled or expired. This reason is only sent when your request sets.
``canceled_supported`` to ``true``, otherwise these orders return ``unpaid``.
* ``already_redeemed`` - Ticket already has been redeemed.
@@ -761,10 +748,9 @@ Order position endpoints
* ``rules`` - Check-in prevented by a user-defined rule.
* ``ambiguous`` - Multiple tickets match scan, rejected.
* ``revoked`` - Ticket code has been revoked.
* ``unapproved`` - Order has not yet been approved.
In case of reason ``rules`` or ``invalid_time``, there might be an additional response field ``reason_explanation``
with a human-readable description of the violated rules. However, that field can also be missing or be ``null``.
In case of reason ``rules``, there might be an additional response field ``reason_explanation`` with a human-readable
description of the violated rules. However, that field can also be missing or be ``null``.
:param organizer: The ``slug`` field of the organizer to fetch
:param event: The ``slug`` field of the event to fetch
@@ -777,4 +763,4 @@ Order position endpoints
:statuscode 404: The requested order position or check-in list does not exist.
.. _security issues: https://pretix.eu/about/de/blog/20220705-release-4111/
.. _security issues: https://pretix.eu/about/de/blog/20220705-release-4111/

View File

@@ -19,7 +19,6 @@ external_identifier string External ID of
the API, but is read-only for customers created through a
SSO integration.
email string Customer email address
phone string Customer phone number
name string Name of this customer (or ``null``)
name_parts object of strings Decomposition of name (i.e. given name, family name)
is_active boolean Whether this account is active
@@ -40,10 +39,6 @@ password string Can only be set
Passwords can now be set through the API during customer creation.
.. versionchanged:: 2024.3
The attribute ``phone`` has been added.
Endpoints
---------
@@ -76,7 +71,6 @@ Endpoints
"identifier": "8WSAJCJ",
"external_identifier": null,
"email": "customer@example.org",
"phone": "+493012345678",
"name": "John Doe",
"name_parts": {
"_scheme": "full",
@@ -124,7 +118,6 @@ Endpoints
"identifier": "8WSAJCJ",
"external_identifier": null,
"email": "customer@example.org",
"phone": "+493012345678",
"name": "John Doe",
"name_parts": {
"_scheme": "full",
@@ -162,7 +155,6 @@ Endpoints
{
"email": "test@example.org",
"phone": "+493012345678",
"password": "verysecret",
"send_email": true
}
@@ -179,7 +171,6 @@ Endpoints
"identifier": "8WSAJCJ",
"external_identifier": null,
"email": "test@example.org",
"phone": "+493012345678",
...
}
@@ -224,7 +215,6 @@ Endpoints
"identifier": "8WSAJCJ",
"external_identifier": null,
"email": "test@example.org",
"phone": "+493012345678",
}
@@ -259,7 +249,6 @@ Endpoints
"identifier": "8WSAJCJ",
"external_identifier": null,
"email": null,
"phone": null,
}

View File

@@ -1,4 +1,4 @@
.. spelling:word-list:: fullname
.. spelling:: fullname
.. _`rest-devices`:
@@ -24,8 +24,6 @@ all_events boolean Whether this de
limit_events list List of event slugs this device has access to
hardware_brand string Device hardware manufacturer (read-only)
hardware_model string Device hardware model (read-only)
os_name string Device operating system name (read-only)
os_version string Device operating system version (read-only)
software_brand string Device software product (read-only)
software_version string Device software version (read-only)
created datetime Creation time
@@ -78,8 +76,6 @@ Device endpoints
"security_profile": "full",
"hardware_brand": "Zebra",
"hardware_model": "TC25",
"os_name": "Android",
"os_version": "8.1.0",
"software_brand": "pretixSCAN",
"software_version": "1.5.1"
}
@@ -127,8 +123,6 @@ Device endpoints
"security_profile": "full",
"hardware_brand": "Zebra",
"hardware_model": "TC25",
"os_name": "Android",
"os_version": "8.1.0",
"software_brand": "pretixSCAN",
"software_version": "1.5.1"
}
@@ -179,8 +173,6 @@ Device endpoints
"initialized": null
"hardware_brand": null,
"hardware_model": null,
"os_name": null,
"os_version": null,
"software_brand": null,
"software_version": null
}

View File

@@ -20,12 +20,8 @@ id integer Internal ID
active boolean The discount will be ignored if this is ``false``
internal_name string A name for the rule used in the backend
position integer An integer, used for sorting the rules which are applied in order
all_sales_channels boolean If ``true`` (default), the discount is available on all sales channels
that support discounts.
limit_sales_channels list of strings List of sales channel identifiers the discount is available on
if ``all_sales_channels`` is ``false``.
sales_channels list of strings **DEPRECATED.** Legacy interface, use ``all_sales_channels``
and ``limit_sales_channels`` instead.
sales_channels list of strings Sales channels this discount is available on, such as
``"web"`` or ``"resellers"``. Defaults to ``["web"]``.
available_from datetime The first date time at which this discount can be applied
(or ``null``).
available_until datetime The last date time at which this discount can be applied
@@ -35,9 +31,9 @@ subevent_mode strings Determines h
``"same"`` (discount is only applied for groups within
the same date), or ``"distinct"`` (discount is only applied
for groups with no two same dates).
condition_all_products boolean If ``true``, the discount condition applies to all items.
condition_all_products boolean If ``true``, the discount applies to all items.
condition_limit_products list of integers If ``condition_all_products`` is not set, this is a list
of internal item IDs that the discount condition applies to.
of internal item IDs that the discount applies to.
condition_apply_to_addons boolean If ``true``, the discount applies to add-on products as well,
otherwise it only applies to top-level items. The discount never
applies to bundled products.
@@ -52,17 +48,6 @@ benefit_discount_matching_percent decimal (string) The percenta
benefit_only_apply_to_cheapest_n_matches integer If set higher than 0, the discount will only be applied to
the cheapest matches. Useful for a "3 for 2"-style discount.
Cannot be combined with ``condition_min_value``.
benefit_same_products boolean If ``true``, the discount benefit applies to the same set of items
as the condition (see above).
benefit_limit_products list of integers If ``benefit_same_products`` is not set, this is a list
of internal item IDs that the discount benefit applies to.
benefit_apply_to_addons boolean (Only used if ``benefit_same_products`` is ``false``.)
If ``true``, the discount applies to add-on products as well,
otherwise it only applies to top-level items. The discount never
applies to bundled products.
benefit_ignore_voucher_discounted boolean (Only used if ``benefit_same_products`` is ``false``.)
If ``true``, the discount does not apply to products which have
been discounted by a voucher.
======================================== ========================== =======================================================
@@ -99,8 +84,6 @@ Endpoints
"active": true,
"internal_name": "3 for 2",
"position": 1,
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_until": null,
@@ -111,10 +94,6 @@ Endpoints
"condition_ignore_voucher_discounted": false,
"condition_min_count": 3,
"condition_min_value": "0.00",
"benefit_same_products": true,
"benefit_limit_products": [],
"benefit_apply_to_addons": true,
"benefit_ignore_voucher_discounted": false,
"benefit_discount_matching_percent": "100.00",
"benefit_only_apply_to_cheapest_n_matches": 1
}
@@ -157,8 +136,6 @@ Endpoints
"active": true,
"internal_name": "3 for 2",
"position": 1,
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_until": null,
@@ -169,10 +146,6 @@ Endpoints
"condition_ignore_voucher_discounted": false,
"condition_min_count": 3,
"condition_min_value": "0.00",
"benefit_same_products": true,
"benefit_limit_products": [],
"benefit_apply_to_addons": true,
"benefit_ignore_voucher_discounted": false,
"benefit_discount_matching_percent": "100.00",
"benefit_only_apply_to_cheapest_n_matches": 1
}
@@ -201,8 +174,6 @@ Endpoints
"active": true,
"internal_name": "3 for 2",
"position": 1,
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_until": null,
@@ -213,10 +184,6 @@ Endpoints
"condition_ignore_voucher_discounted": false,
"condition_min_count": 3,
"condition_min_value": "0.00",
"benefit_same_products": true,
"benefit_limit_products": [],
"benefit_apply_to_addons": true,
"benefit_ignore_voucher_discounted": false,
"benefit_discount_matching_percent": "100.00",
"benefit_only_apply_to_cheapest_n_matches": 1
}
@@ -234,8 +201,6 @@ Endpoints
"active": true,
"internal_name": "3 for 2",
"position": 1,
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_until": null,
@@ -246,10 +211,6 @@ Endpoints
"condition_ignore_voucher_discounted": false,
"condition_min_count": 3,
"condition_min_value": "0.00",
"benefit_same_products": true,
"benefit_limit_products": [],
"benefit_apply_to_addons": true,
"benefit_ignore_voucher_discounted": false,
"benefit_discount_matching_percent": "100.00",
"benefit_only_apply_to_cheapest_n_matches": 1
}
@@ -296,8 +257,6 @@ Endpoints
"active": false,
"internal_name": "3 for 2",
"position": 1,
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_until": null,
@@ -308,10 +267,6 @@ Endpoints
"condition_ignore_voucher_discounted": false,
"condition_min_count": 3,
"condition_min_value": "0.00",
"benefit_same_products": true,
"benefit_limit_products": [],
"benefit_apply_to_addons": true,
"benefit_ignore_voucher_discounted": false,
"benefit_discount_matching_percent": "100.00",
"benefit_only_apply_to_cheapest_n_matches": 1
}

View File

@@ -1,4 +1,4 @@
.. spelling:word-list::
.. spelling::
geo
lat
@@ -36,8 +36,6 @@ geo_lon float Longitude of th
has_subevents boolean ``true`` if the event series feature is active for this
event. Cannot change after event is created.
meta_data object Values set for organizer-specific meta data parameters.
The allowed keys need to be set up as meta properties
in the organizer configuration.
plugins list A list of package names of the enabled plugins for this
event.
seating_plan integer If reserved seating is in use, the ID of a seating
@@ -49,12 +47,8 @@ item_meta_properties object Item-specific m
valid_keys object Cryptographic keys for non-default signature schemes.
For performance reason, value is omitted in lists and
only contained in detail views. Value can be cached.
all_sales_channels boolean If ``true`` (default), the event is available on all sales channels.
limit_sales_channels list of strings List of sales channel identifiers the event is available on
if ``all_sales_channels`` is ``false``.
sales_channels list of strings **DEPRECATED.** Legacy interface, use ``all_sales_channels``
and ``limit_sales_channels`` instead.
public_url string The public, customer-facing URL of the event (read-only).
sales_channels list A list of sales channels this event is available for
sale on.
===================================== ========================== =======================================================
@@ -71,15 +65,6 @@ Endpoints
The ``search`` query parameter has been added to filter events by their slug, name, or location in any language.
.. versionchanged:: 4.17
The ``public_url`` field has been added.
.. versionchanged:: 5.0
The ``date_from_before``, ``date_from_after``, ``date_to_before``, and ``date_to_after`` query parameters have been
added.
.. http:get:: /api/v1/organizers/(organizer)/events/
Returns a list of all events within a given organizer the authenticated user/token has access to.
@@ -134,14 +119,11 @@ Endpoints
"pretix.plugins.paypal",
"pretix.plugins.ticketoutputpdf"
],
"all_sales_channels": false,
"limit_sales_channels": [
"sales_channels": [
"web",
"pretixpos",
"resellers"
],
"sales_channels": [],
"public_url": "https://pretix.eu/bigevents/sampleconf/"
]
}
]
}
@@ -149,14 +131,9 @@ Endpoints
:query page: The page number in case of a multi-page result set, default is 1
:query is_public: If set to ``true``/``false``, only events with a matching value of ``is_public`` are returned.
:query live: If set to ``true``/``false``, only events with a matching value of ``live`` are returned.
:query testmode: If set to ``true``/``false``, only events with a matching value of ``testmode`` are returned.
:query has_subevents: If set to ``true``/``false``, only events with a matching value of ``has_subevents`` are returned.
:query is_future: If set to ``true`` (``false``), only events that happen currently or in the future are (not) returned. Event series are never (always) returned.
:query is_past: If set to ``true`` (``false``), only events that are over are (not) returned. Event series are never (always) returned.
:query date_from_after: If set to a date and time, only events that start at or after the given time are returned.
:query date_from_before: If set to a date and time, only events that start at or before the given time are returned.
:query date_to_after: If set to a date and time, only events that have an end date and end at or after the given time are returned.
:query date_to_before: If set to a date and time, only events that have an end date and end at or before the given time are returned.
:query ends_after: If set to a date and time, only events that happen during of after the given time are returned. Event series are never returned.
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``date_from`` and
``slug``. Keep in mind that ``date_from`` of event series does not really tell you anything.
@@ -230,14 +207,11 @@ Endpoints
"LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUNvd0JRWURLMlZ3QXlFQTdBRDcvdkZBMzNFc1k0ejJQSHI3aVpQc1o4bjVkaDBhalA4Z3l6Tm1tSXM9Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo="
]
},
"all_sales_channels": true,
"limit_sales_channels": [],
"sales_channels": [
"web",
"pretixpos",
"resellers"
],
"public_url": "https://pretix.eu/bigevents/sampleconf/"
]
}
:param organizer: The ``slug`` field of the organizer to fetch
@@ -289,8 +263,11 @@ Endpoints
"pretix.plugins.stripe",
"pretix.plugins.paypal"
],
"all_sales_channels": true,
"limit_sales_channels": []
"sales_channels": [
"web",
"pretixpos",
"resellers"
]
}
**Example response**:
@@ -326,14 +303,11 @@ Endpoints
"pretix.plugins.stripe",
"pretix.plugins.paypal"
],
"all_sales_channels": true,
"limit_sales_channels": [],
"sales_channels": [
"web",
"pretixpos",
"resellers"
],
"public_url": "https://pretix.eu/bigevents/sampleconf/"
]
}
:param organizer: The ``slug`` field of the organizer of the event to create.
@@ -351,8 +325,8 @@ Endpoints
Creates a new event with properties as set in the request body. The properties that are copied are: ``is_public``,
``testmode``, ``has_subevents``, settings, plugin settings, items, variations, add-ons, quotas, categories, tax rules, questions.
If the ``plugins``, ``has_subevents``, ``meta_data`` and/or ``is_public`` fields are present in the post body this will
determine their value. Otherwise their value will be copied from the existing event.
If the ``plugins``, ``has_subevents`` and/or ``is_public`` fields are present in the post body this will determine their
value. Otherwise their value will be copied from the existing event.
Please note that you can only copy from events under the same organizer this way. Use the ``clone_from`` parameter
when creating a new event for this instead.
@@ -393,8 +367,11 @@ Endpoints
"pretix.plugins.stripe",
"pretix.plugins.paypal"
],
"all_sales_channels": true,
"limit_sales_channels": []
"sales_channels": [
"web",
"pretixpos",
"resellers"
]
}
**Example response**:
@@ -430,14 +407,11 @@ Endpoints
"pretix.plugins.stripe",
"pretix.plugins.paypal"
],
"all_sales_channels": true,
"limit_sales_channels": [],
"sales_channels": [
"web",
"pretixpos",
"resellers"
],
"public_url": "https://pretix.eu/bigevents/sampleconf/"
]
}
:param organizer: The ``slug`` field of the organizer of the event to create.
@@ -507,14 +481,11 @@ Endpoints
"pretix.plugins.paypal",
"pretix.plugins.pretixdroid"
],
"all_sales_channels": true,
"limit_sales_channels": [],
"sales_channels": [
"web",
"pretixpos",
"resellers"
],
"public_url": "https://pretix.eu/bigevents/sampleconf/"
]
}
:param organizer: The ``slug`` field of the organizer of the event to update
@@ -565,17 +536,12 @@ Therefore, we're also not including a list of the options here, but instead reco
to see available options. The ``explain=true`` flag enables a verbose mode that provides you with human-readable
information about the properties.
Note that some settings are read-only, e.g. because they can be read on event level but currently only be changed on
organizer level.
.. note:: Please note that this is not a complete representation of all event settings. You will find more settings
in the web interface.
.. warning:: This API is intended for advanced users. Even though we take care to validate your input, you will be
able to break your event using this API by creating situations of conflicting settings. Please take care.
.. note:: When authenticating with :ref:`rest-deviceauth`, only a limited subset of settings is available.
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/settings/
Get current values of event settings.
@@ -616,7 +582,6 @@ organizer level.
{
"value": "https://pretix.eu",
"label": "Imprint URL",
"readonly": false,
"help_text": "This should point e.g. to a part of your website that has your contact details and legal information."
}
},
@@ -630,10 +595,6 @@ organizer level.
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
.. versionchanged:: 4.18
The ``readonly`` flag has been added.
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/settings/
Updates event settings. Note that ``PUT`` is not allowed here, only ``PATCH``.

View File

@@ -1,6 +1,4 @@
.. spelling:word-list:: checkin
.. _rest-exporters:
.. spelling:: checkin
Data exporters
==============
@@ -113,7 +111,7 @@ Listing available exporters
"input_parameters": [
{
"name": "events",
"required": false
"required": true
},
{
"name": "_format",

View File

@@ -20,12 +20,6 @@ currency string Currency of the
testmode boolean Whether this is a test gift card
expires datetime Expiry date (or ``null``)
conditions string Special terms and conditions for this card (or ``null``)
owner_ticket integer Internal ID of an order position that is the "owner" of
this gift card and can view all transactions. When setting
this field, you can also give the ``secret`` of an order
position.
issuer string Organizer slug of the organizer who created this gift
card and is responsible for it.
===================================== ========================== =======================================================
The gift card transaction resource contains the following public fields:
@@ -41,17 +35,8 @@ value money (string) Transaction amo
event string Event slug, if the gift card was used in the web shop (or ``null``)
order string Order code, if the gift card was used in the web shop (or ``null``)
text string Custom text of the transaction (or ``null``)
info object Additional data about the transaction (or ``null``)
acceptor string Organizer slug of the organizer who created this transaction
(can be ``null`` for all transactions performed before
this field was added.)
===================================== ========================== =======================================================
.. versionchanged:: 4.20
The ``owner_ticket`` and ``issuer`` attributes of the gift card and the ``info`` and ``acceptor`` attributes of the
gift card transaction resource have been added.
Endpoints
---------
@@ -87,8 +72,6 @@ Endpoints
"testmode": false,
"expires": null,
"conditions": null,
"owner_ticket": null,
"issuer": "bigevents",
"value": "13.37"
}
]
@@ -96,14 +79,8 @@ Endpoints
:query integer page: The page number in case of a multi-page result set, default is 1
:query string secret: Only show gift cards with the given secret.
:query string value: Only show gift cards with the given value.
:query boolean expired: Filter for gift cards that are (not) expired.
:query boolean testmode: Filter for gift cards that are (not) in test mode.
:query boolean include_accepted: Also show gift cards issued by other organizers that are accepted by this organizer.
:query string expand: If you pass ``"owner_ticket"``, the respective field will be shown as a nested value instead of just an ID.
The nested objects are identical to the respective resources, except that the ``owner_ticket``
will have an attribute of the format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make
matching easier. The parameter can be given multiple times.
:param organizer: The ``slug`` field of the organizer to fetch
:statuscode 200: no error
:statuscode 401: Authentication failure
@@ -136,8 +113,6 @@ Endpoints
"testmode": false,
"expires": null,
"conditions": null,
"owner_ticket": null,
"issuer": "bigevents",
"value": "13.37"
}
@@ -182,16 +157,10 @@ Endpoints
"currency": "EUR",
"expires": null,
"conditions": null,
"owner_ticket": null,
"issuer": "bigevents",
"value": "13.37"
}
:param organizer: The ``slug`` field of the organizer to create a gift card for
:query string expand: If you pass ``"owner_ticket"``, the respective field will be shown as a nested value instead of just an ID.
The nested objects are identical to the respective resources, except that the ``owner_ticket``
will have an attribute of the format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make
matching easier. The parameter can be given multiple times.
:statuscode 201: no error
:statuscode 400: The gift card could not be created due to invalid submitted data.
:statuscode 401: Authentication failure
@@ -236,8 +205,6 @@ Endpoints
"currency": "EUR",
"expires": null,
"conditions": null,
"owner_ticket": null,
"issuer": "bigevents",
"value": "14.00"
}
@@ -283,8 +250,6 @@ Endpoints
"testmode": false,
"expires": null,
"conditions": null,
"owner_ticket": null,
"issuer": "bigevents",
"value": "15.37"
}
@@ -328,11 +293,7 @@ Endpoints
"value": "50.00",
"event": "democon",
"order": "FXQYW",
"text": null,
"acceptor": "bigevents",
"info": {
"created_by": "plugin1"
}
"text": null
}
]
}

View File

@@ -18,7 +18,6 @@ at :ref:`plugin-docs`.
item_variations
item_bundles
item_add-ons
item_meta_properties
questions
question_options
quotas
@@ -30,21 +29,16 @@ at :ref:`plugin-docs`.
checkinlists
waitinglist
customers
saleschannels
membershiptypes
memberships
giftcards
reusablemedia
carts
teams
devices
webhooks
seatingplans
exporters
scheduled_exports
shredders
sendmail_rules
auto_checkin_rules
billing_invoices
billing_var
seats
billing_var

View File

@@ -12,7 +12,6 @@ The invoice resource contains the following public fields:
Field Type Description
===================================== ========================== =======================================================
number string Invoice number (with prefix)
event string The slug of the parent event
order string Order code of the order this invoice belongs to
is_cancellation boolean ``true``, if this invoice is the cancellation of a
different invoice.
@@ -43,7 +42,6 @@ introductory_text string Text to be prin
additional_text string Text to be printed below the product list
payment_provider_text string Text to be printed below the product list with
payment information
payment_provider_stamp string Short text to be visibly printed to indicate payment status
footer_text string Text to be printed in the page footer area
lines list of objects The actual invoice contents
├ position integer Number of the line within an invoice.
@@ -122,13 +120,9 @@ internal_reference string Customer's refe
The attribute ``lines.subevent`` has been added.
.. versionchanged:: 2023.8
The ``event`` attribute has been added. The organizer-level endpoint has been added.
List of all invoices
--------------------
Endpoints
---------
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/invoices/
@@ -157,7 +151,6 @@ List of all invoices
"results": [
{
"number": "SAMPLECONF-00001",
"event": "sampleconf",
"order": "ABC12",
"is_cancellation": false,
"invoice_from_name": "Big Events LLC",
@@ -185,7 +178,6 @@ List of all invoices
"internal_reference": "",
"additional_text": "We are looking forward to see you on our conference!",
"payment_provider_text": "Please transfer the money to our account ABC…",
"payment_provider_stamp": null,
"footer_text": "Big Events LLC - Registration No. 123456 - VAT ID: EU0987654321",
"lines": [
{
@@ -217,9 +209,6 @@ List of all invoices
:query boolean is_cancellation: If set to ``true`` or ``false``, only invoices with this value for the field
``is_cancellation`` will be returned.
:query string order: If set, only invoices belonging to the order with the given order code will be returned.
This parameter may be given multiple times. In this case, all invoices matching one of the inputs will be returned.
:query string number: If set, only invoices with the given invoice number will be returned.
This parameter may be given multiple times. In this case, all invoices matching one of the inputs will be returned.
:query string refers: If set, only invoices referring to the given invoice will be returned.
:query string locale: If set, only invoices with the given locale will be returned.
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``date`` and
@@ -230,50 +219,6 @@ List of all invoices
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
.. http:get:: /api/v1/organizers/(organizer)/invoices/
Returns a list of all invoices within all events of a given organizer (with sufficient access permissions).
Supported query parameters and output format of this endpoint are identical to the list endpoint within an event.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/events/sampleconf/invoices/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"number": "SAMPLECONF-00001",
"event": "sampleconf",
"order": "ABC12",
...
]
}
:param organizer: The ``slug`` field of the organizer to fetch
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
Fetching individual invoices
----------------------------
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/invoices/(number)/
Returns information on one invoice, identified by its invoice number.
@@ -296,7 +241,6 @@ Fetching individual invoices
{
"number": "SAMPLECONF-00001",
"event": "sampleconf",
"order": "ABC12",
"is_cancellation": false,
"invoice_from_name": "Big Events LLC",
@@ -324,7 +268,6 @@ Fetching individual invoices
"internal_reference": "",
"additional_text": "We are looking forward to see you on our conference!",
"payment_provider_text": "Please transfer the money to our account ABC…",
"payment_provider_stamp": null,
"footer_text": "Big Events LLC - Registration No. 123456 - VAT ID: EU0987654321",
"lines": [
{
@@ -391,12 +334,6 @@ Fetching individual invoices
:statuscode 409: The file is not yet ready and will now be prepared. Retry the request after waiting for a few
seconds.
Modifying invoices
------------------
Invoices cannot be edited directly, but the following actions can be triggered:
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/invoices/(invoice_no)/reissue/
Cancels the invoice and creates a new one.

View File

@@ -1,211 +0,0 @@
Item Meta Properties
====================
Resource description
--------------------
An Item Meta Property is used to include (event internally relevant) meta information with every item (product). This
could be internal categories like booking positions.
The Item Meta Properties resource contains the following public fields:
.. rst-class:: rest-resource-table
===================================== ========================== =======================================================
Field Type Description
===================================== ========================== =======================================================
id integer Unique ID for this property
name string Name of the property
default string Value of the default option
required boolean If ``true``, this property will have to be assigned a
value in all items of the related event
allowed_values list List of all permitted values for this property,
or ``null`` for no limitation
===================================== ========================== =======================================================
Endpoints
---------
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/item_meta_properties/
Returns a list of all Item Meta Properties within a given event.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/events/sampleconf/item_meta_properties/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"name": "Color",
"default": "red",
"required": true,
"allowed_values": ["red", "green", "blue"]
}
]
}
:param organizer: The ``slug`` field of the organizer
:param event: The ``slug`` field of the event
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/item_meta_properties/(id)/
Returns information on one property, identified by its id.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/events/sampleconf/item_meta_properties/1/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
{
"id": 1,
"name": "Color",
"default": "red",
"required": true,
"allowed_values": ["red", "green", "blue"]
}
:param organizer: The ``slug`` field of the organizer
:param event: The ``slug`` field of the event
:param id: The ``id`` field of the item meta property to retrieve
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/item_meta_properties/
Creates a new item meta property
**Example request**:
.. sourcecode:: http
POST /api/v1/organizers/bigevents/events/sampleconf/item_meta_properties/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
Content-Type: application/json
{
"name": "ref-code",
"default": "abcde",
"required": true,
"allowed_values": null
}
**Example response**:
.. sourcecode:: http
{
"id": 2,
"name": "ref-code",
"default": "abcde",
"required": true,
"allowed_values": null
}
:param organizer: The ``slug`` field of the organizer
:param event: The ``slug`` field of the event
:statuscode 201: no error
:statuscode 400: The item meta property could not be created due to invalid submitted data.
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to create this resource.
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/item_meta_properties/(id)/
Update an item meta property. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide
all fields of the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the
fields that you want to change.
You can change all fields of the resource except the ``id`` field.
**Example request**:
.. sourcecode:: http
PATCH /api/v1/organizers/bigevents/events/sampleconf/item_meta_properties/2/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
Content-Type: application/json
Content-Length: 94
{
"required": false
}
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"id": 2,
"name": "ref-code",
"default": "abcde",
"required": false,
"allowed_values": []
}
:param organizer: The ``slug`` field of the organizer
:param event: The ``slug`` field of the event
:param id: The ``id`` field of the item meta property to modify
:statuscode 200: no error
:statuscode 400: The property could not be modified due to invalid submitted data
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to change this resource.
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/item_meta_properties/(id)/
Delete an item meta property.
**Example request**:
.. sourcecode:: http
DELETE /api/v1/organizers/bigevents/events/sampleconf/item_meta_properties/1/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 204 No Content
Vary: Accept
:param organizer: The ``slug`` field of the organizer
:param event: The ``slug`` field of the event
:param id: The ``id`` field of the item meta property to delete
:statuscode 204: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to delete this resource.

View File

@@ -18,19 +18,12 @@ default_price money (string) The price set d
price money (string) The price used for this variation. This is either the
same as ``default_price`` if that value is set or equal
to the item's ``default_price`` (read-only).
free_price_suggestion money (string) A suggested price, used as a default value if
``Item.free_price`` is set (or ``null``).
original_price money (string) An original price, shown for comparison, not used
for price calculations (or ``null``).
active boolean If ``false``, this variation will not be sold or shown.
description multi-lingual string A public description of the variation. May contain
Markdown syntax or can be ``null``.
position integer An integer, used for sorting
checkin_attention boolean If ``true``, the check-in app should show a warning
that this ticket requires special attention if such
a variation is being scanned.
checkin_text string Text that will be shown if a ticket of this type is
scanned (or ``null``).
require_approval boolean If ``true``, orders with this variation will need to be
approved by the event organizer before they can be
paid.
@@ -38,26 +31,15 @@ require_membership boolean If ``true``, bo
require_membership_hidden boolean If ``true`` and ``require_membership`` is set, this variation will
be hidden from users without a valid membership.
require_membership_types list of integers Internal IDs of membership types valid if ``require_membership`` is ``true``
all_sales_channels boolean If ``true`` (default), the variation is available on all sales channels.
limit_sales_channels list of strings List of sales channel identifiers the variation is available on
if ``all_sales_channels`` is ``false``.
sales_channels list of strings Sales channels this variation is available on, such as
``"web"`` or ``"resellers"``. Defaults to all existing sales channels.
The item-level list takes precedence, i.e. a sales
channel needs to be on both lists for the variation to be
available (unless ``all_sales_channels`` is used).
sales_channels list of strings **DEPRECATED.** Legacy interface, use ``all_sales_channels``
and ``limit_sales_channels`` instead.
channel needs to be on both lists for the item to be
available.
available_from datetime The first date time at which this variation can be bought
(or ``null``).
available_from_mode string If ``hide`` (the default), this variation is hidden in the shop
if unavailable due to the available_from setting.
If ``info``, the variation is visible, but can't be purchased,
and a note explaining the unavailability is displayed.
available_until datetime The last date time at which this variation can be bought
(or ``null``).
available_until_mode string If ``hide`` (the default), this variation is hidden in the shop
if unavailable due to the available_until setting.
If ``info``, the variation is visible, but can't be purchased,
and a note explaining the unavailability is displayed.
hide_without_voucher boolean If ``true``, this variation is only shown during the voucher
redemption process, but not in the normal shop
frontend.
@@ -66,13 +48,7 @@ meta_data object Values set for
.. versionchanged:: 4.16
The ``meta_data`` and ``checkin_attention`` attributes have been added.
.. versionchanged:: 2023.10
The ``free_price_suggestion`` attribute has been added.
The ``checkin_text`` attribute has been added.
The ``meta_data`` attribute has been added.
Endpoints
---------
@@ -108,19 +84,13 @@ Endpoints
"en": "S"
},
"active": true,
"checkin_attention": false,
"checkin_text": null,
"require_approval": false,
"require_membership": false,
"require_membership_hidden": false,
"require_membership_types": [],
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hide_without_voucher": false,
"description": {
"en": "Test2"
@@ -129,7 +99,6 @@ Endpoints
"default_price": "223.00",
"price": 223.0,
"original_price": null,
"free_price_suggestion": null,
"meta_data": {}
},
{
@@ -138,33 +107,20 @@ Endpoints
"en": "L"
},
"active": true,
"checkin_attention": false,
"checkin_text": null,
"require_approval": false,
"require_membership": false,
"require_membership_hidden": false,
"require_membership_types": [],
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hide_without_voucher": false,
"description": {},
"position": 1,
"default_price": "223.00",
"price": 223.0,
"original_price": null,
"free_price_suggestion": null,
"default_price": null,
"price": 15.0,
"meta_data": {}
}
]
}
:query integer page: The page number in case of a multi-page result set, default is 1
:query string search: Filter the list by the value of the variation (substring search).
:query boolean active: If set to ``true`` or ``false``, only items with this value for the field ``active`` will be
returned.
:param organizer: The ``slug`` field of the organizer to fetch
@@ -202,21 +158,14 @@ Endpoints
"default_price": "10.00",
"price": "10.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"checkin_text": null,
"require_approval": false,
"require_membership": false,
"require_membership_hidden": false,
"require_membership_types": [],
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hide_without_voucher": false,
"description": null,
"position": 0,
@@ -248,18 +197,13 @@ Endpoints
"value": {"en": "Student"},
"default_price": "10.00",
"active": true,
"checkin_attention": false,
"checkin_text": null,
"require_approval": false,
"require_membership": false,
"require_membership_hidden": false,
"require_membership_types": [],
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hide_without_voucher": false,
"description": null,
"position": 0,
@@ -280,21 +224,14 @@ Endpoints
"default_price": "10.00",
"price": "10.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"checkin_text": null,
"require_approval": false,
"require_membership": false,
"require_membership_hidden": false,
"require_membership_types": [],
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hide_without_voucher": false,
"description": null,
"position": 0,
@@ -346,21 +283,14 @@ Endpoints
"default_price": "10.00",
"price": "10.00",
"original_price": null,
"free_price_suggestion": null,
"active": false,
"checkin_attention": false,
"checkin_text": null,
"require_approval": false,
"require_membership": false,
"require_membership_hidden": false,
"require_membership_types": [],
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hide_without_voucher": false,
"description": null,
"position": 1,

View File

@@ -11,201 +11,141 @@ The item resource contains the following public fields:
.. rst-class:: rest-resource-table
======================================= ========================== =======================================================
Field Type Description
======================================= ========================== =======================================================
id integer Internal ID of the item
name multi-lingual string The item's visible name
internal_name string An optional name that is only used in the backend
default_price money (string) The item price that is applied if the price is not
overwritten by variations or other options.
category integer The ID of the category this item belongs to
(or ``null``).
active boolean If ``false``, the item is hidden from all public lists
and will not be sold.
description multi-lingual string A public description of the item. May contain Markdown
syntax or can be ``null``.
free_price boolean If ``true``, customers can change the price at which
they buy the product (however, the price can't be set
lower than the price defined by ``default_price`` or
otherwise).
free_price_suggestion money (string) A suggested price, used as a default value if
``free_price`` is set (or ``null``).
tax_rate decimal (string) The VAT rate to be applied for this item (read-only,
set through ``tax_rule``).
tax_rule integer The internal ID of the applied tax rule (or ``null``).
admission boolean ``true`` for items that grant admission to the event
(such as primary tickets) and ``false`` for others
(such as add-ons or merchandise).
personalized boolean ``true`` for items that require personalization according
to event settings. Only affects system-level fields, not
custom questions. Currently only allowed for products with
``admission`` set to ``true``. For backwards compatibility,
when creating new items and this field is not given, it defaults
to the same value as ``admission``.
position integer An integer, used for sorting
picture file A product picture to be displayed in the shop
(can be ``null``).
all_sales_channels boolean If ``true`` (default), the item is available on all sales channels.
limit_sales_channels list of strings List of sales channel identifiers the item is available on
if ``all_sales_channels`` is ``false``.
sales_channels list of strings **DEPRECATED.** Legacy interface, use ``all_sales_channels``
and ``limit_sales_channels`` instead.
available_from datetime The first date time at which this item can be bought
(or ``null``).
available_from_mode string If ``hide`` (the default), this item is hidden in the shop
if unavailable due to the ``available_from`` setting.
If ``info``, the item is visible, but can't be purchased,
and a note explaining the unavailability is displayed.
available_until datetime The last date time at which this item can be bought
(or ``null``).
available_until_mode string If ``hide`` (the default), this item is hidden in the shop
if unavailable due to the ``available_until`` setting.
If ``info``, the item is visible, but can't be purchased,
and a note explaining the unavailability is displayed.
hidden_if_available integer **DEPRECATED** The internal ID of a quota object, or ``null``. If
set, this item won't be shown publicly as long as this
quota is available.
hidden_if_item_available integer The internal ID of a different item, or ``null``. If
set, this item won't be shown publicly as long as this
other item is available.
require_voucher boolean If ``true``, this item can only be bought using a
voucher that is specifically assigned to this item.
hide_without_voucher boolean If ``true``, this item is only shown during the voucher
redemption process, but not in the normal shop
frontend.
allow_cancel boolean If ``false``, customers cannot cancel orders containing
this item.
min_per_order integer This product can only be bought if it is included at
least this many times in the order (or ``null`` for no
limitation).
max_per_order integer This product can only be bought if it is included at
most this many times in the order (or ``null`` for no
limitation).
checkin_attention boolean If ``true``, the check-in app should show a warning
that this ticket requires special attention if such
a product is being scanned.
checkin_text string Text that will be shown if a ticket of this type is
scanned (or ``null``).
original_price money (string) An original price, shown for comparison, not used
for price calculations (or ``null``).
require_approval boolean If ``true``, orders with this product will need to be
approved by the event organizer before they can be
paid.
require_bundling boolean If ``true``, this item is only available as part of bundles.
require_membership boolean If ``true``, booking this item requires an active membership.
require_membership_hidden boolean If ``true`` and ``require_membership`` is set, this product will
be hidden from users without a valid membership.
require_membership_types list of integers Internal IDs of membership types valid if ``require_membership`` is ``true``
grant_membership_type integer If set to the internal ID of a membership type, purchasing this item will
create a membership of the given type.
grant_membership_duration_like_event boolean If ``true``, the membership created through ``grant_membership_type`` will derive
its term from ``date_from`` to ``date_to`` of the purchased (sub)event.
grant_membership_duration_days integer If ``grant_membership_duration_like_event`` is ``false``, this sets the number of
days for the membership.
grant_membership_duration_months integer If ``grant_membership_duration_like_event`` is ``false``, this sets the number of
calendar months for the membership.
validity_mode string If ``null``, tickets generated for this product do not
have special validity behavior, but follow event configuration and
can be limited e.g. through check-in rules. Other values are ``"fixed"`` and ``"dynamic"``
validity_fixed_from datetime If ``validity_mode`` is ``"fixed"``, this is the start of validity for issued tickets.
validity_fixed_until datetime If ``validity_mode`` is ``"fixed"``, this is the end of validity for issued tickets.
validity_dynamic_duration_minutes integer If ``validity_mode`` is ``"dynamic"``, this is the "minutes" component of the ticket validity duration.
validity_dynamic_duration_hours integer If ``validity_mode`` is ``"dynamic"``, this is the "hours" component of the ticket validity duration.
validity_dynamic_duration_days integer If ``validity_mode`` is ``"dynamic"``, this is the "days" component of the ticket validity duration.
validity_dynamic_duration_months integer If ``validity_mode`` is ``"dynamic"``, this is the "months" component of the ticket validity duration.
validity_dynamic_start_choice boolean If ``validity_mode`` is ``"dynamic"`` and this is ``true``, customers can choose the start of validity.
validity_dynamic_start_choice_day_limit boolean If ``validity_mode`` is ``"dynamic"`` and ``validity_dynamic_start_choice`` is ``true``,
this is the maximum number of days the start can be in the future.
generate_tickets boolean If ``false``, tickets are never generated for this
product, regardless of other settings. If ``true``,
tickets are generated even if this is a
non-admission or add-on product, regardless of event
settings. If this is ``null``, regular ticketing
rules apply.
allow_waitinglist boolean If ``false``, no waiting list will be shown for this
product when it is sold out.
issue_giftcard boolean If ``true``, buying this product will yield a gift card.
media_policy string Policy on how to handle reusable media (experimental feature).
Possible values are ``null``, ``"new"``, ``"reuse"``, and ``"reuse_or_new"``.
media_type string Type of reusable media to work on (experimental feature). See :ref:`rest-reusablemedia` for possible choices.
show_quota_left boolean Publicly show how many tickets are still available.
If this is ``null``, the event default is used.
has_variations boolean Shows whether or not this item has variations.
variations list of objects A list with one object for each variation of this item.
Can be empty. Only writable during creation,
use separate endpoint to modify this later.
├ id integer Internal ID of the variation
├ value multi-lingual string The "name" of the variation
├ default_price money (string) The price set directly for this variation or ``null``
price money (string) The price used for this variation. This is either the
same as ``default_price`` if that value is set or equal
to the item's ``default_price``.
├ free_price_suggestion money (string) A suggested price, used as a default value if
``free_price`` is set (or ``null``).
├ original_price money (string) An original price, shown for comparison, not used
for price calculations (or ``null``).
├ active boolean If ``false``, this variation will not be sold or shown.
├ description multi-lingual string A public description of the variation. May contain
├ checkin_attention boolean If ``true``, the check-in app should show a warning
that this ticket requires special attention if such
a variation is being scanned.
├ checkin_text string Text that will be shown if a ticket of this type is
scanned (or ``null``).
├ require_approval boolean If ``true``, orders with this variation will need to be
approved by the event organizer before they can be
paid.
├ require_membership boolean If ``true``, booking this variation requires an active membership.
├ require_membership_hidden boolean If ``true`` and ``require_membership`` is set, this variation will
be hidden from users without a valid membership.
├ require_membership_types list of integers Internal IDs of membership types valid if ``require_membership`` is ``true``
Markdown syntax or can be ``null``.
├ all_sales_channels boolean If ``true`` (default), the variation is available on all sales channels.
├ limit_sales_channels list of strings List of sales channel identifiers the variation is available on
if ``all_sales_channels`` is ``false``.
The item-level list takes precedence, i.e. a sales
channel needs to be on both lists for the variation to be
available (unless ``all_sales_channels`` is used).
├ sales_channels list of strings **DEPRECATED.** Legacy interface, use ``all_sales_channels``
and ``limit_sales_channels`` instead.
├ available_from datetime The first date time at which this variation can be bought
(or ``null``).
├ available_from_mode string If ``hide`` (the default), this variation is hidden in the shop
if unavailable due to the ``available_from`` setting.
If ``info``, the variation is visible, but can't be purchased,
and a note explaining the unavailability is displayed.
├ available_until datetime The last date time at which this variation can be bought
(or ``null``).
├ available_until_mode string If ``hide`` (the default), this variation is hidden in the shop
if unavailable due to the ``available_until`` setting.
If ``info``, the variation is visible, but can't be purchased,
and a note explaining the unavailability is displayed.
├ hide_without_voucher boolean If ``true``, this variation is only shown during the voucher
redemption process, but not in the normal shop
frontend.
├ meta_data object Values set for event-specific meta data parameters.
└ position integer An integer, used for sorting
addons list of objects Definition of add-ons that can be chosen for this item.
Only writable during creation,
use separate endpoint to modify this later.
├ addon_category integer Internal ID of the item category the add-on can be
chosen from.
├ min_count integer The minimal number of add-ons that need to be chosen.
├ max_count integer The maximal number of add-ons that can be chosen.
├ position integer An integer, used for sorting
├ multi_allowed boolean Adding the same item multiple times is allowed
└ price_included boolean Adding this add-on to the item is free
bundles list of objects Definition of bundles that are included in this item.
Only writable during creation,
use separate endpoint to modify this later.
├ bundled_item integer Internal ID of the item that is included.
├ bundled_variation integer Internal ID of the variation of the item (or ``null``).
├ count integer Number of items included
└ designated_price money (string) Designated price of the bundled product. This will be
used to split the price of the base item e.g. for mixed
taxation. This is not added to the price.
meta_data object Values set for event-specific meta data parameters.
======================================= ========================== =======================================================
===================================== ========================== =======================================================
Field Type Description
===================================== ========================== =======================================================
id integer Internal ID of the item
name multi-lingual string The item's visible name
internal_name string An optional name that is only used in the backend
default_price money (string) The item price that is applied if the price is not
overwritten by variations or other options.
category integer The ID of the category this item belongs to
(or ``null``).
active boolean If ``false``, the item is hidden from all public lists
and will not be sold.
description multi-lingual string A public description of the item. May contain Markdown
syntax or can be ``null``.
free_price boolean If ``true``, customers can change the price at which
they buy the product (however, the price can't be set
lower than the price defined by ``default_price`` or
otherwise).
tax_rate decimal (string) The VAT rate to be applied for this item (read-only,
set through ``tax_rule``).
tax_rule integer The internal ID of the applied tax rule (or ``null``).
admission boolean ``true`` for items that grant admission to the event
(such as primary tickets) and ``false`` for others
(such as add-ons or merchandise).
position integer An integer, used for sorting
picture file A product picture to be displayed in the shop
(can be ``null``).
sales_channels list of strings Sales channels this product is available on, such as
``"web"`` or ``"resellers"``. Defaults to ``["web"]``.
available_from datetime The first date time at which this item can be bought
(or ``null``).
available_until datetime The last date time at which this item can be bought
(or ``null``).
hidden_if_available integer The internal ID of a quota object, or ``null``. If
set, this item won't be shown publicly as long as this
quota is available.
require_voucher boolean If ``true``, this item can only be bought using a
voucher that is specifically assigned to this item.
hide_without_voucher boolean If ``true``, this item is only shown during the voucher
redemption process, but not in the normal shop
frontend.
allow_cancel boolean If ``false``, customers cannot cancel orders containing
this item.
min_per_order integer This product can only be bought if it is included at
least this many times in the order (or ``null`` for no
limitation).
max_per_order integer This product can only be bought if it is included at
most this many times in the order (or ``null`` for no
limitation).
checkin_attention boolean If ``true``, the check-in app should show a warning
that this ticket requires special attention if such
a product is being scanned.
original_price money (string) An original price, shown for comparison, not used
for price calculations (or ``null``).
require_approval boolean If ``true``, orders with this product will need to be
approved by the event organizer before they can be
paid.
require_bundling boolean If ``true``, this item is only available as part of bundles.
require_membership boolean If ``true``, booking this item requires an active membership.
require_membership_hidden boolean If ``true`` and ``require_membership`` is set, this product will
be hidden from users without a valid membership.
require_membership_types list of integers Internal IDs of membership types valid if ``require_membership`` is ``true``
grant_membership_type integer If set to the internal ID of a membership type, purchasing this item will
create a membership of the given type.
grant_membership_duration_like_event boolean If ``true``, the membership created through ``grant_membership_type`` will derive
its term from ``date_from`` to ``date_to`` of the purchased (sub)event.
grant_membership_duration_days integer If ``grant_membership_duration_like_event`` is ``false``, this sets the number of
days for the membership.
grant_membership_duration_months integer If ``grant_membership_duration_like_event`` is ``false``, this sets the number of
calendar months for the membership.
generate_tickets boolean If ``false``, tickets are never generated for this
product, regardless of other settings. If ``true``,
tickets are generated even if this is a
non-admission or add-on product, regardless of event
settings. If this is ``null``, regular ticketing
rules apply.
allow_waitinglist boolean If ``false``, no waiting list will be shown for this
product when it is sold out.
issue_giftcard boolean If ``true``, buying this product will yield a gift card.
show_quota_left boolean Publicly show how many tickets are still available.
If this is ``null``, the event default is used.
has_variations boolean Shows whether or not this item has variations.
variations list of objects A list with one object for each variation of this item.
Can be empty. Only writable during creation,
use separate endpoint to modify this later.
├ id integer Internal ID of the variation
├ value multi-lingual string The "name" of the variation
├ default_price money (string) The price set directly for this variation or ``null``
├ price money (string) The price used for this variation. This is either the
same as ``default_price`` if that value is set or equal
to the item's ``default_price``.
├ original_price money (string) An original price, shown for comparison, not used
for price calculations (or ``null``).
├ active boolean If ``false``, this variation will not be sold or shown.
├ description multi-lingual string A public description of the variation. May contain
├ require_membership boolean If ``true``, booking this variation requires an active membership.
├ require_membership_hidden boolean If ``true`` and ``require_membership`` is set, this variation will
be hidden from users without a valid membership.
├ require_membership_types list of integers Internal IDs of membership types valid if ``require_membership`` is ``true``
Markdown syntax or can be ``null``.
├ sales_channels list of strings Sales channels this variation is available on, such as
``"web"`` or ``"resellers"``. Defaults to all existing sales channels.
The item-level list takes precedence, i.e. a sales
channel needs to be on both lists for the item to be
available.
├ available_from datetime The first date time at which this variation can be bought
(or ``null``).
├ available_until datetime The last date time at which this variation can be bought
(or ``null``).
├ hide_without_voucher boolean If ``true``, this variation is only shown during the voucher
redemption process, but not in the normal shop
frontend.
├ meta_data object Values set for event-specific meta data parameters.
└ position integer An integer, used for sorting
addons list of objects Definition of add-ons that can be chosen for this item.
Only writable during creation,
use separate endpoint to modify this later.
├ addon_category integer Internal ID of the item category the add-on can be
chosen from.
├ min_count integer The minimal number of add-ons that need to be chosen.
├ max_count integer The maximal number of add-ons that can be chosen.
├ position integer An integer, used for sorting
├ multi_allowed boolean Adding the same item multiple times is allowed
└ price_included boolean Adding this add-on to the item is free
bundles list of objects Definition of bundles that are included in this item.
Only writable during creation,
use separate endpoint to modify this later.
bundled_item integer Internal ID of the item that is included.
├ bundled_variation integer Internal ID of the variation of the item (or ``null``).
├ count integer Number of items included
└ designated_price money (string) Designated price of the bundled product. This will be
used to split the price of the base item e.g. for mixed
taxation. This is not added to the price.
meta_data object Values set for event-specific meta data parameters.
===================================== ========================== =======================================================
.. versionchanged:: 4.0
@@ -218,26 +158,7 @@ meta_data object Values set fo
.. versionchanged:: 4.16
The ``variations[x].meta_data`` and ``variations[x].checkin_attention`` attributes have been added.
The ``personalized`` attribute has been added.
.. versionchanged:: 4.17
The ``validity_*`` attributes have been added.
.. versionchanged:: 4.18
The ``media_policy`` and ``media_type`` attributes have been added.
.. versionchanged:: 2023.10
The ``checkin_text`` and ``variations[x].checkin_text`` attributes have been added.
The ``free_price_suggestion`` and ``variations[x].free_price_suggestion`` attributes have been added.
.. versionchanged:: 2023.10
The ``hidden_if_item_available`` attributes has been added, the ``hidden_if_available`` attribute has been
deprecated.
The ``variations[x].meta_data`` attribute has been added.
Notes
-----
@@ -282,8 +203,6 @@ Endpoints
"id": 1,
"name": {"en": "Standard ticket"},
"internal_name": "",
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"default_price": "23.00",
"original_price": null,
@@ -291,30 +210,22 @@ Endpoints
"active": true,
"description": null,
"free_price": false,
"free_price_suggestion": null,
"tax_rate": "0.00",
"tax_rule": 1,
"admission": false,
"personalized": false,
"issue_giftcard": false,
"media_policy": null,
"media_type": null,
"meta_data": {},
"position": 0,
"picture": null,
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hidden_if_available": null,
"hidden_if_item_available": null,
"require_voucher": false,
"hide_without_voucher": false,
"allow_cancel": true,
"min_per_order": null,
"max_per_order": null,
"checkin_attention": false,
"checkin_text": null,
"has_variations": false,
"generate_tickets": null,
"allow_waitinglist": true,
@@ -327,34 +238,18 @@ Endpoints
"grant_membership_duration_like_event": true,
"grant_membership_duration_days": 0,
"grant_membership_duration_months": 0,
"validity_fixed_from": null,
"validity_fixed_until": null,
"validity_dynamic_duration_minutes": null,
"validity_dynamic_duration_hours": null,
"validity_dynamic_duration_days": null,
"validity_dynamic_duration_months": null,
"validity_dynamic_start_choice": false,
"validity_dynamic_start_choice_day_limit": null,
"variations": [
{
"value": {"en": "Student"},
"default_price": "10.00",
"price": "10.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"checkin_text": null,
"require_approval": false,
"require_membership": false,
"require_membership_types": [],
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hide_without_voucher": false,
"description": null,
"meta_data": {},
@@ -365,20 +260,12 @@ Endpoints
"default_price": null,
"price": "23.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"checkin_text": null,
"require_approval": false,
"require_membership": false,
"require_membership_types": [],
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hide_without_voucher": false,
"description": null,
"meta_data": {},
@@ -392,7 +279,6 @@ Endpoints
}
:query integer page: The page number in case of a multi-page result set, default is 1
:query string search: Filter the list by internal name or name of the item (substring search).
:query boolean active: If set to ``true`` or ``false``, only items with this value for the field ``active`` will be
returned.
:query integer category: If set to the ID of a category, only items within that category will be returned.
@@ -433,8 +319,6 @@ Endpoints
"id": 1,
"name": {"en": "Standard ticket"},
"internal_name": "",
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"default_price": "23.00",
"original_price": null,
@@ -442,23 +326,16 @@ Endpoints
"active": true,
"description": null,
"free_price": false,
"free_price_suggestion": null,
"tax_rate": "0.00",
"tax_rule": 1,
"admission": false,
"personalized": false,
"issue_giftcard": false,
"media_policy": null,
"media_type": null,
"meta_data": {},
"position": 0,
"picture": null,
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hidden_if_available": null,
"hidden_if_item_available": null,
"require_voucher": false,
"hide_without_voucher": false,
"allow_cancel": true,
@@ -468,7 +345,6 @@ Endpoints
"min_per_order": null,
"max_per_order": null,
"checkin_attention": false,
"checkin_text": null,
"has_variations": false,
"require_approval": false,
"require_bundling": false,
@@ -478,35 +354,19 @@ Endpoints
"grant_membership_duration_like_event": true,
"grant_membership_duration_days": 0,
"grant_membership_duration_months": 0,
"validity_fixed_from": null,
"validity_fixed_until": null,
"validity_dynamic_duration_minutes": null,
"validity_dynamic_duration_hours": null,
"validity_dynamic_duration_days": null,
"validity_dynamic_duration_months": null,
"validity_dynamic_start_choice": false,
"validity_dynamic_start_choice_day_limit": null,
"variations": [
{
"value": {"en": "Student"},
"default_price": "10.00",
"price": "10.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"checkin_text": null,
"require_approval": false,
"require_membership": false,
"require_membership_types": [],
"description": null,
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hide_without_voucher": false,
"meta_data": {},
"position": 0
@@ -516,20 +376,12 @@ Endpoints
"default_price": null,
"price": "23.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"checkin_text": null,
"require_approval": false,
"require_membership": false,
"require_membership_types": [],
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hide_without_voucher": false,
"description": null,
"meta_data": {},
@@ -564,31 +416,23 @@ Endpoints
"id": 1,
"name": {"en": "Standard ticket"},
"internal_name": "",
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"default_price": "23.00",
"original_price": null,
"category": null,
"active": true,
"description": null,
"free_price": false,
"free_price_suggestion": null,
"tax_rate": "0.00",
"tax_rule": 1,
"admission": false,
"personalized": false,
"issue_giftcard": false,
"media_policy": null,
"media_type": null,
"meta_data": {},
"position": 0,
"picture": null,
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hidden_if_available": null,
"hidden_if_item_available": null,
"require_voucher": false,
"hide_without_voucher": false,
"allow_cancel": true,
@@ -598,7 +442,6 @@ Endpoints
"min_per_order": null,
"max_per_order": null,
"checkin_attention": false,
"checkin_text": null,
"require_approval": false,
"require_bundling": false,
"require_membership": false,
@@ -607,33 +450,18 @@ Endpoints
"grant_membership_duration_like_event": true,
"grant_membership_duration_days": 0,
"grant_membership_duration_months": 0,
"validity_fixed_from": null,
"validity_fixed_until": null,
"validity_dynamic_duration_minutes": null,
"validity_dynamic_duration_hours": null,
"validity_dynamic_duration_days": null,
"validity_dynamic_duration_months": null,
"validity_dynamic_start_choice": false,
"validity_dynamic_start_choice_day_limit": null,
"variations": [
{
"value": {"en": "Student"},
"default_price": "10.00",
"price": "10.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"checkin_text": null,
"require_approval": false,
"require_membership": false,
"require_membership_types": [],
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hide_without_voucher": false,
"description": null,
"meta_data": {},
@@ -644,19 +472,12 @@ Endpoints
"default_price": null,
"price": "23.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"checkin_text": null,
"require_approval": false,
"require_membership": false,
"require_membership_types": [],
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hide_without_voucher": false,
"description": null,
"meta_data": {},
@@ -679,8 +500,6 @@ Endpoints
"id": 1,
"name": {"en": "Standard ticket"},
"internal_name": "",
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"default_price": "23.00",
"original_price": null,
@@ -688,23 +507,16 @@ Endpoints
"active": true,
"description": null,
"free_price": false,
"free_price_suggestion": null,
"tax_rate": "0.00",
"tax_rule": 1,
"admission": false,
"personalized": false,
"issue_giftcard": false,
"media_policy": null,
"media_type": null,
"meta_data": {},
"position": 0,
"picture": null,
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hidden_if_available": null,
"hidden_if_item_available": null,
"require_voucher": false,
"hide_without_voucher": false,
"allow_cancel": true,
@@ -714,7 +526,6 @@ Endpoints
"allow_waitinglist": true,
"show_quota_left": null,
"checkin_attention": false,
"checkin_text": null,
"has_variations": true,
"require_approval": false,
"require_bundling": false,
@@ -724,34 +535,18 @@ Endpoints
"grant_membership_duration_like_event": true,
"grant_membership_duration_days": 0,
"grant_membership_duration_months": 0,
"validity_fixed_from": null,
"validity_fixed_until": null,
"validity_dynamic_duration_minutes": null,
"validity_dynamic_duration_hours": null,
"validity_dynamic_duration_days": null,
"validity_dynamic_duration_months": null,
"validity_dynamic_start_choice": false,
"validity_dynamic_start_choice_day_limit": null,
"variations": [
{
"value": {"en": "Student"},
"default_price": "10.00",
"price": "10.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"checkin_text": null,
"require_approval": false,
"require_membership": false,
"require_membership_types": [],
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hide_without_voucher": false,
"description": null,
"meta_data": {},
@@ -762,20 +557,12 @@ Endpoints
"default_price": null,
"price": "23.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"checkin_text": null,
"require_approval": false,
"require_membership": false,
"require_membership_types": [],
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hide_without_voucher": false,
"description": null,
"meta_data": {},
@@ -829,8 +616,6 @@ Endpoints
"id": 1,
"name": {"en": "Ticket"},
"internal_name": "",
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"default_price": "25.00",
"original_price": null,
@@ -838,23 +623,16 @@ Endpoints
"active": true,
"description": null,
"free_price": false,
"free_price_suggestion": null,
"tax_rate": "0.00",
"tax_rule": 1,
"admission": false,
"personalized": false,
"issue_giftcard": false,
"media_policy": null,
"media_type": null,
"meta_data": {},
"position": 0,
"picture": null,
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hidden_if_available": null,
"hidden_if_item_available": null,
"require_voucher": false,
"hide_without_voucher": false,
"generate_tickets": null,
@@ -864,7 +642,6 @@ Endpoints
"min_per_order": null,
"max_per_order": null,
"checkin_attention": false,
"checkin_text": null,
"has_variations": true,
"require_approval": false,
"require_bundling": false,
@@ -874,34 +651,18 @@ Endpoints
"grant_membership_duration_like_event": true,
"grant_membership_duration_days": 0,
"grant_membership_duration_months": 0,
"validity_fixed_from": null,
"validity_fixed_until": null,
"validity_dynamic_duration_minutes": null,
"validity_dynamic_duration_hours": null,
"validity_dynamic_duration_days": null,
"validity_dynamic_duration_months": null,
"validity_dynamic_start_choice": false,
"validity_dynamic_start_choice_day_limit": null,
"variations": [
{
"value": {"en": "Student"},
"default_price": "10.00",
"price": "10.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"checkin_text": null,
"require_approval": false,
"require_membership": false,
"require_membership_types": [],
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hide_without_voucher": false,
"description": null,
"meta_data": {},
@@ -912,20 +673,12 @@ Endpoints
"default_price": null,
"price": "23.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"checkin_text": null,
"require_approval": false,
"require_membership": false,
"require_membership_types": [],
"all_sales_channels": false,
"limit_sales_channels": ["web"],
"sales_channels": ["web"],
"available_from": null,
"available_from_mode": "hide",
"available_until": null,
"available_until_mode": "hide",
"hide_without_voucher": false,
"description": null,
"meta_data": {},

View File

@@ -1,4 +1,4 @@
.. spelling:word-list::
.. spelling::
checkins
pdf
@@ -20,7 +20,6 @@ The order resource contains the following public fields:
Field Type Description
===================================== ========================== =======================================================
code string Order code
event string The slug of the parent event
status string Order status, one of:
* ``n`` pending
@@ -42,14 +41,10 @@ payment_date date **DEPRECATED AN
payment_provider string **DEPRECATED AND INACCURATE** Payment provider used for this order
total money (string) Total value of this order
comment string Internal comment on this order
api_meta object Meta data for that order. Only available through API, no guarantees
on the content structure. You can use this to save references to your system.
custom_followup_at date Internal date for a custom follow-up action
checkin_attention boolean If ``true``, the check-in app should show a warning
that this ticket requires special attention if a ticket
of this order is scanned.
checkin_text string Text that will be shown if a ticket of this order is
scanned (or ``null``).
invoice_address object Invoice address information (can be ``null``)
├ last_modified datetime Last modification date of the address
├ company string Customer company name
@@ -96,10 +91,6 @@ require_approval boolean If ``true`` and
needs approval by an organizer before it can
continue. If ``true`` and the order is canceled,
this order has been denied by the event organizer.
valid_if_pending boolean If ``true`` and the order is pending, this order
is still treated like a paid order for most purposes,
such as check-in. This may be used e.g. for trusted
customers who only need to pay after the event.
url string The full URL to the order confirmation page
payments list of objects List of payment processes (see below)
refunds list of objects List of refund processes (see below)
@@ -131,26 +122,6 @@ last_modified datetime Last modificati
The ``include`` query parameter has been added.
.. versionchanged:: 4.16
The ``valid_if_pending`` attribute has been added.
.. versionchanged:: 2023.8
The ``event`` attribute has been added. The organizer-level endpoint has been added.
.. versionchanged:: 2023.9
The ``customer`` query parameter has been added.
.. versionchanged:: 2023.10
The ``checkin_text`` attribute has been added.
.. versionchanged:: 2024.1
The ``expires`` attribute can now be passed during order creation.
.. _order-position-resource:
@@ -181,11 +152,6 @@ country string Attendee countr
state string Attendee state (ISO 3166-2 code). Only supported in
AU, BR, CA, CN, MY, MX, and US, otherwise ``null``.
voucher integer Internal ID of the voucher used for this position (or ``null``)
voucher_budget_use money (string) Amount of money discounted by the voucher, corresponding
to how much of the ``budget`` of the voucher is consumed.
**Important:** Do not rely on this amount to be a useful
value if the position's price, product or voucher
are changed *after* the order was created. Can be ``null``.
tax_rate decimal (string) VAT rate applied for this position
tax_value money (string) VAT included in this position
tax_rule integer The ID of the used tax rule (or ``null``)
@@ -193,9 +159,6 @@ secret string Secret code pri
addon_to integer Internal ID of the position this position is an add-on for (or ``null``)
subevent integer ID of the date inside an event series this position belongs to (or ``null``).
discount integer ID of a discount that has been used during the creation of this position in some way (or ``null``).
blocked list of strings A list of strings, or ``null``. Whenever not ``null``, the ticket may not be used (e.g. for check-in).
valid_from datetime The ticket will not be valid before this time. Can be ``null``.
valid_until datetime The ticket will not be valid after this time. Can be ``null``.
pseudonymization_id string A random ID, e.g. for use in lead scanning apps
checkins list of objects List of **successful** check-ins with this ticket
├ id integer Internal ID of the check-in event
@@ -203,8 +166,7 @@ checkins list of objects List of **succe
├ datetime datetime Time of check-in
├ type string Type of scan (defaults to ``entry``)
├ gate integer Internal ID of the gate. Can be ``null``.
├ device integer Internal ID of the device. Can be ``null``. **Deprecated**, since this ID is not otherwise used in the API and is therefore not very useful.
├ device_id integer Attribute ``device_id`` of the device. Can be ``null``.
├ device integer Internal ID of the device. Can be ``null``.
└ auto_checked_in boolean Indicates if this check-in been performed automatically by the system
downloads list of objects List of ticket download options
├ output string Ticket output provider (e.g. ``pdf``, ``passbook``)
@@ -218,21 +180,12 @@ answers list of objects Answers to user
seat objects The assigned seat. Can be ``null``.
├ id integer Internal ID of the seat instance
├ name string Human-readable seat name
├ zone_name string Name of the zone the seat is in
├ row_name string Name/number of the row the seat is in
├ row_label string Additional label of the row (or ``null``)
├ seat_number string Number of the seat within the row
├ seat_label string Additional label of the seat (or ``null``)
└ seat_guid string Identifier of the seat within the seating plan
pdf_data object Data object required for ticket PDF generation. By default,
this field is missing. It will be added only if you add the
``pdf_data=true`` query parameter to your request.
===================================== ========================== =======================================================
.. versionchanged:: 4.16
The attributes ``blocked``, ``valid_from`` and ``valid_until`` have been added.
.. _order-payment-resource:
Order payment resource
@@ -321,7 +274,6 @@ List of all orders
"results": [
{
"code": "ABC12",
"event": "sampleconf",
"status": "p",
"testmode": false,
"secret": "k24fiuwvu8kxz3y1",
@@ -341,9 +293,7 @@ List of all orders
"comment": "",
"custom_followup_at": null,
"checkin_attention": false,
"checkin_text": null,
"require_approval": false,
"valid_if_pending": false,
"invoice_address": {
"last_modified": "2017-12-01T10:00:00Z",
"is_business": true,
@@ -380,16 +330,12 @@ List of all orders
"country": "DE",
"state": null,
"voucher": null,
"voucher_budget_use": null,
"tax_rate": "0.00",
"tax_value": "0.00",
"tax_rule": null,
"secret": "z3fsn8jyufm5kpk768q69gkbyr5f4h6w",
"addon_to": null,
"subevent": null,
"valid_from": null,
"valid_until": null,
"blocked": null,
"discount": null,
"pseudonymization_id": "MQLJvANO3B",
"seat": null,
@@ -449,7 +395,6 @@ List of all orders
:query string code: Only return orders that match the given order code
:query string status: Only return orders in the given order status (see above)
:query string search: Only return orders matching a given search query (matching for names, email addresses, and company names)
:query string customer: Only show orders linked to the given customer.
:query integer item: Only return orders with a position that contains this item ID. *Warning:* Result will also include orders if they contain mixed items, and it will even return orders where the item is only contained in a canceled position.
:query integer variation: Only return orders with a position that contains this variation ID. *Warning:* Result will also include orders if they contain mixed items and variations, and it will even return orders where the variation is only contained in a canceled position.
:query boolean testmode: Only return orders with ``testmode`` set to ``true`` or ``false``
@@ -463,13 +408,10 @@ List of all orders
:query datetime modified_since: Only return orders that have changed since the given date. Be careful: We only
recommend using this in combination with ``testmode=false``, since test mode orders can vanish at any time and
you will not notice it using this method.
:query datetime created_since: Only return orders that have been created since the given date (inclusive).
:query datetime created_before: Only return orders that have been created before the given date (exclusive).
:query datetime created_since: Only return orders that have been created since the given date.
:query integer subevent: Only return orders with a position that contains this subevent ID. *Warning:* Result will also include orders if they contain mixed subevents, and it will even return orders where the subevent is only contained in a canceled position.
:query datetime subevent_after: Only return orders that contain a ticket for a subevent taking place after the given date. This is an exclusive after, and it considers the **end** of the subevent (or its start, if the end is not set).
:query datetime subevent_before: Only return orders that contain a ticket for a subevent taking place after the given date. This is an exclusive before, and it considers the **start** of the subevent.
:query string sales_channel: Only return orders with the given sales channel identifier (e.g. ``"web"``).
:query string payment_provider: Only return orders that contain a payment using the given payment provider. Note that this also searches for partial incomplete, or failed payments within the order and is not useful to get a sum of payment amounts without further processing.
:query string exclude: Exclude a field from the output, e.g. ``fees`` or ``positions.downloads``. Can be used as a performance optimization. Can be passed multiple times.
:query string include: Include only the given field in the output, e.g. ``fees`` or ``positions.downloads``. Can be used as a performance optimization. Can be passed multiple times. ``include`` is applied before ``exclude``, so ``exclude`` takes precedence.
:param organizer: The ``slug`` field of the organizer to fetch
@@ -480,48 +422,6 @@ List of all orders
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
.. http:get:: /api/v1/organizers/(organizer)/orders/
Returns a list of all orders within all events of a given organizer (with sufficient access permissions).
Supported query parameters and output format of this endpoint are identical to the list endpoint within an event,
with the exception that the ``pdf_data`` parameter is not supported here.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/orders/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
X-Page-Generated: 2017-12-01T10:00:00Z
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"code": "ABC12",
"event": "sampleconf",
...
}
]
}
:param organizer: The ``slug`` field of the organizer to fetch
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
Fetching individual orders
--------------------------
@@ -547,7 +447,6 @@ Fetching individual orders
{
"code": "ABC12",
"event": "sampleconf",
"status": "p",
"testmode": false,
"secret": "k24fiuwvu8kxz3y1",
@@ -565,12 +464,9 @@ Fetching individual orders
"fees": [],
"total": "23.00",
"comment": "",
"api_meta": {},
"custom_followup_at": null,
"checkin_attention": false,
"checkin_text": null,
"require_approval": false,
"valid_if_pending": false,
"invoice_address": {
"last_modified": "2017-12-01T10:00:00Z",
"company": "Sample company",
@@ -607,16 +503,12 @@ Fetching individual orders
"country": "DE",
"state": null,
"voucher": null,
"voucher_budget_use": null,
"tax_rate": "0.00",
"tax_rule": null,
"tax_value": "0.00",
"secret": "z3fsn8jyufm5kpk768q69gkbyr5f4h6w",
"addon_to": null,
"subevent": null,
"valid_from": null,
"valid_until": null,
"blocked": null,
"discount": null,
"pseudonymization_id": "MQLJvANO3B",
"seat": null,
@@ -740,22 +632,14 @@ Updating order fields
* ``checkin_attention``
* ``checkin_text``
* ``locale``
* ``comment``
* ``api_meta``
* ``custom_followup_at``
* ``invoice_address`` (you always need to supply the full object, or ``null`` to delete the current address)
* ``valid_if_pending``
* ``expires``
**Example request**:
.. sourcecode:: http
@@ -931,7 +815,6 @@ Creating orders
* does not support or validate memberships
You can supply the following fields of the resource:
* ``code`` (optional) Only ``A-Z`` and ``0-9``, but without ``O`` and ``1``.
@@ -961,9 +844,7 @@ Creating orders
* ``comment`` (optional)
* ``custom_followup_at`` (optional)
* ``checkin_attention`` (optional)
* ``checkin_text`` (optional)
* ``require_approval`` (optional)
* ``valid_if_pending`` (optional)
* ``invoice_address`` (optional)
* ``company``
@@ -999,10 +880,6 @@ Creating orders
* ``secret`` (optional)
* ``addon_to`` (optional, see below)
* ``subevent`` (optional)
* ``valid_from`` (optional, if both ``valid_from`` and ``valid_until`` are **missing** (not ``null``) the availability will be computed from the given product)
* ``valid_until`` (optional, if both ``valid_from`` and ``valid_until`` are **missing** (not ``null``) the availability will be computed from the given product)
* ``requested_valid_from`` (optional, can be set **instead** of ``valid_from`` and ``valid_until`` to signal a user choice for the start time that may or may not be respected)
* ``use_reusable_medium`` (optional, causes the new ticket to take over the given reusable medium, identified by its ID)
* ``answers``
* ``question``
@@ -1073,7 +950,7 @@ Creating orders
"street": "Sesam Street 12",
"zipcode": "12345",
"city": "Sample City",
"country": "GB",
"country": "UK",
"state": "",
"internal_reference": "",
"vat_id": ""
@@ -1562,7 +1439,6 @@ List of all order positions
},
"attendee_email": null,
"voucher": null,
"voucher_budget_use": null,
"tax_rate": "0.00",
"tax_rule": null,
"tax_value": "0.00",
@@ -1572,9 +1448,6 @@ List of all order positions
"seat": null,
"addon_to": null,
"subevent": null,
"valid_from": null,
"valid_until": null,
"blocked": null,
"checkins": [
{
"list": 44,
@@ -1610,7 +1483,6 @@ List of all order positions
``order__datetime,positionid``
:query string order: Only return positions of the order with the given order code
:query string search: Fuzzy search matching the attendee name, order code, invoice address name as well as to the beginning of the secret.
:query string customer: Only show orders linked to the given customer.
:query integer item: Only return positions with the purchased item matching the given ID.
:query integer item__in: Only return positions with the purchased item matching one of the given comma-separated IDs.
:query integer variation: Only return positions with the purchased item variation matching the given ID.
@@ -1676,16 +1548,12 @@ Fetching individual positions
},
"attendee_email": null,
"voucher": null,
"voucher_budget_use": null,
"tax_rate": "0.00",
"tax_rule": null,
"tax_value": "0.00",
"secret": "z3fsn8jyufm5kpk768q69gkbyr5f4h6w",
"addon_to": null,
"subevent": null,
"valid_from": null,
"valid_until": null,
"blocked": null,
"discount": null,
"pseudonymization_id": "MQLJvANO3B",
"seat": null,
@@ -1791,10 +1659,6 @@ Manipulating individual positions
The ``PATCH`` method now supports changing items, variations, subevents, seats, prices, and tax rules.
The ``POST`` endpoint to add individual positions has been added.
.. versionadded:: 4.16
The endpoints to manage blocks have been added.
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/orderpositions/(id)/
Updates specific fields on an order position. Currently, only the following fields are supported:
@@ -1833,10 +1697,6 @@ Manipulating individual positions
* ``tax_rule``
* ``valid_from``
* ``valid_until``
Changing parameters such as ``item`` or ``price`` will **not** automatically trigger creation of a new invoice,
you need to take care of that yourself.
@@ -1911,10 +1771,6 @@ Manipulating individual positions
and ``option_identifiers`` will be ignored. As a special case, you can submit the magic value
``"file:keep"`` as the answer to a file question to keep the current value without re-uploading it.
* ``valid_from``
* ``valid_until``
This will **not** automatically trigger creation of a new invoice, you need to take care of that yourself.
**Example request**:
@@ -1978,82 +1834,6 @@ Manipulating individual positions
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
:statuscode 404: The requested order position does not exist.
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/orderpositions/(id)/add_block/
Blocks an order position from being used. The block name either needs to be ``"admin"`` or start with ``"api:"``. It
may only contain letters, numbers, dots and underscores. ``"admin"`` represents the regular block that can be set
in the backend user interface.
**Example request**:
.. sourcecode:: http
POST /api/v1/organizers/bigevents/events/sampleconf/orderpositions/23/add_block/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
Content-Type: application/json
{
"name": "api:block1"
}
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
(Full order position resource, see above.)
:param organizer: The ``slug`` field of the organizer of the event
:param event: The ``slug`` field of the event
:param code: The ``id`` field of the order position to update
:statuscode 200: no error
:statuscode 400: The order position could not be updated due to invalid submitted data.
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to update this order position.
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/orderpositions/(id)/remove_block/
Unblocks an order position from being used. The block name either needs to be ``"admin"`` or start with ``"api:"``. It
may only contain letters, numbers, dots and underscores. ``"admin"`` represents the regular block that can be set
in the backend user interface. Blocks set by plugins cannot be lifted through this API.
**Example request**:
.. sourcecode:: http
POST /api/v1/organizers/bigevents/events/sampleconf/orderpositions/23/remove_block/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
Content-Type: application/json
{
"name": "api:block1"
}
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
(Full order position resource, see above.)
:param organizer: The ``slug`` field of the organizer of the event
:param event: The ``slug`` field of the event
:param code: The ``id`` field of the order position to update
:statuscode 200: no error
:statuscode 400: The order position could not be updated due to invalid submitted data.
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to update this order position.
Changing order contents
-----------------------
@@ -2072,7 +1852,7 @@ otherwise, such as splitting an order or changing fees.
* ``patch_positions``: A list of objects with the two keys ``position`` specifying an order position ID and
``body`` specifying the desired changed values of the position (``item``, ``variation``, ``subevent``, ``seat``,
``price``, ``tax_rule``, ``valid_from``, ``valid_until``).
``price``, ``tax_rule``).
* ``cancel_positions``: A list of objects with the single key ``position`` specifying an order position ID.
@@ -2761,57 +2541,3 @@ With some non-default ticket secret generation methods, a list of revoked ticket
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
Blocked ticket secrets
----------------------
With some non-default ticket secret generation methods, a list of blocked ticket secrets is required for proper validation.
This endpoint returns all secrets that are currently blocked **or have been blocked before and are now unblocked**, so
be sure to check the ``blocked`` attribute for its actual value. The list is currently always ordered with the most
recently updated ones first.
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/blockedsecrets/
Returns a list of all blocked or historically blocked secrets within a given event.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/events/sampleconf/blockedsecrets/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
X-Page-Generated: 2017-12-01T10:00:00Z
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 1234,
"secret": "k24fiuwvu8kxz3y1",
"blocked": true,
"updated": "2017-12-01T10:00:00Z",
}
]
}
:query integer page: The page number in case of a multi-page result set, default is 1
:query datetime updated_since: Only return records that have been updated since the given date.
:query boolean blocked: Only return blocked / non-blocked records.
:param organizer: The ``slug`` field of the organizer to fetch
:param event: The ``slug`` field of the event to fetch
:resheader X-Page-Generated: The server time at the beginning of the operation. If you're using this API to fetch
differences, this is the value you want to use as ``updated_since`` in your next call.
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.

View File

@@ -17,18 +17,12 @@ Field Type Description
name string The organizer's full name, i.e. the name of an
organization or company.
slug string A short form of the name, used e.g. in URLs.
public_url string The public, customer-facing URL of the organizer, where
the list of all events can be found (read-only).
===================================== ========================== =======================================================
Endpoints
---------
.. versionchanged:: 4.17
The ``public_url`` field has been added.
.. http:get:: /api/v1/organizers/
Returns a list of all organizers the authenticated user/token has access to.
@@ -57,7 +51,6 @@ Endpoints
{
"name": "Big Events LLC",
"slug": "Big Events",
"public_url": "https://pretix.eu/bigevents/"
}
]
}
@@ -91,7 +84,6 @@ Endpoints
{
"name": "Big Events LLC",
"slug": "Big Events",
"public_url": "https://pretix.eu/bigevents/"
}
:param organizer: The ``slug`` field of the organizer to fetch
@@ -157,7 +149,6 @@ information about the properties.
{
"value": "calendar",
"label": "Default overview style",
"readonly": false,
"help_text": "If your event series has more than 50 dates in the future, only the month or week calendar can be used."
}
},

View File

@@ -1,4 +1,4 @@
.. spelling:word-list::
.. spelling::
checkin
datetime
@@ -44,8 +44,6 @@ identifier string An arbitrary st
ask_during_checkin boolean If ``true``, this question will not be asked while
buying the ticket, but will show up when redeeming
the ticket instead.
show_during_checkin boolean If ``true``, the answer to the question will be shown
during check-in (if the check-in client supports it).
hidden boolean If ``true``, the question will only be shown in the
backend.
print_on_invoice boolean If ``true``, the question will only be shown on
@@ -65,7 +63,6 @@ valid_date_max date Maximum value f
valid_datetime_min datetime Minimum value for date and time questions (optional)
valid_datetime_max datetime Maximum value for date and time questions (optional)
valid_file_portrait boolean Turn on file validation for portrait photos
valid_string_length_max integer Maximum length for string questions (optional)
dependency_question integer Internal ID of a different question. The current
question will only be shown if the question given in
this attribute is set to the value given in
@@ -79,10 +76,6 @@ dependency_value string An old version
for one value. **Deprecated.**
===================================== ========================== =======================================================
.. versionchanged:: 2023.8
The ``show_during_checkin`` attribute has been added.
Endpoints
---------
@@ -121,7 +114,6 @@ Endpoints
"position": 1,
"identifier": "WY3TP9SL",
"ask_during_checkin": false,
"show_during_checkin": false,
"hidden": false,
"print_on_invoice": false,
"valid_number_min": null,
@@ -130,7 +122,6 @@ Endpoints
"valid_date_max": null,
"valid_datetime_min": null,
"valid_datetime_max": null,
"valid_string_length_max": null,
"valid_file_portrait": false,
"dependency_question": null,
"dependency_value": null,
@@ -201,7 +192,6 @@ Endpoints
"position": 1,
"identifier": "WY3TP9SL",
"ask_during_checkin": false,
"show_during_checkin": false,
"hidden": false,
"print_on_invoice": false,
"valid_number_min": null,
@@ -211,7 +201,6 @@ Endpoints
"valid_datetime_min": null,
"valid_datetime_max": null,
"valid_file_portrait": false,
"valid_string_length_max": null,
"dependency_question": null,
"dependency_value": null,
"dependency_values": [],
@@ -265,7 +254,6 @@ Endpoints
"items": [1, 2],
"position": 1,
"ask_during_checkin": false,
"show_during_checkin": false,
"hidden": false,
"print_on_invoice": false,
"dependency_question": null,
@@ -302,7 +290,6 @@ Endpoints
"position": 1,
"identifier": "WY3TP9SL",
"ask_during_checkin": false,
"show_during_checkin": false,
"hidden": false,
"print_on_invoice": false,
"dependency_question": null,
@@ -315,7 +302,6 @@ Endpoints
"valid_datetime_min": null,
"valid_datetime_max": null,
"valid_file_portrait": false,
"valid_string_length_max": null,
"options": [
{
"id": 1,
@@ -358,7 +344,7 @@ Endpoints
.. sourcecode:: http
PATCH /api/v1/organizers/bigevents/events/sampleconf/questions/1/ HTTP/1.1
PATCH /api/v1/organizers/bigevents/events/sampleconf/items/1/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
Content-Type: application/json
@@ -386,7 +372,6 @@ Endpoints
"position": 2,
"identifier": "WY3TP9SL",
"ask_during_checkin": false,
"show_during_checkin": false,
"hidden": false,
"print_on_invoice": false,
"dependency_question": null,
@@ -399,7 +384,6 @@ Endpoints
"valid_datetime_min": null,
"valid_datetime_max": null,
"valid_file_portrait": false,
"valid_string_length_max": null,
"options": [
{
"id": 1,
@@ -426,7 +410,7 @@ Endpoints
:param event: The ``slug`` field of the event to modify
:param id: The ``id`` field of the question to modify
:statuscode 200: no error
:statuscode 400: The question could not be modified due to invalid submitted data
:statuscode 400: The item could not be modified due to invalid submitted data
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
@@ -438,7 +422,7 @@ Endpoints
.. sourcecode:: http
DELETE /api/v1/organizers/bigevents/events/sampleconf/questions/1/ HTTP/1.1
DELETE /api/v1/organizers/bigevents/events/sampleconf/items/1/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
@@ -451,7 +435,7 @@ Endpoints
:param organizer: The ``slug`` field of the organizer to modify
:param event: The ``slug`` field of the event to modify
:param id: The ``id`` field of the question to delete
:param id: The ``id`` field of the item to delete
:statuscode 204: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this resource.

View File

@@ -1,327 +0,0 @@
.. _`rest-reusablemedia`:
Reusable media
==============
Reusable media represent things, typically physical tokens like plastic cards or NFC wristbands, which can represent
other entities inside the system. For example, a medium can link to an order position or to a gift card and can be used
in their place. Later, the medium might be reused for a different ticket.
Resource description
--------------------
The reusable medium resource contains the following public fields:
.. rst-class:: rest-resource-table
===================================== ========================== =======================================================
Field Type Description
===================================== ========================== =======================================================
id integer Internal ID of the medium
type string Type of medium, e.g. ``"barcode"``, ``"nfc_uid"`` or ``"nfc_mf0aes"``.
organizer string Organizer slug of the organizer who "owns" this medium.
identifier string Unique identifier of the medium. The format depends on the ``type``.
active boolean Whether this medium may be used.
created datetime Date of creation
updated datetime Date of last modification
expires datetime Expiry date (or ``null``)
customer string Identifier of a customer account this medium belongs to.
linked_orderposition integer Internal ID of a ticket this medium is linked to.
linked_giftcard integer Internal ID of a gift card this medium is linked to.
info object Additional data, content depends on the ``type``. Consider
this internal to the system and don't use it for your own data.
notes string Internal notes and comments (or ``null``)
===================================== ========================== =======================================================
Existing media types are:
- ``barcode``
- ``nfc_uid``
- ``nfc_mf0aes``
Endpoints
---------
.. http:get:: /api/v1/organizers/(organizer)/reusablemedia/
Returns a list of all media issued by a given organizer.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/reusablemedia/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"organizer": "bigevents",
"identifier": "ABCDEFGH",
"created": "2021-04-06T13:44:22.809377Z",
"updated": "2021-04-06T13:44:22.809377Z",
"type": "barcode",
"active": True,
"expires": None,
"customer": None,
"linked_orderposition": None,
"linked_giftcard": None,
"notes": None,
"info": {}
}
]
}
:query integer page: The page number in case of a multi-page result set, default is 1.
:query string identifier: Only show media with the given identifier. Note that you should use the lookup endpoint described below for most use cases.
:query string type: Only show media with the given type.
:query boolean active: Only show media that are (not) active.
:query string customer: Only show media linked to the given customer.
:query string created_since: Only show media created since a given date.
:query string updated_since: Only show media updated since a given date.
:query integer linked_orderposition: Only show media linked to the given ticket.
:query integer linked_giftcard: Only show media linked to the given gift card.
:query string expand: If you pass ``"linked_giftcard"``, ``"linked_giftcard.owner_ticket"``, ``"linked_orderposition"``,
or ``"customer"``, the respective field will be shown as a nested value instead of just an ID.
The nested objects are identical to the respective resources, except that order positions
will have an attribute of the format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make
matching easier. The parameter can be given multiple times.
:param organizer: The ``slug`` field of the organizer to fetch
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
.. http:get:: /api/v1/organizers/(organizer)/reusablemedia/(id)/
Returns information on one medium, identified by its ID.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/reusablemedia/1/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"id": 1,
"organizer": "bigevents",
"identifier": "ABCDEFGH",
"created": "2021-04-06T13:44:22.809377Z",
"updated": "2021-04-06T13:44:22.809377Z",
"type": "barcode",
"active": True,
"expires": None,
"customer": None,
"linked_orderposition": None,
"linked_giftcard": None,
"notes": None,
"info": {}
}
:param organizer: The ``slug`` field of the organizer to fetch
:param id: The ``id`` field of the medium to fetch
:query string expand: If you pass ``"linked_giftcard"``, ``"linked_giftcard.owner_ticket"``, ``"linked_orderposition"``,
or ``"customer"``, the respective field will be shown as a nested value instead of just an ID.
The nested objects are identical to the respective resources, except that order positions
will have an attribute of the format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make
matching easier. The parameter can be given multiple times.
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
.. http:post:: /api/v1/organizers/(organizer)/reusablemedia/lookup/
Look up a new reusable medium by its identifier. In some cases, this might lead to the automatic creation of a new
medium behind the scenes.
This endpoint, and this endpoint only, might return media from a different organizer if there is a cross-acceptance
agreement. In this case, only linked gift cards will be returned, no order position or customer records,
**Example request**:
.. sourcecode:: http
POST /api/v1/organizers/bigevents/reusablemedia/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
Content-Type: application/json
{
"identifier": "ABCDEFGH",
"type": "barcode",
}
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"id": 1,
"organizer": "bigevents",
"identifier": "ABCDEFGH",
"created": "2021-04-06T13:44:22.809377Z",
"updated": "2021-04-06T13:44:22.809377Z",
"type": "barcode",
"active": True,
"expires": None,
"customer": None,
"linked_orderposition": None,
"linked_giftcard": None,
"notes": None,
"info": {}
}
:param organizer: The ``slug`` field of the organizer to look up a medium for
:query string expand: If you pass ``"linked_giftcard"``, ``"linked_orderposition"``, oder ``"customer"``, the respective
field will be shown as a nested value instead of just an ID. The nested objects are identical to
the respective resources, except that the ``linked_orderposition`` will have an attribute of the
format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make matching easier. The parameter
can be given multiple times.
:statuscode 201: no error
:statuscode 400: The medium could not be looked up due to invalid submitted data.
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to create this resource.
.. http:post:: /api/v1/organizers/(organizer)/reusablemedia/
Creates a new reusable medium.
**Example request**:
.. sourcecode:: http
POST /api/v1/organizers/bigevents/reusablemedia/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
Content-Type: application/json
{
"identifier": "ABCDEFGH",
"type": "barcode",
"active": True,
"expires": None,
"customer": None,
"linked_orderposition": None,
"linked_giftcard": None,
"notes": None,
"info": {}
}
**Example response**:
.. sourcecode:: http
HTTP/1.1 201 Created
Vary: Accept
Content-Type: application/json
{
"id": 1,
"organizer": "bigevents",
"identifier": "ABCDEFGH",
"created": "2021-04-06T13:44:22.809377Z",
"updated": "2021-04-06T13:44:22.809377Z",
"type": "barcode",
"active": True,
"expires": None,
"customer": None,
"linked_orderposition": None,
"linked_giftcard": None,
"notes": None,
"info": {}
}
:param organizer: The ``slug`` field of the organizer to create a medium for
:query string expand: If you pass ``"linked_giftcard"``, ``"linked_orderposition"``, oder ``"customer"``, the respective
field will be shown as a nested value instead of just an ID. The nested objects are identical to
the respective resources, except that the ``linked_orderposition`` will have an attribute of the
format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make matching easier. The parameter
can be given multiple times.
:statuscode 201: no error
:statuscode 400: The medium could not be created due to invalid submitted data.
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to create this resource.
.. http:patch:: /api/v1/organizers/(organizer)/reusablemedia/(id)/
Update a reusable medium. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
want to change.
You can change all fields of the resource except the ``id``, ``identifier`` and ``type`` fields.
**Example request**:
.. sourcecode:: http
PATCH /api/v1/organizers/bigevents/reusablemedia/1/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
Content-Type: application/json
Content-Length: 94
{
"linked_orderposition": 13
}
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"id": 1,
"organizer": "bigevents",
"identifier": "ABCDEFGH",
"created": "2021-04-06T13:44:22.809377Z",
"updated": "2021-04-06T13:44:22.809377Z",
"type": "barcode",
"active": True,
"expires": None,
"customer": None,
"linked_orderposition": 13,
"linked_giftcard": None,
"notes": None,
"info": {}
}
:param organizer: The ``slug`` field of the organizer to modify
:param id: The ``id`` field of the medium to modify
:query string expand: If you pass ``"linked_giftcard"``, ``"linked_orderposition"``, oder ``"customer"``, the respective
field will be shown as a nested value instead of just an ID. The nested objects are identical to
the respective resources, except that the ``linked_orderposition`` will have an attribute of the
format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make matching easier. The parameter
can be given multiple times.
:statuscode 200: no error
:statuscode 400: The medium could not be modified due to invalid submitted data
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to change this resource.

View File

@@ -1,219 +0,0 @@
Sales channels
==============
Resource description
--------------------
The sales channel resource contains the following public fields:
.. rst-class:: rest-resource-table
===================================== ========================== =======================================================
Field Type Description
===================================== ========================== =======================================================
identifier string Internal ID of the sales channel. For sales channel types
that allow only one instance, this is the same as ``type``.
For sales channel types that allow multiple instances, this
is always prefixed with ``type.``.
label multi-lingual string Human-readable name of the sales channel
type string Type of the sales channel. Only channels with type ``api``
can currently be created through the API.
position integer Position for sorting lists of sales channels
===================================== ========================== =======================================================
Endpoints
---------
.. http:get:: /api/v1/organizers/(organizer)/saleschannels/
Returns a list of all sales channels within a given organizer.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/saleschannels/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"identifier": "web",
"label": {
"en": "Online shop"
},
"type": "web",
"position": 0
}
]
}
:query integer page: The page number in case of a multi-page result set, default is 1
:param organizer: The ``slug`` field of the organizer to fetch
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
.. http:get:: /api/v1/organizers/(organizer)/saleschannels/(identifier)/
Returns information on one sales channel, identified by its identifier.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/saleschannels/web/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"identifier": "web",
"label": {
"en": "Online shop"
},
"type": "web",
"position": 0
}
:param organizer: The ``slug`` field of the organizer to fetch
:param identifier: The ``identifier`` field of the sales channel to fetch
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
.. http:post:: /api/v1/organizers/(organizer)/saleschannels/
Creates a sales channel
**Example request**:
.. sourcecode:: http
POST /api/v1/organizers/bigevents/saleschannels/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
Content-Type: application/json
{
"identifier": "api.custom",
"label": {
"en": "Custom integration"
},
"type": "api",
"position": 2
}
**Example response**:
.. sourcecode:: http
HTTP/1.1 201 Created
Vary: Accept
Content-Type: application/json
{
"identifier": "api.custom",
"label": {
"en": "Custom integration"
},
"type": "api",
"position": 2
}
:param organizer: The ``slug`` field of the organizer to create a sales channel for
:statuscode 201: no error
:statuscode 400: The sales channel could not be created due to invalid submitted data.
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to create this resource.
.. http:patch:: /api/v1/organizers/(organizer)/saleschannels/(identifier)/
Update a sales channel. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
want to change.
You can change all fields of the resource except the ``identifier`` and ``type`` fields.
**Example request**:
.. sourcecode:: http
PATCH /api/v1/organizers/bigevents/saleschannels/web/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
Content-Type: application/json
Content-Length: 94
{
"position": 5
}
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"identifier": "web",
"label": {
"en": "Online shop"
},
"type": "web",
"position": 5
}
:param organizer: The ``slug`` field of the organizer to modify
:param identifier: The ``identifier`` field of the sales channel to modify
:statuscode 200: no error
:statuscode 400: The sales channel could not be modified due to invalid submitted data
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to change this resource.
.. http:delete:: /api/v1/organizers/(organizer)/saleschannels/(identifier)/
Delete a sales channel. You can not delete sales channels which have already been used or which are integral parts
of the system.
**Example request**:
.. sourcecode:: http
DELETE /api/v1/organizers/bigevents/saleschannels/api.custom/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 204 No Content
Vary: Accept
:param organizer: The ``slug`` field of the organizer to modify
:param identifier: The ``identifier`` field of the sales channel to delete
:statuscode 204: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to delete this resource **or** the sales channel is currently in use.

View File

@@ -1,556 +0,0 @@
.. spelling:word-list:: checkin
Scheduled data exports
======================
pretix and it's plugins include a number of data exporters that allow you to bulk download various data from pretix in
different formats. You should read :ref:`rest-exporters` first to get an understanding of the basic mechanism.
Exports can be scheduled to be sent at specific times automatically, both on organizer level and event level.
Scheduled export resource
-------------------------
The scheduled export contains the following public fields:
.. rst-class:: rest-resource-table
===================================== ========================== =======================================================
Field Type Description
===================================== ========================== =======================================================
id integer Internal ID of the schedule
owner string Email address of the user who created this schedule (read-only).
This address will always receive the export and the export
will only contain data that this user has permission
to access at the time of the export. **We consider this
field experimental, it's behaviour might change in the future.
Note that the email address of a user can change at any time.**
export_identifier string Identifier of the export to run, see :ref:`rest-exporters`
export_form_data object Input data for the export, format depends on the export,
see :ref:`rest-exporters` for more details.
locale string Language to run the export in
mail_additional_recipients string Email addresses to receive the export, comma-separated (or empty string)
mail_additional_recipients_cc string Email addresses to receive the export in copy, comma-separated (or empty string)
mail_additional_recipients_bcc string Email addresses to receive the exportin blind copy, comma-separated (or empty string)
mail_subject string Subject to use for the email (currently no variables supported)
mail_template string Text to use for the email (currently no variables supported)
schedule_rrule string Recurrence specification to determine the **days** this
schedule runs on in ``RRULE`` syntax following `RFC 5545`_
with some restrictions. Only one rule is allowed, only
one occurrence per day is allowed, and some features
are not supported (``BYMONTHDAY``, ``BYYEARDAY``,
``BYEASTER``, ``BYWEEKNO``).
schedule_rrule_time time Time of day to run this on on the specified days.
Will be interpreted as local time of the event for event-level
exports. For organizer-level exports, the timezone is given
in the field ``timezone``. The export will never run **before**
this time but it **may** run **later**.
timezone string Time zone to interpret the schedule in (only for organizer-level exports)
schedule_next_run datetime Next planned execution (read-only, computed by server)
error_counter integer Number of consecutive times this export failed (read-only).
After a number of failures (currently 5), the schedule no
longer is executed. Changing parameters resets the value.
===================================== ========================== =======================================================
Special notes on permissions
----------------------------
Permission handling for scheduled exports is more complex than for most other objects. The reason for this is that
there are two levels of access control involved here: First, you need permission to access or change the configuration
of the scheduled exports in the moment you are doing it. Second, you **continuously** need permission to access the
**data** that is exported as part of the schedule. For this reason, scheduled exports always need one user account
to be their **owner**.
Therefore, scheduled exports **must** be created by an API client using :ref:`OAuth authentication <rest-oauth>`.
It is impossible to create a scheduled export using token authentication. After the export is created, it can also be
modified using token authentication.
A user or token with the "can change settings" permission for a given organizer or event can see and change
**all** scheduled exports created for the respective organizer or event, regardless of who created them.
A user without this permission can only see **their own** scheduled exports.
A token without this permission can not see scheduled exports as all.
Endpoints for event exports
---------------------------
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/scheduled_exports/
Returns a list of all scheduled exports the client has access to.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/events/sampleconf/scheduled_exports/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"owner": "john@example.com",
"export_identifier": "orderlist",
"export_form_data": {"_format": "xlsx", "date_range": "week_previous"},
"locale": "en",
"mail_additional_recipients": "mary@example.org",
"mail_additional_recipients_cc": "",
"mail_additional_recipients_bcc": "",
"mail_subject": "Order list",
"mail_template": "Here is last week's order list\n\nCheers\nJohn",
"schedule_rrule": "DTSTART:20230118T000000\nRRULE:FREQ=WEEKLY;BYDAY=TU,WE,TH",
"schedule_rrule_time": "04:00:00",
"schedule_next_run": "2023-10-26T02:00:00Z",
"error_counter": 0
}
]
}
:query integer page: The page number in case of a multi-page result set, default is 1
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``id``, ``export_identifier``, and ``schedule_next_run``.
Default: ``id``
:param organizer: The ``slug`` field of the organizer to fetch
:param event: The ``slug`` field of the event to fetch
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/scheduled_exports/(id)/
Returns information on one scheduled export, identified by its ID.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/events/sampleconf/scheduled_exports/1/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"id": 1,
"owner": "john@example.com",
"export_identifier": "orderlist",
"export_form_data": {"_format": "xlsx", "date_range": "week_previous"},
"locale": "en",
"mail_additional_recipients": "mary@example.org",
"mail_additional_recipients_cc": "",
"mail_additional_recipients_bcc": "",
"mail_subject": "Order list",
"mail_template": "Here is last week's order list\n\nCheers\nJohn",
"schedule_rrule": "DTSTART:20230118T000000\nRRULE:FREQ=WEEKLY;BYDAY=TU,WE,TH",
"schedule_rrule_time": "04:00:00",
"schedule_next_run": "2023-10-26T02:00:00Z",
"error_counter": 0
}
:param organizer: The ``slug`` field of the organizer to fetch
:param event: The ``slug`` field of the event to fetch
:param id: The ``id`` field of the scheduled export to fetch
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/scheduled_exports/
Schedule a new export.
.. note:: See above for special notes on permissions.
**Example request**:
.. sourcecode:: http
POST /api/v1/organizers/bigevents/events/sampleconf/scheduled_exports/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
Content-Type: application/json
{
"export_identifier": "orderlist",
"export_form_data": {"_format": "xlsx", "date_range": "week_previous"},
"locale": "en",
"mail_additional_recipients": "mary@example.org",
"mail_additional_recipients_cc": "",
"mail_additional_recipients_bcc": "",
"mail_subject": "Order list",
"mail_template": "Here is last week's order list\n\nCheers\nJohn",
"schedule_rrule": "DTSTART:20230118T000000\nRRULE:FREQ=WEEKLY;BYDAY=TU,WE,TH",
"schedule_rrule_time": "04:00:00"
}
**Example response**:
.. sourcecode:: http
HTTP/1.1 201 Created
Vary: Accept
Content-Type: application/json
{
"id": 1,
"owner": "john@example.com",
"export_identifier": "orderlist",
"export_form_data": {"_format": "xlsx", "date_range": "week_previous"},
"locale": "en",
"mail_additional_recipients": "mary@example.org",
"mail_additional_recipients_cc": "",
"mail_additional_recipients_bcc": "",
"mail_subject": "Order list",
"mail_template": "Here is last week's order list\n\nCheers\nJohn",
"schedule_rrule": "DTSTART:20230118T000000\nRRULE:FREQ=WEEKLY;BYDAY=TU,WE,TH",
"schedule_rrule_time": "04:00:00",
"schedule_next_run": "2023-10-26T02:00:00Z",
"error_counter": 0
}
:param organizer: The ``slug`` field of the organizer of the event to create an item for
:param event: The ``slug`` field of the event to create an item for
:statuscode 201: no error
:statuscode 400: The item could not be created due to invalid submitted data.
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create this resource.
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/scheduled_exports/(id)/
Update a scheduled export. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
want to change.
**Example request**:
.. sourcecode:: http
PATCH /api/v1/organizers/bigevents/events/sampleconf/scheduled_exports/1/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
Content-Type: application/json
Content-Length: 94
{
"export_form_data": {"_format": "xlsx", "date_range": "week_this"},
}
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"id": 1,
"owner": "john@example.com",
"export_identifier": "orderlist",
"export_form_data": {"_format": "xlsx", "date_range": "week_this"},
"locale": "en",
"mail_additional_recipients": "mary@example.org",
"mail_additional_recipients_cc": "",
"mail_additional_recipients_bcc": "",
"mail_subject": "Order list",
"mail_template": "Here is last week's order list\n\nCheers\nJohn",
"schedule_rrule": "DTSTART:20230118T000000\nRRULE:FREQ=WEEKLY;BYDAY=TU,WE,TH",
"schedule_rrule_time": "04:00:00",
"schedule_next_run": "2023-10-26T02:00:00Z",
"error_counter": 0
}
:param organizer: The ``slug`` field of the organizer to modify
:param event: The ``slug`` field of the event to modify
:param id: The ``id`` field of the export to modify
:statuscode 200: no error
:statuscode 400: The export could not be modified due to invalid submitted data
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/scheduled_exports/(id)/
Delete a scheduled export.
**Example request**:
.. sourcecode:: http
DELETE /api/v1/organizers/bigevents/events/sampleconf/scheduled_exports/1/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 204 No Content
Vary: Accept
:param organizer: The ``slug`` field of the organizer to modify
:param event: The ``slug`` field of the event to modify
:param id: The ``id`` field of the export to delete
:statuscode 204: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this resource.
Endpoints for organizer exports
---------------------------
.. http:get:: /api/v1/organizers/(organizer)/scheduled_exports/
Returns a list of all scheduled exports the client has access to.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/scheduled_exports/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"owner": "john@example.com",
"export_identifier": "orderlist",
"export_form_data": {"_format": "xlsx", "date_range": "week_previous"},
"locale": "en",
"mail_additional_recipients": "mary@example.org",
"mail_additional_recipients_cc": "",
"mail_additional_recipients_bcc": "",
"mail_subject": "Order list",
"mail_template": "Here is last week's order list\n\nCheers\nJohn",
"schedule_rrule": "DTSTART:20230118T000000\nRRULE:FREQ=WEEKLY;BYDAY=TU,WE,TH",
"schedule_rrule_time": "04:00:00",
"schedule_next_run": "2023-10-26T02:00:00Z",
"timezone": "Europe/Berlin",
"error_counter": 0
}
]
}
:query integer page: The page number in case of a multi-page result set, default is 1
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``id``, ``export_identifier``, and ``schedule_next_run``.
Default: ``id``
:param organizer: The ``slug`` field of the organizer to fetch
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
.. http:get:: /api/v1/organizers/(organizer)/scheduled_exports/(id)/
Returns information on one scheduled export, identified by its ID.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/scheduled_exports/1/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"id": 1,
"owner": "john@example.com",
"export_identifier": "orderlist",
"export_form_data": {"_format": "xlsx", "date_range": "week_previous"},
"locale": "en",
"mail_additional_recipients": "mary@example.org",
"mail_additional_recipients_cc": "",
"mail_additional_recipients_bcc": "",
"mail_subject": "Order list",
"mail_template": "Here is last week's order list\n\nCheers\nJohn",
"schedule_rrule": "DTSTART:20230118T000000\nRRULE:FREQ=WEEKLY;BYDAY=TU,WE,TH",
"schedule_rrule_time": "04:00:00",
"schedule_next_run": "2023-10-26T02:00:00Z",
"timezone": "Europe/Berlin",
"error_counter": 0
}
:param organizer: The ``slug`` field of the organizer to fetch
:param id: The ``id`` field of the scheduled export to fetch
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
.. http:post:: /api/v1/organizers/(organizer)/scheduled_exports/
Schedule a new export.
.. note:: See above for special notes on permissions.
**Example request**:
.. sourcecode:: http
POST /api/v1/organizers/bigevents/scheduled_exports/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
Content-Type: application/json
{
"export_identifier": "orderlist",
"export_form_data": {"_format": "xlsx", "date_range": "week_previous"},
"locale": "en",
"mail_additional_recipients": "mary@example.org",
"mail_additional_recipients_cc": "",
"mail_additional_recipients_bcc": "",
"mail_subject": "Order list",
"mail_template": "Here is last week's order list\n\nCheers\nJohn",
"schedule_rrule": "DTSTART:20230118T000000\nRRULE:FREQ=WEEKLY;BYDAY=TU,WE,TH",
"schedule_rrule_time": "04:00:00",
"timezone": "Europe/Berlin"
}
**Example response**:
.. sourcecode:: http
HTTP/1.1 201 Created
Vary: Accept
Content-Type: application/json
{
"id": 1,
"owner": "john@example.com",
"export_identifier": "orderlist",
"export_form_data": {"_format": "xlsx", "date_range": "week_previous"},
"locale": "en",
"mail_additional_recipients": "mary@example.org",
"mail_additional_recipients_cc": "",
"mail_additional_recipients_bcc": "",
"mail_subject": "Order list",
"mail_template": "Here is last week's order list\n\nCheers\nJohn",
"schedule_rrule": "DTSTART:20230118T000000\nRRULE:FREQ=WEEKLY;BYDAY=TU,WE,TH",
"schedule_rrule_time": "04:00:00",
"schedule_next_run": "2023-10-26T02:00:00Z",
"timezone": "Europe/Berlin",
"error_counter": 0
}
:param organizer: The ``slug`` field of the organizer of the event to create an item for
:statuscode 201: no error
:statuscode 400: The item could not be created due to invalid submitted data.
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to create this resource.
.. http:patch:: /api/v1/organizers/(organizer)/scheduled_exports/(id)/
Update a scheduled export. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
want to change.
**Example request**:
.. sourcecode:: http
PATCH /api/v1/organizers/bigevents/scheduled_exports/1/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
Content-Type: application/json
Content-Length: 94
{
"export_form_data": {"_format": "xlsx", "date_range": "week_this"},
}
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"id": 1,
"owner": "john@example.com",
"export_identifier": "orderlist",
"export_form_data": {"_format": "xlsx", "date_range": "week_this"},
"locale": "en",
"mail_additional_recipients": "mary@example.org",
"mail_additional_recipients_cc": "",
"mail_additional_recipients_bcc": "",
"mail_subject": "Order list",
"mail_template": "Here is last week's order list\n\nCheers\nJohn",
"schedule_rrule": "DTSTART:20230118T000000\nRRULE:FREQ=WEEKLY;BYDAY=TU,WE,TH",
"schedule_rrule_time": "04:00:00",
"schedule_next_run": "2023-10-26T02:00:00Z",
"timezone": "Europe/Berlin",
"error_counter": 0
}
:param organizer: The ``slug`` field of the organizer to modify
:param id: The ``id`` field of the export to modify
:statuscode 200: no error
:statuscode 400: The export could not be modified due to invalid submitted data
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to change this resource.
.. http:delete:: /api/v1/organizers/(organizer)/scheduled_exports/(id)/
Delete a scheduled export.
**Example request**:
.. sourcecode:: http
DELETE /api/v1/organizers/bigevents/scheduled_exports/1/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 204 No Content
Vary: Accept
:param organizer: The ``slug`` field of the organizer to modify
:param id: The ``id`` field of the export to delete
:statuscode 204: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to delete this resource.
.. _RFC 5545: https://datatracker.ietf.org/doc/html/rfc5545#section-3.8.5.3

View File

@@ -1,262 +0,0 @@
.. _`rest-reusablemedia`:
Seats
=====
The seat resource represents the seats in a seating plan in a specific event or subevent.
Resource description
--------------------
The seat resource contains the following public fields:
.. rst-class:: rest-resource-table
===================================== ========================== =======================================================
Field Type Description
===================================== ========================== =======================================================
id integer Internal ID of this seat
subevent integer Internal ID of the subevent this seat belongs to
zone_name string Name of the zone the seat is in
row_name string Name/number of the row the seat is in
row_label string Additional label of the row (or ``null``)
seat_number string Number of the seat within the row
seat_label string Additional label of the seat (or ``null``)
seat_guid string Identifier of the seat within the seating plan
product integer Internal ID of the product that is mapped to this seat
blocked boolean Whether this seat is blocked manually.
orderposition integer / object Internal ID of an order position reserving this seat.
cartposition integer / object Internal ID of a cart position reserving this seat.
voucher integer / object Internal ID of a voucher reserving this seat.
===================================== ========================== =======================================================
Endpoints
---------
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/seats/
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/subevents/(subevent_id)/seats/
Returns a list of all seats in the specified event or subevent. Depending on whether the event has subevents, the
according endpoint has to be used.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/events/sampleconf/seats/ HTTP/1.1
Host: pretix.eu
Accept: application/json
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"count": 500,
"next": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/seats/?page=2",
"previous": null,
"results": [
{
"id": 1633,
"subevent": null,
"zone_name": "Ground floor",
"row_name": "1",
"row_label": null,
"seat_number": "1",
"seat_label": null,
"seat_guid": "b9746230-6f31-4f41-bbc9-d6b60bdb3342",
"product": 104,
"blocked": false,
"orderposition": null,
"cartposition": null,
"voucher": 51
},
{
"id": 1634,
"subevent": null,
"zone_name": "Ground floor",
"row_name": "1",
"row_label": null,
"seat_number": "2",
"seat_label": null,
"seat_guid": "1d29fe20-8e1e-4984-b0ee-2773b0d07e07",
"product": 104,
"blocked": true,
"orderposition": 4321,
"cartposition": null,
"voucher": null
},
// ...
]
}
:query integer page: The page number in case of a multi-page result set, default is 1.
:query string zone_name: Only show seats with the given zone_name.
:query string row_name: Only show seats with the given row_name.
:query string row_label: Only show seats with the given row_label.
:query string seat_number: Only show seats with the given seat_number.
:query string seat_label: Only show seats with the given seat_label.
:query string seat_guid: Only show seats with the given seat_guid.
:query boolean blocked: Only show seats with the given blocked status.
:query boolean is_available: Only show seats that are (not) currently available.
:query string expand: If you pass ``"orderposition"``, ``"cartposition"``, or ``"voucher"``, the respective field will be
shown as a nested value instead of just an ID. This requires permission to access that object.
The nested objects are identical to the respective resources, except that order positions
will have an attribute of the format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make
matching easier, and won't include the `seat` attribute, as that would be redundant.
The parameter can be given multiple times.
:param organizer: The ``slug`` field of the organizer to fetch
:param event: The ``slug`` field of the event to fetch
:param subevent_id: The ``id`` field of the subevent to fetch
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
:statuscode 404: Endpoint without subevent id was used for event with subevents, or vice versa.
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/seats/(id)/
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/subevents/(subevent_id)/seats/(id)/
Returns information on one seat, identified by its ID.
**Example request**:
.. sourcecode:: http
GET /api/v1/organizers/bigevents/events/sampleconf/seats/1634/?expand=orderposition HTTP/1.1
Host: pretix.eu
Accept: application/json
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"id": 1634,
"subevent": null,
"zone_name": "Ground floor",
"row_name": "1",
"row_label": null,
"seat_number": "2",
"seat_label": null,
"seat_guid": "1d29fe20-8e1e-4984-b0ee-2773b0d07e07",
"product": 104,
"blocked": true,
"orderposition": {
"id": 134,
"order": {
"code": "U0HW7",
"event": "sampleconf"
},
"positionid": 1,
"item": 104,
"variation": 59,
"price": "60.00",
"attendee_name": "",
"attendee_name_parts": {
"_scheme": "given_family"
},
"company": null,
"street": null,
"zipcode": null,
"city": null,
"country": null,
"state": null,
"discount": null,
"attendee_email": null,
"voucher": null,
"tax_rate": "0.00",
"tax_value": "0.00",
"secret": "4rfgp263jduratnsvwvy6cc6r6wnptbj",
"addon_to": null,
"subevent": null,
"checkins": [],
"downloads": [],
"answers": [],
"tax_rule": null,
"pseudonymization_id": "ZSNYSG3URZ",
"canceled": false,
"valid_from": null,
"valid_until": null,
"blocked": null,
"voucher_budget_use": null
},
"cartposition": null,
"voucher": null
}
:param organizer: The ``slug`` field of the organizer to fetch
:param event: The ``slug`` field of the event to fetch
:param subevent_id: The ``id`` field of the subevent to fetch
:param id: The ``id`` field of the seat to fetch
:query string expand: If you pass ``"orderposition"``, ``"cartposition"``, or ``"voucher"``, the respective field will be
shown as a nested value instead of just an ID. This requires permission to access that object.
The nested objects are identical to the respective resources, except that order positions
will have an attribute of the format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make
matching easier, and won't include the `seat` attribute, as that would be redundant.
The parameter can be given multiple times.
:statuscode 200: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
:statuscode 404: Seat does not exist; or the endpoint without subevent id was used for event with subevents, or vice versa.
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/seats/(id)/
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/subevents/(id)/seats/(id)/
Update a seat.
You can only change the ``blocked`` field.
**Example request**:
.. sourcecode:: http
PATCH /api/v1/organizers/bigevents/events/sampleconf/seats/1636/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
Content-Type: application/json
{
"blocked": true
}
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json
{
"id": 1636,
"subevent": null,
"zone_name": "Ground floor",
"row_name": "1",
"row_label": null,
"seat_number": "4",
"seat_label": null,
"seat_guid": "6c0e29e5-05d6-421f-99f3-afd01478ecad",
"product": 104,
"blocked": true,
"orderposition": null,
"cartposition": null,
"voucher": null
},
:param organizer: The ``slug`` field of the organizer to modify
:param event: The ``slug`` field of the event to modify
:param subevent_id: The ``id`` field of the subevent to modify
:param id: The ``id`` field of the seat to modify
:statuscode 200: no error
:statuscode 400: The seat could not be modified due to invalid submitted data
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer or event does not exist **or** you have no permission to change this resource.
:statuscode 404: Seat does not exist; or the endpoint without subevent id was used for event with subevents, or vice versa.

View File

@@ -1,12 +1,10 @@
Scheduled email rules
Automated email rules
=====================
This feature requires the bundled ``pretix.plugins.sendmail`` plugin to be active for the event in order to work properly.
Resource description
--------------------
Scheduled email rules that specify emails that the system will send automatically at a specific point in time, e.g.
Automated email rules that specify emails that the system will send automatically at a specific point in time, e.g.
the day of the event.
.. rst-class:: rest-resource-table
@@ -20,19 +18,8 @@ subject multi-lingual string The subject of
template multi-lingual string The body of the email
all_products boolean If ``true``, the email is sent to buyers of all products
limit_products list of integers List of product IDs, if ``all_products`` is not set
[**DEPRECATED**] include_pending boolean If ``true``, the email is sent to pending orders. If ``false``,
include_pending boolean If ``true``, the email is sent to pending orders. If ``false``,
only paid orders are considered.
restrict_to_status list List of order states to restrict recipients to. Valid
entries are ``p`` for paid, ``e`` for expired, ``c`` for canceled,
``n__pending_approval`` for pending approval,
``n__not_pending_approval_and_not_valid_if_pending`` for payment
pending, ``n__valid_if_pending`` for payment pending but already confirmed,
and ``n__pending_overdue`` for pending with payment overdue.
The default is ``["p", "n__valid_if_pending"]``.
checked_in_status string Check-in status to restrict recipients to. Valid strings are:
``null`` for no filtering (default), ``checked_in`` for
limiting to attendees that are or have been checked in, and
``no_checkin`` for limiting to attendees who have not checked in.
date_is_absolute boolean If ``true``, the email is set at a specific point in time.
send_date datetime If ``date_is_absolute`` is set: Date and time to send the email.
send_offset_days integer If ``date_is_absolute`` is not set, this is the number of days
@@ -51,10 +38,6 @@ send_to string Can be ``"order
date. Otherwise it is relative to the event start date.
===================================== ========================== =======================================================
.. versionchanged:: 2023.7
The ``include_pending`` field has been deprecated.
The ``restrict_to_status`` field has been added.
Endpoints
---------
@@ -91,12 +74,7 @@ Endpoints
"template": {"en": "Don't forget your tickets, download them at {url}"},
"all_products": true,
"limit_products": [],
"restrict_to_status": [
"p",
"n__not_pending_approval_and_not_valid_if_pending",
"n__valid_if_pending"
],
"checked_in_status": null,
"include_pending": false,
"send_date": null,
"send_offset_days": 1,
"send_offset_time": "18:00",
@@ -142,12 +120,7 @@ Endpoints
"template": {"en": "Don't forget your tickets, download them at {url}"},
"all_products": true,
"limit_products": [],
"restrict_to_status": [
"p",
"n__not_pending_approval_and_not_valid_if_pending",
"n__valid_if_pending"
],
"checked_in_status": null,
"include_pending": false,
"send_date": null,
"send_offset_days": 1,
"send_offset_time": "18:00",
@@ -184,12 +157,7 @@ Endpoints
"template": {"en": "Don't forget your tickets, download them at {url}"},
"all_products": true,
"limit_products": [],
"restrict_to_status": [
"p",
"n__not_pending_approval_and_not_valid_if_pending",
"n__valid_if_pending"
],
"checked_in_status": "checked_in",
"include_pending": false,
"send_date": null,
"send_offset_days": 1,
"send_offset_time": "18:00",
@@ -214,12 +182,7 @@ Endpoints
"template": {"en": "Don't forget your tickets, download them at {url}"},
"all_products": true,
"limit_products": [],
"restrict_to_status": [
"p",
"n__not_pending_approval_and_not_valid_if_pending",
"n__valid_if_pending"
],
"checked_in_status": "checked_in",
"include_pending": false,
"send_date": null,
"send_offset_days": 1,
"send_offset_time": "18:00",
@@ -272,12 +235,7 @@ Endpoints
"template": {"en": "Don't forget your tickets, download them at {url}"},
"all_products": true,
"limit_products": [],
"restrict_to_status": [
"p",
"n__not_pending_approval_and_not_valid_if_pending",
"n__valid_if_pending"
],
"checked_in_status": "checked_in",
"include_pending": false,
"send_date": null,
"send_offset_days": 1,
"send_offset_time": "18:00",

View File

@@ -1,4 +1,4 @@
.. spelling:word-list:: checkin
.. spelling:: checkin
Data shredders
==============

View File

@@ -1,4 +1,4 @@
.. spelling:word-list::
.. spelling::
geo
lat
@@ -63,15 +63,6 @@ last_modified datetime Last modificati
The ``search`` query parameter has been added to filter sub-events by their name or location in any language.
.. versionchanged:: 5.0
The ``date_from_before``, ``date_from_after``, ``date_to_before``, and ``date_to_after`` query parameters have been
added.
.. versionchanged:: 2023.8.0
For the organizer-wide endpoint, the ``search`` query parameter has been modified to filter sub-events by their parent events slug too.
Endpoints
---------
@@ -136,14 +127,9 @@ Endpoints
}
:query page: The page number in case of a multi-page result set, default is 1
:query is_public: If set to ``true``/``false``, only subevents with a matching value of ``is_public`` are returned.
:query active: If set to ``true``/``false``, only events with a matching value of ``active`` are returned.
:query is_future: If set to ``true`` (``false``), only events that happen currently or in the future are (not) returned.
:query is_past: If set to ``true`` (``false``), only events that are over are (not) returned.
:query date_from_after: If set to a date and time, only events that start at or after the given time are returned.
:query date_from_before: If set to a date and time, only events that start at or before the given time are returned.
:query date_to_after: If set to a date and time, only events that have an end date and end at or after the given time are returned.
:query date_to_before: If set to a date and time, only events that have an end date and end at or before the given time are returned.
:query ends_after: If set to a date and time, only events that happen during of after the given time are returned.
:query search: Only return events matching a given search query.
:param organizer: The ``slug`` field of a valid organizer
@@ -468,17 +454,11 @@ Endpoints
}
:query page: The page number in case of a multi-page result set, default is 1
:query is_public: If set to ``true``/``false``, only subevents with a matching value of ``is_public`` are returned.
:query active: If set to ``true``/``false``, only events with a matching value of ``active`` are returned.
:query event__live: If set to ``true``/``false``, only events with a matching value of ``live`` on the parent event are returned.
:query is_future: If set to ``true`` (``false``), only events that happen currently or in the future are (not) returned.
:query is_past: If set to ``true`` (``false``), only events that are over are (not) returned.
:query date_from_after: If set to a date and time, only events that start at or after the given time are returned.
:query date_from_before: If set to a date and time, only events that start at or before the given time are returned.
:query date_to_after: If set to a date and time, only events that have an end date and end at or after the given time are returned.
:query date_to_before: If set to a date and time, only events that have an end date and end at or before the given time are returned.
:query ends_after: If set to a date and time, only events that happen during of after the given time are returned.
:query search: Only return events matching a given search query.
:query sales_channel: If set to a sales channel identifier, the response will only contain subevents from events available on this sales channel.
:param organizer: The ``slug`` field of a valid organizer
:param event: The ``slug`` field of the event to fetch

View File

@@ -20,17 +20,11 @@ internal_name string An optional nam
rate decimal (string) Tax rate in percent
price_includes_tax boolean If ``true`` (default), tax is assumed to be included in
the specified product price
eu_reverse_charge boolean **DEPRECATED**. If ``true``, EU reverse charge rules
are applied. Will be ignored if custom rules are set.
Use custom rules instead.
eu_reverse_charge boolean If ``true``, EU reverse charge rules are applied
home_country string Merchant country (required for reverse charge), can be
``null`` or empty string
keep_gross_if_rate_changes boolean If ``true``, changes of the tax rate based on custom
rules keep the gross price constant (default is ``false``)
custom_rules object Dynamic rules specification. Each list element
corresponds to one rule that will be processed in order.
The current version of the schema in use can be found
`here`_.
===================================== ========================== =======================================================
@@ -38,10 +32,6 @@ custom_rules object Dynamic rules s
The ``internal_name`` and ``keep_gross_if_rate_changes`` attributes have been added.
.. versionchanged:: 2023.6
The ``custom_rules`` attribute has been added.
Endpoints
---------
@@ -78,7 +68,6 @@ Endpoints
"price_includes_tax": true,
"eu_reverse_charge": false,
"keep_gross_if_rate_changes": false,
"custom_rules": null,
"home_country": "DE"
}
]
@@ -119,7 +108,6 @@ Endpoints
"price_includes_tax": true,
"eu_reverse_charge": false,
"keep_gross_if_rate_changes": false,
"custom_rules": null,
"home_country": "DE"
}
@@ -168,7 +156,6 @@ Endpoints
"price_includes_tax": true,
"eu_reverse_charge": false,
"keep_gross_if_rate_changes": false,
"custom_rules": null,
"home_country": "DE"
}
@@ -216,7 +203,6 @@ Endpoints
"price_includes_tax": true,
"eu_reverse_charge": false,
"keep_gross_if_rate_changes": false,
"custom_rules": null,
"home_country": "DE"
}
@@ -256,5 +242,3 @@ Endpoints
:statuscode 204: no error
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event/rule does not exist **or** you have no permission to change it **or** this tax rule cannot be deleted since it is currently in use.
.. _here: https://github.com/pretix/pretix/blob/master/src/pretix/static/schema/tax-rules-custom.schema.json

View File

@@ -1,4 +1,4 @@
.. spelling:word-list:: fullname checkin
.. spelling:: fullname checkin
.. _`rest-teams`:
@@ -22,13 +22,10 @@ id integer Internal ID of
name string Team name
all_events boolean Whether this team has access to all events
limit_events list List of event slugs this team has access to
require_2fa boolean Whether members of this team are required to use
two-factor authentication
can_create_events boolean
can_change_teams boolean
can_change_organizer_settings boolean
can_manage_customers boolean
can_manage_reusable_media boolean
can_manage_gift_cards boolean
can_change_event_settings boolean
can_change_items boolean
@@ -39,10 +36,6 @@ can_change_vouchers boolean
can_checkin_orders boolean
===================================== ========================== =======================================================
.. versionchanged:: 4.18
The ``can_manage_reusable_media`` permission has been added.
Team member resource
--------------------
@@ -124,7 +117,6 @@ Team endpoints
"name": "Admin team",
"all_events": true,
"limit_events": [],
"require_2fa": true,
"can_create_events": true,
...
}
@@ -162,7 +154,6 @@ Team endpoints
"name": "Admin team",
"all_events": true,
"limit_events": [],
"require_2fa": true,
"can_create_events": true,
...
}
@@ -190,7 +181,6 @@ Team endpoints
"name": "Admin team",
"all_events": true,
"limit_events": [],
"require_2fa": true,
"can_create_events": true,
...
}
@@ -208,7 +198,6 @@ Team endpoints
"name": "Admin team",
"all_events": true,
"limit_events": [],
"require_2fa": true,
"can_create_events": true,
...
}
@@ -252,7 +241,6 @@ Team endpoints
"name": "Admin team",
"all_events": true,
"limit_events": [],
"require_2fa": true,
"can_create_events": true,
...
}

View File

@@ -47,8 +47,6 @@ tag string A string that i
comment string An internal comment on the voucher
subevent integer ID of the date inside an event series this voucher belongs to (or ``null``).
show_hidden_items boolean Only if set to ``true``, this voucher allows to buy products with the property ``hide_without_voucher``. Defaults to ``true``.
all_addons_included boolean If set to ``true``, all add-on products for the product purchased with this voucher are included in the base price.
all_bundles_included boolean If set to ``true``, all bundled products for the product purchased with this voucher are added without their designated price.
===================================== ========================== =======================================================
@@ -97,9 +95,6 @@ Endpoints
"comment": "",
"seat": null,
"subevent": null,
"show_hidden_items": false,
"all_addons_included": false,
"all_bundles_included": false
}
]
}
@@ -166,10 +161,7 @@ Endpoints
"tag": "testvoucher",
"comment": "",
"seat": null,
"subevent": null,
"show_hidden_items": false,
"all_addons_included": false,
"all_bundles_included": false
"subevent": null
}
:param organizer: The ``slug`` field of the organizer to fetch
@@ -206,10 +198,7 @@ Endpoints
"quota": null,
"tag": "testvoucher",
"comment": "",
"subevent": null,
"show_hidden_items": false,
"all_addons_included": false,
"all_bundles_included": false
"subevent": null
}
**Example response**:
@@ -236,10 +225,7 @@ Endpoints
"tag": "testvoucher",
"comment": "",
"seat": null,
"subevent": null,
"show_hidden_items": false,
"all_addons_included": false,
"all_bundles_included": false
"subevent": null
}
:param organizer: The ``slug`` field of the organizer to create a voucher for
@@ -278,10 +264,7 @@ Endpoints
"quota": null,
"tag": "testvoucher",
"comment": "",
"subevent": null,
"show_hidden_items": false,
"all_addons_included": false,
"all_bundles_included": false
"subevent": null
},
{
"code": "ASDKLJCYXCASDASD",
@@ -296,10 +279,7 @@ Endpoints
"quota": null,
"tag": "testvoucher",
"comment": "",
"subevent": null,
"show_hidden_items": false,
"all_addons_included": false,
"all_bundles_included": false
"subevent": null
},
**Example response**:
@@ -373,10 +353,7 @@ Endpoints
"tag": "testvoucher",
"comment": "",
"seat": null,
"subevent": null,
"show_hidden_items": false,
"all_addons_included": false,
"all_bundles_included": false
"subevent": null
}
:param organizer: The ``slug`` field of the organizer to modify

View File

@@ -26,7 +26,6 @@ limit_events list of strings If ``all_events
action_types list of strings A list of action type filters that limit the
notifications sent to this webhook. See below for
valid values
comment string Internal comment on this webhook, default ``null``
===================================== ========================== =======================================================
The following values for ``action_types`` are valid with pretix core:
@@ -41,20 +40,14 @@ The following values for ``action_types`` are valid with pretix core:
* ``pretix.event.order.modified``
* ``pretix.event.order.contact.changed``
* ``pretix.event.order.changed.*``
* ``pretix.event.order.deleted`` (can only occur for test mode orders)
* ``pretix.event.order.refund.created``
* ``pretix.event.order.refund.created.externally``
* ``pretix.event.order.refund.requested``
* ``pretix.event.order.refund.done``
* ``pretix.event.order.refund.canceled``
* ``pretix.event.order.refund.failed``
* ``pretix.event.order.payment.confirmed``
* ``pretix.event.order.approved``
* ``pretix.event.order.denied``
* ``pretix.event.orders.waitinglist.added``
* ``pretix.event.orders.waitinglist.changed``
* ``pretix.event.orders.waitinglist.deleted``
* ``pretix.event.orders.waitinglist.voucher_assigned``
* ``pretix.event.checkin``
* ``pretix.event.checkin.reverted``
* ``pretix.event.added``
@@ -63,14 +56,10 @@ The following values for ``action_types`` are valid with pretix core:
* ``pretix.subevent.added``
* ``pretix.subevent.changed``
* ``pretix.subevent.deleted``
* ``pretix.event.item.*``
* ``pretix.event.live.activated``
* ``pretix.event.live.deactivated``
* ``pretix.event.testmode.activated``
* ``pretix.event.testmode.deactivated``
* ``pretix.customer.created``
* ``pretix.customer.changed``
* ``pretix.customer.anonymized``
Installed plugins might register more valid values.
@@ -109,14 +98,12 @@ Endpoints
"target_url": "https://httpstat.us/200",
"all_events": false,
"limit_events": ["democon"],
"action_types": ["pretix.event.order.modified", "pretix.event.order.changed.*"],
"comment": null
"action_types": ["pretix.event.order.modified", "pretix.event.order.changed.*"]
}
]
}
:query integer page: The page number in case of a multi-page result set, default is 1
:query boolean enabled: Only show webhooks that are or are not enabled
:param organizer: The ``slug`` field of the organizer to fetch
:statuscode 200: no error
:statuscode 401: Authentication failure
@@ -148,8 +135,7 @@ Endpoints
"target_url": "https://httpstat.us/200",
"all_events": false,
"limit_events": ["democon"],
"action_types": ["pretix.event.order.modified", "pretix.event.order.changed.*"],
"comment": null
"action_types": ["pretix.event.order.modified", "pretix.event.order.changed.*"]
}
:param organizer: The ``slug`` field of the organizer to fetch
@@ -176,8 +162,7 @@ Endpoints
"target_url": "https://httpstat.us/200",
"all_events": false,
"limit_events": ["democon"],
"action_types": ["pretix.event.order.modified", "pretix.event.order.changed.*"],
"comment": "Called for changes"
"action_types": ["pretix.event.order.modified", "pretix.event.order.changed.*"]
}
**Example response**:
@@ -194,8 +179,7 @@ Endpoints
"target_url": "https://httpstat.us/200",
"all_events": false,
"limit_events": ["democon"],
"action_types": ["pretix.event.order.modified", "pretix.event.order.changed.*"],
"comment": "Called for changes"
"action_types": ["pretix.event.order.modified", "pretix.event.order.changed.*"]
}
:param organizer: The ``slug`` field of the organizer to create a webhook for
@@ -240,8 +224,7 @@ Endpoints
"target_url": "https://httpstat.us/200",
"all_events": false,
"limit_events": ["democon"],
"action_types": ["pretix.event.order.modified", "pretix.event.order.changed.*"],
"comment": null
"action_types": ["pretix.event.order.modified", "pretix.event.order.changed.*"]
}
:param organizer: The ``slug`` field of the organizer to modify

View File

@@ -13,6 +13,10 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
from docutils.parsers.rst.directives.admonitions import BaseAdmonition
from sphinx.util import compat
compat.make_admonition = BaseAdmonition # See https://github.com/spinus/sphinxcontrib-images/issues/41
import sys
import os
@@ -24,13 +28,12 @@ from datetime import date
sys.path.insert(0, os.path.abspath('../src'))
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pretix.testutils.settings")
django.setup()
try:
import enchant # noqa
try:
import enchant
HAS_PYENCHANT = True
except:
HAS_PYENCHANT = False
@@ -38,7 +41,7 @@ except:
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
# needs_sphinx = '1.0'
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
@@ -49,7 +52,6 @@ extensions = [
'sphinx.ext.coverage',
'sphinxcontrib.httpdomain',
'sphinxcontrib.images',
'sphinxcontrib.jquery',
'sphinxemoji.sphinxemoji',
]
if HAS_PYENCHANT:
@@ -62,7 +64,7 @@ templates_path = ['_templates']
source_suffix = '.rst'
# The encoding of source files.
# source_encoding = 'utf-8-sig'
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
@@ -77,20 +79,19 @@ copyright = '2014-{}, Raphael Michel'.format(date.today().year)
#
# The short X.Y version.
from pretix import __version__
version = '.'.join(__version__.split('.')[:2])
# The full version, including alpha/beta/rc tags.
release = __version__
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
# language = None
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
# today = ''
#today = ''
# Else, today_fmt is used as the format for a strftime call.
# today_fmt = '%B %d, %Y'
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
@@ -98,34 +99,34 @@ exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all
# documents.
# default_role = None
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
# add_function_parentheses = True
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
# add_module_names = True
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
# show_authors = False
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []
#modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
# keep_warnings = False
#keep_warnings = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
# html_theme = ""
#html_theme = ""
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
@@ -135,14 +136,14 @@ html_theme_options = {
}
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
# html_title = None
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
# html_short_title = None
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
@@ -151,7 +152,7 @@ html_logo = 'images/logo-white.svg'
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
# html_favicon = None
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
@@ -165,18 +166,18 @@ html_static_path = [
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
# html_extra_path = []
#html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
# html_last_updated_fmt = '%b %d, %Y'
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
# html_use_smartypants = True
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
# html_sidebars = {}
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
@@ -191,24 +192,24 @@ html_domain_indices = False
html_use_index = False
# If true, the index is split into individual pages for each letter.
# html_split_index = False
#html_split_index = False
# If true, links to the reST sources are added to the pages.
html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
# html_show_sphinx = True
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
# html_show_copyright = True
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
# html_use_opensearch = ''
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
# html_file_suffix = None
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'pretixdoc'
@@ -216,46 +217,47 @@ htmlhelp_basename = 'pretixdoc'
html_theme = 'pretix_theme'
html_theme_path = [os.path.abspath('_themes')]
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
# The paper size ('letterpaper' or 'a4paper').
'papersize': 'a4paper',
# The font size ('10pt', '11pt' or '12pt').
# The font size ('10pt', '11pt' or '12pt').
'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
# 'preamble': '',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
('index', 'pretix.tex', 'pretix Documentation',
'Raphael Michel', 'manual'),
('index', 'pretix.tex', 'pretix Documentation',
'Raphael Michel', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
# latex_logo = None
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
# latex_use_parts = False
#latex_use_parts = False
# If true, show page references after internal links.
# latex_show_pagerefs = False
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
# latex_show_urls = False
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
# latex_appendices = []
#latex_appendices = []
# If false, no module index is generated.
# latex_domain_indices = True
#latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
@@ -268,7 +270,7 @@ man_pages = [
]
# If true, show URL addresses after external links.
# man_show_urls = False
#man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
@@ -277,22 +279,22 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'pretix', 'pretix Documentation',
'Raphael Michel', 'pretix', 'One line description of project.',
'Miscellaneous'),
('index', 'pretix', 'pretix Documentation',
'Raphael Michel', 'pretix', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
# texinfo_appendices = []
#texinfo_appendices = []
# If false, no module index is generated.
# texinfo_domain_indices = True
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
# texinfo_show_urls = 'footnote'
#texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
# texinfo_no_detailmenu = False
#texinfo_no_detailmenu = False
images_config = {
@@ -312,13 +314,12 @@ if HAS_PYENCHANT:
# String specifying a file containing a list of words known to be spelled
# correctly but that do not appear in the language dictionary selected by
# spelling_lang. The file should contain one word per line.
spelling_word_list_filename = 'spelling_wordlist.txt'
spelling_word_list_filename='spelling_wordlist.txt'
# Boolean controlling whether suggestions for misspelled words are printed.
# Defaults to False.
spelling_show_suggestions = True
spelling_show_suggestions=True
# List of filter classes to be added to the tokenizer that produces words to be checked.
from checkin_filter import CheckinFilter
spelling_filters = [CheckinFilter]
spelling_filters=[CheckinFilter]

View File

@@ -18,13 +18,13 @@ If you want to add a custom view to the control area of an event, just register
.. code-block:: python
from django.urls import re_path
from django.conf.urls import url
from . import views
urlpatterns = [
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/mypluginname/',
views.admin_view, name='backend'),
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/mypluginname/',
views.admin_view, name='backend'),
]
It is required that your URL parameters are called ``organizer`` and ``event``. If you want to

View File

@@ -76,10 +76,6 @@ The exporter class
This is an abstract attribute, you **must** override this!
.. autoattribute:: description
.. autoattribute:: category
.. autoattribute:: export_form_fields
.. automethod:: render

View File

@@ -11,10 +11,9 @@ Core
----
.. automodule:: pretix.base.signals
:members: periodic_task, event_live_issues, event_copy_data, email_filter, register_notification_types, notification,
item_copy_data, register_sales_channel_types, register_global_settings, quota_availability, global_email_filter,
register_ticket_secret_generators, gift_card_transaction_display,
register_text_placeholders, register_mail_placeholders, device_info_updated
:members: periodic_task, event_live_issues, event_copy_data, email_filter, register_notification_types,
item_copy_data, register_sales_channels, register_global_settings, quota_availability, global_email_filter,
register_ticket_secret_generators
Order events
""""""""""""
@@ -22,7 +21,7 @@ Order events
There are multiple signals that will be sent out in the ordering cycle:
.. automodule:: pretix.base.signals
:members: validate_cart, validate_cart_addons, validate_order, order_valid_if_pending, order_fee_calculation, order_paid, order_placed, order_canceled, order_reactivated, order_expired, order_modified, order_changed, order_approved, order_denied, order_fee_type_name, allow_ticket_download, order_split, order_gracefully_delete, invoice_line_text
:members: validate_cart, validate_cart_addons, validate_order, order_fee_calculation, order_paid, order_placed, order_canceled, order_reactivated, order_expired, order_modified, order_changed, order_approved, order_denied, order_fee_type_name, allow_ticket_download, order_split, order_gracefully_delete, invoice_line_text
Check-ins
"""""""""
@@ -35,11 +34,11 @@ Frontend
--------
.. automodule:: pretix.presale.signals
:members: html_head, html_footer, footer_link, global_footer_link, front_page_top, front_page_bottom, front_page_bottom_widget, fee_calculation_for_cart, contact_form_fields, question_form_fields, contact_form_fields_overrides, question_form_fields_overrides, checkout_confirm_messages, checkout_confirm_page_content, checkout_all_optional, html_page_header, render_seating_plan, checkout_flow_steps, position_info, position_info_top, item_description, global_html_head, global_html_footer, global_html_page_header, seatingframe_html_head
:members: html_head, html_footer, footer_link, global_footer_link, front_page_top, front_page_bottom, front_page_bottom_widget, fee_calculation_for_cart, contact_form_fields, question_form_fields, contact_form_fields_overrides, question_form_fields_overrides, checkout_confirm_messages, checkout_confirm_page_content, checkout_all_optional, html_page_header, sass_preamble, sass_postamble, render_seating_plan, checkout_flow_steps, position_info, position_info_top, item_description, global_html_head, global_html_footer, global_html_page_header
.. automodule:: pretix.presale.signals
:members: order_info, order_info_top, order_meta_from_request, order_api_meta_from_request
:members: order_info, order_info_top, order_meta_from_request
Request flow
""""""""""""
@@ -62,7 +61,7 @@ Backend
item_formsets, order_search_filter_q, order_search_forms
.. automodule:: pretix.base.signals
:members: logentry_display, logentry_object_link, requiredaction_display, timeline_events, orderposition_blocked_display, customer_created, customer_signed_in
:members: logentry_display, logentry_object_link, requiredaction_display, timeline_events
Vouchers
""""""""

View File

@@ -3,12 +3,11 @@
.. _`importcol`:
Extending the import process
============================
Extending the order import process
==================================
It's possible through the backend to import objects into pretix, for example orders from a legacy ticketing system. If
your plugin defines additional data structures around those objects, it might be useful to make it possible to import
them as well.
It's possible through the backend to import orders into pretix, for example from a legacy ticketing system. If your
plugins defines additional data structures around orders, it might be useful to make it possible to import them as well.
Import process
--------------
@@ -41,7 +40,7 @@ Column registration
The import API does not make a lot of usage from signals, however, it
does use a signal to get a list of all available import columns. Your plugin
should listen for this signal and return the subclass of ``pretix.base.modelimport.ImportColumn``
should listen for this signal and return the subclass of ``pretix.base.orderimport.ImportColumn``
that we'll provide in this plugin:
.. sourcecode:: python
@@ -57,16 +56,10 @@ that we'll provide in this plugin:
EmailColumn(sender),
]
Similar signals exist for other objects:
.. automodule:: pretix.base.signals
:members: voucher_import_columns
The column class API
--------------------
.. class:: pretix.base.modelimport.ImportColumn
.. class:: pretix.base.orderimport.ImportColumn
The central object of each import extension is the subclass of ``ImportColumn``.

View File

@@ -84,8 +84,6 @@ convenient to you:
.. automethod:: _register_fonts
.. automethod:: _register_event_fonts
.. automethod:: _on_first_page
.. automethod:: _on_other_page

View File

@@ -70,8 +70,6 @@ The provider class
.. autoattribute:: settings_form_fields
.. autoattribute:: walletqueries
.. automethod:: settings_form_clean
.. automethod:: settings_content_render
@@ -104,8 +102,6 @@ The provider class
.. automethod:: render_invoice_text
.. automethod:: render_invoice_stamp
.. automethod:: order_change_allowed
.. automethod:: payment_prepare
@@ -124,8 +120,6 @@ The provider class
.. automethod:: refund_control_render
.. automethod:: refund_control_render_short
.. automethod:: new_refund_control_form_render
.. automethod:: new_refund_control_form_process
@@ -136,8 +130,6 @@ The provider class
.. automethod:: matching_id
.. automethod:: refund_matching_id
.. automethod:: shred_payment_info
.. automethod:: cancel_payment

View File

@@ -1,11 +1,10 @@
.. highlight:: python
:linenothreshold: 5
Writing a template placeholder plugin
=====================================
Writing an e-mail placeholder plugin
====================================
A template placeholder is a dynamic value that pretix users can use in their email templates and in other
configurable texts.
An email placeholder is a dynamic value that pretix users can use in their email templates.
Please read :ref:`Creating a plugin <pluginsetup>` first, if you haven't already.
@@ -13,31 +12,31 @@ Placeholder registration
------------------------
The placeholder API does not make a lot of usage from signals, however, it
does use a signal to get a list of all available placeholders. Your plugin
should listen for this signal and return an instance of a subclass of ``pretix.base.services.placeholders.BaseTextPlaceholder``:
does use a signal to get a list of all available email placeholders. Your plugin
should listen for this signal and return an instance of a subclass of ``pretix.base.email.BaseMailTextPlaceholder``:
.. code-block:: python
from django.dispatch import receiver
from pretix.base.signals import register_text_placeholders
from pretix.base.signals import register_mail_placeholders
@receiver(register_text_placeholders, dispatch_uid="placeholder_custom")
def register_placeholder_renderers(sender, **kwargs):
from .placeholders import MyPlaceholderClass
@receiver(register_mail_placeholders, dispatch_uid="placeholder_custom")
def register_mail_renderers(sender, **kwargs):
from .email import MyPlaceholderClass
return MyPlaceholder()
Context mechanism
-----------------
Templates are used in different "contexts" within pretix. For example, many emails are rendered from
templates in the context of an order, but some are not, such as the notification of a waiting list voucher.
Emails are sent in different "contexts" within pretix. For example, many emails are sent in the
the context of an order, but some are not, such as the notification of a waiting list voucher.
Not all placeholders make sense everywhere, and placeholders usually depend on some parameters
Not all placeholders make sense in every email, and placeholders usually depend some parameters
themselves, such as the ``Order`` object. Therefore, placeholders are expected to explicitly declare
what values they depend on and they will only be available in a context where all those dependencies are
what values they depend on and they will only be available in an email if all those dependencies are
met. Currently, placeholders can depend on the following context parameters:
* ``event``
@@ -52,7 +51,7 @@ There are a few more that are only to be used internally but not by plugins.
The placeholder class
---------------------
.. class:: pretix.base.services.placeholders.BaseTextPlaceholder
.. class:: pretix.base.email.BaseMailTextPlaceholder
.. autoattribute:: identifier
@@ -78,15 +77,7 @@ functions:
.. code-block:: python
placeholder = SimpleFunctionalTextPlaceholder(
placeholder = SimpleFunctionalMailTextPlaceholder(
'code', ['order'], lambda order: order.code, sample='F8VVL'
)
Signals
-------
.. automodule:: pretix.base.signals
:members: register_text_placeholders
.. automodule:: pretix.base.signals
:members: register_mail_placeholders

View File

@@ -55,6 +55,7 @@ visible boolean (optional) ``True`` by default, can hide a plugin s
restricted boolean (optional) ``False`` by default, restricts a plugin such that it can only be enabled
for an event by system administrators / superusers.
experimental boolean (optional) ``False`` by default, marks a plugin as an experimental feature in the plugins list.
picture string (optional) Path to a picture resolvable through the static file system.
compatibility string Specifier for compatible pretix versions.
================== ==================== ===========================================================

View File

@@ -17,7 +17,7 @@ The project pretix is split into several components. The main components are:
create and manage their events, items, orders and tickets.
**presale**
This is the ticket shop itself, containing all of the parts visible to the
This is the ticket-shop itself, containing all of the parts visible to the
end user. Also called "frontend" in parts of this documentation.
**api**

View File

@@ -1,4 +1,4 @@
.. spelling:word-list:: Rebase rebasing
.. spelling:: Rebase rebasing
Coding style and quality
========================

View File

@@ -37,7 +37,7 @@ you to execute a piece of code with a different locale:
This is very useful e.g. when sending an email to a user that has a different language than the user performing the
action that causes the mail to be sent.
.. _translation features: https://docs.djangoproject.com/en/4.2/topics/i18n/translation/
.. _translation features: https://docs.djangoproject.com/en/1.9/topics/i18n/translation/
.. _GNU gettext: https://www.gnu.org/software/gettext/
.. _strings: https://django-i18nfield.readthedocs.io/en/latest/strings.html
.. _database fields: https://django-i18nfield.readthedocs.io/en/latest/quickstart.html

View File

@@ -18,5 +18,3 @@ Contents:
email
permissions
logging
locking
timemachine

View File

@@ -1,69 +0,0 @@
.. highlight:: python
Resource locking
================
.. versionchanged:: 2023.8
Our locking mechanism changed heavily in version 2023.8. Read `this PR`_ for background information.
One of pretix's core objectives as a ticketing system could be described as the management of scarce resources.
Specifically, the following types of scarce-ness exist in pretix:
- Quotas can limit the number of tickets available
- Seats can only be booked once
- Vouchers can only be used a limited number of times
- Some memberships can only be used a limited number of times
For all of these, it is critical that we prevent race conditions.
While for some events it wouldn't be a big deal to sell a ticket more or less, for some it would be problematic and selling the same seat twice would always be catastrophic.
We therefore implement a standardized locking approach across the system to limit concurrency in cases where it could
be problematic.
To acquire a lock on a set of quotas to create a new order that uses that quota, you should follow the following pattern::
with transaction.atomic(durable=True):
quotas = Quota.objects.filter(...)
lock_objects(quotas, shared_lock_objects=[event])
check_quota(quotas)
create_ticket()
The lock will automatically be released at the end of your database transaction.
Generally, follow the following guidelines during your development:
- **Always** acquire a lock on every **quota**, **voucher** or **seat** that you "use" during your transaction. "Use"
here means any action after which the quota, voucher or seat will be **less available**, such as creating a cart
position, creating an order, creating a blocking voucher, etc.
- There is **no need** to acquire a lock if you **free up** capacity, e.g. by canceling an order, deleting a voucher, etc.
- **Always** acquire a shared lock on the ``event`` you are working in whenever you acquire a lock on a quota, voucher,
or seat.
- Only call ``lock_objects`` **once** per transaction. If you violate this rule, `deadlocks`_ become possible.
- For best performance, call ``lock_objects`` as **late** in your transaction as possible, but always before you check
if the desired resource is still available in sufficient quantity.
Behind the scenes, the locking is implemented through `PostgreSQL advisory locks`_. You should also be aware of the following
properties of our system:
- In some situations, an exclusive lock on the ``event`` is used, such as when the system can't determine for sure which
seats will become unavailable after the transaction.
- An exclusive lock on the event is also used if you pass more than 20 objects to ``lock_objects``. This is a performance
trade-off because it would take long to acquire all of the individual locks.
- If ``lock_objects`` is unable to acquire a lock within 3 seconds, a ``LockTimeoutException`` will be thrown.
.. note::
We currently do not use ``lock_objects`` for memberships. Instead, we use ``select_for_update()`` on the membership
model. This might change in the future, but you should usually not be concerned about it since
``validate_memberships_in_order(lock=True)`` will handle it for you.
.. _this PR: https://github.com/pretix/pretix/pull/2408
.. _deadlocks: https://www.postgresql.org/docs/current/explicit-locking.html#LOCKING-DEADLOCKS
.. _PostgreSQL advisory locks: https://www.postgresql.org/docs/11/explicit-locking.html#ADVISORY-LOCKS

View File

@@ -1,7 +1,7 @@
.. highlight:: python
:linenothreshold: 5
.. spelling:word-list:: answ contrib
.. spelling:: answ contrib
Data model
==========

View File

@@ -15,7 +15,7 @@ includes serializers for serializing the following types:
* Built-in types: ``int``, ``float``, ``decimal.Decimal``, ``dict``, ``list``, ``bool``
* ``datetime.date``, ``datetime.datetime``, ``datetime.time``
* ``LazyI18nString``
* References to Django ``File`` objects that are already stored in a storage backend [#f1]_
* References to Django ``File`` objects that are already stored in a storage backend
* References to model instances
In code, we recommend to always use the ``.get()`` method on the settings object to access a value, but for
@@ -55,9 +55,6 @@ You can simply use it like this:
"preserve his reservation."),
)
.. _settings-defaults-in-plugins:
Defaults in plugins
-------------------
@@ -73,9 +70,3 @@ Make sure that you include this code in a module that is imported at app loading
.. _django-hierarkey: https://github.com/raphaelm/django-hierarkey
.. _documentation: https://django-hierarkey.readthedocs.io/en/latest/
.. rubric:: Footnotes
.. [#f1] If you store ``File`` instances in per-event settings, make sure to always register them with ``add_default``
as described above in :ref:`settings-defaults-in-plugins`. Otherwise, the file won't get copied properly if the
user copies the settings of an existing event to a new one.

View File

@@ -1,32 +0,0 @@
Time machine mode
=================
In test mode, pretix provides a "time machine" feature which allows event organizers
to test their shop as if it were a different date and time. To enable this feature, they can
click on the "time machine"-link in the test mode warning box on the event page.
Internally, this time machine mode is implemented by calling our custom :py:meth:`time_machine_now()`
function instead of :py:meth:`django.utils.timezone.now()` in all places where the fake time should be
taken into account. If you add code that uses the current date and time for checking whether some
product can be bought, you should use :py:meth:`time_machine_now`.
.. autofunction:: pretix.base.timemachine.time_machine_now
Background tasks
----------------
The time machine datetime is passed through the request flow via a thread-local variable (ContextVar).
Therefore, if you call a background task in the order process, where time_machine_now should be
respected, you need to pass it through manually as shown in the example below:
.. code-block:: python
@app.task()
def my_task(self, override_now_dt: datetime=None) -> None:
with time_machine_now_assigned(override_now_dt):
# ...do something that uses time_machine_now()
my_task.apply_async(kwargs={'override_now_dt': time_machine_now(default=None)})
.. autofunction:: pretix.base.timemachine.time_machine_now_assigned

View File

@@ -15,41 +15,33 @@ and the admin panel is available at ``https://pretix.eu/control/event/bigorg/awe
If the organizer now configures a custom domain like ``tickets.bigorg.com``, his event will
from now on be available on ``https://tickets.bigorg.com/awesomecon/``. The former URL at
``pretix.eu`` will redirect there. It's also possible to do this for just an event, in which
case the event will be available on ``https://tickets.awesomecon.org/``.
However, the admin panel will still only be available on ``pretix.eu`` for convenience and security reasons.
``pretix.eu`` will redirect there. However, the admin panel will still only be available
on ``pretix.eu`` for convenience and security reasons.
URL routing
-----------
The hard part about implementing this URL routing in Django is that
``https://pretix.eu/bigorg/awesomecon/`` contains two parameters of nearly arbitrary content
and ``https://tickets.bigorg.com/awesomecon/`` contains only one and ``https://tickets.awesomecon.org/`` does not contain any.
The only robust way to do this is by having *separate* URL configuration for those three cases.
and ``https://tickets.bigorg.com/awesomecon/`` contains only one. The only robust way to do
this is by having *separate* URL configuration for those two cases. In pretix, we call the
former our ``maindomain`` config and the latter our ``subdomain`` config. For pretix's core
modules we do some magic to avoid duplicate configuration, but for a fairly simple plugin with
only a handful of routes, we recommend just configuring the two URL sets separately.
In pretix, we therefore do not have a global URL configuration, but three, living in the following modules:
- ``pretix.multidomain.maindomain_urlconf``
- ``pretix.multidomain.organizer_domain_urlconf``
- ``pretix.multidomain.event_domain_urlconf``
We provide some helper utilities to work with these to avoid duplicate configuration of the individual URLs.
The file ``urls.py`` inside your plugin package will be loaded and scanned for URL configuration
automatically and should be provided by any plugin that provides any view.
However, unlike plain Django, we look not only for a ``urlpatterns`` attribute on the module but support other
attributes like ``event_patterns`` and ``organizer_patterns`` as well.
For example, for a simple plugin that adds one URL to the backend and one event-level URL to the frontend, you can
create the following configuration in your ``urls.py``::
A very basic example that provides one view in the admin panel and one view in the frontend
could look like this::
from django.urls import re_path
from django.conf.urls import url
from . import views
urlpatterns = [
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/mypluginname/',
views.AdminView.as_view(), name='backend'),
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/mypluginname/',
views.AdminView.as_view(), name='backend'),
]
event_patterns = [
@@ -60,7 +52,7 @@ create the following configuration in your ``urls.py``::
As you can see, the view in the frontend is not included in the standard Django ``urlpatterns``
setting but in a separate list with the name ``event_patterns``. This will automatically prepend
the appropriate parameters to the regex (e.g. the event or the event and the organizer, depending
on the called domain). For organizer-level views, ``organizer_patterns`` works the same way.
on the called domain).
If you only provide URLs in the admin area, you do not need to provide a ``event_patterns`` attribute.
@@ -79,21 +71,12 @@ is a python method that emulates a behavior similar to ``reverse``:
.. autofunction:: pretix.multidomain.urlreverse.eventreverse
If you need to communicate the URL externally, you can use a different method to ensure that it is always an absolute URL:
.. autofunction:: pretix.multidomain.urlreverse.build_absolute_uri
In addition, there is a template tag that works similar to ``url`` but takes an event or organizer object
as its first argument and can be used like this::
{% load eventurl %}
<a href="{% eventurl request.event "presale:event.checkout" step="payment" %}">Pay</a>
<a href="{% abseventurl request.event "presale:event.checkout" step="payment" %}">Pay</a>
To generate absolute URLs on the main domain, you can use the ``absurl`` template tag::
{% load eventurl %}
<a href="{% absmainurl "control:event.settings" organizer=request.event.organizer.slug event=request.event.slug %}">Event settings</a>
Implementation details
----------------------

View File

@@ -12,4 +12,3 @@ Developer documentation
api/index
structure
translation/index
nfc/index

View File

@@ -1,15 +0,0 @@
NFC media
=========
pretix supports using NFC chips as "reusable media", for example to store gift cards or tickets.
Most of this implementation currently lives in our proprietary app pretixPOS, but in the future might also become part of our open-source pretixSCAN solution.
Either way, we want this to be an open ecosystem and therefore document the exact mechanisms in use on the following pages.
We support multiple implementations of NFC media, each documented on its own page:
.. toctree::
:maxdepth: 2
uid
mf0aes

View File

@@ -1,113 +0,0 @@
Mifare Ultralight AES
=====================
We offer an implementation that provides a higher security level than the UID-based approach and uses the `Mifare Ultralight AES`_ chip sold by NXP.
We believe the security model of this approach is adequate to the situation where this will usually be used and we'll outline known risks below.
If you want to dive deeper into the properties of the Mifare Ultralight AES chip, we recommend reading the `data sheet`_.
Random UIDs
-----------
Mifare Ultralight AES supports a feature that returns a randomized UID every time a non-authenticated user tries to
read the UID. This has a strong privacy benefit, since no unauthorized entity can use the NFC chips to track users.
On the other hand, this reduces interoperability of the system. For example, this prevents you from using the same NFC
chips for a different purpose where you only need the UID. This will also prevent your guests from reading their UID
themselves with their phones, which might be useful e.g. in debugging situations.
Since there's no one-size-fits-all choice here, you can enable or disable this feature in the pretix organizer
settings. If you change it, the change will apply to all newly encoded chips after the change.
Key management
--------------
For every organizer, the server will generate create a "key set", which consists of a publicly known ID (random 32-bit integer) and two 16-byte keys ("diversification key" and "UID key").
Using our :ref:`Device authentication mechanism <rest-deviceauth>`, an authorized device can submit a locally generated RSA public key to the server.
This key can no longer changed on the server once it is set, thus protecting against the attack scenario of a leaked device API token.
The server will then include key sets in the response to ``/api/v1/device/info``, encrypted with the device's RSA key.
This includes all key sets generated for the organizer the device belongs to, as well as all keys of organizers that have granted sufficient access to this organizer.
The device will decrypt the key sets using its RSA key and store the key sets locally.
.. warning:: The device **will** have access to the raw key sets. Therefore, there is a risk of leaked master keys if an
authorized device is stolen or abused. Our implementation in pretixPOS attempts to make this very hard on
modern, non-rooted Android devices by keeping them encrypted with the RSA key and only storing the RSA key
in the hardware-backed keystore of the device. A sufficiently motivated attacker, however, will likely still
be able to extract the keys from a stolen device.
Encoding a chip
---------------
When a new chip is encoded, the following steps will be taken:
- The UID of the chip is retrieved.
- A chip-specific key is generated using the mechanism documented in `AN10922`_ using the "diversification key" from the
organizer's key set as the CMAC key and the diversification input concatenated in the from of ``0x01 + UID + APPID + SYSTEMID``
with the following values:
- The UID of the chip as ``UID``
- ``"eu.pretix"`` (``0x65 0x75 0x2e 0x70 0x72 0x65 0x74 0x69 0x78``) as ``APPID``
- The ``public_id`` from the organizer's key set as a 4-byte big-endian value as ``SYSTEMID``
- The chip-specific key is written to the chip as the "data protection key" (config pages 0x30 to 0x33)
- The UID key from the organizer's key set is written to the chip as the "UID retrieval key" (config pages 0x34 to 0x37)
- The config page 0x29 is set like this:
- ``RID_ACT`` (random UID) to ``1`` or ``0`` based on the organizer's configuration
- ``SEC_MSG_ACT`` (secure messaging) to ``1``
- ``AUTH0`` (first page that needs authentication) to 0x04 (first non-UID page)
- The config page 0x2A is set like this:
- ``PROT`` to ``0`` (only write access restricted, not read access)
- ``AUTHLIM`` to ``256`` (maximum number of wrong authentications before "self-desctruction")
- Everything else to its default value (no lock bits are set)
- The ``public_id`` of the key set will be written to page 0x04 as a big-endian value
- The UID of the chip will be registered as a reusable medium on the server.
.. warning:: During encoding, the chip-specific key and the UID key are transmitted in plain text over the air. The
security model therefore relies on the encoding of chips being performed in a trusted physical environment
to prevent a nearby attacker from sniffing the keys with a strong antenna.
.. note:: If an attacker tries to authenticate with the chip 256 times using the wrong key, the chip will become
unusable. A chip may also become unusable if it is detached from the reader in the middle of the encoding
process (even though we've tried to implement it in a way that makes this unlikely).
Usage
-----
When a chip is presented to the NFC reader, the following steps will be taken:
- Command ``GET_VERSION`` is used to determine if it is a Mifare Ultralight AES chip (if not, abort).
- Page 0x04 is read. If it is all zeroes, the chip is considered un-encoded (abort). If it contains a value that
corresponds to the ``public_id`` of a known key set, this key set is used for all further operations. If it contains
a different value, we consider this chip to belong to a different organizer or not to a pretix system at all (abort).
- An authentication with the chip using the UID key is performed.
- The UID of the chip will be read.
- The chip-specific key will be derived using the mechanism described above in the encoding step.
- An authentication with the chip using the chip-specific key is performed. If this is fully successful, this step
proves that the chip knows the same chip-specific key as we do and is therefore an authentic chip encoded by us and
we can trust its UID value.
- The UID is transmitted to the server to fetch the correct medium.
During these steps, the keys are never transmitted in plain text and can thus not be sniffed by a nearby attacker
with a strong antenna.
.. _Mifare Ultralight AES: https://www.nxp.com/products/rfid-nfc/mifare-hf/mifare-ultralight/mifare-ultralight-aes-enhanced-security-for-limited-use-contactless-applications:MF0AESx20
.. _data sheet: https://www.nxp.com/docs/en/data-sheet/MF0AES(H)20.pdf
.. _AN10922: https://www.nxp.com/docs/en/application-note/AN10922.pdf

View File

@@ -1,10 +0,0 @@
UID-based
=========
With UID-based NFC, only the unique ID (UID) of the NFC chip is used for identification purposes.
This can be used with virtually all NFC chips that provide compatibility with the NFC reader in use, typically at least all chips that comply with ISO/IEC 14443-3A.
We make only one restriction: The UID may not start with ``08``, since that usually signifies a randomized UID that changes on every read (which would not be very useful).
.. warning:: The UID-based approach provides only a very low level of security. It is easy to clone a chip with the same
UID and impersonate someone else.

View File

@@ -58,11 +58,11 @@ If you do not have a recent installation of ``nodejs``, install it now::
To make sure it is on your path variable, close and reopen your terminal. Now, install the Python-level dependencies of pretix::
cd src/
pip3 install -e ".[dev]"
Next, you need to copy the SCSS files from the source folder to the STATIC_ROOT directory::
cd src/
python manage.py collectstatic --noinput
Then, create the local database::
@@ -96,20 +96,6 @@ http://localhost:8000/control/ for the admin view.
port (for example because you develop on `pretixdroid`_), you can check
`Django's documentation`_ for more options.
When running the local development webserver, ensure Celery is not configured
in ``pretix.cfg``. i.e., you should remove anything such as::
[celery]
backend=redis://redis:6379/2
broker=redis://redis:6379/2
If you choose to use Celery for development, you must also start a Celery worker
process::
celery -A pretix.celery_app worker -l info
However, beware that code changes will not auto-reload within Celery.
.. _`checksandtests`:
Code checks and unit tests
@@ -136,7 +122,9 @@ It is a good idea to put this command into your git hook ``.git/hooks/pre-commit
for example, to check for any errors in any staged files when committing::
#!/bin/bash
cd $GIT_DIR/../src
export GIT_WORK_TREE=../
export GIT_DIR=../.git
source ../env/bin/activate # Adjust to however you activate your virtual environment
for file in $(git diff --cached --name-only | grep -E '\.py$' | grep -Ev "migrations|mt940\.py|pretix/settings\.py|make_testdata\.py|testutils/settings\.py|tests/settings\.py|pretix/base/models/__init__\.py|.*_pb2\.py")
do
@@ -162,13 +150,6 @@ Add this to your ``src/pretix.cfg``::
Then execute ``python -m smtpd -n -c DebuggingServer localhost:1025``.
Working with periodic tasks
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Periodic tasks (like sendmail rules) are run when an external scheduler (like cron)
triggers the ``runperiodic`` command.
To run periodic tasks, execute ``python manage.py runperiodic``.
Working with translations
^^^^^^^^^^^^^^^^^^^^^^^^^
If you want to translate new strings that are not yet known to the translation system,
@@ -209,15 +190,5 @@ with the documentation a lot, you might find it useful to use sphinx-autobuild::
Then, go to http://localhost:8081 for a version of the documentation that automatically re-builds
whenever you change a source file.
Working with frontend assets
----------------------------
To update the frontend styles of shops with a custom styling, run the following commands inside
your virtual environment.::
python -m pretix collectstatic --noinput
python -m pretix updateassets
.. _Django's documentation: https://docs.djangoproject.com/en/1.11/ref/django-admin/#runserver
.. _pretixdroid: https://github.com/pretix/pretixdroid

View File

@@ -31,7 +31,7 @@ pretix/
Additional code implementing our customized :ref:`URL handling <urlconf>`.
static/
Contains all static files (CSS/SASS, JavaScript, images) of pretix' core.
Contains all static files (CSS/SASS, JavaScript, images) of pretix' core
We use libsass as a preprocessor for CSS. Our own sass code is built in the same
step as Bootstrap and FontAwesome, so their mixins etc. are fully available.
@@ -41,6 +41,6 @@ pretix/
tests/
This is the root directory for all test codes. It includes subdirectories ``api``, ``base``,
``control``, ``presale``, ``helpers``, ``multidomain`` and ``plugins`` to mirror the structure
``control``, ``presale``, ``helpers`, ``multidomain`` and ``plugins`` to mirror the structure
of the pretix source code as well as ``testdummy``, which is a pretix plugin used during
testing.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 287 KiB

After

Width:  |  Height:  |  Size: 274 KiB

View File

@@ -23,50 +23,30 @@ partition "data-based check" {
"Is the order in status PAID or PENDING\nand is the position not canceled?" --> if "" then
-right->[no] "Return error CANCELED"
else
-down->[yes] "Is one or more block set on the ticket?"
-down->[yes] "Is the product part of the check-in list?"
--> if "" then
-right->[yes] "Return error BLOCKED"
-right->[no] "Return error PRODUCT"
else
-down->[no] "Is the order in status PENDING and not yet approved?"
-down->[yes] "Is the subevent part of the check-in list?"
--> if "" then
-right->[yes] "Return error UNAPPROVED"
-right->[no] "Return error INVALID"
note bottom: TODO\ninconsistent\nwith online\ncheck
else
-down->[no] "If this is not an exit, is the valid_from/valid_until\nconstraint on the ticket fulfilled?"
-down->[yes] "Is the order in status PAID?"
--> if "" then
-right->[no] "Return error INVALID_TIME"
else
-down->[yes] "Is the product part of the check-in list?"
-right->[no] "Does the check-in list include pending orders?"
--> if "" then
-right->[no] "Return error PRODUCT"
-right->[no] "Return error UNPAID "
else
-down->[yes] "Is the subevent part of the check-in list?"
-down->[yes] "Is ignore_unpaid set?\n(Has the operator confirmed\nthe checkin?)"
--> if "" then
-right->[no] "Return error INVALID"
note bottom: TODO\ninconsistent\nwith online\ncheck
-right->[no] "Return error UNPAID "
else
-down->[yes] "Is the order in status PAID?"
--> if "" then
-right->[no] "Is Order.valid_if_pending set?"
--> if "" then
-->[yes] "Is this an entry or exit?"
else
-->[no] "Does the check-in list include pending orders?"
--> if "" then
-->[no] "Return error UNPAID "
else
-->[yes] "Is ignore_unpaid set on the request?\n(Has the operator confirmed\nthe checkin?)"
--> if "" then
-->[no] "Return error UNPAID "
else
-->[yes] "Is this an entry or exit?"
endif
endif
endif
else
-down->[yes] "Is this an entry or exit?"
endif
-down->[yes] "Is this an entry or exit?"
endif
endif
else
-down->[yes] "Is this an entry or exit?"
endif
endif
endif
@@ -118,26 +98,16 @@ partition "dataless check" {
--> if "" then
-right->[yes] "Return error REVOKED"
else
-down->[yes] "Is the ticket secret on the block list?"
-down->[no] "Is the product part of the check-in list? "
--> if "" then
-right->[yes] "Return error BLOCKED "
-right->[no] "Return error PRODUCT "
else
-down->[yes] "If this is not an exit, is the valid_from/valid_until\nconstraint on the ticket fulfilled? "
-down->[yes] "Is the subevent part of the check-in list? "
--> if "" then
-right->[no] "Return error INVALID_TIME "
-right->[no] "Return error INVALID "
note bottom: TODO\ninconsistent\nwith online\ncheck
else
-down->[no] "Is the product part of the check-in list? "
--> if "" then
-right->[no] "Return error PRODUCT "
else
-down->[yes] "Is the subevent part of the check-in list? "
--> if "" then
-right->[no] "Return error INVALID "
note bottom: TODO\ninconsistent\nwith online\ncheck
else
--> "Is this an entry or exit? "
endif
endif
--> "Is this an entry or exit? "
endif
endif
endif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 183 KiB

After

Width:  |  Height:  |  Size: 175 KiB

View File

@@ -38,51 +38,31 @@ else
endif
"Is the order in status PAID or PENDING\nand is the position not canceled?" --> if "" then
-right->[no && !force] "Return error CANCELED"
-right->[no] "Return error CANCELED"
else
-down->[yes || force] "Is one or more block set on the ticket?"
-down->[yes] "Is the product part of the check-in list?"
--> if "" then
-right->[yes && !force] "Return error BLOCKED"
-right->[no] "Return error PRODUCT"
else
-down->[no || force] "Is the order in status PENDING and not yet approved?"
-down->[yes] "Is the subevent part of the check-in list?"
--> if "" then
-right->[yes && !force] "Return error UNAPPROVED"
-right->[no] "Return error PRODUCT "
else
-down->[no || force] "If this is not an exit, is the valid_from/valid_until\nconstraint on the ticket fulfilled?"
-down->[yes] "Is the order in status PAID\nor is this a forced upload?"
--> if "" then
-right->[no && !force] "Return error INVALID_TIME"
else
-down->[yes || force] "Is the product part of the check-in list?"
-right->[no] "Does the check-in list include pending orders?"
--> if "" then
-right->[no && !force] "Return error PRODUCT"
-right->[no] "Return error UNPAID "
else
-down->[yes || force] "Is the subevent part of the check-in list?"
-down->[yes] "Is ignore_unpaid set?\n(Has the operator confirmed\nthe checkin?)"
--> if "" then
-right->[no && !force] "Return error PRODUCT "
-right->[no] "Return error UNPAID "
else
-down->[yes] "Is the order in status PAID?"
--> if "" then
-->[no] "Is Order.valid_if_pending set?"
--> if "" then
-down->[yes] "Is this an entry or exit?\nIs the upload forced?"
else
-right->[no] "Does the check-in list include pending orders?"
--> if "" then
-right->[no] "Return error UNPAID "
else
-down->[yes] "Is ignore_unpaid set on the request?\n(Has the operator confirmed\nthe checkin?)"
--> if "" then
-right->[no] "Return error UNPAID "
else
-down->[yes] "Is this an entry or exit?\nIs the upload forced?"
endif
endif
endif
else
-down->[yes || force] "Is this an entry or exit?\nIs the upload forced?"
endif
-down->[yes] "Is this an entry or exit?\nIs the upload forced?"
endif
endif
else
-down->[yes] "Is this an entry or exit?\nIs the upload forced?"
endif
endif
endif

View File

@@ -1 +1,69 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="254.156" height="109.594" version="1.1"><g transform="scale(1.9856)"><path d="M36.29 23.21c-.35 0-.61.06-.83.13v8.29c.19.06.45.13.77.13 1.73 0 2.46-1.44 2.46-4.26s-.64-4.29-2.4-4.29z" fill="#f8f8f8"/><path d="M61.22 23.15c-1.44 0-2.21 1.31-2.08 3.71l3.9-.58c.03-2.11-.58-3.14-1.82-3.14z" fill="#f8f8f8"/><path d="M127.39 17.1c.35-.03.61-.29.61-.64V.64c0-.35-.29-.64-.64-.64H75.94v2.48c0 .62-.5 1.12-1.12 1.12-.62 0-1.12-.5-1.12-1.12V0H.64C.29 0 0 .29 0 .64v15.82c0 .35.26.61.61.64 5.47.32 9.82 4.86 9.82 10.43 0 5.57-4.35 10.08-9.82 10.37-.35.03-.61.29-.61.64v15.82c0 .35.29.64.64.64h73.22-.16v-2.48c0-.63.49-1.12 1.12-1.12.63 0 1.12.5 1.12 1.12V55h-.16 51.58c.35 0 .64-.29.64-.64V38.54c0-.35-.26-.61-.61-.64-5.47-.32-9.82-4.83-9.82-10.4s4.35-10.11 9.82-10.4zM37.41 34.57c-.86 0-1.6-.1-1.95-.19v5.54H30.6v-18.5c1.31-.61 3.07-1.06 5.73-1.06 4.26 0 7.17 2.27 7.17 7.1 0 4.35-2.53 7.1-6.08 7.1zm15.58-10.78c-.9-.45-1.76-.45-2.4-.22v10.85h-4.86V21.43c1.41-.7 3.55-1.09 6.69-1.06.45 0 .93.03 1.41.06L53 23.79Zm14.56 4.26-8.03 1.12c.32 1.47 1.09 2.21 2.85 2.21 1.63 0 2.91-.35 3.68-.74l1.09 2.98c-1.22.58-2.82 1.06-5.38 1.06-4.51 0-6.88-3.04-6.88-7.17s2.21-7.1 6.53-7.1c4.35-.03 6.4 2.98 6.14 7.65zm8.38 18.56c0 .62-.5 1.12-1.12 1.12-.62 0-1.12-.5-1.12-1.12v-5.12c0-.62.5-1.12 1.12-1.12.62 0 1.12.52 1.12 1.12zm0-11.07c0 .6-.52 1.12-1.12 1.12-.6 0-1.12-.52-1.12-1.12v-5.12c0-.63.49-1.12 1.12-1.12.63 0 1.12.5 1.12 1.12zm0-11.01c0 .62-.5 1.12-1.12 1.12-.62 0-1.12-.5-1.12-1.12v-5.12c0-.62.5-1.12 1.12-1.12.62 0 1.12.52 1.12 1.12zm0-11.07c0 .6-.52 1.12-1.12 1.12-.6 0-1.12-.52-1.12-1.12V8.34c0-.63.49-1.12 1.12-1.12.63 0 1.12.5 1.12 1.12zM90.11 23.8h-2.02v6.18c0 1.02.35 1.41 1.09 1.41.35 0 .54-.06.93-.19v2.98c-.35.19-1.22.48-2.34.48-3.1 0-4.51-1.89-4.51-4.26v-6.59h-1.44v-3.17h1.44v-2.82l4.86-1.22v4.03h1.98v3.17zm7.07 10.62h-4.86V20.66h4.86zm-2.43-15.58c-1.38 0-2.5-.99-2.5-2.21s1.12-2.18 2.5-2.18 2.53.96 2.53 2.18c0 1.22-1.12 2.21-2.53 2.21zm12.35 15.58-1.76-3.81h-.06l-1.82 3.81h-4.9l4.32-7.1-3.87-6.66h5.06l1.66 3.46h.06l1.82-3.46h4.51l-4 6.37 4.38 7.42-5.41-.03z" fill="#f8f8f8"/></g></svg>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="254.15625"
height="109.59375"
viewBox="0 0 254.15625 109.59375"
version="1.1"
id="svg5"
sodipodi:docname="logo-white.svg"
inkscape:version="0.92.1 r"><metadata
id="metadata9">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1364"
inkscape:window-height="676"
id="namedview7"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="1"
inkscape:cx="56.462442"
inkscape:cy="54.796875"
inkscape:window-x="0"
inkscape:window-y="72"
inkscape:window-maximized="0"
inkscape:current-layer="svg5" />
id=&quot;svg2&quot;
version=&quot;1.1&quot;&gt;
<defs
id="defs4" />
<g
id="layer1"
transform="translate(-277.78125,-568.75)">
<path
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;enable-background:accumulate"
d="m 20,20 v 34.09375 c 11.43679,0 20.71875,9.28196 20.71875,20.71875 C 40.71875,86.24928 31.43679,95.5 20,95.5 v 34.09375 h 146.6875 v -9.5 h 3 v 9.5 H 274.15625 V 95.5 c -0.0105,2e-5 -0.0208,0 -0.0312,0 -11.43678,0 -20.71875,-9.25072 -20.71875,-20.6875 0,-11.43679 9.28197,-20.71875 20.71875,-20.71875 0.0105,0 0.0208,-2e-5 0.0312,0 V 20 H 169.6875 v 9.09375 h -3 V 20 Z m 146.6875,16.09375 h 3 v 14 h -3 z m 41.44141,12.833984 c 2.79067,0 5.02343,1.92774 5.02343,4.3125 0,2.38476 -2.23276,4.363282 -5.02343,4.363282 -2.73994,0 -4.97266,-1.978522 -4.97266,-4.363282 0,-2.38476 2.23272,-4.3125 4.97266,-4.3125 z m -13.22852,4.210938 v 8.017578 h 3.95899 v 6.291016 h -3.95899 v 12.279296 c 0,2.02959 0.71015,2.791016 2.13086,2.791016 0.71035,0 1.06703,-0.10181 1.82813,-0.40625 v 5.935547 c -0.71036,0.40591 -2.38661,0.964844 -4.61915,0.964844 -6.13949,0 -8.98046,-3.753876 -8.98046,-8.472657 V 67.447266 h -2.8418 V 61.15625 h 2.8418 V 55.574219 Z M 166.6875,57.09375 h 3 v 14 h -3 z m -74.568359,3.554688 c 8.473509,0 14.207029,4.515688 14.207029,14.105468 0,8.62573 -5.02336,14.105469 -12.07617,14.105469 -1.72514,0 -3.147072,-0.20329 -3.857422,-0.40625 V 99.414062 H 80.751953 V 62.728516 c 2.58772,-1.21775 6.090268,-2.080081 11.367188,-2.080078 z m 49.863279,0 c 8.57499,0 12.63436,5.935363 12.12696,15.220703 l -15.93165,2.234375 c 0.60888,2.94289 2.18061,4.414062 5.68165,4.414062 3.24732,0 5.78445,-0.711556 7.30664,-1.472656 l 2.13086,5.886719 c -2.38476,1.16701 -5.58034,2.080078 -10.6543,2.080078 -8.93017,0 -13.64844,-6.037993 -13.64844,-14.257813 0,-8.21981 4.41329,-14.105468 12.98828,-14.105468 z m -17.92187,0.0059 c 0.8928,0.01358 1.82795,0.04496 2.80468,0.0957 l -1.67578,6.697266 c -1.77589,-0.86257 -3.50104,-0.913692 -4.76953,-0.457032 v 21.513672 h -9.64062 v -25.77539 c 2.79702,-1.376314 7.03166,-2.16926 13.28125,-2.074219 z m 79.24804,0.501953 h 9.64063 v 27.347656 h -9.64063 z m 13.23438,0 h 10.04687 l 3.29883,6.849609 h 0.10156 l 3.60157,-6.849609 h 8.98047 l -7.96485,12.632812 8.72656,14.714844 H 232.67969 L 229.17773,80.9434 h -0.10156 l -3.65234,7.560547 h -9.74219 l 8.57422,-14.105468 z m -74.9668,5.023438 c -2.84142,0 -4.41381,2.585948 -4.10937,7.355468 l 7.76367,-1.166015 c 0,-4.16064 -1.2188,-6.189454 -3.6543,-6.189453 z m -49.507811,0.09961 c -0.71035,0 -1.219131,0.101686 -1.675781,0.253906 v 16.439453 c 0.35517,0.15221 0.863828,0.253906 1.523438,0.253906 3.4503,0 4.871093,-2.840514 4.871093,-8.421874 0,-5.733571 -1.21772,-8.525391 -4.71875,-8.525391 z M 166.6875,78.09375 h 3 v 14 h -3 z m 0,21 h 3 v 14 h -3 z"
transform="translate(257.78125,548.75)"
id="rect3888"
inkscape:connector-curvature="0" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@@ -1,4 +1,4 @@
.. spelling:word-list::
.. spelling::
AGPL
AGPLv3

View File

@@ -32,7 +32,6 @@ transactions list of objects Transactions in
├ checksum string Checksum computed from payer, reference, amount and
date
├ payer string Payment source
├ external_id string Unique ID of the payment from an external source
├ reference string Payment reference
├ amount string Payment amount
├ iban string Payment IBAN
@@ -86,7 +85,6 @@ Endpoints
"date": "26.06.2017",
"payer": "John Doe",
"order": null,
"external_id": null,
"iban": "",
"bic": "",
"checksum": "5de03a601644dfa63420dacfd285565f8375a8f2",
@@ -141,7 +139,6 @@ Endpoints
"iban": "",
"bic": "",
"order": null,
"external_id": null,
"checksum": "5de03a601644dfa63420dacfd285565f8375a8f2",
"reference": "GUTSCHRIFT\r\nSAMPLECONF-NAB12 EREF: SAMPLECONF-NAB12\r\nIBAN: DE1234556…",
"state": "nomatch",

View File

@@ -1,143 +0,0 @@
ePayBL
======
.. note::
Since ePayBL is only available to german federal, provincial and communal entities, the following page is also
only provided in german. Should you require assistance with ePayBL and do not speak this language, please feel free
reach out to support@pretix.eu.
Einführung
----------
.. note::
Sollten Sie lediglich schnell entscheiden wollen, welcher Kontierungsmodus in den Einstellungen des pretix
ePayBL-plugins gewählt werden soll, so springen Sie direkt zur Sektion :ref:`Kontierungsmodus`.
`ePayBL`_ - das ePayment-System von Bund und Länder - ist das am weitesten verbreitete Zahlungssystem für Bundes-, Länder-
sowie kommunale Aufgabenträger. Während es nur wie eines von vielen anderen Zahlungssystemen scheint, so bietet es
seinen Nutzern besondere Vorteile, wie die automatische Erfassung von Zahlungsbelegen, dem Übertragen von Buchungen in
Haushaltskassen/-systeme sowie die automatische Erfassung von Kontierungen und Steuermerkmalen.
Rein technisch gesehen ist ePayBL hierbei nicht ein eigenständiger Zahlungsdienstleister sondern nur ein eine Komponente
im komplexen System, dass die Zahlungsabwicklung für Kommunen und Behörden ist.
Im folgenden der schematische Aufbau einer Umgebung, in welcher ePayBL zum Einsatz kommt:
.. figure:: img/epaybl_flowchart.png
:class: screenshot
Quelle: Integrationshandbuch ePayBL-Konnektor, DResearch Digital Media Systems GmbH
In diesem Schaubild stellt pretix, bzw. die von Ihnen als Veranstalter angelegten Ticketshops, das Fachverfahren dar.
ePayBL stellt das Bindeglied zwischen den Fachverfahren, Haushaltssystemen und dem eigentlichen Zahlungsdienstleister,
dem sog. ZV-Provider dar. Dieser ZV-Provider ist die Stelle, welche die eigentlichen Kundengelder einzieht und an den
Händler auszahlt. Das Gros der Zahlungsdienstleister unterstützt pretix hierbei auch direkt; sprich: Sollten Sie die
Anbindung an Ihre Haushaltssysteme nicht benötigen, kann eine direkte Anbindung in der Regel ebenso - und dies bei meist
vermindertem Aufwand - vorgenommen werden.
In der Vergangenheit zeigte sich jedoch schnell, dass nicht jeder IT-Dienstleister immer sofort die neueste Version von
ePayBL seinen Nutzern angeboten hat. Die Gründe hierfür sind mannigfaltig: Von fest vorgegebenen Update-Zyklen bis hin
zu Systeme mit speziellen Anpassungen, kann leider nicht davon ausgegangen werden, dass alle ePayBL-Systeme exakt gleich
ansprechbar sind - auch wenn es sich dabei eigentlich um einen standardisierten Dienst handelt.
Aus diesem Grund gibt es mit dem ePayBL-Konnektor eine weitere Abstraktionsschicht welche optional zwischen den
Fachverfahren und dem ePayBL-Server sitzt. Dieser Konnektor wird so gepflegt, dass er zum einen eine dauerhaft
gleichartige Schnittstelle den Fachverfahren bietet aber gleichzeitig auch mit jeder Version des ePayBL-Servers
kommunizieren kann - egal wie neu oder alt, wie regulär oder angepasst diese ist.
Im Grunde müsste daher eigentlich immer gesagt werden, dass pretix eine Anbindung an den ePayBL-Konnektor bietet; nicht
an "ePayBL" oder den "ePayBL-Server". Diese Unterscheidung kann bei der Ersteinrichtung und Anforderung von Zugangsdaten
von Relevanz sein. Da in der Praxis jedoch beide Begriffe gleichbedeutend genutzt werden, wird im Folgenden auch nur von
einer ePayBL-Anbindung die Rede sein - auch wenn explizit der Konnektor gemeint ist.
.. _`Kontierungsmodus`:
Kontierungsmodus
----------------
ePayBL ist ein Produkt, welches für die Abwicklung von Online-Zahlungsvorgängen in der Verwaltung geschaffen wurde. Ein
Umfeld, in dem klar definiert ist, was ein Kunde gerade bezahlt und wohin das Geld genau fließt. Diese Annahmen lassen
sich in einem Ticketshop wie pretix jedoch nur teilweise genauso abbilden.
Die ePayBL-Integration für pretix bietet daher zwei unterschiedliche Modi an, wie Buchungen erfasst und an ePayBL und
damit auch an die dahinterliegenden Haushaltssysteme gemeldet werden können.
Kontierung pro Position/Artikel
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Dieser Modus versucht den klassischen, behördentypischen ePayBL-Zahlungsvorgang abzubilden: Jede einzelne Position, die
ein Kunde in den Warenkorb legt, wird auch genauso 1:1 an ePayBL und die Hintergrundsysteme übermittelt.
Hierbei muss zwingend auch für jede Position ein Kennzeichen für Haushaltsstelle und Objektnummer, sowie optional ein
Kontierungsobjekt (``HREF``; bspw. ``stsl=Steuerschlüssel;psp=gsb:Geschäftsbereich,auft:Innenauftrag,kst:Kostenstelle;``
) übermittelt werden.
Diese Daten sind vom Veranstalter entsprechend für jeden in der Veranstaltung angelegten Artikel innerhalb des Tabs
"Zusätzliche Einstellungen" der Produkteinstellungen zu hinterlegen.
Während diese Einstellung eine größtmögliche Menge an Kontierungsdaten überträgt und auch ein separates Verbuchen von
Leistungen auf unterschiedliche Haushaltsstellen erlaubt, so hat diese Option auch einen großen Nachteil: Der Kunde kann
nur eine Zahlung für seine Bestellung leisten.
Während sich dies nicht nach einem großen Problem anhört, so kann dies beim Kunden zu Frust führen. pretix bietet die
Option an, dass ein Veranstalter eine Bestellung jederzeit verändern kann: Ändern von Preisen von Positionen in einer
aufgegebenen Bestellung, Zubuchen und Entfernen von Bestellpositionen, etc. Hat der Kunde seine ursprüngliche Bestellung
jedoch schon bezahlt, kann pretix nicht mehr die komplette Bestellung mit den passenden Kontierungen übertragen - es
müsste nur ein Differenz-Abbild zwischen Ursprungsbestellung und aktueller Bestellung übertragen werden. Aber auch wenn
eine "Nachmeldung" möglich wäre, so wäre ein konkretes Auflösen für was jetzt genau gezahlt wird, nicht mehr möglich.
Daher gilt bei der Nutzung der Kontierung pro Position/Artikel: Der Kunde kann nur eine (erfolgreiche) Zahlung auf seine
Bestellung leisten.
Eine weitere Einschränkung dieses Modus ist, dass aktuell keine Gebühren-Positionen (Versandkosten, Zahlungs-, Storno-
oder Servicegebühren) in diesem Modus übertragen werden können. Bitte wenden Sie sich an uns, wenn Sie diese
Funktionalität benötigen.
Kontierung pro Zahlvorgang
^^^^^^^^^^^^^^^^^^^^^^^^^^
Dieser Modus verabschiedet sich vom behördlichen "Jede Position gehört genau zu einem Haushaltskonto und muss genau
zugeordnet werden". Stattdessen werden alle Bestellpositionen - inklusive eventuell definierter Gebühren - vermengt und
nur als ein großer Warenkorb, genauer gesagt: eine einzige Position an ePayBL sowie die Hintergrundsysteme gemeldet.
Während im "pro Postion/Artikel"-Modus jeder Artikel einzeln übermittelt wird und damit auch korrekt pro Artikel der
jeweilige Brutto- und Nettopreis, sowie der anfallende Steuerbetrag und ein Steuerkennzeichen (mit Hilfe des optionalen
``HREF``-Attributs) übermittelt werden, ist dies im "pro Zahlvorgang"-Modus nicht möglich.
Stattdessen übermittelt pretix nur einen Betrag für den gesamten Warenkorb: Bruttopreis == Nettopreis. Der Steuerbetrag
wird hierbei als 0 übermittelt.
Die Angabe einer Haushaltsstelle und Objektnummer, sowie optional der ``HREF``-Kontierungsinformationen ist jedoch
weiterhin notwendig - allerdings nicht mehr individuell für jeden Artikel/jede Position sondern nur für die gesamte
Bestellung. Diese Daten sind direkt in den ePayBL-Einstellungen der Veranstaltung unter Einstellungen -> Zahlung ->
ePayBL vorzunehmen
In der Praxis bedeutet dies, dass in einem angeschlossenen Haushaltssystem nicht nachvollzogen kann, welche Positionen
konkret erworben und bezahlt wurden - stattdessen kann nur der Fakt, dass etwas verkauft wurde erfasst werden.
Je nach Aufbau und Vorgaben der Finanzbuchhaltung kann dies jedoch ausreichend sein - wenn bspw. eine Ferienfahrt
angeboten wird und seitens der Haushaltssysteme nicht erfasst werden muss, wie viel vom Gesamtbetrag einer Bestellung
auf die Ferienfahrt an sich, auf einen Zubringerbus und einen Satz Bettwäsche entfallen ist, sondern (vereinfacht
gesagt) es ausreichend ist, dass "Eine Summe X für die Haushaltsstelle/Objektnummer geflossen ist".
Dieser Modus der Kontierung bietet Ihnen auch als Vorteil gegenüber dem vorhergehenden an, dass die Bestellungen der
Kunden jederzeit erweitert und verändert werden können - auch wenn die Ursprungsbestellung schon bezahlt wurde und nur
noch eine Differenz gezahlt wird.
Einschränkungen
---------------
Zum aktuellen Zeitpunkt erlaubt die pretix-Anbindung an ePayBL nicht das durchführen von Erstattungen von bereits
geleisteten Zahlungen. Der Prozess hierfür unterscheidet sich von Behörde zu Behörde und muss daher händisch
durchgeführt werden.
.. _ePayBL: https://www.epaybl.de/

View File

@@ -34,19 +34,13 @@ internal_id string Can be used for
contact_name string Contact person (or ``null``)
contact_name_parts object of strings Decomposition of contact name (i.e. given name, family name)
contact_email string Contact person email address (or ``null``)
contact_cc_email string Copy email addresses, can be multiple separated by comma (or ``null``)
booth string Booth number (or ``null``). Maximum 100 characters.
locale string Locale for communication with the exhibitor.
locale string Locale for communication with the exhibitor (or ``null``).
access_code string Access code for the exhibitor to access their data or use the lead scanning app (read-only).
lead_scanning_access_code string Access code for the exhibitor to use the lead scanning app but not access data (read-only).
allow_lead_scanning boolean Enables lead scanning app
allow_lead_access boolean Enables access to data gathered by the lead scanning app
allow_voucher_access boolean Enables access to data gathered by exhibitor vouchers
lead_scanning_scope_by_device string Enables lead scanning to be handled as one lead per attendee
per scanning device, instead of only per exhibitor.
comment string Internal comment, not shown to exhibitor
exhibitor_tags list of strings Internal tags to categorize exhibitors, not shown to exhibitor.
The tags need to be created through the web interface currently.
===================================== ========================== =======================================================
You can also access the scanned leads through the API which contains the following public fields:
@@ -68,7 +62,6 @@ data list of objects Attendee data s
except in a few cases where it contains an additional list of objects
with ``value`` and ``label`` keys (e.g. splitting of names).
device_name string User-defined name for the device used for scanning (or ``null``).
device_uuid string UUID of device used for scanning (or ``null``).
===================================== ========================== =======================================================
Endpoints
@@ -112,17 +105,13 @@ Endpoints
"title": "Dr"
},
"contact_email": "johnson@as.example.org",
"contact_cc_email": "miller@as.example.org,smith@as.example.org",
"booth": "A2",
"locale": "de",
"access_code": "VKHZ2FU84",
"lead_scanning_access_code": "WVK2B8PZ",
"lead_scanning_scope_by_device": false,
"access_code": "VKHZ2FU8",
"allow_lead_scanning": true,
"allow_lead_access": true,
"allow_voucher_access": true,
"comment": "",
"exhibitor_tags": []
"comment": ""
}
]
}
@@ -167,17 +156,13 @@ Endpoints
"title": "Dr"
},
"contact_email": "johnson@as.example.org",
"contact_cc_email": "miller@as.example.org,smith@as.example.org",
"booth": "A2",
"locale": "de",
"access_code": "VKHZ2FU84",
"lead_scanning_access_code": "WVK2B8PZ",
"lead_scanning_scope_by_device": false,
"access_code": "VKHZ2FU8",
"allow_lead_scanning": true,
"allow_lead_access": true,
"allow_voucher_access": true,
"comment": "",
"exhibitor_tags": []
"comment": ""
}
:param organizer: The ``slug`` field of the organizer to fetch
@@ -245,8 +230,7 @@ Endpoints
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/exhibitors/(id)/vouchers/
Returns a list of all vouchers connected to an exhibitor. The response contains the same data as described in
:ref:`rest-vouchers` as well as for each voucher an additional field ``exhibitor_comment`` that is shown to the exhibitor. It can only
be modified using the ``attach`` API call below.
:ref:`rest-vouchers`.
**Example request**:
@@ -301,7 +285,7 @@ Endpoints
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/exhibitors/(id)/vouchers/attach/
Attaches an **existing** voucher to an exhibitor. You need to send either the ``id`` **or** the ``code`` field of
the voucher. You can call this method multiple times to update the optional ``exhibitor_comment`` field.
the voucher.
**Example request**:
@@ -312,8 +296,7 @@ Endpoints
Accept: application/json, text/javascript
{
"id": 15,
"exhibitor_comment": "Free ticket"
"id": 15
}
**Example request**:
@@ -325,8 +308,7 @@ Endpoints
Accept: application/json, text/javascript
{
"code": "43K6LKM37FBVR2YG",
"exhibitor_comment": "Free ticket"
"code": "43K6LKM37FBVR2YG"
}
**Example response**:
@@ -372,16 +354,13 @@ Endpoints
"title": "Dr"
},
"contact_email": "johnson@as.example.org",
"contact_cc_email": "miller@as.example.org,smith@as.example.org",
"booth": "A2",
"locale": "de",
"access_code": "VKHZ2FU8",
"allow_lead_scanning": true,
"allow_lead_access": true,
"allow_voucher_access": true,
"comment": "",
"exhibitor_tags": [
"Gold Sponsor"
]
"comment": ""
}
**Example response**:
@@ -405,19 +384,13 @@ Endpoints
"title": "Dr"
},
"contact_email": "johnson@as.example.org",
"contact_cc_email": "miller@as.example.org,smith@as.example.org",
"booth": "A2",
"locale": "de",
"access_code": "VKHZ2FU84",
"lead_scanning_access_code": "WVK2B8PZ",
"lead_scanning_scope_by_device": false,
"access_code": "VKHZ2FU8",
"allow_lead_scanning": true,
"allow_lead_access": true,
"allow_voucher_access": true,
"comment": "",
"exhibitor_tags": [
"Gold Sponsor"
]
"comment": ""
}
:param organizer: The ``slug`` field of the organizer to create new exhibitor for
@@ -438,7 +411,7 @@ Endpoints
.. sourcecode:: http
PATCH /api/v1/organizers/bigevents/events/sampleconf/exhibitors/1/ HTTP/1.1
PATCH /api/v1/organizers/bigevents/events/sampleconf/digitalcontents/1/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
Content-Type: application/json
@@ -469,19 +442,13 @@ Endpoints
"title": "Dr"
},
"contact_email": "johnson@as.example.org",
"contact_cc_email": "miller@as.example.org,smith@as.example.org",
"booth": "A2",
"locale": "de",
"access_code": "VKHZ2FU84",
"lead_scanning_access_code": "WVK2B8PZ",
"lead_scanning_scope_by_device": false,
"access_code": "VKHZ2FU8",
"allow_lead_scanning": true,
"allow_lead_access": true,
"allow_voucher_access": true,
"comment": "",
"exhibitor_tags": [
"Gold Sponsor"
]
"comment": ""
}
:param organizer: The ``slug`` field of the organizer to modify
@@ -492,36 +459,6 @@ Endpoints
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event/exhibitor does not exist **or** you have no permission to change it.
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/exhibitors/(id)/send_access_code/
Sends an email to the exhibitor with their access code.
**Example request**:
.. sourcecode:: http
POST /api/v1/organizers/bigevents/events/sampleconf/exhibitors/1/send_access_code/ HTTP/1.1
Host: pretix.eu
Accept: application/json, text/javascript
**Example response**:
.. sourcecode:: http
HTTP/1.1 204 No Content
Vary: Accept
:param organizer: The ``slug`` field of the organizer to modify
:param event: The ``slug`` field of the event to modify
:param code: The ``id`` field of the exhibitor to send an email for
:statuscode 200: no error
:statuscode 400: The exhibitor does not have an email address associated
:statuscode 401: Authentication failure
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
:statuscode 404: The requested exhibitor does not exist.
:statuscode 503: The email could not be sent.
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/exhibitors/(id)/
@@ -592,7 +529,6 @@ name string Exhibitor name
booth string Booth number (or ``null``)
event object Object describing the event
├ name multi-lingual string Event name
├ end_date datetime End date of the event. After this time, the app could show a warning that the event is over.
├ imprint_url string URL to legal notice page. If not ``null``, a button in the app should link to this page.
├ privacy_url string URL to privacy notice page. If not ``null``, a button in the app should link to this page.
├ help_url string URL to help page. If not ``null``, a button in the app should link to this page.
@@ -628,7 +564,6 @@ scan_types list of objects Only used for a
"booth": "A2",
"event": {
"name": {"en": "Sample conference", "de": "Beispielkonferenz"},
"end_date": "2017-12-28T10:00:00+00:00",
"slug": "bigevents",
"imprint_url": null,
"privacy_url": null,
@@ -667,7 +602,6 @@ On the request, you should set the following properties:
* ``tags`` with the list of selected tags
* ``rating`` with the rating assigned by the exhibitor
* ``device_name`` with a user-specified name of the device used for scanning (max. 190 characters), or ``null``
* ``device_uuid`` with a auto-generated UUID of the device used for scanning, or ``null``
If you submit ``tags`` and ``rating`` to be ``null`` and ``notes`` to be ``""``, the server
responds with the previously saved information and will not delete that information. If you
@@ -702,8 +636,7 @@ The request for this looks like this:
"scan_type": "lead",
"tags": ["foo"],
"rating": 4,
"device_name": "DEV1",
"device_uuid": "d8c2ec53-d602-4a08-882d-db4cf54344a2"
"device_name": "DEV1"
}
**Example response:**
@@ -736,9 +669,7 @@ The request for this looks like this:
},
"rating": 4,
"tags": ["foo"],
"notes": "Great customer, wants our newsletter",
"device_name": "DEV1",
"device_uuid": "d8c2ec53-d602-4a08-882d-db4cf54344a2"
"notes": "Great customer, wants our newsletter"
}
:statuscode 200: No error, leads was not scanned for the first time
@@ -793,9 +724,7 @@ You can also fetch existing leads (if you are authorized to do so):
},
"rating": 4,
"tags": ["foo"],
"notes": "Great customer, wants our newsletter",
"device_name": "DEV1",
"device_uuid": "d8c2ec53-d602-4a08-882d-db4cf54344a2"
"notes": "Great customer, wants our newsletter"
}
]
}

View File

@@ -1,105 +0,0 @@
GetYourGuide
============
.. note::
The GetYourGuide integration is currently in Beta. Please contact support@pretix.eu to enable the integration
for your pretix.eu organizer account.
Introduction
------------
Using third party aggregators, such als GetYourGuide, event organizers can sell tickets to their events not only on
their own ticket-shop but also on the aggregator's portal. While this service is not for free, it allows event
organizers to reacher a larger audience that would otherwise not have found their way into the organizers webshop.
Using pretix' integration with GetYourGuide, event organizers can profit from an additional sales and revenue channel,
while keeping the effort for setting up and maintaining multiple ticket shops to a minimum.
Preparing your organizer account
--------------------------------
The first step in enabling the GetYourGuide integration, is to setup a corresponding Sales Channel, which will be used
to properly attribute the sales generated. This needs to be done only once per organizer account.
To do so, log into the pretix backend, select ``Organizers`` from the navigation and then the organizer in question.
Extending the ``Settings``-menu, find the ``Sales channels`` configuration and click the ``Add a new channel`` button.
On the following page, you will be able to select ``GetYourGuide`` as the sales channel type and give it a custom name.
Preparing your event
--------------------
In order to now sell your events on GetYourGuide, you will need to configure each event in question.
1. Enabling the plugin
Within your event, extend the ``Settings`` menu and navigate to ``Plugins``. Activate the plugin in the
``Integrations`` tab.
2. Sell the event on the sales channel
Pick the sales channel or channels, on which you would like to sell your event by navigating to the event's general
settings page using the ``Sell on all sales channels`` or ``Restrict to specific sales channels`` checkboxes.
3. Configure one or more products to be sold on GetYourGuide
Either create a new or edit an existing product, that you would like to sell on GetYourGuide. To do so, you will
need to have checked the ``Sell on all sales channels`` or appropriate ``Restrict to specific sales channels``
checkbox of the product within it's ``Availability`` tab.
In addition, you will also need to set the GetYourGuide equivalent ticket category in the product's accordingly
named settings tab. Within your event, there can be only one product per ticket category. Depending on your further
configuration, you must at least select one product to be in the ``Adult`` or ``Group`` category.
4. Configuring the GetYourGuide-plugin
Once you have configured one or more products to be eligible to be sold on GetYourGuide, you'll need to configure a
few basic settings within the event (``Settings`` --> ``GetYourGuide``). The most important settings can be found
the in the ``Configuration`` tab, such as the location of the event on sale.
Ticket Categories
-----------------
While pretix only uses the ticket category term loosely to group together multiple products for nicer display,
GetYourGuide is relying on the ticket categories to price the tickets.
First of all, you need to make the decision on how you are planning on selling your tickets on GetYourGuide - in most
cases, this will reflect your current sales strategy within your pretix shop.
- Individual tickets
Every single person attending will need to purchase their own ticket. A family of two adults and two
children will have to purchase and pay for a total of 4 tickets.
In this case, you will need to offer *at least* a ticket of the ``Adult`` type, but may offer any other ticket
category type (Child, Youth, Senior, ...) in addition. But you cannot offer a ``Group`` ticket.
- Group tickets
Two groups, consisting of 10 and 20 participants respectively, won't need to purchase a total of 30 tickets, but
rather two group tickets. It is up to you to configure the group size limits within the GetYourGuide-settings of your
product.
Choosing this option, you cannot offer any other ticket categories besides ``Group``.
Setting up event dates and quotas
---------------------------------
Of course, in addition to creating products, you will also need to add them to a quota for them to be available for
sale. The process for doing this is the very same as for any regular event or event series.
.. note::
When selling individual tickets through GetYourGuide, you will not be able to offer differing quantities for
individual ticket categories.
For this reason, we recommend to place all GetYourGuide-eligible products into the same quota. Should you however opt
to create multiple quotas which create an imbalance, pretix will report only the available number of tickets for the
lowest relevant quota.
Connecting your event to GetYourGuide
-------------------------------------
Once you have set up your event and products and performed all necessary configuration, you may want to use the
Analyzer-feature of our GetYourGuide-plugin (``Settings`` -> ``GetYourGuide`` -> tab ``Analyzer``).
The Analyzer should not display any blocking error messages and at least one event date that is ready for publishing on
the GetYourGuide platform.
At this point, you will need to setup your event (called ``product`` in the GetYourGuide universe) on their
`Supplier Portal`_ and connect it with your pretix shop. To do so, please follow the
`Connecting a new product to your Reservation System`_ on the GetYourGuide Supply Partner Help Center.
Select ``pretix.eu`` as your reservation system; the required ``product ID`` can be found in the ``Configuration`` tab
of the GetYourGuide plugin settings page.
From this point on, GetYourGuide will automatically import the availabilities and products and offer them for sale.
.. _Supplier Portal: https://suppliers.getyourguide.com/
.. _Connecting a new product to your Reservation System: https://supply.getyourguide.support/hc/en-us/articles/18008029689373-Connecting-a-new-product-to-your-Reservation-system

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

View File

@@ -18,11 +18,8 @@ If you want to **create** a plugin, please go to the
campaigns
certificates
digital
epaybl
exhibitors
shipping
imported_secrets
webinar
presale-saml
kulturpass
getyourguide

Some files were not shown because too many files have changed in this diff Show More