Booking substitution
The log: who did what, when and through which channel.
GET/api/event/booking_substitution_log
Query parameters
idstring | |
actionstring | |
channelstring | |
substitutionstring | |
bookingstring | |
eventstring | |
actorPersonstring | |
fromPersonstring | |
toPersonstring | |
slotstring | |
createdstring | |
searchStringstring | text to search for in the list |
orderFieldNamestring | name of the order field |
orderFieldSortstring | sorting modeAllowed: DESCASC |
pageinteger | page of the list |
pageSizeinteger | number of entries for each page |
withMaxPageNumberstring | returns the number of pages available as a header if this is set |
Responses
200Returns a list of EventBookingSubstitutionLog objects, newest firstarray<EventBookingSubstitutionLog>
Show fields (12)
substitution_idintegerbooking_idintegeridintegerPrimary key of the log entry. Internal ID.
booking_labelstringLabel of the booking at the time of the entry.
slotintegerSlot of the substitution, for example the position in the list.
actionstringAction that was logged, for example claimed or filled.
actor_namestringName of the acting person or user at the time, or the system user.
channelstringChannel of the action, for example app or e-mail.
from_statestringState before the change.
to_statestringState after the change.
messagestringMessage written with the entry.
createdstring (date-time)Time the entry was logged.
curl --request GET \
--url https://your-instance.iw-erp.de/api/event/booking_substitution_log \
--header 'x-iw-jwt-token: <TOKEN>'const options = {method: 'GET', headers: {'x-iw-jwt-token': '<TOKEN>'}};
fetch('https://your-instance.iw-erp.de/api/event/booking_substitution_log', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://your-instance.iw-erp.de/api/event/booking_substitution_log"
headers = {"x-iw-jwt-token": "<TOKEN>"}
response = requests.get(url, headers=headers)
print(response.text)<?php
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://your-instance.iw-erp.de/api/event/booking_substitution_log', [
'headers' => [
'x-iw-jwt-token' => '<TOKEN>',
],
]);
echo $response->getBody();using System.Net.Http.Headers;
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("https://your-instance.iw-erp.de/api/event/booking_substitution_log"),
Headers =
{
{ "x-iw-jwt-token", "<TOKEN>" },
},
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://your-instance.iw-erp.de/api/event/booking_substitution_log")
.get()
.addHeader("x-iw-jwt-token", "<TOKEN>")
.build();
Response response = client.newCall(request).execute();package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://your-instance.iw-erp.de/api/event/booking_substitution_log"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-iw-jwt-token", "<TOKEN>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}Dart with the iw_erp_api package
import 'package:iw_erp_api/clients/event_booking_substitution_controller.dart';
import 'package:iw_erp_api/logic/iw_api_state.dart';
IwApiState().host = 'your-instance.iw-erp.de';
IwApiState().currentJwtApiToken = '<TOKEN>';
final result = await EventBookingSubstitutionController.getLog();
if (result.success) {
print(result.data);
}[
{
"id": 42,
"actor_name": "Beispiel",
"substitution_id": 42,
"booking_id": 42,
"booking_label": "string",
"slot": 1,
"action": "string",
"channel": "string",
"from_state": "string",
"to_state": "string"
}
]All substitutions; default order by appointment start.
GET/api/event/booking_substitution
Query parameters
idstring | |
statestring | |
reasonstring | |
slotstring | 1 = main trainer (performingPerson), 2 = secondary ... 5 = fifth. |
bookingstring | |
eventstring | |
originalPersonstring | |
candidatePersonstring | Who requested or took the slot, or whom the office assigned. |
bookingStartstring | Copy of the appointment start: list ordering and filters without a join, and the history stays readable after the appointment is gone. |
filledViastring | |
qualificationSourcestring | |
sourceTicketstring | |
sourceNonWorkTimeRequeststring | |
createdstring | |
updatedstring | |
searchStringstring | text to search for in the list |
orderFieldNamestring | name of the order field |
orderFieldSortstring | sorting modeAllowed: DESCASC |
pageinteger | page of the list |
pageSizeinteger | number of entries for each page |
withMaxPageNumberstring | returns the number of pages available as a header if this is set |
Responses
200Returns a list of EventBookingSubstitution objectsarray<EventBookingSubstitution>
Show fields (24)
booking_idintegersource_ticket_idintegersource_non_work_time_request_idintegeridintegerPrimary key of the substitution. Internal ID.
lock_versionintegerVersion used to prevent parallel changes to the substitution.
booking_startstring (date-time)Copy of the appointment start: list ordering and filters without a join, and the history stays readable after the appointment is gone.
booking_endstring (date-time)End of the booking that needs a substitute.
booking_labelstringName and start of the appointment at creation, for the history.
slotinteger1 = main trainer (performingPerson), 2 = secondary ... 5 = fifth.
reasonstringReason for the substitution, for example illness.
statestringState of the substitution, for example open, claimed or filled.
qualification_match_modestringHow the qualifications of substitutes are matched.
qualification_sourcestringSource of the qualifications used to find substitutes.
filled_viastringHow the substitution was filled, for example by a trainer or by staff.
claimed_atstring (date-time)Time the substitution was claimed.
filled_atstring (date-time)Time the substitution was filled.
decided_atstring (date-time)Time the substitution was decided.
decided_by_usernamestringLogin name of the person who decided the substitution.
decision_notestringNote on the decision.
closed_atstring (date-time)Time the substitution was closed.
notified_atstring (date-time)Time the possible substitutes were last notified.
notified_countintegerNumber of possible substitutes that were notified.
createdstring (date-time)Point in time the entity was created.
updatedstring (date-time)Point in time the entity was last updated.
curl --request GET \
--url https://your-instance.iw-erp.de/api/event/booking_substitution \
--header 'x-iw-jwt-token: <TOKEN>'const options = {method: 'GET', headers: {'x-iw-jwt-token': '<TOKEN>'}};
fetch('https://your-instance.iw-erp.de/api/event/booking_substitution', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://your-instance.iw-erp.de/api/event/booking_substitution"
headers = {"x-iw-jwt-token": "<TOKEN>"}
response = requests.get(url, headers=headers)
print(response.text)<?php
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://your-instance.iw-erp.de/api/event/booking_substitution', [
'headers' => [
'x-iw-jwt-token' => '<TOKEN>',
],
]);
echo $response->getBody();using System.Net.Http.Headers;
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("https://your-instance.iw-erp.de/api/event/booking_substitution"),
Headers =
{
{ "x-iw-jwt-token", "<TOKEN>" },
},
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://your-instance.iw-erp.de/api/event/booking_substitution")
.get()
.addHeader("x-iw-jwt-token", "<TOKEN>")
.build();
Response response = client.newCall(request).execute();package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://your-instance.iw-erp.de/api/event/booking_substitution"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-iw-jwt-token", "<TOKEN>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}Dart with the iw_erp_api package
import 'package:iw_erp_api/clients/event_booking_substitution_controller.dart';
import 'package:iw_erp_api/logic/iw_api_state.dart';
IwApiState().host = 'your-instance.iw-erp.de';
IwApiState().currentJwtApiToken = '<TOKEN>';
final result = await EventBookingSubstitutionController.getAll();
if (result.success) {
print(result.data);
}[
{
"id": 42,
"decided_by_username": "lena.hartmann@example.org",
"booking_id": 42,
"source_ticket_id": 42,
"source_non_work_time_request_id": 42,
"lock_version": 1,
"booking_start": "2026-10-15T09:30:00+02:00",
"booking_end": "2026-10-15T09:30:00+02:00",
"booking_label": "string",
"slot": 1
}
]Look for a substitute for one slot of an appointment. A person still in the slot is taken out and becomes the original trainer.
POST/api/event/booking_substitution
Request body application/json
bookingintegerslotintegernotestring
Responses
200The opened substitutionEventBookingSubstitution
Show fields (24)
booking_idintegersource_ticket_idintegersource_non_work_time_request_idintegeridintegerPrimary key of the substitution. Internal ID.
lock_versionintegerVersion used to prevent parallel changes to the substitution.
booking_startstring (date-time)Copy of the appointment start: list ordering and filters without a join, and the history stays readable after the appointment is gone.
booking_endstring (date-time)End of the booking that needs a substitute.
booking_labelstringName and start of the appointment at creation, for the history.
slotinteger1 = main trainer (performingPerson), 2 = secondary ... 5 = fifth.
reasonstringReason for the substitution, for example illness.
statestringState of the substitution, for example open, claimed or filled.
qualification_match_modestringHow the qualifications of substitutes are matched.
qualification_sourcestringSource of the qualifications used to find substitutes.
filled_viastringHow the substitution was filled, for example by a trainer or by staff.
claimed_atstring (date-time)Time the substitution was claimed.
filled_atstring (date-time)Time the substitution was filled.
decided_atstring (date-time)Time the substitution was decided.
decided_by_usernamestringLogin name of the person who decided the substitution.
decision_notestringNote on the decision.
closed_atstring (date-time)Time the substitution was closed.
notified_atstring (date-time)Time the possible substitutes were last notified.
notified_countintegerNumber of possible substitutes that were notified.
createdstring (date-time)Point in time the entity was created.
updatedstring (date-time)Point in time the entity was last updated.
curl --request POST \
--url https://your-instance.iw-erp.de/api/event/booking_substitution \
--header 'content-type: application/json' \
--header 'x-iw-jwt-token: <TOKEN>' \
--data '
{
"booking": 1,
"slot": 1,
"note": "string"
}
'const options = {
method: 'POST',
headers: {'x-iw-jwt-token': '<TOKEN>', 'content-type': 'application/json'},
body: JSON.stringify({booking: 1, slot: 1, note: 'string'})
};
fetch('https://your-instance.iw-erp.de/api/event/booking_substitution', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://your-instance.iw-erp.de/api/event/booking_substitution"
payload = {
"booking": 1,
"slot": 1,
"note": "string"
}
headers = {
"x-iw-jwt-token": "<TOKEN>",
"content-type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)<?php
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', 'https://your-instance.iw-erp.de/api/event/booking_substitution', [
'body' => '{"booking":1,"slot":1,"note":"string"}',
'headers' => [
'content-type' => 'application/json',
'x-iw-jwt-token' => '<TOKEN>',
],
]);
echo $response->getBody();using System.Net.Http.Headers;
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://your-instance.iw-erp.de/api/event/booking_substitution"),
Headers =
{
{ "x-iw-jwt-token", "<TOKEN>" },
},
Content = new StringContent("{\"booking\":1,\"slot\":1,\"note\":\"string\"}")
{
Headers =
{
ContentType = new MediaTypeHeaderValue("application/json")
}
}
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\"booking\":1,\"slot\":1,\"note\":\"string\"}");
Request request = new Request.Builder()
.url("https://your-instance.iw-erp.de/api/event/booking_substitution")
.post(body)
.addHeader("x-iw-jwt-token", "<TOKEN>")
.addHeader("content-type", "application/json")
.build();
Response response = client.newCall(request).execute();package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://your-instance.iw-erp.de/api/event/booking_substitution"
payload := strings.NewReader("{\"booking\":1,\"slot\":1,\"note\":\"string\"}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-iw-jwt-token", "<TOKEN>")
req.Header.Add("content-type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}Dart with the iw_erp_api package
import 'package:iw_erp_api/clients/event_booking_substitution_controller.dart';
import 'package:iw_erp_api/logic/iw_api_state.dart';
IwApiState().host = 'your-instance.iw-erp.de';
IwApiState().currentJwtApiToken = '<TOKEN>';
final result = await EventBookingSubstitutionController.open(bookingId: 42);
if (result.success) {
print(result.data);
}{
"id": 42,
"decided_by_username": "lena.hartmann@example.org",
"booking_id": 42,
"source_ticket_id": 42,
"source_non_work_time_request_id": 42,
"lock_version": 1,
"booking_start": "2026-10-15T09:30:00+02:00",
"booking_end": "2026-10-15T09:30:00+02:00",
"booking_label": "string",
"slot": 1
}Returns a single event booking substitution entry.
GET/api/event/booking_substitution/{id}
Path parameters
idrequiredstring |
Responses
200Returns a single EventBookingSubstitutionEventBookingSubstitution
Show fields (24)
booking_idintegersource_ticket_idintegersource_non_work_time_request_idintegeridintegerPrimary key of the substitution. Internal ID.
lock_versionintegerVersion used to prevent parallel changes to the substitution.
booking_startstring (date-time)Copy of the appointment start: list ordering and filters without a join, and the history stays readable after the appointment is gone.
booking_endstring (date-time)End of the booking that needs a substitute.
booking_labelstringName and start of the appointment at creation, for the history.
slotinteger1 = main trainer (performingPerson), 2 = secondary ... 5 = fifth.
reasonstringReason for the substitution, for example illness.
statestringState of the substitution, for example open, claimed or filled.
qualification_match_modestringHow the qualifications of substitutes are matched.
qualification_sourcestringSource of the qualifications used to find substitutes.
filled_viastringHow the substitution was filled, for example by a trainer or by staff.
claimed_atstring (date-time)Time the substitution was claimed.
filled_atstring (date-time)Time the substitution was filled.
decided_atstring (date-time)Time the substitution was decided.
decided_by_usernamestringLogin name of the person who decided the substitution.
decision_notestringNote on the decision.
closed_atstring (date-time)Time the substitution was closed.
notified_atstring (date-time)Time the possible substitutes were last notified.
notified_countintegerNumber of possible substitutes that were notified.
createdstring (date-time)Point in time the entity was created.
updatedstring (date-time)Point in time the entity was last updated.
curl --request GET \
--url https://your-instance.iw-erp.de/api/event/booking_substitution/42 \
--header 'x-iw-jwt-token: <TOKEN>'const options = {method: 'GET', headers: {'x-iw-jwt-token': '<TOKEN>'}};
fetch('https://your-instance.iw-erp.de/api/event/booking_substitution/42', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://your-instance.iw-erp.de/api/event/booking_substitution/42"
headers = {"x-iw-jwt-token": "<TOKEN>"}
response = requests.get(url, headers=headers)
print(response.text)<?php
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://your-instance.iw-erp.de/api/event/booking_substitution/42', [
'headers' => [
'x-iw-jwt-token' => '<TOKEN>',
],
]);
echo $response->getBody();using System.Net.Http.Headers;
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("https://your-instance.iw-erp.de/api/event/booking_substitution/42"),
Headers =
{
{ "x-iw-jwt-token", "<TOKEN>" },
},
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://your-instance.iw-erp.de/api/event/booking_substitution/42")
.get()
.addHeader("x-iw-jwt-token", "<TOKEN>")
.build();
Response response = client.newCall(request).execute();package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://your-instance.iw-erp.de/api/event/booking_substitution/42"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-iw-jwt-token", "<TOKEN>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}Dart with the iw_erp_api package
import 'package:iw_erp_api/clients/event_booking_substitution_controller.dart';
import 'package:iw_erp_api/logic/iw_api_state.dart';
IwApiState().host = 'your-instance.iw-erp.de';
IwApiState().currentJwtApiToken = '<TOKEN>';
final result = await EventBookingSubstitutionController.get('42');
if (result.success) {
print(result.data);
}{
"id": 42,
"decided_by_username": "lena.hartmann@example.org",
"booking_id": 42,
"source_ticket_id": 42,
"source_non_work_time_request_id": 42,
"lock_version": 1,
"booking_start": "2026-10-15T09:30:00+02:00",
"booking_end": "2026-10-15T09:30:00+02:00",
"booking_label": "string",
"slot": 1
}Every pool member with the reasons that would block them, eligible ones first. The office may assign people with reasons, too, with a note.
GET/api/event/booking_substitution/{id}/candidates
Path parameters
idrequiredstring |
Query parameters
onlyEligibleboolean |
Responses
200List of {person, eligible, reasons}
curl --request GET \
--url https://your-instance.iw-erp.de/api/event/booking_substitution/42/candidates \
--header 'x-iw-jwt-token: <TOKEN>'const options = {method: 'GET', headers: {'x-iw-jwt-token': '<TOKEN>'}};
fetch('https://your-instance.iw-erp.de/api/event/booking_substitution/42/candidates', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://your-instance.iw-erp.de/api/event/booking_substitution/42/candidates"
headers = {"x-iw-jwt-token": "<TOKEN>"}
response = requests.get(url, headers=headers)
print(response.text)<?php
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://your-instance.iw-erp.de/api/event/booking_substitution/42/candidates', [
'headers' => [
'x-iw-jwt-token' => '<TOKEN>',
],
]);
echo $response->getBody();using System.Net.Http.Headers;
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("https://your-instance.iw-erp.de/api/event/booking_substitution/42/candidates"),
Headers =
{
{ "x-iw-jwt-token", "<TOKEN>" },
},
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://your-instance.iw-erp.de/api/event/booking_substitution/42/candidates")
.get()
.addHeader("x-iw-jwt-token", "<TOKEN>")
.build();
Response response = client.newCall(request).execute();package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://your-instance.iw-erp.de/api/event/booking_substitution/42/candidates"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-iw-jwt-token", "<TOKEN>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}Dart with the iw_erp_api package
import 'package:iw_erp_api/clients/event_booking_substitution_controller.dart';
import 'package:iw_erp_api/logic/iw_api_state.dart';
IwApiState().host = 'your-instance.iw-erp.de';
IwApiState().currentJwtApiToken = '<TOKEN>';
final result = await EventBookingSubstitutionController.getCandidates(42);
if (result.success) {
print(result.data);
}Eligibility of one person (e.g. before assigning somebody outside the pool).
GET/api/event/booking_substitution/{id}/test_person
Path parameters
idrequiredstring |
Query parameters
personrequiredinteger |
Responses
200eligible and reason codes
curl --request GET \
--url 'https://your-instance.iw-erp.de/api/event/booking_substitution/42/test_person?person=1' \
--header 'x-iw-jwt-token: <TOKEN>'const options = {method: 'GET', headers: {'x-iw-jwt-token': '<TOKEN>'}};
fetch('https://your-instance.iw-erp.de/api/event/booking_substitution/42/test_person?person=1', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://your-instance.iw-erp.de/api/event/booking_substitution/42/test_person?person=1"
headers = {"x-iw-jwt-token": "<TOKEN>"}
response = requests.get(url, headers=headers)
print(response.text)<?php
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://your-instance.iw-erp.de/api/event/booking_substitution/42/test_person?person=1', [
'headers' => [
'x-iw-jwt-token' => '<TOKEN>',
],
]);
echo $response->getBody();using System.Net.Http.Headers;
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("https://your-instance.iw-erp.de/api/event/booking_substitution/42/test_person?person=1"),
Headers =
{
{ "x-iw-jwt-token", "<TOKEN>" },
},
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://your-instance.iw-erp.de/api/event/booking_substitution/42/test_person?person=1")
.get()
.addHeader("x-iw-jwt-token", "<TOKEN>")
.build();
Response response = client.newCall(request).execute();package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://your-instance.iw-erp.de/api/event/booking_substitution/42/test_person?person=1"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-iw-jwt-token", "<TOKEN>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}Dart with the iw_erp_api package
import 'package:iw_erp_api/clients/event_booking_substitution_controller.dart';
import 'package:iw_erp_api/logic/iw_api_state.dart';
IwApiState().host = 'your-instance.iw-erp.de';
IwApiState().currentJwtApiToken = '<TOKEN>';
final result = await EventBookingSubstitutionController.testPerson(42, 42);
if (result.success) {
print(result.data);
}approve, decline (note), assign (person, note), cancel (note), reopen (note), notify (push to the matching trainers again).
PUT/api/event/booking_substitution/{id}/{action}
Path parameters
idrequiredstring | |
actionrequiredstring |
Query parameters
lock_versioninteger |
Request body application/json
personintegernotestring
Responses
200The substitution after the actionEventBookingSubstitution
Show fields (24)
booking_idintegersource_ticket_idintegersource_non_work_time_request_idintegeridintegerPrimary key of the substitution. Internal ID.
lock_versionintegerVersion used to prevent parallel changes to the substitution.
booking_startstring (date-time)Copy of the appointment start: list ordering and filters without a join, and the history stays readable after the appointment is gone.
booking_endstring (date-time)End of the booking that needs a substitute.
booking_labelstringName and start of the appointment at creation, for the history.
slotinteger1 = main trainer (performingPerson), 2 = secondary ... 5 = fifth.
reasonstringReason for the substitution, for example illness.
statestringState of the substitution, for example open, claimed or filled.
qualification_match_modestringHow the qualifications of substitutes are matched.
qualification_sourcestringSource of the qualifications used to find substitutes.
filled_viastringHow the substitution was filled, for example by a trainer or by staff.
claimed_atstring (date-time)Time the substitution was claimed.
filled_atstring (date-time)Time the substitution was filled.
decided_atstring (date-time)Time the substitution was decided.
decided_by_usernamestringLogin name of the person who decided the substitution.
decision_notestringNote on the decision.
closed_atstring (date-time)Time the substitution was closed.
notified_atstring (date-time)Time the possible substitutes were last notified.
notified_countintegerNumber of possible substitutes that were notified.
createdstring (date-time)Point in time the entity was created.
updatedstring (date-time)Point in time the entity was last updated.
curl --request PUT \
--url https://your-instance.iw-erp.de/api/event/booking_substitution/42/42 \
--header 'content-type: application/json' \
--header 'x-iw-jwt-token: <TOKEN>' \
--data '
{
"person": 1,
"note": "string"
}
'const options = {
method: 'PUT',
headers: {'x-iw-jwt-token': '<TOKEN>', 'content-type': 'application/json'},
body: JSON.stringify({person: 1, note: 'string'})
};
fetch('https://your-instance.iw-erp.de/api/event/booking_substitution/42/42', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://your-instance.iw-erp.de/api/event/booking_substitution/42/42"
payload = {
"person": 1,
"note": "string"
}
headers = {
"x-iw-jwt-token": "<TOKEN>",
"content-type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)<?php
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$response = $client->request('PUT', 'https://your-instance.iw-erp.de/api/event/booking_substitution/42/42', [
'body' => '{"person":1,"note":"string"}',
'headers' => [
'content-type' => 'application/json',
'x-iw-jwt-token' => '<TOKEN>',
],
]);
echo $response->getBody();using System.Net.Http.Headers;
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Put,
RequestUri = new Uri("https://your-instance.iw-erp.de/api/event/booking_substitution/42/42"),
Headers =
{
{ "x-iw-jwt-token", "<TOKEN>" },
},
Content = new StringContent("{\"person\":1,\"note\":\"string\"}")
{
Headers =
{
ContentType = new MediaTypeHeaderValue("application/json")
}
}
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\"person\":1,\"note\":\"string\"}");
Request request = new Request.Builder()
.url("https://your-instance.iw-erp.de/api/event/booking_substitution/42/42")
.put(body)
.addHeader("x-iw-jwt-token", "<TOKEN>")
.addHeader("content-type", "application/json")
.build();
Response response = client.newCall(request).execute();package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://your-instance.iw-erp.de/api/event/booking_substitution/42/42"
payload := strings.NewReader("{\"person\":1,\"note\":\"string\"}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("x-iw-jwt-token", "<TOKEN>")
req.Header.Add("content-type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}Dart with the iw_erp_api package
import 'package:iw_erp_api/clients/event_booking_substitution_controller.dart';
import 'package:iw_erp_api/logic/iw_api_state.dart';
import 'package:iw_erp_api/model/event_booking_substitution.dart';
IwApiState().host = 'your-instance.iw-erp.de';
IwApiState().currentJwtApiToken = '<TOKEN>';
final result = await EventBookingSubstitutionController.action(EventBookingSubstitution.fromJson({
"person": 1,
"note": "string"
}), '42');
if (result.success) {
print(result.data);
}{
"id": 42,
"decided_by_username": "lena.hartmann@example.org",
"booking_id": 42,
"source_ticket_id": 42,
"source_non_work_time_request_id": 42,
"lock_version": 1,
"booking_start": "2026-10-15T09:30:00+02:00",
"booking_end": "2026-10-15T09:30:00+02:00",
"booking_label": "string",
"slot": 1
}approve, decline (note), assign (person, note), cancel (note), reopen (note), notify (push to the matching trainers again).
PATCH/api/event/booking_substitution/{id}/{action}
Path parameters
idrequiredstring | |
actionrequiredstring |
Query parameters
lock_versioninteger |
Request body application/json
personintegernotestring
Responses
200The substitution after the actionEventBookingSubstitution
Show fields (24)
booking_idintegersource_ticket_idintegersource_non_work_time_request_idintegeridintegerPrimary key of the substitution. Internal ID.
lock_versionintegerVersion used to prevent parallel changes to the substitution.
booking_startstring (date-time)Copy of the appointment start: list ordering and filters without a join, and the history stays readable after the appointment is gone.
booking_endstring (date-time)End of the booking that needs a substitute.
booking_labelstringName and start of the appointment at creation, for the history.
slotinteger1 = main trainer (performingPerson), 2 = secondary ... 5 = fifth.
reasonstringReason for the substitution, for example illness.
statestringState of the substitution, for example open, claimed or filled.
qualification_match_modestringHow the qualifications of substitutes are matched.
qualification_sourcestringSource of the qualifications used to find substitutes.
filled_viastringHow the substitution was filled, for example by a trainer or by staff.
claimed_atstring (date-time)Time the substitution was claimed.
filled_atstring (date-time)Time the substitution was filled.
decided_atstring (date-time)Time the substitution was decided.
decided_by_usernamestringLogin name of the person who decided the substitution.
decision_notestringNote on the decision.
closed_atstring (date-time)Time the substitution was closed.
notified_atstring (date-time)Time the possible substitutes were last notified.
notified_countintegerNumber of possible substitutes that were notified.
createdstring (date-time)Point in time the entity was created.
updatedstring (date-time)Point in time the entity was last updated.
curl --request PATCH \
--url https://your-instance.iw-erp.de/api/event/booking_substitution/42/42 \
--header 'content-type: application/json' \
--header 'x-iw-jwt-token: <TOKEN>' \
--data '
{
"person": 1,
"note": "string"
}
'const options = {
method: 'PATCH',
headers: {'x-iw-jwt-token': '<TOKEN>', 'content-type': 'application/json'},
body: JSON.stringify({person: 1, note: 'string'})
};
fetch('https://your-instance.iw-erp.de/api/event/booking_substitution/42/42', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://your-instance.iw-erp.de/api/event/booking_substitution/42/42"
payload = {
"person": 1,
"note": "string"
}
headers = {
"x-iw-jwt-token": "<TOKEN>",
"content-type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)<?php
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$response = $client->request('PATCH', 'https://your-instance.iw-erp.de/api/event/booking_substitution/42/42', [
'body' => '{"person":1,"note":"string"}',
'headers' => [
'content-type' => 'application/json',
'x-iw-jwt-token' => '<TOKEN>',
],
]);
echo $response->getBody();using System.Net.Http.Headers;
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Patch,
RequestUri = new Uri("https://your-instance.iw-erp.de/api/event/booking_substitution/42/42"),
Headers =
{
{ "x-iw-jwt-token", "<TOKEN>" },
},
Content = new StringContent("{\"person\":1,\"note\":\"string\"}")
{
Headers =
{
ContentType = new MediaTypeHeaderValue("application/json")
}
}
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\"person\":1,\"note\":\"string\"}");
Request request = new Request.Builder()
.url("https://your-instance.iw-erp.de/api/event/booking_substitution/42/42")
.patch(body)
.addHeader("x-iw-jwt-token", "<TOKEN>")
.addHeader("content-type", "application/json")
.build();
Response response = client.newCall(request).execute();package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://your-instance.iw-erp.de/api/event/booking_substitution/42/42"
payload := strings.NewReader("{\"person\":1,\"note\":\"string\"}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("x-iw-jwt-token", "<TOKEN>")
req.Header.Add("content-type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}Dart with package:http (no controller in the iw_erp_api package)
import 'dart:convert';
import 'package:http/http.dart' as http;
final response = await http.patch(
Uri.parse('https://your-instance.iw-erp.de/api/event/booking_substitution/42/42'),
headers: {'x-iw-jwt-token': '<TOKEN>', 'content-type': 'application/json'},
body: jsonEncode({
"person": 1,
"note": "string"
}),
);
print(response.body);{
"id": 42,
"decided_by_username": "lena.hartmann@example.org",
"booking_id": 42,
"source_ticket_id": 42,
"source_non_work_time_request_id": 42,
"lock_version": 1,
"booking_start": "2026-10-15T09:30:00+02:00",
"booking_end": "2026-10-15T09:30:00+02:00",
"booking_label": "string",
"slot": 1
}