Introduction
REST API for the Flexxr staffing platform. Manage employees, organizations, jobs, shifts, and more.
## Welcome to the Flexxr API
This documentation provides everything you need to integrate with the Flexxr staffing platform.
### Base URL
All API endpoints are prefixed with `/api/v1`.
### Authentication
Most endpoints require a **Bearer token** obtained via the login endpoint for your guard:
- **Mobile users (employees)**: `POST /api/v1/mobile/auth/login`
- **Organizations (companies)**: `POST /api/v1/org/auth/login`
- **Admins**: `POST /api/v1/admin/auth/login`
Include the token in the `Authorization` header: `Bearer {YOUR_TOKEN}`
### Organization Status Requirements
Organization accounts have status states:
- `pending_verification` — Awaiting admin KYC review
- `active` — Verified and can access all features
- `suspended` — Temporarily blocked
- `rejected` — Application rejected
Pending organizations can only access profile, notifications, and security endpoints. All other endpoints (dashboard, team, jobs, shifts) require `active` status.
### Registration Flow (Mobile)
Registration is a multi-step process:
1. `POST /api/v1/mobile/auth/register` — Submit phone/email → verification code sent
2. `POST /api/v1/mobile/auth/verify` — Verify code
3. `POST /api/v1/mobile/auth/complete` — Complete profile
### Rate Limiting
- Authentication endpoints: **5 requests/minute**
- Authenticated endpoints: **60 requests/minute**
- File uploads: **10 requests/minute**
Check `X-RateLimit-Remaining` and `X-RateLimit-Limit` response headers.
### Response Format
All responses follow a consistent JSON envelope:
```json
{
"status": "SUCCESS|ERROR|CREATED",
"message": "Human-readable message",
"data": { ... },
"errors": null,
"meta": { "request_id": "uuid", "timestamp": "ISO 8601" }
}
```
<aside>As you scroll, you'll see code examples for working with the API in different programming languages in the dark area to the right (or as part of the content on mobile).
You can switch the language used with the tabs at the top right (or from the nav menu at the top left on mobile).</aside>
Authenticating requests
To authenticate requests, include an Authorization header with the value "Bearer {YOUR_AUTH_KEY}".
All authenticated endpoints are marked with a requires authentication badge in the documentation below.
Obtain a token via the login endpoint for your guard (mobile, org, or admin). Include it as Bearer {token} in the Authorization header.
Public API
Publicly accessible endpoints that do not require authentication. Use these for browsing jobs, organizations, and app settings.
App Settings
Health check endpoint for infrastructure monitoring.
Returns system health status including database, cache, and storage connectivity.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/health" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/health"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/health';
$response = $client->get(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/health');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "healthy",
"timestamp": "2026-08-05T16:18:33+00:00",
"checks": {
"database": {
"status": "ok",
"latency_ms": 3.4
},
"cache": {
"status": "ok",
"latency_ms": 0.31
},
"storage": {
"status": "ok",
"latency_ms": 0.06
}
}
}
Example response (503, Degraded):
{
"status": "degraded",
"timestamp": "2026-06-11T10:00:00.000000Z",
"checks": {
"database": {
"status": "error",
"latency_ms": null,
"error": "Connection refused"
},
"cache": {
"status": "ok",
"latency_ms": 1.2
},
"storage": {
"status": "ok",
"latency_ms": 3.1
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Public Jobs
Browse available jobs without authentication. Returns limited information to encourage registration. Only shows active jobs with future deadlines.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/public/jobs?category=gastronomy&city=Wien&lat=48.2082&lng=16.3738&radius=25&start_date=2026-06-15&end_date=2026-07-15&per_page=10" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/public/jobs"
);
const params = {
"category": "gastronomy",
"city": "Wien",
"lat": "48.2082",
"lng": "16.3738",
"radius": "25",
"start_date": "2026-06-15",
"end_date": "2026-07-15",
"per_page": "10",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/public/jobs';
$response = $client->get(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'category' => 'gastronomy',
'city' => 'Wien',
'lat' => '48.2082',
'lng' => '16.3738',
'radius' => '25',
'start_date' => '2026-06-15',
'end_date' => '2026-07-15',
'per_page' => '10',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/public/jobs')
.replace(queryParameters: {
'category': 'gastronomy',
'city': 'Wien',
'lat': '48.2082',
'lng': '16.3738',
'radius': '25',
'start_date': '2026-06-15',
'end_date': '2026-07-15',
'per_page': '10',
});
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"jobs": [],
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 10,
"total": 0
}
},
"message": "Register or log in to apply for this job."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Public Job Details
View details of a specific job without authentication. Returns limited information (no exact wage, no contact details) to encourage registration.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/public/jobs/550e8400-e29b-41d4-a716-446655440000" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/public/jobs/550e8400-e29b-41d4-a716-446655440000"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/public/jobs/550e8400-e29b-41d4-a716-446655440000';
$response = $client->get(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/public/jobs/550e8400-e29b-41d4-a716-446655440000');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"job": {
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant",
"description": "Ut nostrum rerum ut alias quia libero excepturi. Voluptatum et aut non quia quisquam molestias. Perferendis qui hic unde.",
"category": {
"id": "019fd2b7-f39f-73e6-870b-fe7584e4f9bc",
"slug": "office",
"name": "Büro",
"name_localized": "Office",
"icon": "briefcase",
"color": null
},
"location_city": "East Eliseo",
"start_date": "2026-08-12",
"end_date": "2026-08-19",
"shift_types": null,
"shift_start_time": "01:49:00",
"shift_end_time": "18:57:00",
"workers_needed": null,
"wage_hint": null,
"requirements": {
"qualifications": [],
"languages": null
},
"organization": {
"name": "Caritas",
"logo_url": null,
"city": "Vienna"
},
"application_deadline": "2026-09-05 16:18"
}
},
"message": "Register or log in to apply for this job."
}
Example response (404, Not Found):
{
"status": "RESOURCE_NOT_FOUND",
"message": "Job not found."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Legal
List Legal Documents
List all active legal documents (public endpoint, no auth required).
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/public/legal" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/public/legal"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/public/legal';
$response = $client->get(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/public/legal');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Legal documents retrieved.",
"data": {
"documents": [
{
"id": "019fd2b7-ef7c-732a-b29e-ef789f899c9d",
"type": "aug_info",
"title": "Information gemäß AÜG (Arbeitskräfteüberlassungsgesetz)",
"version": 1,
"locale": "de",
"published_at": "2026-08-05T16:18:17+00:00",
"requires_reacceptance": false
},
{
"id": "019fd2b7-ef86-70be-8580-5a1ac1757a9a",
"type": "cookie_policy",
"title": "Cookie-Richtlinie",
"version": 1,
"locale": "de",
"published_at": "2026-08-05T16:18:17+00:00",
"requires_reacceptance": false
},
{
"id": "019fd2b7-ef76-73b5-a9c5-d7cca778324b",
"type": "data_processing",
"title": "Einwilligung zur Datenverarbeitung",
"version": 1,
"locale": "de",
"published_at": "2026-08-05T16:18:17+00:00",
"requires_reacceptance": true
},
{
"id": "019fd2b7-ef8a-7286-ada6-84f13beb905f",
"type": "imprint",
"title": "Impressum",
"version": 1,
"locale": "de",
"published_at": "2026-08-05T16:18:17+00:00",
"requires_reacceptance": false
},
{
"id": "019fd2b7-ef68-7312-a1a3-6b14820cf9e2",
"type": "privacy_policy",
"title": "Datenschutzerklärung",
"version": 1,
"locale": "de",
"published_at": "2026-08-05T16:18:17+00:00",
"requires_reacceptance": true
},
{
"id": "019fd2b7-ef83-7298-a78c-af4b1e36b67b",
"type": "svnr_consent",
"title": "Einwilligung zur Verarbeitung der Sozialversicherungsnummer",
"version": 1,
"locale": "de",
"published_at": "2026-08-05T16:18:17+00:00",
"requires_reacceptance": true
},
{
"id": "019fd2b7-ef6f-72ae-8c86-d9977da26ec0",
"type": "terms_of_service",
"title": "Allgemeine Geschäftsbedingungen (AGB)",
"version": 1,
"locale": "de",
"published_at": "2026-08-05T16:18:17+00:00",
"requires_reacceptance": true
}
],
"available_locales": [
"de",
"en"
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Latest Legal Document
Get the latest active version of a legal document by type (public endpoint).
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/public/legal/latest/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/public/legal/latest/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/public/legal/latest/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->get(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/public/legal/latest/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "51e25b3b-a569-46f5-b6b5-5047b558e6d2",
"timestamp": "2026-08-21T05:14:32.469716Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Show Legal Document
Show a specific legal document by ID (public endpoint, no auth required).
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/public/legal/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/public/legal/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/public/legal/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->get(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/public/legal/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Legal document retrieved.",
"data": {
"id": "019fd2b7-ef68-7312-a1a3-6b14820cf9e2",
"type": "privacy_policy",
"title": "Datenschutzerklärung",
"content": "# Datenschutzerklärung\n\n**Stand: 05.08.2026**\n**Version: 1.0**\n\n---\n\n## 1. Verantwortlicher\n\n**Flexxer**\nMusterstraße 1\n1010 Wien, Österreich\n\n- **Firmenbuchnummer:** FN 123456x\n- **UID-Nummer:** ATU12345678\n- **Telefon:** +43 1 234 5678\n- **E-Mail:** privacy@flexxr.at\n- **Website:** https://flexxr.at\n\n### 1.1 Datenschutzbeauftragter\n\nFür Fragen zum Datenschutz erreichen Sie unseren Datenschutzbeauftragten unter:\n- **E-Mail:** dpo@flexxr.at\n\n---\n\n## 2. Rechtsgrundlagen der Verarbeitung\n\nWir verarbeiten Ihre personenbezogenen Daten ausschließlich auf Basis der folgenden Rechtsgrundlagen gemäß **Datenschutz-Grundverordnung (DSGVO)** und dem **österreichischen Datenschutzgesetz (DSG)**:\n\n| Rechtsgrundlage | DSGVO Artikel | Anwendungsbereich |\n|-----------------|---------------|-------------------|\n| Vertragserfüllung | Art. 6 Abs. 1 lit. b | Durchführung des Arbeits-/Überlassungsvertrags |\n| Rechtliche Verpflichtung | Art. 6 Abs. 1 lit. c | ASVG-Meldungen, Lohnsteuer, AÜG-Compliance |\n| Berechtigtes Interesse | Art. 6 Abs. 1 lit. f | Betrugsprävention, IT-Sicherheit |\n| Einwilligung | Art. 6 Abs. 1 lit. a | Marketing, optionale Datenverarbeitung |\n\n---\n\n## 3. Kategorien personenbezogener Daten\n\n### 3.1 Stammdaten\n- Vor- und Nachname\n- Geburtsdatum und Geburtsort\n- Staatsangehörigkeit\n- Geschlecht\n- Familienstand\n\n### 3.2 Kontaktdaten\n- E-Mail-Adresse\n- Telefonnummer\n- Wohnadresse\n\n### 3.3 Beschäftigungsdaten\n- Sozialversicherungsnummer (SVNR) gemäß ASVG\n- Steuernummer\n- Bankverbindung (IBAN)\n- Qualifikationen und Zertifikate\n- Arbeitszeitaufzeichnungen\n\n### 3.4 Besondere Kategorien (Art. 9 DSGVO)\n- Gesundheitsdaten (nur bei medizinischen Bescheinigungen)\n- Gewerkschaftszugehörigkeit (nur bei KV-Anwendung)\n\nDiese Daten werden nur mit ausdrücklicher Einwilligung oder aufgrund gesetzlicher Verpflichtung verarbeitet.\n\n---\n\n## 4. Zwecke der Verarbeitung\n\n### 4.1 Vertragserfüllung\n- Durchführung des Arbeitsvertrags gemäß **AÜG § 11**\n- Vermittlung von Arbeitseinsätzen\n- Arbeitszeiterfassung und Abrechnung\n- Lohn- und Gehaltsabrechnung\n\n### 4.2 Gesetzliche Verpflichtungen\n- ELDA-Meldungen an die ÖGK (gemäß **ASVG §§ 33-34**)\n- Lohnsteuerabzug und Meldung an das Finanzamt (**EStG**)\n- Aufbewahrungspflichten (**BAO § 132**: 7 Jahre für Geschäftsunterlagen)\n- AÜG-Meldepflichten an die Gewerbebehörde\n\n### 4.3 Berechtigte Interessen\n- Betrugsprävention und Identitätsprüfung\n- IT-Sicherheit und Systemstabilität\n- Qualitätssicherung und Prozessoptimierung\n\n---\n\n## 5. Empfänger der Daten\n\nIhre Daten werden an folgende Kategorien von Empfängern übermittelt:\n\n| Empfänger | Zweck | Rechtsgrundlage |\n|-----------|-------|-----------------|\n| ÖGK (Österreichische Gesundheitskasse) | Sozialversicherungsmeldungen | ASVG §§ 33-34 |\n| Finanzamt | Lohnsteuer, Lohnzettel | EStG § 84 |\n| Beschäftiger (Kundenunternehmen) | Arbeitseinsatz | AÜG § 12 |\n| Lohnverrechnungsdienstleister | Gehaltsabrechnung | Auftragsverarbeitung |\n| IT-Dienstleister | Hosting, Cloud-Services | Auftragsverarbeitung |\n\n---\n\n## 6. Speicherdauer\n\n| Datenkategorie | Speicherdauer | Rechtsgrundlage |\n|----------------|---------------|-----------------|\n| Lohnabrechnungsunterlagen | 7 Jahre | BAO § 132 |\n| Arbeitszeitaufzeichnungen | 3 Jahre nach Ende des Arbeitsverhältnisses | AZG § 26 |\n| SV-Meldungen | 7 Jahre | ASVG |\n| Bewerbungsunterlagen (bei Ablehnung) | 6 Monate | DSGVO Art. 17 |\n| Vertragsdokumente | 30 Jahre (Verjährungsfrist) | ABGB § 1489 |\n\n---\n\n## 7. Ihre Rechte nach DSGVO\n\nSie haben folgende Rechte bezüglich Ihrer personenbezogenen Daten:\n\n### 7.1 Auskunftsrecht (Art. 15 DSGVO)\nSie haben das Recht, eine Bestätigung darüber zu verlangen, ob personenbezogene Daten verarbeitet werden, und gegebenenfalls Auskunft über diese Daten zu erhalten.\n\n### 7.2 Recht auf Berichtigung (Art. 16 DSGVO)\nSie haben das Recht, unrichtige personenbezogene Daten unverzüglich berichtigen zu lassen.\n\n### 7.3 Recht auf Löschung (Art. 17 DSGVO)\nSie haben das Recht, die Löschung Ihrer Daten zu verlangen, sofern keine gesetzlichen Aufbewahrungspflichten entgegenstehen.\n\n### 7.4 Recht auf Einschränkung (Art. 18 DSGVO)\nSie haben das Recht, die Einschränkung der Verarbeitung zu verlangen.\n\n### 7.5 Recht auf Datenübertragbarkeit (Art. 20 DSGVO)\nSie haben das Recht, Ihre Daten in einem strukturierten, gängigen und maschinenlesbaren Format zu erhalten.\n\n### 7.6 Widerspruchsrecht (Art. 21 DSGVO)\nSie haben das Recht, gegen die Verarbeitung Ihrer Daten Widerspruch einzulegen.\n\n### 7.7 Recht auf Widerruf der Einwilligung (Art. 7 Abs. 3 DSGVO)\nSie haben das Recht, erteilte Einwilligungen jederzeit zu widerrufen.\n\n---\n\n## 8. Beschwerderecht bei der Aufsichtsbehörde\n\nSie haben das Recht, eine Beschwerde bei der zuständigen Aufsichtsbehörde einzureichen:\n\n**Österreichische Datenschutzbehörde**\nBarichgasse 40-42\n1030 Wien\n\n- **E-Mail:** dsb@dsb.gv.at\n- **Website:** https://www.dsb.gv.at\n\n---\n\n## 9. Automatisierte Entscheidungsfindung\n\nEs findet keine automatisierte Entscheidungsfindung im Sinne von **Art. 22 DSGVO** statt, die rechtliche Wirkung entfaltet oder Sie in ähnlicher Weise erheblich beeinträchtigt.\n\n---\n\n## 10. Drittlandübermittlung\n\nEine Übermittlung Ihrer Daten in Drittländer (außerhalb des EWR) erfolgt nur:\n- Auf Basis von Angemessenheitsbeschlüssen der EU-Kommission\n- Unter Verwendung von EU-Standardvertragsklauseln\n- Mit Ihrer ausdrücklichen Einwilligung\n\n---\n\n## 11. Änderungen dieser Datenschutzerklärung\n\nWir behalten uns vor, diese Datenschutzerklärung anzupassen, um sie an geänderte Rechtslagen oder bei Änderungen unserer Dienste anzupassen. Die aktuelle Version finden Sie stets unter: https://flexxr.at/legal/privacy_policy\n\n---\n\n## 12. Kontakt\n\nBei Fragen zum Datenschutz wenden Sie sich bitte an:\n\n**Flexxer**\nMusterstraße 1, 1010 Wien\nE-Mail: privacy@flexxr.at\n",
"content_format": "markdown",
"version": 1,
"locale": "de",
"published_at": "2026-08-05T16:18:17+00:00",
"effective_until": null,
"requires_reacceptance": true,
"content_hash": "7d28b9a8ddc190e477a58a1d95a0a50d2f0428e19594df2dfff7742c94e784ff"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Privacy Contact
Controller identity and data-protection contact points (public endpoint).
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/public/privacy-contact" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/public/privacy-contact"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/public/privacy-contact';
$response = $client->get(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/public/privacy-contact');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "801b4111-2078-4137-a396-974adbf7aed6",
"timestamp": "2026-08-21T05:14:32.487770Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Dashboard
Get Public Dashboard (Guest Home Screen)
Returns the public home screen data for unauthenticated users:
- Popular jobs this week
- Recently added jobs
Does NOT include:
- Today's shift (requires auth)
- Profile completion (requires auth)
- Personalized recommendations (requires auth)
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/home" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/home"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/home';
$response = $client->get(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/home');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"popular_jobs": [
{
"id": "019fd2b8-22cf-71c5-8edd-5e3ce9d29e8b",
"title": "Promoter*in Vienna Marathon",
"description": "Für ein großes Outdoor-Event suchen wir Promoter*innen und Koordinator*innen. Teamgeist und Flexibilität sind gefragt.",
"status": "published",
"is_featured": false,
"category": {
"id": "019fd2b7-f398-7300-a216-c64584fea8f7",
"slug": "event",
"name": "Events",
"name_localized": "Events",
"icon": "calendar-star",
"color": null
},
"tags": [
"Events",
"Tagschicht",
"Veranstaltungserfahrung",
"Teamfähigkeit"
],
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Promoter*in Vienna Marathon",
"address": "Hauptstraße 48, 1010 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2082,
"lng": 16.3738,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-26",
"end_date": "2026-08-28",
"shift_start_time": "09:00:00",
"shift_end_time": "17:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 13.5,
"supplements": null,
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 20,
"filled": 0,
"available": 20
},
"deadlines": {
"application": "2026-08-23T00:00:00+00:00"
},
"created_at": "2026-08-05T16:18:30+00:00",
"is_saved": false,
"can_apply": false,
"rate": null,
"wage_hint": "€12-14/hr"
},
{
"id": "019fd2b8-2599-7355-a7f1-dcb185b05faa",
"title": "Rezeptionist*in Hotel Sacher",
"description": "Für unser Haus suchen wir freundliche und belastbare Mitarbeiter*innen für den Front- und Back-Office-Bereich.",
"status": "published",
"is_featured": false,
"category": {
"id": "019fd2b7-f375-724e-84b8-4f9647ef6419",
"slug": "hotel",
"name": "Hotellerie",
"name_localized": "Hospitality",
"icon": "hotel",
"color": null
},
"tags": [
"Hospitality",
"Tagschicht",
"Hotellerie-Erfahrung",
"Deutsch B2"
],
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Rezeptionist*in Hotel Sacher",
"address": "Hauptstraße 87, 1010 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2034,
"lng": 16.3694,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-17",
"end_date": "2026-08-19",
"shift_start_time": "09:00:00",
"shift_end_time": "17:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 17.5,
"supplements": null,
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 4,
"filled": 0,
"available": 4
},
"deadlines": {
"application": "2026-08-14T00:00:00+00:00"
},
"created_at": "2026-08-05T16:18:31+00:00",
"is_saved": false,
"can_apply": false,
"rate": null,
"wage_hint": "€14-18/hr"
},
{
"id": "019fd2b8-1f86-7376-9a3a-c072ab5675cb",
"title": "Service-Mitarbeiter*in Wiener Prater Festival",
"description": "Wir suchen engagierte Service-Mitarbeiter*innen für unser Team. Du bringst Freude am Umgang mit Gästen mit und arbeitest gerne im Team.",
"status": "published",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Tagschicht",
"Serviceerfahrung",
"Deutsch B2"
],
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Service-Mitarbeiter*in Wiener Prater Festival",
"address": "Hauptstraße 91, 1020 Wien",
"city": "Wien",
"postal_code": "1020",
"lat": 48.2117,
"lng": 16.3969,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-19",
"end_date": "2026-08-21",
"shift_start_time": "09:00:00",
"shift_end_time": "17:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 15.5,
"supplements": null,
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 12,
"filled": 0,
"available": 12
},
"deadlines": {
"application": "2026-08-16T00:00:00+00:00"
},
"created_at": "2026-08-05T16:18:29+00:00",
"is_saved": false,
"can_apply": false,
"rate": null,
"wage_hint": "€14-18/hr"
},
{
"id": "019fd2b8-21c8-72cc-80b1-47fd13450522",
"title": "Barkeeper*in Sommernacht Open Air",
"description": "Wir suchen engagierte Service-Mitarbeiter*innen für unser Team. Du bringst Freude am Umgang mit Gästen mit und arbeitest gerne im Team.",
"status": "published",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Nachtschicht",
"Serviceerfahrung",
"Deutsch B2"
],
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Barkeeper*in Sommernacht Open Air",
"address": "Hauptstraße 35, 1060 Wien",
"city": "Wien",
"postal_code": "1060",
"lat": 48.1953,
"lng": 16.356,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-15",
"end_date": "2026-08-17",
"shift_start_time": "22:00:00",
"shift_end_time": "06:00:00",
"shift_type": "night",
"shift_type_label": "Nachtschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 16,
"supplements": null,
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 8,
"filled": 0,
"available": 8
},
"deadlines": {
"application": "2026-08-12T00:00:00+00:00"
},
"created_at": "2026-08-05T16:18:30+00:00",
"is_saved": false,
"can_apply": false,
"rate": null,
"wage_hint": "€14-18/hr"
},
{
"id": "019fd2b8-24b0-700a-ae2a-142f5e48aead",
"title": "Lagerhelfer*in Logistikzentrum Inzersdorf",
"description": "Für unser Logistikzentrum suchen wir zuverlässige Helfer*innen. Körperliche Belastbarkeit und Pünktlichkeit sind Voraussetzung.",
"status": "published",
"is_featured": false,
"category": {
"id": "019fd2b7-f38b-7209-8b83-b345b172def2",
"slug": "warehouse",
"name": "Lager",
"name_localized": "Warehouse",
"icon": "industry",
"color": null
},
"tags": [
"Warehouse",
"Nachtschicht",
"Staplerführerschein von Vorteil",
"Körperliche Belastbarkeit"
],
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Lagerhelfer*in Logistikzentrum Inzersdorf",
"address": "Hauptstraße 28, 1230 Wien",
"city": "Wien",
"postal_code": "1230",
"lat": 48.1454,
"lng": 16.3499,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-12",
"end_date": "2026-08-14",
"shift_start_time": "22:00:00",
"shift_end_time": "06:00:00",
"shift_type": "night",
"shift_type_label": "Nachtschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 14.8,
"supplements": null,
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 15,
"filled": 0,
"available": 15
},
"deadlines": {
"application": "2026-08-09T00:00:00+00:00"
},
"created_at": "2026-08-05T16:18:31+00:00",
"is_saved": false,
"can_apply": false,
"rate": null,
"wage_hint": "€14-18/hr"
}
],
"recent_jobs": [
{
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant",
"description": "Ut nostrum rerum ut alias quia libero excepturi. Voluptatum et aut non quia quisquam molestias. Perferendis qui hic unde.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f39f-73e6-870b-fe7584e4f9bc",
"slug": "office",
"name": "Büro",
"name_localized": "Office",
"icon": "briefcase",
"color": null
},
"tags": [
"Office",
"Nachtschicht"
],
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Barrows, Christiansen and Jones",
"address": "586 Tremaine Row",
"city": "East Eliseo",
"postal_code": "10547-3697",
"lat": 46.931383,
"lng": 11.998284,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-12",
"end_date": "2026-08-19",
"shift_start_time": "01:49:00",
"shift_end_time": "18:57:00",
"shift_type": "night",
"shift_type_label": "Nachtschicht",
"duration_hours": 17.133333333333333
},
"compensation": {
"hourly_rate_gross": 32.08,
"supplements": {
"night": 0.7,
"weekend": 3.86
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 5,
"filled": 0,
"available": 5
},
"deadlines": {
"application": "2026-09-05T16:18:32+00:00"
},
"created_at": "2026-08-05T16:18:32+00:00",
"is_saved": false,
"can_apply": true,
"rate": null,
"wage_hint": "€30+/hr"
},
{
"id": "019fd2b8-1405-709f-bca9-b0a418fb6a75",
"title": "Silvesternacht Service",
"description": "Wir suchen motivierte Silvesternacht Service für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Nachtschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-fe56-70d1-bb3a-641339ce636a",
"name": "Lagerhaus Steiermark",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Hotel Imperial Wien",
"address": "Kärntner Ring 16, 1015 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2082,
"lng": 16.3739,
"distance_km": null
},
"schedule": {
"start_date": "2027-02-09",
"end_date": "2027-02-10",
"shift_start_time": "22:00:00",
"shift_end_time": "06:00:00",
"shift_type": "night",
"shift_type_label": "Nachtschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 25,
"supplements": {
"night_bonus": 50,
"holiday_bonus": 100,
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 12,
"filled": 0,
"available": 12
},
"deadlines": {
"application": "2027-02-04T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null,
"wage_hint": "€22-26/hr"
},
{
"id": "019fd2b8-15b5-7019-8521-6ea79edc4ba5",
"title": "Garderobenservice Ball",
"description": "Für unsere bevorstehende Veranstaltung suchen wir tatkräftige Unterstützung. Als Garderobenservice Ball sind Sie das Aushängeschild unserer Veranstaltung und sorgen für einen reibungslosen Ablauf.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f398-7300-a216-c64584fea8f7",
"slug": "event",
"name": "Events",
"name_localized": "Events",
"icon": "calendar-star",
"color": null
},
"tags": [
"Events",
"Tagschicht"
],
"organization": {
"id": "019fd2b7-ff32-7117-ab28-06e2d3082002",
"name": "Bildungszentrum Mitte",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Wiener Rathaus",
"address": "Friedrich-Schmidt-Platz 1, 1010 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2082,
"lng": 16.3739,
"distance_km": null
},
"schedule": {
"start_date": "2027-01-22",
"end_date": "2027-01-23",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 14.5,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 10,
"filled": 0,
"available": 10
},
"deadlines": {
"application": "2027-01-19T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:27+00:00",
"is_saved": false,
"can_apply": true,
"rate": null,
"wage_hint": "€14-18/hr"
},
{
"id": "019fd2b8-18d3-718f-bbe2-32c97903f559",
"title": "Verkaufshilfe Weihnachtsgeschäft",
"description": "Für unser Retail-Team suchen wir freundliche und kundenorientierte Verkaufshilfe Weihnachtsgeschäft. Sie beraten unsere Kunden, wickeln Kassiervorgänge ab und sorgen für eine ansprechende Warenpräsentation.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f37d-712d-92b3-aa5540f6b2a7",
"slug": "retail",
"name": "Einzelhandel",
"name_localized": "Retail",
"icon": "shopping-cart",
"color": null
},
"tags": [
"Retail",
"Tagschicht"
],
"organization": {
"id": "019fd2b7-fca6-71cf-8683-c97f6f50a24a",
"name": "Reinigungsservice Alpin",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Wiener Innenstadt",
"address": "Kärntner Straße 15, 1010 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2082,
"lng": 16.3739,
"distance_km": null
},
"schedule": {
"start_date": "2027-01-12",
"end_date": "2027-02-01",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 13.5,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 10,
"filled": 0,
"available": 10
},
"deadlines": {
"application": "2027-01-08T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:28+00:00",
"is_saved": false,
"can_apply": true,
"rate": null,
"wage_hint": "€12-14/hr"
},
{
"id": "019fd2b8-13e2-7390-a987-e12b987cdbb8",
"title": "Weihnachtsmarkt Servicekraft",
"description": "Wir suchen motivierte Weihnachtsmarkt Servicekraft für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Tagschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-f91f-70cb-8409-8632db9df3c7",
"name": "Sicherheitsdienst Österreich",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Christkindlmarkt Rathausplatz",
"address": "Rathausplatz 1, 1010 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2082,
"lng": 16.3739,
"distance_km": null
},
"schedule": {
"start_date": "2027-01-02",
"end_date": "2027-02-01",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 14,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 30,
"filled": 0,
"available": 30
},
"deadlines": {
"application": "2026-12-29T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null,
"wage_hint": "€14-18/hr"
}
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Invitations
Accept Invitation
Phase-1 of the invitation signup flow.
Stamps accepted_at and accepted_by_email on the invitation row,
then returns the resolved preset key and label so the front-end can
render a confirmation screen before the user completes signup.
The endpoint is idempotent until member_created_at is set: a second
call for the same token (e.g. page reload) returns the same 200 body
instead of a conflict error.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/public/org/invitations/accept" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"token\": \"abc123...\",
\"accepted_by_email\": \"invitee@example.com\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/public/org/invitations/accept"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"token": "abc123...",
"accepted_by_email": "invitee@example.com"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/public/org/invitations/accept';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'token' => 'abc123...',
'accepted_by_email' => 'invitee@example.com',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/public/org/invitations/accept');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"token": "abc123...",
"accepted_by_email": "invitee@example.com"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Invitation accepted.",
"data": {
"status": "accepted",
"preset_key": "viewer",
"preset_label": "Viewer"
},
"errors": null,
"meta": {
"request_id": "cb6e38a7-5b78-481e-aa81-9f9501c5c4d0",
"timestamp": "2026-08-05T16:19:05.938455Z"
}
}
Example response (410):
{
"status": "INVITATION_EXPIRED",
"message": "Invitation has expired."
}
Example response (422):
{
"status": "INVITATION_REVOKED",
"message": "Invitation has been revoked."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Complete Invitation Signup
Phase-2 of the invitation signup flow.
Creates a User and OrganizationMember record, assigns the ACL preset from the invitation (with fallbacks for legacy rows), and stamps member_created_at on the invitation.
Preset resolution order:
- invitation.preset_key if non-null and registered in catalog → 'invitation'
- invitation.preset_key is null → role map (PRESET_FOR_LEGACY_ROLE) → 'fallback_legacy_role'
- invitation.preset_key is stale (not in catalog) → 'viewer' → 'fallback_missing_catalog'
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/public/org/invitations/signup" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"token\": \"abc123...\",
\"name\": \"Jane Doe\",
\"password\": \"SecureP4ssword!1\",
\"password_confirmation\": \"architecto\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/public/org/invitations/signup"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"token": "abc123...",
"name": "Jane Doe",
"password": "SecureP4ssword!1",
"password_confirmation": "architecto"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/public/org/invitations/signup';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'token' => 'abc123...',
'name' => 'Jane Doe',
'password' => 'SecureP4ssword!1',
'password_confirmation' => 'architecto',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/public/org/invitations/signup');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"token": "abc123...",
"name": "Jane Doe",
"password": "SecureP4ssword!1",
"password_confirmation": "architecto"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Account created.",
"data": {
"acl": {
"scope": "org-member",
"presets": [
"viewer"
]
},
"presets": [
"viewer"
]
},
"errors": null,
"meta": {
"request_id": "8b8ff3cf-05df-49f1-aa0c-aaacc096a0ea",
"timestamp": "2026-08-05T16:19:06.535113Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Mobile API
Endpoints for the mobile application (employee users). All endpoints (except authentication) require a valid Bearer token with 2FA verification.
Authentication
Check Email Availability
Checks if an email address is available for registration.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/check-email" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"max@example.com\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/check-email"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "max@example.com"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/check-email';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'max@example.com',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/check-email');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "max@example.com"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Email is available.",
"data": {
"available": true
},
"errors": null,
"meta": {
"request_id": "307c14e3-4d54-46dc-bf54-13557ff1a48a",
"timestamp": "2026-08-05T16:18:34.040638Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "email",
"message": "The email field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-06-11T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Check Phone Availability
Checks if a phone number is available for registration.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/check-phone" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"country_code\": \"+43\",
\"phone_number\": \"6641234567\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/check-phone"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"country_code": "+43",
"phone_number": "6641234567"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/check-phone';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'country_code' => '+43',
'phone_number' => '6641234567',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/check-phone');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"country_code": "+43",
"phone_number": "6641234567"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Phone number is already registered.",
"data": {
"available": false
},
"errors": null,
"meta": {
"request_id": "c64348be-986c-4365-8fa5-702eeb4a5699",
"timestamp": "2026-08-05T16:18:34.044831Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "phone_number",
"message": "The phone number field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-06-11T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Confirm Email Verification
Consumes the token from the email verification link. On success the user account is verified and the EmployeeProfile advances to profile_incomplete. An invalid, expired, or already-used token returns a 410 Gone response so the client can prompt the user to request a new link.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/verify-email/confirm" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"boris@example.com\",
\"token\": \"abc123def456...\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/verify-email/confirm"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "boris@example.com",
"token": "abc123def456..."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/verify-email/confirm';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'boris@example.com',
'token' => 'abc123def456...',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/verify-email/confirm');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "boris@example.com",
"token": "abc123def456..."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Success):
{
"status": "SUCCESS",
"message": "Email verified successfully.",
"data": {
"email": "boris@example.com",
"status": "profile_incomplete"
},
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (410, Token Invalid or Expired):
{
"status": "VERIFICATION_LINK_EXPIRED",
"message": "Verification link is invalid, expired, or already used. Please request a new one.",
"data": null,
"errors": [
{
"field": "token",
"message": "Verification link is invalid, expired, or already used."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "token",
"message": "The token field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Resend Verification Link
Resends the email verification link to the given address. Silently succeeds when the email is not registered or already verified to prevent account enumeration.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/verify-email/resend" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"boris@example.com\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/verify-email/resend"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "boris@example.com"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/verify-email/resend';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'boris@example.com',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/verify-email/resend');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "boris@example.com"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "If this address has a pending verification, a new link has been sent.",
"data": {
"email": "boris@example.com"
},
"errors": null,
"meta": {
"request_id": "4d862349-74df-4e13-892f-638a1e742726",
"timestamp": "2026-08-05T16:18:34.053350Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "email",
"message": "The email must be a valid email address."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Register User
Creates the user account in REGISTERED status and queues an email verification link. Phone (country_code + phone_number) and GDPR document IDs (terms_document_id, privacy_document_id, processing_data_document_id) are all required. No session token is issued; the user verifies via the emailed link and then signs in.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/register" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"first_name\": \"Boris\",
\"last_name\": \"Jacobi\",
\"email\": \"boris@example.com\",
\"country_code\": \"+43\",
\"phone_number\": \"6641234567\",
\"password\": \"SuperSecret123!\",
\"password_confirmation\": \"SuperSecret123!\",
\"terms_document_id\": \"01958e69-a8fe-7000-9abc-123456789abc\",
\"privacy_document_id\": \"01958e69-b8fe-7000-9abc-123456789def\",
\"processing_data_document_id\": \"01958e69-c8fe-7000-9abc-123456789ghi\",
\"marketing_consent\": false,
\"referral_code\": \"AB12CD34\",
\"language\": \"de\",
\"device_info\": {
\"device_id\": \"b\",
\"platform\": \"n\",
\"os_version\": \"g\",
\"app_version\": \"z\",
\"device_model\": \"m\"
}
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/register"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"first_name": "Boris",
"last_name": "Jacobi",
"email": "boris@example.com",
"country_code": "+43",
"phone_number": "6641234567",
"password": "SuperSecret123!",
"password_confirmation": "SuperSecret123!",
"terms_document_id": "01958e69-a8fe-7000-9abc-123456789abc",
"privacy_document_id": "01958e69-b8fe-7000-9abc-123456789def",
"processing_data_document_id": "01958e69-c8fe-7000-9abc-123456789ghi",
"marketing_consent": false,
"referral_code": "AB12CD34",
"language": "de",
"device_info": {
"device_id": "b",
"platform": "n",
"os_version": "g",
"app_version": "z",
"device_model": "m"
}
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/register';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'first_name' => 'Boris',
'last_name' => 'Jacobi',
'email' => 'boris@example.com',
'country_code' => '+43',
'phone_number' => '6641234567',
'password' => 'SuperSecret123!',
'password_confirmation' => 'SuperSecret123!',
'terms_document_id' => '01958e69-a8fe-7000-9abc-123456789abc',
'privacy_document_id' => '01958e69-b8fe-7000-9abc-123456789def',
'processing_data_document_id' => '01958e69-c8fe-7000-9abc-123456789ghi',
'marketing_consent' => false,
'referral_code' => 'AB12CD34',
'language' => 'de',
'device_info' => ['device_id' => 'b', 'platform' => 'n', 'os_version' => 'g', 'app_version' => 'z', 'device_model' => 'm'],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/register');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"first_name": "Boris",
"last_name": "Jacobi",
"email": "boris@example.com",
"country_code": "+43",
"phone_number": "6641234567",
"password": "SuperSecret123!",
"password_confirmation": "SuperSecret123!",
"terms_document_id": "01958e69-a8fe-7000-9abc-123456789abc",
"privacy_document_id": "01958e69-b8fe-7000-9abc-123456789def",
"processing_data_document_id": "01958e69-c8fe-7000-9abc-123456789ghi",
"marketing_consent": false,
"referral_code": "AB12CD34",
"language": "de",
"device_info": {
"device_id": "b",
"platform": "n",
"os_version": "g",
"app_version": "z",
"device_model": "m"
}
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Success):
{
"status": "CREATED",
"message": "Registration successful.",
"data": {
"employee_id": "usr-uuid",
"email": "boris@example.com",
"status": "registered",
"verification_sent": true,
"next_step": "email_verification"
},
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (409, Email Already Registered):
{
"status": "EMAIL_ALREADY_EXISTS",
"message": "This email is already registered.",
"data": {
"can_login": true,
"can_reset_password": true
},
"errors": [
{
"field": "email",
"message": "This email is already registered."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "password",
"message": "The password must be at least 8 characters."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests.",
"data": {
"retry_after": 900
},
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Login User
Authenticates an end-user against the user guard and issues a Sanctum token. If the user has 2FA enabled a limited challenge token is returned and the client must complete the two-factor challenge before accessing any protected endpoints.
Supports login via email or phone number:
- Email login: email + password
- Phone login: country_code + phone_number + password
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/login" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"boris@example.com\",
\"country_code\": \"+43\",
\"phone_number\": \"6641234567\",
\"password\": \"SuperSecret123!\",
\"code\": \"123456\",
\"recovery_code\": \"ABCD-1234-EFGH\",
\"remember_me\": false
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/login"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "boris@example.com",
"country_code": "+43",
"phone_number": "6641234567",
"password": "SuperSecret123!",
"code": "123456",
"recovery_code": "ABCD-1234-EFGH",
"remember_me": false
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/login';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'boris@example.com',
'country_code' => '+43',
'phone_number' => '6641234567',
'password' => 'SuperSecret123!',
'code' => '123456',
'recovery_code' => 'ABCD-1234-EFGH',
'remember_me' => false,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/login');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "boris@example.com",
"country_code": "+43",
"phone_number": "6641234567",
"password": "SuperSecret123!",
"code": "123456",
"recovery_code": "ABCD-1234-EFGH",
"remember_me": false
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Login successful.",
"data": {
"token": "5|1f6S0lbLjAalzY2SdWUu1tdHThVkOGy2vnHx7WdX9e1f8795",
"refresh_token": "6|IZHjJiYI6X4IOrBpe0wRa0MXGE1sdBHywaUzaQDMcf7756ed",
"expires_in": 604800,
"user": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"first_name": "Anna",
"last_name": "Neuling",
"email": "pending@demo.flexxr.at",
"country_code": "+43",
"phone_number": "6769876543",
"status": "active",
"avatar_url": null,
"bio": null,
"date_of_birth": null,
"country": null,
"city": null,
"notify_push": true,
"notify_email": true,
"notify_sms": true,
"notify_marketing": false,
"email_verified_at": "2026-08-05T16:18:32+00:00",
"phone_verified_at": "2026-08-05T16:18:32+00:00",
"created_at": "2026-08-05T16:18:18+00:00",
"updated_at": "2026-08-05T16:18:34+00:00",
"employee_profile": {
"address_line_1": "Neugasse 5",
"address_line_2": null,
"postal_code": "4020"
}
},
"employee_status": "active"
},
"errors": null,
"meta": {
"request_id": "db53cffc-fb25-412c-8049-67967cc3b0d8",
"timestamp": "2026-08-05T16:18:34.317645Z"
}
}
Example response (401, 2FA Required):
{
"status": "TWO_FACTOR_REQUIRED",
"message": "Two-factor authentication is required.",
"data": {
"token": "2|challenge-token...",
"two_factor_method": "totp"
},
"errors": [
{
"field": null,
"message": "Two-factor authentication is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (401, Invalid Credentials):
{
"status": "INVALID_CREDENTIALS",
"message": "The provided credentials are incorrect.",
"data": null,
"errors": [
{
"field": "email",
"message": "The provided credentials are incorrect."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (401, Invalid Credentials with CAPTCHA):
{
"status": "INVALID_CREDENTIALS",
"message": "The provided credentials are incorrect.",
"data": {
"captcha_required": true
},
"errors": [
{
"field": "email",
"message": "The provided credentials are incorrect."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (401, Account Deactivated):
{
"status": "ACCOUNT_DEACTIVATED",
"message": "Your account has been deactivated.",
"data": null,
"errors": [
{
"field": "email",
"message": "Your account has been deactivated."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (403, Account Banned):
{
"status": "ACCOUNT_BANNED",
"message": "Your account has been banned.",
"data": null,
"errors": [
{
"field": "email",
"message": "Your account has been banned."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "email",
"message": "The email field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (423, Account Temporarily Locked):
{
"status": "ACCOUNT_TEMPORARILY_LOCKED",
"message": "Account temporarily locked. Try again in 15 minutes.",
"data": null,
"errors": [
{
"field": "email",
"message": "Account temporarily locked. Try again in 15 minutes."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (423, Account Locked for Review):
{
"status": "ACCOUNT_LOCKED_FOR_REVIEW",
"message": "Account locked pending admin review.",
"data": null,
"errors": [
{
"field": "email",
"message": "Account locked pending admin review."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Social Login
Handles social login (Google / Apple) via Firebase ID token verification. On success returns a Sanctum token; if the linked user has 2FA enabled a limited challenge token is returned instead and the client must complete the 2FA challenge. Brand-new social users who have not yet recorded TERMS and PRIVACY consent receive a limited supplementary token and must call POST /auth/social/complete before accessing the feature surface.
Refresh Token
requires authentication
Rotates the caller's refresh token. The presented refresh token is deleted and a new access + refresh token pair is returned. This endpoint does NOT require 2FA verification — the refresh token itself is the credential.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/refresh" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/refresh"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/refresh';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/refresh');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Success):
{
"status": "SUCCESS",
"message": "Token refreshed.",
"data": {
"token": "3|newaccess...",
"refresh_token": "4|newrefresh...",
"expires_in": 900
},
"errors": null,
"meta": {}
}
Example response (401, Not a refresh token):
{
"status": "UNAUTHORIZED",
"message": "Invalid refresh token.",
"data": null,
"errors": [
{
"field": null,
"message": "Invalid refresh token."
}
],
"meta": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Complete Social Registration
requires authentication
Finalises consent capture and profile data for a social-login user who received requires_supplementary = true. Requires the limited social-supplementary token issued by POST /auth/social-login.
Verify Phone via Firebase
requires authentication
Verifies a phone number using a Firebase ID token. The mobile app uses Firebase Phone Auth to verify the user's phone number, then sends the Firebase ID token to this endpoint.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/verify-phone" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"firebase_id_token\": \"eyJhbGciOiJSUzI1NiIs...\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/verify-phone"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"firebase_id_token": "eyJhbGciOiJSUzI1NiIs..."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/verify-phone';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'firebase_id_token' => 'eyJhbGciOiJSUzI1NiIs...',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/verify-phone');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"firebase_id_token": "eyJhbGciOiJSUzI1NiIs..."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Success):
{
"status": "SUCCESS",
"message": "Phone number verified successfully.",
"data": {
"phone_verified_at": "2026-06-11T12:00:00.000000Z"
},
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-06-11T12:00:00.000000Z"
}
}
Example response (400, Phone Mismatch):
{
"status": "ERROR",
"message": "Phone number does not match.",
"data": null,
"errors": [
{
"field": "firebase_id_token",
"message": "Phone number from Firebase does not match user profile."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-06-11T12:00:00.000000Z"
}
}
Example response (401, Invalid Token):
{
"status": "FIREBASE_TOKEN_INVALID",
"message": "The Firebase ID token is invalid or has expired.",
"data": null,
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-06-11T12:00:00.000000Z"
}
}
Example response (409, Phone Already Verified):
{
"status": "ERROR",
"message": "Phone number is already verified.",
"data": null,
"errors": [
{
"field": "firebase_id_token",
"message": "Phone number is already verified."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-06-11T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Profile
Get User Profile
requires authentication
Returns the authenticated user's account profile including personal info, contact details, and two-factor authentication status.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/profile" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/profile"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/profile';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/profile');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"first_name": "Anna",
"last_name": "Neuling",
"email": "pending@demo.flexxr.at",
"country_code": "+43",
"phone_number": "6769876543",
"status": "active",
"avatar_url": null,
"bio": null,
"date_of_birth": null,
"country": null,
"city": null,
"notify_push": true,
"notify_email": true,
"notify_sms": true,
"notify_marketing": false,
"email_verified_at": "2026-08-05T16:18:32+00:00",
"phone_verified_at": "2026-08-05T16:18:32+00:00",
"created_at": "2026-08-05T16:18:18+00:00",
"updated_at": "2026-08-05T16:18:33+00:00",
"employee_profile": null
},
"errors": null,
"meta": {
"request_id": "930c5193-62e0-4ecd-953f-e1066486631b",
"timestamp": "2026-08-05T16:18:34.713826Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Change User Password
requires authentication
Changes the authenticated user's password.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/mobile/profile/password" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"current_password\": \"S3cure-Passw0rd!\",
\"password\": \"S3cure-Passw0rd!\",
\"logout_other_devices\": true
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/profile/password"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"current_password": "S3cure-Passw0rd!",
"password": "S3cure-Passw0rd!",
"logout_other_devices": true
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/profile/password';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'current_password' => 'S3cure-Passw0rd!',
'password' => 'S3cure-Passw0rd!',
'logout_other_devices' => true,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/profile/password');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"current_password": "S3cure-Passw0rd!",
"password": "S3cure-Passw0rd!",
"logout_other_devices": true
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Password changed successfully.",
"data": null,
"errors": null,
"meta": {
"request_id": "3f784394-7936-45b9-9fb2-0f9bc3e527cb",
"timestamp": "2026-08-05T16:18:35.373354Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Upload Profile Photo
requires authentication
Upload (or replace) the authenticated worker's profile photo.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/profile/photo" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "photo=@/tmp/phpi3ec0op4vs6d2HbU8Nl" const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/profile/photo"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('photo', document.querySelector('input[name="photo"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/profile/photo';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'multipart/form-data',
'Accept' => 'application/json',
],
'multipart' => [
[
'name' => 'photo',
'contents' => fopen('/tmp/phpi3ec0op4vs6d2HbU8Nl', 'r')
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/profile/photo');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'multipart/form-data',
'Accept': 'application/json',
};
final request = http.MultipartRequest('POST', uri);
request.headers.addAll(headers);
request.files.add(await http.MultipartFile.fromPath('photo', '/tmp/phpi3ec0op4vs6d2HbU8Nl'));
final streamed = await request.send();
final response = await http.Response.fromStream(streamed);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Your profile photo has been updated.",
"data": {
"avatar_url": "/storage/avatars/employees/BlRaQOE7e1f5iXoxW40ek9H2IYGSe998YjY9LItd.jpg"
},
"errors": null,
"meta": {
"request_id": "c3d2c124-78c4-49c6-beac-5278c8e18aed",
"timestamp": "2026-08-05T16:18:35.399573Z"
}
}
Example response (422, Not an image):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "photo",
"message": "The photo must be an image."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-07-28T10:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Request Email Change
requires authentication
Request an email change with verification to the new email.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/profile/email/request-change" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"new_email\": \"name@example.at\",
\"password\": \"S3cure-Passw0rd!\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/profile/email/request-change"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"new_email": "name@example.at",
"password": "S3cure-Passw0rd!"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/profile/email/request-change';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'new_email' => 'name@example.at',
'password' => 'S3cure-Passw0rd!',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/profile/email/request-change');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"new_email": "name@example.at",
"password": "S3cure-Passw0rd!"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Verification email sent. Please check your inbox to confirm the change.",
"data": {
"pending_email": "ganz.neue@example.at",
"expires_at": "2026-08-05T16:48:35+00:00",
"verification_sent_to": "ganz.neue@example.at"
},
"errors": null,
"meta": {
"request_id": "f0798fcd-a4d3-4ab4-b502-97285b1866f5",
"timestamp": "2026-08-05T16:18:35.641680Z"
}
}
Example response (409, Address already in use):
{
"status": "EMAIL_ALREADY_EXISTS",
"message": "That email address is already taken.",
"data": null,
"errors": [
{
"field": "new_email",
"message": "That email address is already taken."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-07-28T10:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Cancel Pending Email
requires authentication
Cancel a pending email change request.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/mobile/profile/email/pending" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/profile/email/pending"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/profile/email/pending';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/profile/email/pending');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The pending email change has been cancelled.",
"data": {
"cancelled_email": "neue.adresse@example.at",
"current_email": "pending@demo.flexxr.at"
},
"errors": null,
"meta": {
"request_id": "1afeaa90-82ab-4363-8d65-679ca592a11a",
"timestamp": "2026-08-05T16:18:35.656630Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Set Phone Number
requires authentication
Add a phone number (country code + local number, as in registration) to an account whose phone has never been verified — typically a social-login account. Refused once a verified number exists; use the phone-change flow instead.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/profile/phone" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"country_code\": \"+43\",
\"phone_number\": \"6641234567\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/profile/phone"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"country_code": "+43",
"phone_number": "6641234567"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/profile/phone';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'country_code' => '+43',
'phone_number' => '6641234567',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/profile/phone');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"country_code": "+43",
"phone_number": "6641234567"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Saved):
{
"status": "SUCCESS",
"message": "Phone number saved. Please verify it.",
"data": {
"country_code": "+43",
"phone_number": "6641234567",
"phone": "+436641234567",
"phone_verified": false,
"next_step": "phone_verification"
},
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-08-13T10:00:00.000000Z"
}
}
Example response (409, Already verified):
{
"status": "INVALID_OPERATION",
"message": "Your phone number is verified. Use the phone change flow to replace it.",
"data": null,
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-08-13T10:00:00.000000Z"
}
}
Example response (409, Number taken):
{
"status": "PHONE_ALREADY_EXISTS",
"message": "This phone number is already registered to another account.",
"data": null,
"errors": [
{
"field": "phone_number",
"message": "This phone number is already registered to another account."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-08-13T10:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Request Phone Change
requires authentication
Request a phone number change.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/profile/phone/request-change" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"country_code\": \"AT\",
\"phone_number\": \"6641234567\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/profile/phone/request-change"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"country_code": "AT",
"phone_number": "6641234567"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/profile/phone/request-change';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'country_code' => 'AT',
'phone_number' => '6641234567',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/profile/phone/request-change');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"country_code": "AT",
"phone_number": "6641234567"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Code sent):
{
"status": "SUCCESS",
"message": "We sent a verification code to the new number.",
"data": {
"pending_phone": "+436641234567",
"expires_at": "2026-07-28T10:10:00+00:00"
},
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-07-28T10:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Verify Phone Change
requires authentication
Complete a phone number change using a Firebase Phone Auth ID token.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/profile/phone/verify" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"firebase_id_token\": \"Beispieltext\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/profile/phone/verify"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"firebase_id_token": "Beispieltext"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/profile/phone/verify';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'firebase_id_token' => 'Beispieltext',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/profile/phone/verify');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"firebase_id_token": "Beispieltext"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Verified):
{
"status": "SUCCESS",
"message": "Phone number updated.",
"data": {
"phone_number": "6641234567",
"country_code": "+43",
"phone_verified_at": "2026-07-28T10:05:00+00:00"
},
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-07-28T10:00:00.000000Z"
}
}
Example response (422, Wrong code):
{
"status": "VALIDATION_ERROR",
"message": "That code is not valid.",
"data": null,
"errors": [
{
"field": "code",
"message": "That code is not valid."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-07-28T10:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Cancel Pending Phone
requires authentication
Cancel a pending phone change request.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/mobile/profile/phone/pending" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/profile/phone/pending"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/profile/phone/pending';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/profile/phone/pending');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The pending phone change has been cancelled.",
"data": {
"cancelled_phone": "+436641239876",
"current_phone": "+436769876543"
},
"errors": null,
"meta": {
"request_id": "64b580b3-bf62-4a88-9be6-28b5ed633dcc",
"timestamp": "2026-08-05T16:18:35.683946Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Documents
List My Documents
requires authentication
Everything the worker has uploaded, with each document's review state —
pending, verified, rejected, reupload_requested, expired or
superseded — and the reviewer's note where one was left.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/documents" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/documents"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/documents';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/documents');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"documents": [
{
"id": "019fd2b7-f280-73fe-83af-4fdd5f9db332",
"type": "id_card",
"type_label": "ID card",
"original_filename": "ausweis.pdf",
"status": "pending",
"status_label": "Ausstehend",
"status_color": "yellow",
"rejection_reason": null,
"expires_at": null,
"is_expired": false,
"expires_soon": false,
"is_valid": false,
"created_at": "2026-08-05 16:18:18"
},
{
"id": "019fd2b8-28ce-735c-aa32-c03c49655e69",
"type": "passport",
"type_label": "Passport",
"original_filename": "veniam.pdf",
"status": "verified",
"status_label": "Verifiziert",
"status_color": "green",
"rejection_reason": null,
"expires_at": "2033-05-22",
"is_expired": false,
"expires_soon": false,
"is_valid": true,
"created_at": "2026-08-05 16:18:32"
}
],
"counts": {
"total": 2,
"pending": 1,
"verified": 1,
"rejected": 0,
"expiring_soon": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Document Checklist
requires authentication
Which documents this worker must provide before their profile can be submitted, and whether each is satisfied. The set is not fixed: a third-country national is additionally asked for work authorisation, resolved from the residence status on their profile.
items holds both kinds in one list, required ones first, each marked
with required:
required: true— the platform asks every worker for this, and it gates profile submission. Only these decideready.required: false— nobody is obliged to hold it, but a company may put it on a job as a requirement. Returned so a worker can upload one before any job asks: verification is a manual review rather than an instant check, so arriving with the document already verified is the difference between applying and missing the deadline.
accepts lists the document types that satisfy the item — several for a
required slot (identity takes a passport or an ID card), exactly one
for an optional entry. Those values are what POST /mobile/documents
takes as type and what a job requirement names, so an upload made from
this list satisfies the matching requirement with no further mapping.
document is the file answering the item, in the same shape
GET /mobile/documents returns, or null when nothing has been
uploaded against it. Where a worker holds several of one type the most
relevant wins, so a replacement outranks the rejection it replaced.
Note that satisfied means "on file", which includes a document still
under review — document.status is what separates pending from
verified, and only a verified one counts towards a job requirement.
counts summarises the worker's uploads and matches
GET /mobile/documents exactly, so the screen needs one call rather
than two.
This is the account-level checklist. For what a particular job demands,
use GET /jobs/{jobId}/requirements.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/documents/checklist" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/documents/checklist"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/documents/checklist';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/documents/checklist');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The document checklist has been retrieved.",
"data": {
"ready": false,
"items": [
{
"key": "identity",
"label": "Reisepass oder Personalausweis",
"accepts": [
"passport",
"id_card"
],
"required": true,
"satisfied": true,
"document": {
"id": "019fd2b8-28ce-735c-aa32-c03c49655e69",
"type": "passport",
"type_label": "Passport",
"original_filename": "veniam.pdf",
"status": "verified",
"status_label": "Verifiziert",
"status_color": "green",
"rejection_reason": null,
"expires_at": "2033-05-22",
"is_expired": false,
"expires_soon": false,
"is_valid": true,
"created_at": "2026-08-05 16:18:32"
}
},
{
"key": "address_proof",
"label": "Meldezettel",
"accepts": [
"proof_of_address"
],
"required": true,
"satisfied": false,
"document": null
},
{
"key": "social_insurance",
"label": "e-card (Sozialversicherung)",
"accepts": [
"social_insurance_card"
],
"required": true,
"satisfied": false,
"document": null
},
{
"key": "bank",
"label": "Kontoauszug",
"accepts": [
"bank_statement"
],
"required": true,
"satisfied": false,
"document": null
},
{
"key": "driver_license",
"label": "Driver's licence",
"accepts": [
"driver_license"
],
"required": false,
"satisfied": false,
"document": null
},
{
"key": "certification",
"label": "Certification",
"accepts": [
"certification"
],
"required": false,
"satisfied": false,
"document": null
},
{
"key": "health_certificate",
"label": "Health certificate",
"accepts": [
"health_certificate"
],
"required": false,
"satisfied": false,
"document": null
},
{
"key": "criminal_record_check",
"label": "Criminal record check",
"accepts": [
"criminal_record_check"
],
"required": false,
"satisfied": false,
"document": null
},
{
"key": "tax_document",
"label": "Tax document",
"accepts": [
"tax_document"
],
"required": false,
"satisfied": false,
"document": null
}
],
"counts": {
"total": 2,
"pending": 1,
"verified": 1,
"rejected": 0,
"expiring_soon": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Upload a Document
requires authentication
Submits one of the documents the profile or a job requires. The type
matches the requirement_code returned by
GET /jobs/{jobId}/requirements, so the app can pass it straight through
from the row the worker tapped.
Uploading does not satisfy a requirement on its own — the document lands
as pending and an administrator verifies it. Until then the checklist
still reports the item as outstanding, and applications that depend on it
are still refused.
Two-sided documents may send file_back alongside file.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/documents" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "type=social_insurance_card"\
--form "document_number=AT1234567"\
--form "issued_at=2024-03-01"\
--form "expires_at=2034-03-01"\
--form "issuing_country=AT"\
--form "issuing_authority=Magistrat Wien"\
--form "file=@/tmp/php7ob920j5k99q5t0Rmk6" const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/documents"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('type', 'social_insurance_card');
body.append('document_number', 'AT1234567');
body.append('issued_at', '2024-03-01');
body.append('expires_at', '2034-03-01');
body.append('issuing_country', 'AT');
body.append('issuing_authority', 'Magistrat Wien');
body.append('file', document.querySelector('input[name="file"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/documents';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'multipart/form-data',
'Accept' => 'application/json',
],
'multipart' => [
[
'name' => 'type',
'contents' => 'social_insurance_card'
],
[
'name' => 'document_number',
'contents' => 'AT1234567'
],
[
'name' => 'issued_at',
'contents' => '2024-03-01'
],
[
'name' => 'expires_at',
'contents' => '2034-03-01'
],
[
'name' => 'issuing_country',
'contents' => 'AT'
],
[
'name' => 'issuing_authority',
'contents' => 'Magistrat Wien'
],
[
'name' => 'file',
'contents' => fopen('/tmp/php7ob920j5k99q5t0Rmk6', 'r')
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/documents');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'multipart/form-data',
'Accept': 'application/json',
};
final request = http.MultipartRequest('POST', uri);
request.headers.addAll(headers);
request.fields['type'] = 'social_insurance_card';
request.fields['document_number'] = 'AT1234567';
request.fields['issued_at'] = '2024-03-01';
request.fields['expires_at'] = '2034-03-01';
request.fields['issuing_country'] = 'AT';
request.fields['issuing_authority'] = 'Magistrat Wien';
request.files.add(await http.MultipartFile.fromPath('file', '/tmp/php7ob920j5k99q5t0Rmk6'));
final streamed = await request.send();
final response = await http.Response.fromStream(streamed);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The document has been uploaded successfully.",
"data": {
"document": {
"id": "019fd2b8-672d-7348-ae17-4de67610d176",
"type": "work_permit",
"type_label": "Work permit",
"original_filename": "reisepass.pdf",
"status": "pending",
"status_label": "Ausstehend",
"status_color": "yellow",
"rejection_reason": null,
"expires_at": "2027-08-05",
"is_expired": false,
"expires_soon": false,
"is_valid": false,
"created_at": "2026-08-05 16:18:48",
"has_back_side": false
}
}
}
Example response (422, Rejected file):
{
"status": "VALIDATION_ERROR",
"message": "The file must be a PDF or image and no larger than the configured limit."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get a Document
requires authentication
One document with its review state and, when a reviewer rejected it, the reason they gave.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"document": {
"id": "019fd2b8-6103-7134-bdc4-ac4ec15c8ab5",
"type": "passport",
"type_label": "Passport",
"original_filename": "reisepass.pdf",
"mime_type": "application/pdf",
"file_size": 131072,
"status": "ocr_failed",
"status_label": "OCR fehlgeschlagen",
"status_color": "orange",
"rejection_reason": null,
"document_number": null,
"issued_at": null,
"expires_at": null,
"issuing_country": null,
"issuing_authority": null,
"is_expired": false,
"expires_soon": false,
"is_valid": false,
"reviewed_at": null,
"created_at": "2026-08-05 16:18:46",
"download_url": "http://localhost:8001/api/v1/mobile/documents/019fd2b8-6103-7134-bdc4-ac4ec15c8ab5/download",
"has_back_side": false
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Download a Document
requires authentication
Streams the worker's own file. The link is short-lived by design — a document contains identity data and should not sit in a shareable URL.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2/download" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2/download"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2/download';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2/download');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "948c444a-46c2-4c6e-b672-2eb6ffadfda0",
"timestamp": "2026-08-21T05:14:33.114939Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Replace a Document
requires authentication
Supersedes an existing document — used after a reviewer rejects one or
asks for a fresh copy, and when the original has expired. The previous
version is archived rather than deleted, so the review history stays
intact, and the replacement enters pending for verification.
The type is taken from the document being replaced and cannot be changed;
upload a new document instead. Everything else the upload endpoint
accepts is accepted here, file_back included — a two-sided document
replaced without its reverse side would lose it.
expires_at is required when replacing a work-authorisation document
(permit, Rot-Weiß-Rot Karte, EU Blue Card): that date decides whether its
holder may still be sent to a shift, and one without it counts as
expired.
This is a POST with a multipart/form-data body. It also needs an
Idempotency-Key header; replaying the same key returns the first result
rather than superseding the document twice.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "document_number=AT1234567"\
--form "issued_at=2024-03-01"\
--form "expires_at=2034-03-01"\
--form "issuing_country=AT"\
--form "issuing_authority=Magistrat Wien"\
--form "file=@/tmp/phpiob44qtm7pg23rOcGlH" const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('document_number', 'AT1234567');
body.append('issued_at', '2024-03-01');
body.append('expires_at', '2034-03-01');
body.append('issuing_country', 'AT');
body.append('issuing_authority', 'Magistrat Wien');
body.append('file', document.querySelector('input[name="file"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'multipart/form-data',
'Accept' => 'application/json',
],
'multipart' => [
[
'name' => 'document_number',
'contents' => 'AT1234567'
],
[
'name' => 'issued_at',
'contents' => '2024-03-01'
],
[
'name' => 'expires_at',
'contents' => '2034-03-01'
],
[
'name' => 'issuing_country',
'contents' => 'AT'
],
[
'name' => 'issuing_authority',
'contents' => 'Magistrat Wien'
],
[
'name' => 'file',
'contents' => fopen('/tmp/phpiob44qtm7pg23rOcGlH', 'r')
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'multipart/form-data',
'Accept': 'application/json',
};
final request = http.MultipartRequest('POST', uri);
request.headers.addAll(headers);
request.fields['document_number'] = 'AT1234567';
request.fields['issued_at'] = '2024-03-01';
request.fields['expires_at'] = '2034-03-01';
request.fields['issuing_country'] = 'AT';
request.fields['issuing_authority'] = 'Magistrat Wien';
request.files.add(await http.MultipartFile.fromPath('file', '/tmp/phpiob44qtm7pg23rOcGlH'));
final streamed = await request.send();
final response = await http.Response.fromStream(streamed);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The document has been re-uploaded and is awaiting review.",
"data": {
"document": {
"id": "019fd2b8-36f1-70c6-8a88-6e076134cc2a",
"type": "id_card",
"type_label": "ID card",
"original_filename": "beispiel.pdf",
"status": "pending",
"status_label": "Ausstehend",
"status_color": "yellow",
"rejection_reason": null,
"expires_at": "2034-03-01",
"is_expired": false,
"expires_soon": false,
"is_valid": false,
"created_at": "2026-08-05 16:18:35",
"supersedes": "019fd2b7-f280-73fe-83af-4fdd5f9db332"
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete a Document
requires authentication
Removes a document the worker uploaded. A verified document that a requirement depends on cannot simply be dropped — replace it instead, so the profile does not silently fall out of compliance.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/mobile/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The document has been deleted successfully."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List My Attachments
requires authentication
Files the worker has supplied that the platform does not review — a reference, a course certificate, anything a company asked to see that the document types do not name.
These are not documents. They carry no review status and no expiry, a
worker may hold as many as they like, and none of them satisfies a job
requirement — nothing has checked what they contain. Use
GET /mobile/documents for the reviewed set.
They share the worker's storage quota with documents, so quota is
returned alongside: used_bytes split by what is consuming it, against
the same limit_bytes an upload is refused for exceeding.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/attachments" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/attachments"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/attachments';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/attachments');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"attachments": [
{
"id": "019fd2b8-29e0-72e1-be30-9be100181d40",
"label": "voluptas nihil",
"original_filename": "est.pdf",
"mime_type": "application/pdf",
"file_size": 293696,
"scanned_at": "2026-08-05T16:18:32+00:00",
"created_at": "2026-08-05 16:18:32"
}
],
"quota": {
"used_bytes": 1270224,
"documents_bytes": 976528,
"attachments_bytes": 293696,
"limit_bytes": 104857600,
"available_bytes": 103587376
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Add an Attachment
requires authentication
Supplies a file the platform does not review: a reference, a course
certificate, whatever a company asked to see that the document types do
not name. label says what it is, and is required — a reviewer looking at
an application cannot act on an untitled file.
A worker may hold as many as they like, including several with the same
label. Nothing here expires, nothing enters the review queue, and an
attachment never satisfies a job requirement — the platform has not
checked it. Use POST /mobile/documents for anything that has to be
verified.
The file is still scanned for malware, and still counts against the same storage quota as documents; an infected file is removed rather than rejected, since there is no review state to move it to.
Same size and format limits as a document: PDF, JPEG, PNG or WebP.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/attachments" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "label=Staplerschein"\
--form "file=@/tmp/phpdqrl4bufd3tvc9m5wFw" const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/attachments"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('label', 'Staplerschein');
body.append('file', document.querySelector('input[name="file"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/attachments';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'multipart/form-data',
'Accept' => 'application/json',
],
'multipart' => [
[
'name' => 'label',
'contents' => 'Staplerschein'
],
[
'name' => 'file',
'contents' => fopen('/tmp/phpdqrl4bufd3tvc9m5wFw', 'r')
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/attachments');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'multipart/form-data',
'Accept': 'application/json',
};
final request = http.MultipartRequest('POST', uri);
request.headers.addAll(headers);
request.fields['label'] = 'Staplerschein';
request.files.add(await http.MultipartFile.fromPath('file', '/tmp/phpdqrl4bufd3tvc9m5wFw'));
final streamed = await request.send();
final response = await http.Response.fromStream(streamed);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The attachment has been added.",
"data": {
"attachment": {
"id": "019fd2b8-3720-719d-87d9-bb06b1cafe16",
"label": "Staplerschein",
"original_filename": "beispiel.pdf",
"mime_type": "application/pdf",
"file_size": 65536,
"scanned_at": null,
"created_at": "2026-08-05 16:18:35"
},
"quota": {
"used_bytes": 1335760,
"documents_bytes": 976528,
"attachments_bytes": 359232,
"limit_bytes": 104857600,
"available_bytes": 103521840
}
}
}
Example response (422, Quota exhausted):
{
"status": "INVALID_OPERATION",
"message": "The storage quota has been reached.",
"data": {
"quota": {
"used_bytes": 104857600,
"documents_bytes": 94371840,
"attachments_bytes": 10485760,
"limit_bytes": 104857600,
"available_bytes": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete an Attachment
requires authentication
Removes a file the worker attached, freeing the storage it occupied. Nothing depends on an attachment — it satisfies no requirement and is part of no review — so it is deleted outright rather than superseded the way a document is.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/mobile/attachments/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/attachments/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/attachments/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/attachments/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The attachment has been removed."
}
Example response (404, Not found):
{
"status": "RESOURCE_NOT_FOUND",
"message": "The attachment was not found."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Jobs
List Job Categories
Returns all active job categories in a hierarchical structure.
Root categories are returned at the top level; their active children are
nested under the children key.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/job-categories?include_children=1&featured_only=" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/job-categories"
);
const params = {
"include_children": "1",
"featured_only": "0",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/job-categories';
$response = $client->get(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'include_children' => '1',
'featured_only' => '0',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/job-categories')
.replace(queryParameters: {
'include_children': '1',
'featured_only': '',
});
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"categories": [
{
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_en": "Gastronomy",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null,
"kollektivvertrag": "Gastgewerbe",
"description": null,
"is_featured": true,
"parent_id": null,
"sort_order": 1,
"children": []
},
{
"id": "019fd2b7-f375-724e-84b8-4f9647ef6419",
"slug": "hotel",
"name": "Hotellerie",
"name_en": "Hospitality",
"name_localized": "Hospitality",
"icon": "hotel",
"color": null,
"kollektivvertrag": "Hotel- und Gastgewerbe",
"description": null,
"is_featured": true,
"parent_id": null,
"sort_order": 2,
"children": []
},
{
"id": "019fd2b7-f377-7108-8400-efa89715a39f",
"slug": "food_service",
"name": "Food Service",
"name_en": "Food Service",
"name_localized": "Food Service",
"icon": "utensils",
"color": null,
"kollektivvertrag": "Gastgewerbe",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 3,
"children": []
},
{
"id": "019fd2b7-f37a-72a9-84a9-7862f636e2fd",
"slug": "catering",
"name": "Catering",
"name_en": "Catering",
"name_localized": "Catering",
"icon": "utensils",
"color": null,
"kollektivvertrag": "Gastgewerbe",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 4,
"children": []
},
{
"id": "019fd2b7-f37d-712d-92b3-aa5540f6b2a7",
"slug": "retail",
"name": "Einzelhandel",
"name_en": "Retail",
"name_localized": "Retail",
"icon": "shopping-cart",
"color": null,
"kollektivvertrag": "Handel",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 5,
"children": []
},
{
"id": "019fd2b7-f380-7300-91c6-75c968e6d045",
"slug": "supermarket",
"name": "Lebensmittelhandel",
"name_en": "Grocery",
"name_localized": "Grocery",
"icon": "shopping-cart",
"color": null,
"kollektivvertrag": "Handel",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 6,
"children": []
},
{
"id": "019fd2b7-f384-7071-b096-674d16b4ad00",
"slug": "pharmacy",
"name": "Apotheke",
"name_en": "Pharmacy",
"name_localized": "Pharmacy",
"icon": "heart-pulse",
"color": null,
"kollektivvertrag": "Pharmazeutischer Großhandel",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 7,
"children": []
},
{
"id": "019fd2b7-f388-7098-b463-ae170338e60f",
"slug": "production",
"name": "Produktion",
"name_en": "Production",
"name_localized": "Production",
"icon": "industry",
"color": null,
"kollektivvertrag": "Industrie",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 8,
"children": []
},
{
"id": "019fd2b7-f38b-7209-8b83-b345b172def2",
"slug": "warehouse",
"name": "Lager",
"name_en": "Warehouse",
"name_localized": "Warehouse",
"icon": "industry",
"color": null,
"kollektivvertrag": "Industrie",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 9,
"children": []
},
{
"id": "019fd2b7-f38e-7255-bfe3-0f010aca0086",
"slug": "logistics",
"name": "Logistik",
"name_en": "Logistics",
"name_localized": "Logistics",
"icon": "truck",
"color": null,
"kollektivvertrag": "Industrie",
"description": null,
"is_featured": true,
"parent_id": null,
"sort_order": 10,
"children": []
},
{
"id": "019fd2b7-f391-727d-9871-61207ae27ab3",
"slug": "manufacturing",
"name": "Fertigung",
"name_en": "Manufacturing",
"name_localized": "Manufacturing",
"icon": "industry",
"color": null,
"kollektivvertrag": "Industrie",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 11,
"children": []
},
{
"id": "019fd2b7-f394-7015-b80e-5fa954b27658",
"slug": "transportation",
"name": "Transport",
"name_en": "Transportation",
"name_localized": "Transportation",
"icon": "truck",
"color": null,
"kollektivvertrag": "Güterbeförderungsgewerbe",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 12,
"children": []
},
{
"id": "019fd2b7-f398-7300-a216-c64584fea8f7",
"slug": "event",
"name": "Events",
"name_en": "Events",
"name_localized": "Events",
"icon": "calendar-star",
"color": null,
"kollektivvertrag": "Veranstaltungsdienstleistung",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 13,
"children": []
},
{
"id": "019fd2b7-f39c-7064-8f21-15054bddd646",
"slug": "security",
"name": "Security",
"name_en": "Security",
"name_localized": "Security",
"icon": "shield",
"color": null,
"kollektivvertrag": "Bewachungsgewerbe",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 14,
"children": []
},
{
"id": "019fd2b7-f39f-73e6-870b-fe7584e4f9bc",
"slug": "office",
"name": "Büro",
"name_en": "Office",
"name_localized": "Office",
"icon": "briefcase",
"color": null,
"kollektivvertrag": "Handel/Büro",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 15,
"children": []
},
{
"id": "019fd2b7-f3a2-7147-883f-c3207db81b51",
"slug": "reception",
"name": "Empfang",
"name_en": "Reception",
"name_localized": "Reception",
"icon": "briefcase",
"color": null,
"kollektivvertrag": "Handel/Büro",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 16,
"children": []
},
{
"id": "019fd2b7-f3a5-70a8-a3b1-9140f01abf8e",
"slug": "call_center",
"name": "Call Center",
"name_en": "Call Center",
"name_localized": "Call Center",
"icon": "briefcase",
"color": null,
"kollektivvertrag": "Handel/Büro",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 17,
"children": []
},
{
"id": "019fd2b7-f3a8-72f6-8ad1-0f499f6816e1",
"slug": "customer_service",
"name": "Kundenservice",
"name_en": "Customer Service",
"name_localized": "Customer Service",
"icon": "briefcase",
"color": null,
"kollektivvertrag": "Handel/Büro",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 18,
"children": []
},
{
"id": "019fd2b7-f3ab-70a0-9523-b474e2007212",
"slug": "software",
"name": "Software",
"name_en": "Software",
"name_localized": "Software",
"icon": "code",
"color": null,
"kollektivvertrag": "IT-KV",
"description": null,
"is_featured": true,
"parent_id": null,
"sort_order": 19,
"children": []
},
{
"id": "019fd2b7-f3c2-73b2-9873-51431d14404e",
"slug": "it_services",
"name": "IT Services",
"name_en": "IT Services",
"name_localized": "IT Services",
"icon": "code",
"color": null,
"kollektivvertrag": "IT-KV",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 20,
"children": []
},
{
"id": "019fd2b7-f3cc-728f-a1eb-11d5120b3dca",
"slug": "cleaning",
"name": "Reinigung",
"name_en": "Cleaning",
"name_localized": "Cleaning",
"icon": "broom",
"color": null,
"kollektivvertrag": "Gebäudereinigung",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 21,
"children": []
},
{
"id": "019fd2b7-f3d1-72e1-a261-10207b6d759d",
"slug": "facility",
"name": "Facility Management",
"name_en": "Facility Management",
"name_localized": "Facility Management",
"icon": "broom",
"color": null,
"kollektivvertrag": "Gebäudereinigung",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 22,
"children": []
},
{
"id": "019fd2b7-f3d5-71b4-bece-4ea026852495",
"slug": "care",
"name": "Pflege/Betreuung",
"name_en": "Care",
"name_localized": "Care",
"icon": "heart-pulse",
"color": null,
"kollektivvertrag": "Sozialwirtschaft",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 23,
"children": []
},
{
"id": "019fd2b7-f3d8-72d5-842e-c1f00337e9ec",
"slug": "healthcare",
"name": "Gesundheitswesen",
"name_en": "Healthcare",
"name_localized": "Healthcare",
"icon": "heart-pulse",
"color": null,
"kollektivvertrag": "Sozialwirtschaft",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 24,
"children": []
},
{
"id": "019fd2b7-f3dc-70cb-a662-0fc23b0ec307",
"slug": "construction",
"name": "Bau (Hilfstätigkeiten)",
"name_en": "Construction",
"name_localized": "Construction",
"icon": "building",
"color": null,
"kollektivvertrag": "Bauindustrie",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 25,
"children": []
},
{
"id": "019fd2b7-f3df-70bb-8881-36c5f2234495",
"slug": "real_estate",
"name": "Immobilien",
"name_en": "Real Estate",
"name_localized": "Real Estate",
"icon": "building",
"color": null,
"kollektivvertrag": "Bauindustrie",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 26,
"children": []
},
{
"id": "019fd2b7-f3e5-714f-8db2-a5ae4350ae5c",
"slug": "graphic_design",
"name": "Grafikdesign",
"name_en": "Graphic Design",
"name_localized": "Graphic Design",
"icon": "palette",
"color": null,
"kollektivvertrag": "Werbewirtschaft",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 27,
"children": []
},
{
"id": "019fd2b7-f3e9-71c6-b382-7451adaf4bb7",
"slug": "media",
"name": "Medien",
"name_en": "Media",
"name_localized": "Media",
"icon": "palette",
"color": null,
"kollektivvertrag": "Werbewirtschaft",
"description": null,
"is_featured": true,
"parent_id": null,
"sort_order": 28,
"children": []
},
{
"id": "019fd2b7-f3ec-717a-ac4d-13011f3096f1",
"slug": "education",
"name": "Bildung",
"name_en": "Education",
"name_localized": "Education",
"icon": "graduation-cap",
"color": null,
"kollektivvertrag": "Bildungseinrichtungen",
"description": null,
"is_featured": true,
"parent_id": null,
"sort_order": 29,
"children": []
},
{
"id": "019fd2b7-f3f0-70a8-b7be-6be4c17c9429",
"slug": "finance",
"name": "Finanzen",
"name_en": "Finance",
"name_localized": "Finance",
"icon": "chart-line",
"color": null,
"kollektivvertrag": "Banken und Versicherungen",
"description": null,
"is_featured": true,
"parent_id": null,
"sort_order": 30,
"children": []
},
{
"id": "019fd2b7-f3f3-737d-9abe-5edb92ceb02a",
"slug": "agriculture",
"name": "Landwirtschaft",
"name_en": "Agriculture",
"name_localized": "Agriculture",
"icon": "leaf",
"color": null,
"kollektivvertrag": "Land- und Forstwirtschaft",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 31,
"children": []
},
{
"id": "019fd2b7-f3f6-70c7-868b-6ac419f0d02c",
"slug": "other",
"name": "Sonstiges",
"name_en": "Other",
"name_localized": "Other",
"icon": "ellipsis",
"color": null,
"kollektivvertrag": "Arbeitskräfteüberlasser",
"description": null,
"is_featured": false,
"parent_id": null,
"sort_order": 32,
"children": []
}
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Available Jobs
Returns available jobs with comprehensive filtering options. Supports location (state/radius), category, rate range, shift type, and sorting.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/jobs?sort=highest_salary&exclude_applied=1&per_page=15" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/jobs"
);
const params = {
"sort": "highest_salary",
"exclude_applied": "1",
"per_page": "15",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/jobs';
$response = $client->get(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'sort' => 'highest_salary',
'exclude_applied' => '1',
'per_page' => '15',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/jobs')
.replace(queryParameters: {
'sort': 'highest_salary',
'exclude_applied': '1',
'per_page': '15',
});
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"jobs": [
{
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant",
"description": "Ut nostrum rerum ut alias quia libero excepturi. Voluptatum et aut non quia quisquam molestias. Perferendis qui hic unde.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f39f-73e6-870b-fe7584e4f9bc",
"slug": "office",
"name": "Büro",
"name_localized": "Office",
"icon": "briefcase",
"color": null
},
"tags": [
"Office",
"Nachtschicht"
],
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Barrows, Christiansen and Jones",
"address": "586 Tremaine Row",
"city": "East Eliseo",
"postal_code": "10547-3697",
"lat": 46.931383,
"lng": 11.998284,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-12",
"end_date": "2026-08-19",
"shift_start_time": "01:49:00",
"shift_end_time": "18:57:00",
"shift_type": "night",
"shift_type_label": "Nachtschicht",
"duration_hours": 17.133333333333333
},
"compensation": {
"hourly_rate_gross": 32.08,
"supplements": {
"night": 0.7,
"weekend": 3.86
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 5,
"filled": 0,
"available": 5
},
"deadlines": {
"application": "2026-09-05T16:18:32+00:00"
},
"created_at": "2026-08-05T16:18:32+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
{
"id": "019fd2b8-1ccb-7322-8d33-448afd9b027b",
"title": "Testingenieur Vertretung",
"description": "Wir suchen engagierte Testingenieur Vertretung zur Verstärkung unseres Teams. Sie erwartet ein abwechslungsreiches Aufgabengebiet in einem dynamischen Umfeld.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f3c2-73b2-9873-51431d14404e",
"slug": "it_services",
"name": "IT Services",
"name_localized": "IT Services",
"icon": "code",
"color": null
},
"tags": [
"IT Services",
"Tagschicht"
],
"organization": {
"id": "019fd2b7-f842-71ba-a318-a919a24d4bcf",
"name": "Hotel & Spa Imperial",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "BAWAG IT-Abteilung",
"address": "Wiesingerstraße 4, 1010 Wien",
"city": "Wien",
"postal_code": "1030",
"lat": 48.2006,
"lng": 16.3882,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-15",
"end_date": "2026-09-04",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 25,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 1,
"filled": 0,
"available": 1
},
"deadlines": {
"application": "2026-08-12T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:29+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
{
"id": "019fd2b8-1405-709f-bca9-b0a418fb6a75",
"title": "Silvesternacht Service",
"description": "Wir suchen motivierte Silvesternacht Service für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Nachtschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-fe56-70d1-bb3a-641339ce636a",
"name": "Lagerhaus Steiermark",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Hotel Imperial Wien",
"address": "Kärntner Ring 16, 1015 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2082,
"lng": 16.3739,
"distance_km": null
},
"schedule": {
"start_date": "2027-02-09",
"end_date": "2027-02-10",
"shift_start_time": "22:00:00",
"shift_end_time": "06:00:00",
"shift_type": "night",
"shift_type_label": "Nachtschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 25,
"supplements": {
"night_bonus": 50,
"holiday_bonus": 100,
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 12,
"filled": 0,
"available": 12
},
"deadlines": {
"application": "2027-02-04T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
{
"id": "019fd2b8-1cb9-72ec-bbe0-4f5f78a6a459",
"title": "IT Helpdesk Mitarbeiter*in",
"description": "Für unser IT-Team suchen wir erfahrene IT Helpdesk Mitarbeiter*in. Sie unterstützen bei technischen Aufgaben, Systemwartung und Kundensupport.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f3ab-70a0-9523-b474e2007212",
"slug": "software",
"name": "Software",
"name_localized": "Software",
"icon": "code",
"color": null
},
"tags": [
"Software",
"Tagschicht",
"IT-Grundkenntnisse",
"Windows/Mac Erfahrung"
],
"organization": {
"id": "019fd2b7-fbb4-73fa-b801-e0c8a8de2651",
"name": "Bauwerk GmbH",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Erste Bank IT",
"address": "Graben 21, 1010 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2082,
"lng": 16.3739,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-10",
"end_date": "2026-11-03",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 22,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 2,
"filled": 0,
"available": 2
},
"deadlines": {
"application": "2026-08-08T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:29+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
{
"id": "019fd2b8-1ce9-736a-9a61-22cea78283c9",
"title": "Support-Techniker Außeneinsatz",
"description": "Wir suchen engagierte Support-Techniker Außeneinsatz zur Verstärkung unseres Teams. Sie erwartet ein abwechslungsreiches Aufgabengebiet in einem dynamischen Umfeld.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f3c2-73b2-9873-51431d14404e",
"slug": "it_services",
"name": "IT Services",
"name_localized": "IT Services",
"icon": "code",
"color": null
},
"tags": [
"IT Services",
"Tagschicht"
],
"organization": {
"id": "019fd2b7-f91f-70cb-8409-8632db9df3c7",
"name": "Sicherheitsdienst Österreich",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "IT Company Graz",
"address": "Münzgrabenstraße 10, 8010 Graz",
"city": "Graz",
"postal_code": "8020",
"lat": 47.064,
"lng": 15.46,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-12",
"end_date": "2026-10-04",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 20,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 2,
"filled": 0,
"available": 2
},
"deadlines": {
"application": "2026-08-10T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:29+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
{
"id": "019fd2b8-1615-7120-9b3f-e0d90c1f57ef",
"title": "Barkraft VIP-Lounge",
"description": "Für unsere bevorstehende Veranstaltung suchen wir tatkräftige Unterstützung. Als Barkraft VIP-Lounge sind Sie das Aushängeschild unserer Veranstaltung und sorgen für einen reibungslosen Ablauf.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f398-7300-a216-c64584fea8f7",
"slug": "event",
"name": "Events",
"name_localized": "Events",
"icon": "calendar-star",
"color": null
},
"tags": [
"Events",
"Tagschicht"
],
"organization": {
"id": "019fd2b7-fad7-719c-887a-a0f510bbd31d",
"name": "IT Solutions GmbH",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Salzburger Festspiele",
"address": "Hofstallgasse 1, 5020 Salzburg",
"city": "Salzburg",
"postal_code": "5020",
"lat": 47.8095,
"lng": 13.055,
"distance_km": null
},
"schedule": {
"start_date": "2026-10-24",
"end_date": "2026-11-13",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 18,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 5,
"filled": 0,
"available": 5
},
"deadlines": {
"application": "2026-10-21T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:27+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
{
"id": "019fd2b8-1d1e-7188-9438-b0d6050c492a",
"title": "Kursleiter*in Deutschkurs",
"description": "Wir suchen engagierte Kursleiter*in Deutschkurs zur Verstärkung unseres Teams. Sie erwartet ein abwechslungsreiches Aufgabengebiet in einem dynamischen Umfeld.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f3ec-717a-ac4d-13011f3096f1",
"slug": "education",
"name": "Bildung",
"name_localized": "Education",
"icon": "graduation-cap",
"color": null
},
"tags": [
"Education",
"Tagschicht"
],
"organization": {
"id": "019fd2b8-00e8-7186-8fa6-5b042a30b10d",
"name": "Transport & Spedition GmbH",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "VHS Wien",
"address": "Mariahilfer Straße 53, 1060 Wien",
"city": "Wien",
"postal_code": "1050",
"lat": 48.1944,
"lng": 16.3585,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-12",
"end_date": "2026-11-03",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 18,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 3,
"filled": 0,
"available": 3
},
"deadlines": {
"application": "2026-08-09T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:29+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
{
"id": "019fd2b8-14dd-7377-92d2-447578550d00",
"title": "Convention Coordinator",
"description": "Wir suchen engagierte Convention Coordinator zur Verstärkung unseres Teams. Sie erwartet ein abwechslungsreiches Aufgabengebiet in einem dynamischen Umfeld.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f375-724e-84b8-4f9647ef6419",
"slug": "hotel",
"name": "Hotellerie",
"name_localized": "Hospitality",
"icon": "hotel",
"color": null
},
"tags": [
"Hospitality",
"Tagschicht"
],
"organization": {
"id": "019fd2b8-000d-719b-a73e-71665713a4fc",
"name": "Supermarkt AG",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Austria Center Vienna",
"address": "Bruno-Kreisky-Platz 1, 1220 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2082,
"lng": 16.3739,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-25",
"end_date": "2026-08-30",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 18,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 5,
"filled": 0,
"available": 5
},
"deadlines": {
"application": "2026-08-23T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:27+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
{
"id": "019fd2b8-17b4-72f3-9ab2-f5a5a2902d4c",
"title": "Staplerfahrer*in Zentrallager",
"description": "Wir suchen zuverlässige Staplerfahrer*in Zentrallager für unser Logistikzentrum. Sie unterstützen uns bei der Warenwirtschaft, Kommissionierung und dem allgemeinen Lagerbetrieb. Körperliche Belastbarkeit und Teamfähigkeit sind Voraussetzung.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f38e-7255-bfe3-0f010aca0086",
"slug": "logistics",
"name": "Logistik",
"name_localized": "Logistics",
"icon": "truck",
"color": null
},
"tags": [
"Logistics",
"Tagschicht",
"Körperliche Belastbarkeit",
"Deutschkenntnisse Grundstufe"
],
"organization": {
"id": "019fd2b7-f68e-713d-888b-ff71714f0874",
"name": "Logistik Austria GmbH",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "REWE Lager Linz",
"address": "Industriestraße 3, 4030 Linz",
"city": "Linz",
"postal_code": "4030",
"lat": 48.2757,
"lng": 14.3213,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-12",
"end_date": "2027-02-01",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 16.5,
"supplements": {
"weekend_bonus": 8,
"forklift_license": true
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 4,
"filled": 0,
"available": 4
},
"deadlines": {
"application": "2026-08-07T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:27+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
{
"id": "019fd2b8-1d63-71f8-b82b-eb790b71f0b3",
"title": "Produktionshelfer*in Fabrik",
"description": "Wir suchen engagierte Produktionshelfer*in Fabrik zur Verstärkung unseres Teams. Sie erwartet ein abwechslungsreiches Aufgabengebiet in einem dynamischen Umfeld.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f388-7098-b463-ae170338e60f",
"slug": "production",
"name": "Produktion",
"name_localized": "Production",
"icon": "industry",
"color": null
},
"tags": [
"Production",
"Tagschicht"
],
"organization": {
"id": "019fd2b7-f9fd-71a9-b71e-466dc30c8aac",
"name": "Pflege & Betreuung GmbH",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "voestalpine Stahl GmbH",
"address": "voestalpine-Straße 1, 4020 Linz",
"city": "Linz",
"postal_code": "4030",
"lat": 48.2757,
"lng": 14.3213,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-10",
"end_date": "2026-11-03",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 16.5,
"supplements": {
"weekend_bonus": 8,
"shift_allowance": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 10,
"filled": 0,
"available": 10
},
"deadlines": {
"application": "2026-08-07T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:29+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
{
"id": "019fd2b8-15d2-72e5-a3dc-cf69f63524e6",
"title": "Technik Aufbau Konzert",
"description": "Für unsere bevorstehende Veranstaltung suchen wir tatkräftige Unterstützung. Als Technik Aufbau Konzert sind Sie das Aushängeschild unserer Veranstaltung und sorgen für einen reibungslosen Ablauf.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f398-7300-a216-c64584fea8f7",
"slug": "event",
"name": "Events",
"name_localized": "Events",
"icon": "calendar-star",
"color": null
},
"tags": [
"Events",
"Tagschicht"
],
"organization": {
"id": "019fd2b7-f91f-70cb-8409-8632db9df3c7",
"name": "Sicherheitsdienst Österreich",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Wiener Stadthalle",
"address": "Roland-Rainer-Platz 1, 1150 Wien",
"city": "Wien",
"postal_code": "1030",
"lat": 48.1883,
"lng": 16.3957,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-10",
"end_date": "2026-08-11",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 16,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 8,
"filled": 0,
"available": 8
},
"deadlines": {
"application": "2026-08-07T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:27+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
{
"id": "019fd2b8-171e-7183-b2d6-b7fae57dd92b",
"title": "Personenkontrolle Flughafen",
"description": "Als Personenkontrolle Flughafen sind Sie für die Sicherheit unserer Einrichtung/Veranstaltung verantwortlich. Sie überwachen Zugänge, kontrollieren Personen und sorgen für Ordnung und Sicherheit.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f39c-7064-8f21-15054bddd646",
"slug": "security",
"name": "Security",
"name_localized": "Security",
"icon": "shield",
"color": null
},
"tags": [
"Security",
"Tagschicht",
"Sicherheitsausweis (§ 133 GewO)",
"Erste-Hilfe-Kurs"
],
"organization": {
"id": "019fd2b8-000d-719b-a73e-71665713a4fc",
"name": "Supermarkt AG",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Flughafen Wien-Schwechat",
"address": "Flughafen Wien, 1300 Wien",
"city": "Wien",
"postal_code": "1300",
"lat": 48.1103,
"lng": 16.5697,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-10",
"end_date": "2026-11-03",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 16,
"supplements": {
"weekend_bonus": 8,
"shift_allowance": 10
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 6,
"filled": 0,
"available": 6
},
"deadlines": {
"application": "2026-08-06T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:27+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
{
"id": "019fd2b8-1c02-7040-a155-5d35418e0953",
"title": "Medizinische Sekretärin",
"description": "Wir suchen engagierte Medizinische Sekretärin zur Verstärkung unseres Teams. Sie erwartet ein abwechslungsreiches Aufgabengebiet in einem dynamischen Umfeld.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f3d8-72d5-842e-c1f00337e9ec",
"slug": "healthcare",
"name": "Gesundheitswesen",
"name_localized": "Healthcare",
"icon": "heart-pulse",
"color": null
},
"tags": [
"Healthcare",
"Tagschicht",
"Medizinische Grundkenntnisse",
"Hygieneschulung"
],
"organization": {
"id": "019fd2b7-fca6-71cf-8683-c97f6f50a24a",
"name": "Reinigungsservice Alpin",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Ambulanz AKH Wien",
"address": "Währinger Gürtel 18-20, 1090 Wien",
"city": "Wien",
"postal_code": "1090",
"lat": 48.2228,
"lng": 16.3568,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-12",
"end_date": "2026-10-04",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 16,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 2,
"filled": 0,
"available": 2
},
"deadlines": {
"application": "2026-08-07T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:28+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
{
"id": "019fd2b8-1547-703f-bfe4-177b0923bd1d",
"title": "Concierge Nightshift",
"description": "Wir suchen engagierte Concierge Nightshift zur Verstärkung unseres Teams. Sie erwartet ein abwechslungsreiches Aufgabengebiet in einem dynamischen Umfeld.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f375-724e-84b8-4f9647ef6419",
"slug": "hotel",
"name": "Hotellerie",
"name_localized": "Hospitality",
"icon": "hotel",
"color": null
},
"tags": [
"Hospitality",
"Nachtschicht"
],
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Grand Hotel Wien",
"address": "Kärntner Ring 9, 1010 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2082,
"lng": 16.3739,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-20",
"end_date": "2027-08-05",
"shift_start_time": "22:00:00",
"shift_end_time": "06:00:00",
"shift_type": "night",
"shift_type_label": "Nachtschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 16,
"supplements": {
"night_bonus": 20,
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 1,
"filled": 0,
"available": 1
},
"deadlines": {
"application": "2026-08-17T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:27+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
{
"id": "019fd2b8-1287-7146-a673-6798f3d03acc",
"title": "Barkeeper Spätschicht Club",
"description": "Wir suchen motivierte Barkeeper Spätschicht Club für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Nachtschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-f5ae-7390-a778-c08c8d56cdc0",
"name": "Event Solutions Austria",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Club Passage",
"address": "Babenbergerstraße 9, 1010 Wien",
"city": "Wien",
"postal_code": "1070",
"lat": 48.2003,
"lng": 16.3465,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-08",
"end_date": "2026-11-03",
"shift_start_time": "22:00:00",
"shift_end_time": "06:00:00",
"shift_type": "night",
"shift_type_label": "Nachtschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 16,
"supplements": {
"night_bonus": 15,
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 4,
"filled": 0,
"available": 4
},
"deadlines": {
"application": "2026-08-06T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
}
],
"pagination": {
"current_page": 1,
"last_page": 5,
"per_page": 15,
"total": 71
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Job Filters
Returns all available filter options for the job listing screen. This endpoint is designed to be called once per session (on app start or when opening the filter sheet) and cached client-side.
Includes live job counts per category and the actual hourly-rate range from currently active jobs so the Flutter slider is always bounded correctly.
Response is cacheable for 1 hour (Cache-Control: public, max-age=3600).
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/jobs/filters" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/jobs/filters"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/jobs/filters';
$response = $client->get(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/jobs/filters');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"categories": [
{
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"is_featured": true,
"parent_id": null,
"job_count": 13
},
{
"id": "019fd2b7-f375-724e-84b8-4f9647ef6419",
"slug": "hotel",
"name": "Hotellerie",
"name_localized": "Hospitality",
"icon": "hotel",
"is_featured": true,
"parent_id": null,
"job_count": 5
},
{
"id": "019fd2b7-f377-7108-8400-efa89715a39f",
"slug": "food_service",
"name": "Food Service",
"name_localized": "Food Service",
"icon": "utensils",
"is_featured": false,
"parent_id": null,
"job_count": 0
},
{
"id": "019fd2b7-f37a-72a9-84a9-7862f636e2fd",
"slug": "catering",
"name": "Catering",
"name_localized": "Catering",
"icon": "utensils",
"is_featured": false,
"parent_id": null,
"job_count": 4
},
{
"id": "019fd2b7-f37d-712d-92b3-aa5540f6b2a7",
"slug": "retail",
"name": "Einzelhandel",
"name_localized": "Retail",
"icon": "shopping-cart",
"is_featured": false,
"parent_id": null,
"job_count": 4
},
{
"id": "019fd2b7-f380-7300-91c6-75c968e6d045",
"slug": "supermarket",
"name": "Lebensmittelhandel",
"name_localized": "Grocery",
"icon": "shopping-cart",
"is_featured": false,
"parent_id": null,
"job_count": 2
},
{
"id": "019fd2b7-f384-7071-b096-674d16b4ad00",
"slug": "pharmacy",
"name": "Apotheke",
"name_localized": "Pharmacy",
"icon": "heart-pulse",
"is_featured": false,
"parent_id": null,
"job_count": 0
},
{
"id": "019fd2b7-f388-7098-b463-ae170338e60f",
"slug": "production",
"name": "Produktion",
"name_localized": "Production",
"icon": "industry",
"is_featured": false,
"parent_id": null,
"job_count": 2
},
{
"id": "019fd2b7-f38b-7209-8b83-b345b172def2",
"slug": "warehouse",
"name": "Lager",
"name_localized": "Warehouse",
"icon": "industry",
"is_featured": false,
"parent_id": null,
"job_count": 0
},
{
"id": "019fd2b7-f38e-7255-bfe3-0f010aca0086",
"slug": "logistics",
"name": "Logistik",
"name_localized": "Logistics",
"icon": "truck",
"is_featured": true,
"parent_id": null,
"job_count": 5
},
{
"id": "019fd2b7-f391-727d-9871-61207ae27ab3",
"slug": "manufacturing",
"name": "Fertigung",
"name_localized": "Manufacturing",
"icon": "industry",
"is_featured": false,
"parent_id": null,
"job_count": 1
},
{
"id": "019fd2b7-f394-7015-b80e-5fa954b27658",
"slug": "transportation",
"name": "Transport",
"name_localized": "Transportation",
"icon": "truck",
"is_featured": false,
"parent_id": null,
"job_count": 0
},
{
"id": "019fd2b7-f398-7300-a216-c64584fea8f7",
"slug": "event",
"name": "Events",
"name_localized": "Events",
"icon": "calendar-star",
"is_featured": false,
"parent_id": null,
"job_count": 13
},
{
"id": "019fd2b7-f39c-7064-8f21-15054bddd646",
"slug": "security",
"name": "Security",
"name_localized": "Security",
"icon": "shield",
"is_featured": false,
"parent_id": null,
"job_count": 5
},
{
"id": "019fd2b7-f39f-73e6-870b-fe7584e4f9bc",
"slug": "office",
"name": "Büro",
"name_localized": "Office",
"icon": "briefcase",
"is_featured": false,
"parent_id": null,
"job_count": 2
},
{
"id": "019fd2b7-f3a2-7147-883f-c3207db81b51",
"slug": "reception",
"name": "Empfang",
"name_localized": "Reception",
"icon": "briefcase",
"is_featured": false,
"parent_id": null,
"job_count": 1
},
{
"id": "019fd2b7-f3a5-70a8-a3b1-9140f01abf8e",
"slug": "call_center",
"name": "Call Center",
"name_localized": "Call Center",
"icon": "briefcase",
"is_featured": false,
"parent_id": null,
"job_count": 0
},
{
"id": "019fd2b7-f3a8-72f6-8ad1-0f499f6816e1",
"slug": "customer_service",
"name": "Kundenservice",
"name_localized": "Customer Service",
"icon": "briefcase",
"is_featured": false,
"parent_id": null,
"job_count": 1
},
{
"id": "019fd2b7-f3ab-70a0-9523-b474e2007212",
"slug": "software",
"name": "Software",
"name_localized": "Software",
"icon": "code",
"is_featured": true,
"parent_id": null,
"job_count": 1
},
{
"id": "019fd2b7-f3c2-73b2-9873-51431d14404e",
"slug": "it_services",
"name": "IT Services",
"name_localized": "IT Services",
"icon": "code",
"is_featured": false,
"parent_id": null,
"job_count": 2
},
{
"id": "019fd2b7-f3cc-728f-a1eb-11d5120b3dca",
"slug": "cleaning",
"name": "Reinigung",
"name_localized": "Cleaning",
"icon": "broom",
"is_featured": false,
"parent_id": null,
"job_count": 3
},
{
"id": "019fd2b7-f3d1-72e1-a261-10207b6d759d",
"slug": "facility",
"name": "Facility Management",
"name_localized": "Facility Management",
"icon": "broom",
"is_featured": false,
"parent_id": null,
"job_count": 0
},
{
"id": "019fd2b7-f3d5-71b4-bece-4ea026852495",
"slug": "care",
"name": "Pflege/Betreuung",
"name_localized": "Care",
"icon": "heart-pulse",
"is_featured": false,
"parent_id": null,
"job_count": 1
},
{
"id": "019fd2b7-f3d8-72d5-842e-c1f00337e9ec",
"slug": "healthcare",
"name": "Gesundheitswesen",
"name_localized": "Healthcare",
"icon": "heart-pulse",
"is_featured": false,
"parent_id": null,
"job_count": 2
},
{
"id": "019fd2b7-f3dc-70cb-a662-0fc23b0ec307",
"slug": "construction",
"name": "Bau (Hilfstätigkeiten)",
"name_localized": "Construction",
"icon": "building",
"is_featured": false,
"parent_id": null,
"job_count": 2
},
{
"id": "019fd2b7-f3df-70bb-8881-36c5f2234495",
"slug": "real_estate",
"name": "Immobilien",
"name_localized": "Real Estate",
"icon": "building",
"is_featured": false,
"parent_id": null,
"job_count": 0
},
{
"id": "019fd2b7-f3e5-714f-8db2-a5ae4350ae5c",
"slug": "graphic_design",
"name": "Grafikdesign",
"name_localized": "Graphic Design",
"icon": "palette",
"is_featured": false,
"parent_id": null,
"job_count": 0
},
{
"id": "019fd2b7-f3e9-71c6-b382-7451adaf4bb7",
"slug": "media",
"name": "Medien",
"name_localized": "Media",
"icon": "palette",
"is_featured": true,
"parent_id": null,
"job_count": 0
},
{
"id": "019fd2b7-f3ec-717a-ac4d-13011f3096f1",
"slug": "education",
"name": "Bildung",
"name_localized": "Education",
"icon": "graduation-cap",
"is_featured": true,
"parent_id": null,
"job_count": 2
},
{
"id": "019fd2b7-f3f0-70a8-b7be-6be4c17c9429",
"slug": "finance",
"name": "Finanzen",
"name_localized": "Finance",
"icon": "chart-line",
"is_featured": true,
"parent_id": null,
"job_count": 0
},
{
"id": "019fd2b7-f3f3-737d-9abe-5edb92ceb02a",
"slug": "agriculture",
"name": "Landwirtschaft",
"name_localized": "Agriculture",
"icon": "leaf",
"is_featured": false,
"parent_id": null,
"job_count": 0
},
{
"id": "019fd2b7-f3f6-70c7-868b-6ac419f0d02c",
"slug": "other",
"name": "Sonstiges",
"name_localized": "Other",
"icon": "ellipsis",
"is_featured": false,
"parent_id": null,
"job_count": 0
}
],
"categories_grouped": {
"Gastronomie": [],
"Hotellerie": [],
"Food Service": [],
"Catering": [],
"Einzelhandel": [],
"Lebensmittelhandel": [],
"Apotheke": [],
"Produktion": [],
"Lager": [],
"Logistik": [],
"Fertigung": [],
"Transport": [],
"Events": [],
"Security": [],
"Büro": [],
"Empfang": [],
"Call Center": [],
"Kundenservice": [],
"Software": [],
"IT Services": [],
"Reinigung": [],
"Facility Management": [],
"Pflege/Betreuung": [],
"Gesundheitswesen": [],
"Bau (Hilfstätigkeiten)": [],
"Immobilien": [],
"Grafikdesign": [],
"Medien": [],
"Bildung": [],
"Finanzen": [],
"Landwirtschaft": [],
"Sonstiges": []
},
"states": [
{
"value": "wien",
"label": "Wien"
},
{
"value": "niederoesterreich",
"label": "Niederösterreich"
},
{
"value": "oberoesterreich",
"label": "Oberösterreich"
},
{
"value": "steiermark",
"label": "Steiermark"
},
{
"value": "salzburg",
"label": "Salzburg"
},
{
"value": "tirol",
"label": "Tirol"
},
{
"value": "vorarlberg",
"label": "Vorarlberg"
},
{
"value": "kaernten",
"label": "Kärnten"
},
{
"value": "burgenland",
"label": "Burgenland"
}
],
"sort_options": [
{
"value": "newest",
"label": "Neueste"
},
{
"value": "highest_salary",
"label": "Höchstes Gehalt"
},
{
"value": "lowest_salary",
"label": "Niedrigstes Gehalt"
},
{
"value": "nearest",
"label": "Nächstgelegen"
},
{
"value": "starting_soon",
"label": "Bald startend"
},
{
"value": "morning_shifts",
"label": "Morgenschichten"
},
{
"value": "night_shifts",
"label": "Nachtschichten"
},
{
"value": "featured",
"label": "Empfohlen"
},
{
"value": "relevance",
"label": "Relevanz"
}
],
"shift_types": [
{
"value": "day",
"label": "Tagschicht"
},
{
"value": "night",
"label": "Nachtschicht"
},
{
"value": "weekend",
"label": "Wochenendschicht"
},
{
"value": "holiday",
"label": "Feiertagsschicht"
}
],
"rate_range": {
"min": 10,
"max": 100,
"step": 0.5,
"active_min": 13,
"active_max": 32.08
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get detailed information about a specific job.
Returns comprehensive job data including shifts, requirements, organization info, and application statistics.
Two shift arrays come back. They are keyed identically — date,
formatted_date, start_time, end_time, available_spots,
is_past, is_applied — so one parser reads both. What differs is
whether the entries are real:
shift_slots— the job's actual shift rows. Each adds anid, plusworkers_needed,is_full,meeting_pointand its ownapplication_deadline. These ids are whatPOST /mobile/jobs/{jobId}/applytakes asshift_ids, and the times and capacity here are the shift's own. An empty array means the job has no shifts and cannot be applied to.shifts— a calendar synthesised by walking the job's start and end dates, carrying the job-level times and the job-wide vacancy count repeated on every entry. No ids, so nothing in it can be applied for.
Where they disagree, shift_slots is right: a company can move one
shift's hours or headcount, and the calendar will not know.
applied_shift_dates is output only: the dates this worker already
chose. shift_slots[].is_applied says the same thing per shift.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/jobs/9c7f8e6d-5b4a-3c2d-1e0f-9a8b7c6d5e4f" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/jobs/9c7f8e6d-5b4a-3c2d-1e0f-9a8b7c6d5e4f"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/jobs/9c7f8e6d-5b4a-3c2d-1e0f-9a8b7c6d5e4f';
$response = $client->get(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/jobs/9c7f8e6d-5b4a-3c2d-1e0f-9a8b7c6d5e4f');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"job": {
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant",
"description": "Ut nostrum rerum ut alias quia libero excepturi. Voluptatum et aut non quia quisquam molestias. Perferendis qui hic unde.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f39f-73e6-870b-fe7584e4f9bc",
"slug": "office",
"name": "Büro",
"name_localized": "Office",
"icon": "briefcase",
"color": null,
"kollektivvertrag": "Handel/Büro",
"description": null,
"is_featured": false
},
"tags": [
"Office",
"Nachtschicht"
],
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"logo_url": null,
"description": "Caritas test organisation used for end-to-end portal QA. Safe to delete.",
"website": "https://www.caritas.at",
"city": "Vienna",
"country": "Austria",
"industry_code": null,
"company_size": null,
"is_verified": true
},
"location": {
"name": "Barrows, Christiansen and Jones",
"address": "586 Tremaine Row",
"city": "East Eliseo",
"postal_code": "10547-3697",
"lat": 46.931383,
"lng": 11.998284,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-12",
"end_date": "2026-08-19",
"shift_start_time": "01:49:00",
"shift_end_time": "18:57:00",
"shift_type": "night",
"shift_type_label": "Nachtschicht",
"duration_hours": 17.133333333333333
},
"compensation": {
"hourly_rate_gross": 32.08,
"supplements": {
"night": 0.7,
"weekend": 3.86
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 5,
"filled": 0,
"available": 5,
"is_fully_booked": false,
"is_open_for_applications": true
},
"deadlines": {
"application": "2026-09-05T16:18:32+00:00",
"confirmation": "2026-08-16T10:20:06+00:00"
},
"created_at": "2026-08-05T16:18:32+00:00",
"is_saved": false,
"can_apply": true,
"rate": null,
"published_at": null,
"shifts": [
{
"date": "2026-08-12",
"formatted_date": "Mi., 12. August",
"start_time": "01:49:00",
"end_time": "18:57:00",
"available_spots": 5,
"is_past": false,
"is_applied": false
},
{
"date": "2026-08-13",
"formatted_date": "Do., 13. August",
"start_time": "01:49:00",
"end_time": "18:57:00",
"available_spots": 5,
"is_past": false,
"is_applied": false
},
{
"date": "2026-08-14",
"formatted_date": "Fr., 14. August",
"start_time": "01:49:00",
"end_time": "18:57:00",
"available_spots": 5,
"is_past": false,
"is_applied": false
},
{
"date": "2026-08-15",
"formatted_date": "Sa., 15. August",
"start_time": "01:49:00",
"end_time": "18:57:00",
"available_spots": 5,
"is_past": false,
"is_applied": false
},
{
"date": "2026-08-16",
"formatted_date": "So., 16. August",
"start_time": "01:49:00",
"end_time": "18:57:00",
"available_spots": 5,
"is_past": false,
"is_applied": false
},
{
"date": "2026-08-17",
"formatted_date": "Mo., 17. August",
"start_time": "01:49:00",
"end_time": "18:57:00",
"available_spots": 5,
"is_past": false,
"is_applied": false
},
{
"date": "2026-08-18",
"formatted_date": "Di., 18. August",
"start_time": "01:49:00",
"end_time": "18:57:00",
"available_spots": 5,
"is_past": false,
"is_applied": false
},
{
"date": "2026-08-19",
"formatted_date": "Mi., 19. August",
"start_time": "01:49:00",
"end_time": "18:57:00",
"available_spots": 5,
"is_past": false,
"is_applied": false
}
],
"shift_slots": [
{
"id": "019fd2b8-28d5-7103-b951-9f6ff1d94556",
"date": "2026-08-05",
"formatted_date": "Mi., 5. August",
"start_time": "08:00:00",
"end_time": "16:00:00",
"available_spots": 2,
"is_past": false,
"is_applied": false,
"workers_needed": 2,
"is_full": false,
"meeting_point": null,
"application_deadline": null
}
],
"application_id": null,
"application_status": null,
"applied_shift_dates": [],
"applications": {
"total": 1,
"pending": 0
},
"requirements": [
{
"id": "019fd2b8-28c9-704f-b685-1cf9be0c3dff",
"type": "document",
"type_label": "Dokument",
"name": "Reisepass",
"description": null,
"is_mandatory": true
},
{
"id": "019fd2b8-28cb-7212-a83d-b62d519bbbf1",
"type": "document",
"type_label": "Dokument",
"name": "Führerschein",
"description": null,
"is_mandatory": true
}
],
"custom_document_requests": [],
"qualifications": [],
"dress_code": "Tempore necessitatibus quia illo suscipit.",
"equipment_provided": "Adipisci fugiat doloremque atque consectetur necessitatibus sunt cumque.",
"rules": {
"payment_terms": "Direktzahlung (innerhalb von 3 Werktagen)",
"cancellation_policy": "Stornierungsrichtlinien gelten",
"insurance": "Kostenlose Unfallversicherung inklusive"
},
"contact": {
"person_avatar_url": null
},
"additional_info": {
"parking_info": null,
"special_instructions": null
}
}
}
}
Example response (404, Not Found):
{
"status": "RESOURCE_NOT_FOUND",
"message": "Job not found"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Job Requirements
requires authentication
What the authenticated employee needs before they can apply for a job: every document-backed requirement the company set, whether the employee currently satisfies it, and when the satisfying document expires.
The same rules gate the application itself — {@see JobRequirementGate} is shared with ApplyForJobAction — so this can never disagree with what happens on submit. Without it the app could only discover an unmet requirement by attempting to apply and reading back the rejection.
ready reports on mandatory requirements only. Optional ones are returned
so the employee can see them, but they never block an application.
Item status is one of verified, pending, rejected,
reupload_requested, expired or not_provided.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2
The framework agreement is reported separately from `items`: everything
in that list is answered by uploading a document, while this one is
answered by signing. Its id is included so the app can post straight to
`POST /mobile/contracts/1/sign` and return here. It counts
towards `ready` all the same — applying is refused without it.
`account_status` is the worker's lifecycle state, in the same vocabulary
as the 403 notices. Applying and signing both need `active`; until then
`ready` is false however complete the checklist is, and the agreement
reads `awaiting_approval` rather than `signature_required` — signing
before approval answers 403, so an app that offered the button would be
offering a dead one./requirements" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2
The framework agreement is reported separately from `items`: everything
in that list is answered by uploading a document, while this one is
answered by signing. Its id is included so the app can post straight to
`POST /mobile/contracts/1/sign` and return here. It counts
towards `ready` all the same — applying is refused without it.
`account_status` is the worker's lifecycle state, in the same vocabulary
as the 403 notices. Applying and signing both need `active`; until then
`ready` is false however complete the checklist is, and the agreement
reads `awaiting_approval` rather than `signature_required` — signing
before approval answers 403, so an app that offered the button would be
offering a dead one./requirements"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2
The framework agreement is reported separately from `items`: everything
in that list is answered by uploading a document, while this one is
answered by signing. Its id is included so the app can post straight to
`POST /mobile/contracts/1/sign` and return here. It counts
towards `ready` all the same — applying is refused without it.
`account_status` is the worker's lifecycle state, in the same vocabulary
as the 403 notices. Applying and signing both need `active`; until then
`ready` is false however complete the checklist is, and the agreement
reads `awaiting_approval` rather than `signature_required` — signing
before approval answers 403, so an app that offered the button would be
offering a dead one./requirements';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2
The framework agreement is reported separately from `items`: everything
in that list is answered by uploading a document, while this one is
answered by signing. Its id is included so the app can post straight to
`POST /mobile/contracts/1/sign` and return here. It counts
towards `ready` all the same — applying is refused without it.
`account_status` is the worker's lifecycle state, in the same vocabulary
as the 403 notices. Applying and signing both need `active`; until then
`ready` is false however complete the checklist is, and the agreement
reads `awaiting_approval` rather than `signature_required` — signing
before approval answers 403, so an app that offered the button would be
offering a dead one./requirements');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Ready to apply):
{
"status": "SUCCESS",
"message": "Requirements retrieved.",
"data": {
"ready": true,
"account_status": "active",
"contract": {
"status": "signed",
"id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2"
},
"items": []
}
}
Example response (200, Still under review):
{
"status": "SUCCESS",
"message": "Requirements retrieved.",
"data": {
"ready": false,
"account_status": "pending_approval",
"contract": {
"status": "awaiting_approval",
"id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2"
},
"items": []
}
}
Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Requirements retrieved.",
"data": {
"ready": false,
"account_status": "active",
"contract": {
"status": "unavailable",
"id": null
},
"items": [
{
"requirement_code": "passport",
"name": "Reisepass",
"description": null,
"requirement_type": "document",
"requirement_type_label": "Dokument",
"is_mandatory": true,
"accepts": [
"passport"
],
"satisfied": true,
"status": "verified",
"valid_until": "2033-05-22"
},
{
"requirement_code": "driver_license",
"name": "Führerschein",
"description": null,
"requirement_type": "document",
"requirement_type_label": "Dokument",
"is_mandatory": true,
"accepts": [
"driver_license"
],
"satisfied": false,
"status": "not_provided",
"valid_until": null
}
]
}
}
Example response (404, Job not found):
{
"status": "RESOURCE_NOT_FOUND",
"message": "The job was not found."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Apply For Job
requires authentication
Applies to a job and, in the same request, says which of its shifts the worker wants. The application is job-level; the chosen shifts are attached to it.
shift_ids come from shift_slots in GET /mobile/jobs/{jobId} —
the id of each slot the worker picked. Do not send dates: the shifts
array on that same response is a display-only calendar synthesised from
the job's date range and carries no ids, and applied_shift_dates is
what the platform reports back after applying, not an input. A job whose
shift_slots is empty has no shifts to choose and cannot be applied to.
A full shift may still be chosen — that places the worker on standby for it rather than refusing the application.
Calling this again for a job already applied to adds shifts rather
than being refused: a worker applies for shifts, and wanting a further
day is a new request, not a repeat. The application keeps its id and
status, so the company still sees one applicant, and the response
carries added_shift_ids — the subset that was new — with 200 instead
of 201. On a selected application the added shifts are booked
immediately — the company already chose this worker, so the new days
become assignments (with their own Überlassungsvertrag) right away; if
none of them still has room, the request is refused and nothing is
attached.
It is refused with DUPLICATE_ENTRY only when every shift sent is
already on the application, or when it is closed (rejected, withdrawn,
expired, cancelled): there the decision was against working, and adding
work to it is not the worker's to do.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/apply" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"shift_ids\": [
\"019f9939-c4c3-70fb-a54e-5ebf63db36d2\"
],
\"acknowledge_conflict\": false
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/apply"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"shift_ids": [
"019f9939-c4c3-70fb-a54e-5ebf63db36d2"
],
"acknowledge_conflict": false
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/apply';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'shift_ids' => ['019f9939-c4c3-70fb-a54e-5ebf63db36d2'],
'acknowledge_conflict' => false,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/apply');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"shift_ids": [
"019f9939-c4c3-70fb-a54e-5ebf63db36d2"
],
"acknowledge_conflict": false
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Further shifts added to an existing application):
{
"status": "SUCCESS",
"message": "Die Schichten wurden Ihrer Bewerbung hinzugefügt.",
"data": {
"application": {
"id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"status": "pending",
"added_shift_ids": [
"019f9939-c4c3-70fb-a54e-5ebf63db36d3"
],
"shift_dates": [
"2026-08-12",
"2026-08-19"
]
}
}
}
Example response (201, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Your application has been submitted successfully.",
"data": {
"application": {
"id": "019fd2b8-76c6-72bb-a2d9-98ed4934fb02",
"job_id": "019fd2b8-7568-72f7-89ad-5bec0d9779ff",
"status": "pending",
"applied_at": "2026-08-05T16:18:52+00:00",
"has_scheduling_conflict": false,
"shift_ids": [
"019fd2b8-756e-70aa-a7ad-01157af79df0"
],
"shift_dates": [
"2026-08-12"
]
}
}
}
Example response (409, Nothing new in the request):
{
"status": "DUPLICATE_ENTRY",
"message": "Sie haben sich für diese Schichten bereits beworben."
}
Example response (422, No shifts chosen):
{
"status": "VALIDATION_ERROR",
"message": "Bitte wähle mindestens eine Schicht aus, bevor du dich bewirbst."
}
Example response (422, A chosen shift is not selectable):
{
"status": "VALIDATION_ERROR",
"message": "Mindestens eine der gewählten Schichten ist nicht mehr verfügbar."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List employee's saved jobs (Merkzettel).
requires authentication
Returns only active saved jobs (not auto-removed). Includes job details and application status if applied.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/saved-jobs" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/saved-jobs"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/saved-jobs';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/saved-jobs');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"saved_jobs": [],
"meta": {
"total": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Save Job
requires authentication
Puts a job on the worker's Merkzettel, with an optional note and reminder preferences. Saving a job that is already saved updates it rather than adding a second entry, so this doubles as the edit call: send only what is changing, omitted fields keep their value.
DELETE on the same path unsaves it.
POST /mobile/jobs/{jobId}/bookmark also exists — it toggles saved
state and takes no body. Use that for a one-tap heart, and this when the
worker is setting a note or a reminder.
notify_deadline is acted on: a worker who asks for it is told once,
shortly before applications close, by the jobs:remind-saved-deadlines
sweep.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/save" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"notes\": \"Nachtschicht, Anfahrt 25 min\",
\"notify_deadline\": true,
\"notify_vacancy_change\": false
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/save"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"notes": "Nachtschicht, Anfahrt 25 min",
"notify_deadline": true,
"notify_vacancy_change": false
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/save';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'notes' => 'Nachtschicht, Anfahrt 25 min',
'notify_deadline' => true,
'notify_vacancy_change' => false,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/save');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"notes": "Nachtschicht, Anfahrt 25 min",
"notify_deadline": true,
"notify_vacancy_change": false
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The job has been saved.",
"data": {
"saved_job_id": "019fd2b8-7687-717b-a68d-76c060caa63f",
"saved_at": "2026-08-05T16:18:52+00:00"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Save Job
requires authentication
Puts a job on the worker's Merkzettel, with an optional note and reminder preferences. Saving a job that is already saved updates it rather than adding a second entry, so this doubles as the edit call: send only what is changing, omitted fields keep their value.
DELETE on the same path unsaves it.
POST /mobile/jobs/{jobId}/bookmark also exists — it toggles saved
state and takes no body. Use that for a one-tap heart, and this when the
worker is setting a note or a reminder.
notify_deadline is acted on: a worker who asks for it is told once,
shortly before applications close, by the jobs:remind-saved-deadlines
sweep.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/mobile/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/save" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"notes\": \"Nachtschicht, Anfahrt 25 min\",
\"notify_deadline\": true,
\"notify_vacancy_change\": false
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/save"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"notes": "Nachtschicht, Anfahrt 25 min",
"notify_deadline": true,
"notify_vacancy_change": false
};
fetch(url, {
method: "DELETE",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/save';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'notes' => 'Nachtschicht, Anfahrt 25 min',
'notify_deadline' => true,
'notify_vacancy_change' => false,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/save');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"notes": "Nachtschicht, Anfahrt 25 min",
"notify_deadline": true,
"notify_vacancy_change": false
};
final response = await http.delete(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The job has been saved.",
"data": {
"saved_job_id": "019fd2b8-7687-717b-a68d-76c060caa63f",
"saved_at": "2026-08-05T16:18:52+00:00"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Toggle bookmark (save/unsave) for a job.
requires authentication
POST /mobile/jobs/{jobId}/bookmark
If the job is already bookmarked → removes it (is_bookmarked: false). If not bookmarked → saves it (is_bookmarked: true).
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/jobs/9c7f8e6d-5b4a-3c2d-1e0f-9a8b7c6d5e4f/bookmark" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/jobs/9c7f8e6d-5b4a-3c2d-1e0f-9a8b7c6d5e4f/bookmark"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/jobs/9c7f8e6d-5b4a-3c2d-1e0f-9a8b7c6d5e4f/bookmark';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/jobs/9c7f8e6d-5b4a-3c2d-1e0f-9a8b7c6d5e4f/bookmark');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Unbookmarked):
{
"status": "SUCCESS",
"data": {
"is_bookmarked": false,
"saved_job_id": null
}
}
Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"is_bookmarked": true,
"saved_job_id": "019fd2b8-3879-73c5-8283-53557bc9c066"
}
}
Example response (404, Not Found):
{
"status": "RESOURCE_NOT_FOUND",
"message": "Job nicht gefunden."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get AI-powered job recommendations for the employee.
requires authentication
Returns jobs scored by:
- Location proximity (40%)
- Qualification match (25%)
- Past job category history (15%)
- Company rating (10%)
- Reliability score (10%)
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/recommended-jobs?limit=20" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/recommended-jobs"
);
const params = {
"limit": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/recommended-jobs';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'limit' => '20',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/recommended-jobs')
.replace(queryParameters: {
'limit': '20',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"recommendations": [
{
"job": {
"id": "019fd2b8-1a90-7125-af02-72f37fef65ea",
"title": "Backoffice Assistenz",
"description": "Wir suchen engagierte Backoffice Assistenz zur Verstärkung unseres Teams. Sie erwartet ein abwechslungsreiches Aufgabengebiet in einem dynamischen Umfeld.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f39f-73e6-870b-fe7584e4f9bc",
"slug": "office",
"name": "Büro",
"name_localized": "Office",
"icon": "briefcase",
"color": null
},
"tags": [
"Office",
"Tagschicht"
],
"organization": {
"id": "019fd2b7-f768-7325-b254-280a67b1a995",
"name": "Retail Services GmbH",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Steuerberatung Wien",
"address": "Margaretenstraße 90, 1050 Wien",
"city": "Wien",
"postal_code": "1050",
"lat": 48.1944,
"lng": 16.3585,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-15",
"end_date": "2026-09-04",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 16,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 1,
"filled": 0,
"available": 1
},
"deadlines": {
"application": "2026-08-10T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:28+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 61.5,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 10,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-1265-737c-ae21-e5265dc709d8",
"title": "Servicekraft Restaurant Mitte",
"description": "Wir suchen motivierte Servicekraft Restaurant Mitte für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Tagschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-ff32-7117-ab28-06e2d3082002",
"name": "Bildungszentrum Mitte",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Brasserie Mitte",
"address": "Schwarzenbergplatz 3, 1010 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2082,
"lng": 16.3739,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-10",
"end_date": "2026-09-09",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 14.5,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 8,
"filled": 0,
"available": 8
},
"deadlines": {
"application": "2026-08-07T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-1287-7146-a673-6798f3d03acc",
"title": "Barkeeper Spätschicht Club",
"description": "Wir suchen motivierte Barkeeper Spätschicht Club für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Nachtschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-f5ae-7390-a778-c08c8d56cdc0",
"name": "Event Solutions Austria",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Club Passage",
"address": "Babenbergerstraße 9, 1010 Wien",
"city": "Wien",
"postal_code": "1070",
"lat": 48.2003,
"lng": 16.3465,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-08",
"end_date": "2026-11-03",
"shift_start_time": "22:00:00",
"shift_end_time": "06:00:00",
"shift_type": "night",
"shift_type_label": "Nachtschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 16,
"supplements": {
"night_bonus": 15,
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 4,
"filled": 0,
"available": 4
},
"deadlines": {
"application": "2026-08-06T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-1298-737e-bbfd-295992feb4db",
"title": "Küchenhilfe Großküche",
"description": "Wir suchen motivierte Küchenhilfe Großküche für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Tagschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-fad7-719c-887a-a0f510bbd31d",
"name": "IT Solutions GmbH",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "SV Gastronomie Wien",
"address": "Gablenzgasse 11, 1150 Wien",
"city": "Wien",
"postal_code": "1150",
"lat": 48.196,
"lng": 16.3268,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-12",
"end_date": "2026-12-03",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 13.5,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 10,
"filled": 0,
"available": 10
},
"deadlines": {
"application": "2026-08-07T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-12b2-72ff-8be7-dadbf8e167b6",
"title": "Kellner*in Haubenrestaurant",
"description": "Wir suchen motivierte Kellner*in Haubenrestaurant für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Tagschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-fca6-71cf-8683-c97f6f50a24a",
"name": "Reinigungsservice Alpin",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Restaurant Steirereck",
"address": "Am Heumarkt 2a, 1030 Wien",
"city": "Wien",
"postal_code": "1030",
"lat": 48.2014,
"lng": 16.387,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-15",
"end_date": "2026-10-04",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 15.5,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 3,
"filled": 0,
"available": 3
},
"deadlines": {
"application": "2026-08-10T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-12c7-72ab-bd18-53060b989f57",
"title": "Buffetkraft Messe",
"description": "Wir suchen motivierte Buffetkraft Messe für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Tagschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-fe56-70d1-bb3a-641339ce636a",
"name": "Lagerhaus Steiermark",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Reed Messe Wien",
"address": "Messeplatz 1, 1021 Wien",
"city": "Wien",
"postal_code": "1020",
"lat": 48.2176,
"lng": 16.4138,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-19",
"end_date": "2026-08-21",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 13.8,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 15,
"filled": 0,
"available": 15
},
"deadlines": {
"application": "2026-08-15T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-12d6-722c-8511-2aaa42b3d821",
"title": "Servicepersonal Weinbar",
"description": "Wir suchen motivierte Servicepersonal Weinbar für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Tagschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b8-000d-719b-a73e-71665713a4fc",
"name": "Supermarkt AG",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Weinbar Graz",
"address": "Herrengasse 5, 8010 Graz",
"city": "Graz",
"postal_code": "8010",
"lat": 47.0707,
"lng": 15.4395,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-09",
"end_date": "2027-02-01",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 14,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 5,
"filled": 0,
"available": 5
},
"deadlines": {
"application": "2026-08-07T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-12f4-73f7-a675-8bf7331044c3",
"title": "Koch/Köchin Bistro",
"description": "Wir suchen motivierte Koch/Köchin Bistro für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Tagschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-f4d3-71a1-89d4-ca7d5731b32a",
"name": "Wiener Gastro GmbH",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Bistro Donau",
"address": "Landstraße 30, 4020 Linz",
"city": "Linz",
"postal_code": "4020",
"lat": 48.3069,
"lng": 14.2858,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-17",
"end_date": "2026-11-03",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 15.8,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 2,
"filled": 0,
"available": 2
},
"deadlines": {
"application": "2026-08-14T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-130c-7006-942a-09ca3ab2b639",
"title": "Bankettkellner Festsaal",
"description": "Wir suchen motivierte Bankettkellner Festsaal für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Tagschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-fca6-71cf-8683-c97f6f50a24a",
"name": "Reinigungsservice Alpin",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Schlosshotel Mirabell",
"address": "Mirabellplatz 2, 5020 Salzburg",
"city": "Salzburg",
"postal_code": "5020",
"lat": 47.8095,
"lng": 13.055,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-13",
"end_date": "2026-09-19",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 14.8,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 8,
"filled": 0,
"available": 8
},
"deadlines": {
"application": "2026-08-10T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-13e2-7390-a987-e12b987cdbb8",
"title": "Weihnachtsmarkt Servicekraft",
"description": "Wir suchen motivierte Weihnachtsmarkt Servicekraft für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Tagschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-f91f-70cb-8409-8632db9df3c7",
"name": "Sicherheitsdienst Österreich",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Christkindlmarkt Rathausplatz",
"address": "Rathausplatz 1, 1010 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2082,
"lng": 16.3739,
"distance_km": null
},
"schedule": {
"start_date": "2027-01-02",
"end_date": "2027-02-01",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 14,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 30,
"filled": 0,
"available": 30
},
"deadlines": {
"application": "2026-12-29T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-14dd-7377-92d2-447578550d00",
"title": "Convention Coordinator",
"description": "Wir suchen engagierte Convention Coordinator zur Verstärkung unseres Teams. Sie erwartet ein abwechslungsreiches Aufgabengebiet in einem dynamischen Umfeld.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f375-724e-84b8-4f9647ef6419",
"slug": "hotel",
"name": "Hotellerie",
"name_localized": "Hospitality",
"icon": "hotel",
"color": null
},
"tags": [
"Hospitality",
"Tagschicht"
],
"organization": {
"id": "019fd2b8-000d-719b-a73e-71665713a4fc",
"name": "Supermarkt AG",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Austria Center Vienna",
"address": "Bruno-Kreisky-Platz 1, 1220 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2082,
"lng": 16.3739,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-25",
"end_date": "2026-08-30",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 18,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 5,
"filled": 0,
"available": 5
},
"deadlines": {
"application": "2026-08-23T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:27+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-1405-709f-bca9-b0a418fb6a75",
"title": "Silvesternacht Service",
"description": "Wir suchen motivierte Silvesternacht Service für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Nachtschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-fe56-70d1-bb3a-641339ce636a",
"name": "Lagerhaus Steiermark",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Hotel Imperial Wien",
"address": "Kärntner Ring 16, 1015 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2082,
"lng": 16.3739,
"distance_km": null
},
"schedule": {
"start_date": "2027-02-09",
"end_date": "2027-02-10",
"shift_start_time": "22:00:00",
"shift_end_time": "06:00:00",
"shift_type": "night",
"shift_type_label": "Nachtschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 25,
"supplements": {
"night_bonus": 50,
"holiday_bonus": 100,
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 12,
"filled": 0,
"available": 12
},
"deadlines": {
"application": "2027-02-04T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-1414-7267-ab60-1d28e4726b22",
"title": "Oktoberfest Kellner",
"description": "Wir suchen motivierte Oktoberfest Kellner für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Tagschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b8-000d-719b-a73e-71665713a4fc",
"name": "Supermarkt AG",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Zelte Messe Graz",
"address": "Messeplatz 1, 8010 Graz",
"city": "Graz",
"postal_code": "8010",
"lat": 47.0707,
"lng": 15.4395,
"distance_km": null
},
"schedule": {
"start_date": "2026-11-13",
"end_date": "2026-11-23",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 15,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 25,
"filled": 0,
"available": 25
},
"deadlines": {
"application": "2026-11-10T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-1432-72a1-8757-db2b167892ea",
"title": "Pop-Up Restaurant Service",
"description": "Wir suchen motivierte Pop-Up Restaurant Service für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Tagschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-fad7-719c-887a-a0f510bbd31d",
"name": "IT Solutions GmbH",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Temporary Dining Wien",
"address": "Mariahilfer Straße 125, 1060 Wien",
"city": "Wien",
"postal_code": "1060",
"lat": 48.1985,
"lng": 16.359,
"distance_km": null
},
"schedule": {
"start_date": "2026-09-04",
"end_date": "2026-10-04",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 14,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 6,
"filled": 0,
"available": 6
},
"deadlines": {
"application": "2026-09-02T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-1441-71c8-a069-cb0d50c6165e",
"title": "Bierstandl Heuriger",
"description": "Wir suchen motivierte Bierstandl Heuriger für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Tagschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-f768-7325-b254-280a67b1a995",
"name": "Retail Services GmbH",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Heuriger Mayer am Pfarrplatz",
"address": "Pfarrplatz 2, 1190 Wien",
"city": "Wien",
"postal_code": "1190",
"lat": 48.26,
"lng": 16.34,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-25",
"end_date": "2027-01-02",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 13.5,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 4,
"filled": 0,
"available": 4
},
"deadlines": {
"application": "2026-08-21T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:27+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-147c-7006-b991-64f8acb70696",
"title": "Nachtportier",
"description": "Wir suchen engagierte Nachtportier zur Verstärkung unseres Teams. Sie erwartet ein abwechslungsreiches Aufgabengebiet in einem dynamischen Umfeld.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f375-724e-84b8-4f9647ef6419",
"slug": "hotel",
"name": "Hotellerie",
"name_localized": "Hospitality",
"icon": "hotel",
"color": null
},
"tags": [
"Hospitality",
"Nachtschicht"
],
"organization": {
"id": "019fd2b7-fd7d-724b-8a64-b4836c66d92f",
"name": "Catering Deluxe GmbH",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "NH Salzburg City",
"address": "Franz-Josef-Straße 26, 5020 Salzburg",
"city": "Salzburg",
"postal_code": "5020",
"lat": 47.8063,
"lng": 13.0477,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-12",
"end_date": "2027-02-01",
"shift_start_time": "22:00:00",
"shift_end_time": "06:00:00",
"shift_type": "night",
"shift_type_label": "Nachtschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 15.5,
"supplements": {
"night_bonus": 15,
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 2,
"filled": 0,
"available": 2
},
"deadlines": {
"application": "2026-08-10T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:27+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-1492-71be-933a-093e7178ae22",
"title": "Room Service Mitarbeiter",
"description": "Wir suchen engagierte Room Service Mitarbeiter zur Verstärkung unseres Teams. Sie erwartet ein abwechslungsreiches Aufgabengebiet in einem dynamischen Umfeld.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f375-724e-84b8-4f9647ef6419",
"slug": "hotel",
"name": "Hotellerie",
"name_localized": "Hospitality",
"icon": "hotel",
"color": null
},
"tags": [
"Hospitality",
"Tagschicht"
],
"organization": {
"id": "019fd2b7-f842-71ba-a318-a919a24d4bcf",
"name": "Hotel & Spa Imperial",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Hilton Vienna City",
"address": "Am Stadtpark 3, 1030 Wien",
"city": "Wien",
"postal_code": "1030",
"lat": 48.2006,
"lng": 16.3882,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-10",
"end_date": "2026-11-03",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 14,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 4,
"filled": 0,
"available": 4
},
"deadlines": {
"application": "2026-08-06T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:27+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-14a4-7258-8b10-6da8b27fb862",
"title": "Spa-Mitarbeiter*in",
"description": "Wir suchen engagierte Spa-Mitarbeiter*in zur Verstärkung unseres Teams. Sie erwartet ein abwechslungsreiches Aufgabengebiet in einem dynamischen Umfeld.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f375-724e-84b8-4f9647ef6419",
"slug": "hotel",
"name": "Hotellerie",
"name_localized": "Hospitality",
"icon": "hotel",
"color": null
},
"tags": [
"Hospitality",
"Tagschicht"
],
"organization": {
"id": "019fd2b7-f842-71ba-a318-a919a24d4bcf",
"name": "Hotel & Spa Imperial",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Schlosshotel Fuschl",
"address": "Schlossstraße 19, 5322 Hof bei Salzburg",
"city": "Salzburg",
"postal_code": "5020",
"lat": 47.8095,
"lng": 13.055,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-15",
"end_date": "2026-10-04",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 14.5,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 2,
"filled": 0,
"available": 2
},
"deadlines": {
"application": "2026-08-13T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:27+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-1547-703f-bfe4-177b0923bd1d",
"title": "Concierge Nightshift",
"description": "Wir suchen engagierte Concierge Nightshift zur Verstärkung unseres Teams. Sie erwartet ein abwechslungsreiches Aufgabengebiet in einem dynamischen Umfeld.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f375-724e-84b8-4f9647ef6419",
"slug": "hotel",
"name": "Hotellerie",
"name_localized": "Hospitality",
"icon": "hotel",
"color": null
},
"tags": [
"Hospitality",
"Nachtschicht"
],
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Grand Hotel Wien",
"address": "Kärntner Ring 9, 1010 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2082,
"lng": 16.3739,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-20",
"end_date": "2027-08-05",
"shift_start_time": "22:00:00",
"shift_end_time": "06:00:00",
"shift_type": "night",
"shift_type_label": "Nachtschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 16,
"supplements": {
"night_bonus": 20,
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 1,
"filled": 0,
"available": 1
},
"deadlines": {
"application": "2026-08-17T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:27+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-1560-70a6-abb3-020a87eccbc2",
"title": "Eventhelfer*in Musikfestival",
"description": "Für unsere bevorstehende Veranstaltung suchen wir tatkräftige Unterstützung. Als Eventhelfer*in Musikfestival sind Sie das Aushängeschild unserer Veranstaltung und sorgen für einen reibungslosen Ablauf.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f398-7300-a216-c64584fea8f7",
"slug": "event",
"name": "Events",
"name_localized": "Events",
"icon": "calendar-star",
"color": null
},
"tags": [
"Events",
"Tagschicht"
],
"organization": {
"id": "019fd2b7-fbb4-73fa-b801-e0c8a8de2651",
"name": "Bauwerk GmbH",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Donauinsel Festival",
"address": "Donauinsel, 1020 Wien",
"city": "Wien",
"postal_code": "1020",
"lat": 48.2112,
"lng": 16.4184,
"distance_km": null
},
"schedule": {
"start_date": "2026-10-04",
"end_date": "2026-10-07",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 14,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 50,
"filled": 0,
"available": 50
},
"deadlines": {
"application": "2026-10-02T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:27+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
}
],
"meta": {
"total": 20,
"algorithm_version": "1.0"
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List the authenticated user's job applications.
requires authentication
Each row carries the application's full state — status timestamps, waitlist position, scheduling-conflict details, chosen shift dates and shift ids, rejection reason — plus whether it can still be withdrawn and, once selected, a summary of the assignments it produced with any contracts still awaiting the worker's signature.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/applications?status=pending&per_page=15" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"status\": [
\"withdrawn\"
],
\"per_page\": 16
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/applications"
);
const params = {
"status": "pending",
"per_page": "15",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"status": [
"withdrawn"
],
"per_page": 16
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/applications';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'status' => 'pending',
'per_page' => '15',
],
'json' => [
'status' => ['withdrawn'],
'per_page' => 16,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/applications')
.replace(queryParameters: {
'status': 'pending',
'per_page': '15',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"status": [
"withdrawn"
],
"per_page": 16
};
final response = await http.get(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"applications": [],
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 15,
"total": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Withdraw a Job Application
requires authentication
Takes back an application the company has not decided yet. Allowed while the application is pending, shortlisted or on the waitlist; a selected application holds live assignments and is released by cancelling those shifts instead, so it cannot be withdrawn here.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/applications/019f9939-c4c3-70fb-a54e-5ebf63db36d2/withdraw" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Ich habe eine andere Stelle angenommen.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/applications/019f9939-c4c3-70fb-a54e-5ebf63db36d2/withdraw"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Ich habe eine andere Stelle angenommen."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/applications/019f9939-c4c3-70fb-a54e-5ebf63db36d2/withdraw';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'Ich habe eine andere Stelle angenommen.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/applications/019f9939-c4c3-70fb-a54e-5ebf63db36d2/withdraw');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "Ich habe eine andere Stelle angenommen."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (409, No longer withdrawable):
{
"status": "INVALID_OPERATION",
"message": "Diese Bewerbung kann nicht mehr zurückgezogen werden."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Shifts
List My Shifts
requires authentication
Returns the authenticated user's shifts (upcoming and past). Includes job and organization details, compensation info, and action flags.
Without a status filter, expired and cancelled entries are excluded;
request them explicitly via status to see them.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/shifts?status=signed&period=upcoming&per_page=15" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/shifts"
);
const params = {
"status": "signed",
"period": "upcoming",
"per_page": "15",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/shifts';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'status' => 'signed',
'period' => 'upcoming',
'per_page' => '15',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/shifts')
.replace(queryParameters: {
'status': 'signed',
'period': 'upcoming',
'per_page': '15',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"shifts": [
{
"id": "019fd4e7-8db5-7390-a768-5cc04b8a5ecc",
"status": "signed",
"status_label": "Unterschrieben",
"shift_date": "2026-08-07",
"scheduled_start_time": "08:00:00",
"scheduled_end_time": "16:00:00",
"shift_type": "holiday",
"confirmation_deadline": "2026-08-11T11:32:34+00:00",
"notes": null,
"location": {
"name": "Mohr-Bernier",
"address": "57499 Okuneva Springs",
"lat": 46.819652,
"lng": 9.690901
},
"compensation": {
"hourly_rate_gross": 32.63,
"estimated_gross": 230.33,
"currency": "EUR",
"supplements": {
"night": 0,
"weekend": 0
}
},
"can_confirm": false,
"can_clock_in": false,
"contact_person_name": null,
"contact_person_phone": null,
"contact_person_avatar_url": null,
"meeting_point": null,
"dress_code": "Vero amet fugiat quaerat odit.",
"job": {
"id": "019fd4e7-8da0-718d-8b0a-7fa0f29523e2",
"title": "Loan Interviewer",
"category": "retail"
},
"organization": {
"id": "019fd4e7-5633-700f-ad54-9f03c0661fd1",
"name": "Caritas",
"logo_url": null,
"average_rating": null
},
"contract": null
}
],
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 15,
"total": 1
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Shift Calendar
requires authentication
Returns shifts organized for calendar display. Supports weekly view (default) and monthly view (±15 days or full month).
Weekly view: Returns shifts grouped by date for current week or specified week. Monthly view: Returns dates with shifts marked + shift list for that month.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/shifts/calendar?view=weekly" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/calendar"
);
const params = {
"view": "weekly",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/shifts/calendar';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'view' => 'weekly',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/shifts/calendar')
.replace(queryParameters: {
'view': 'weekly',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Monthly):
{"status":"SUCCESS","data":{"view":"monthly","month":"2026-06","dates_with_shifts":["2026-06-18","2026-06-20","2026-06-25"],"calendar_weeks":[[...]],"shifts":[...]}}
Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"view": "weekly",
"date_range": {
"start": "2026-08-03",
"end": "2026-08-09"
},
"dates_with_shifts": [
"2026-08-04",
"2026-08-05",
"2026-08-06",
"2026-08-07"
],
"shifts_by_date": {
"2026-08-04": [
{
"id": "019fd4e7-8dc3-7045-999d-0b5016e16805",
"status": "completed",
"status_label": "Abgeschlossen",
"shift_date": "2026-08-04",
"day_of_week": "Tuesday",
"scheduled_start_time": "08:17:00",
"scheduled_end_time": "09:08:00",
"scheduled_hours": null,
"shift_type": "day",
"location": {
"name": "Beatty Ltd",
"address": "780 Vergie Courts"
},
"compensation": {
"hourly_rate_gross": 30.4,
"total_gross": 251.38
},
"badges": {
"1": "3_more_shifts"
},
"job": {
"id": "019fd4e7-8da0-718d-8b0a-7fa0f29523e2",
"title": "Loan Interviewer",
"category": "retail"
},
"organization": {
"id": "019fd4e7-5633-700f-ad54-9f03c0661fd1",
"name": "Caritas",
"logo_url": null
}
}
],
"2026-08-05": [
{
"id": "019fd4e7-8dae-73bd-8647-588dbb86c1a6",
"status": "awaiting_signature",
"status_label": "Unterschrift ausstehend",
"shift_date": "2026-08-05",
"day_of_week": "Wednesday",
"scheduled_start_time": "19:33:00",
"scheduled_end_time": "06:36:00",
"scheduled_hours": null,
"shift_type": "day",
"location": {
"name": "Marvin and Sons",
"address": "886 Schimmel Plaza Suite 357"
},
"compensation": {
"hourly_rate_gross": 16.24,
"total_gross": 132.68
},
"badges": {
"1": "2_more_shifts"
},
"job": {
"id": "019fd4e7-8da0-718d-8b0a-7fa0f29523e2",
"title": "Loan Interviewer",
"category": "retail"
},
"organization": {
"id": "019fd4e7-5633-700f-ad54-9f03c0661fd1",
"name": "Caritas",
"logo_url": null
}
}
],
"2026-08-06": [
{
"id": "019fd4e7-8dbb-71a3-bba2-05174a59c0ad",
"status": "checked_in",
"status_label": "Eingecheckt",
"shift_date": "2026-08-06",
"day_of_week": "Thursday",
"scheduled_start_time": "00:19:00",
"scheduled_end_time": "23:37:00",
"scheduled_hours": null,
"shift_type": "holiday",
"location": {
"name": "Harris-Klocko",
"address": "15800 Grant Shore Apt. 974"
},
"compensation": {
"hourly_rate_gross": 17.81,
"total_gross": 163.15
},
"badges": {
"1": "1_more_shifts"
},
"job": {
"id": "019fd4e7-8da0-718d-8b0a-7fa0f29523e2",
"title": "Loan Interviewer",
"category": "retail"
},
"organization": {
"id": "019fd4e7-5633-700f-ad54-9f03c0661fd1",
"name": "Caritas",
"logo_url": null
}
}
],
"2026-08-07": [
{
"id": "019fd4e7-8db5-7390-a768-5cc04b8a5ecc",
"status": "signed",
"status_label": "Unterschrieben",
"shift_date": "2026-08-07",
"day_of_week": "Friday",
"scheduled_start_time": "08:00:00",
"scheduled_end_time": "16:00:00",
"scheduled_hours": null,
"shift_type": "holiday",
"location": {
"name": "Mohr-Bernier",
"address": "57499 Okuneva Springs"
},
"compensation": {
"hourly_rate_gross": 32.63,
"total_gross": 230.33
},
"badges": [
"last_shift"
],
"job": {
"id": "019fd4e7-8da0-718d-8b0a-7fa0f29523e2",
"title": "Loan Interviewer",
"category": "retail"
},
"organization": {
"id": "019fd4e7-5633-700f-ad54-9f03c0661fd1",
"name": "Caritas",
"logo_url": null
}
}
]
},
"totals": {
"shifts_count": 4,
"total_hours": 0,
"total_earnings_gross": 777.5400000000001
},
"navigation": {
"prev_week": "2026-07-27",
"next_week": "2026-08-10"
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Shift Readiness
requires authentication
Returns whether the authenticated employee is ready to clock in for a specific shift, plus a list of any blocking conditions.
Readiness checks (in order):
- Shift belongs to the authenticated employee
- Shift status is
signed(not yet clocked in) - Shift date is today (Austrian time)
- Current time is within the clock-in window: 30 minutes before scheduled_start_time up to 30 minutes after end_time
- No active attendance record already exists (prevents double clock-in)
The response always returns HTTP 200; ready indicates whether the
employee may proceed to clock in.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/shifts/9c3f5f3d-0123-4abc-b456-426614174000/readiness" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/9c3f5f3d-0123-4abc-b456-426614174000/readiness"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/shifts/9c3f5f3d-0123-4abc-b456-426614174000/readiness';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/shifts/9c3f5f3d-0123-4abc-b456-426614174000/readiness');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Not Ready):
{
"status": "SUCCESS",
"data": {
"ready": false,
"shift_id": "9c3f5f3d-0123-4abc-b456-426614174000",
"shift_date": "2026-06-28",
"scheduled_start_time": "08:00",
"scheduled_end_time": "16:00",
"blockers": [
"not_today",
"outside_clock_in_window"
]
}
}
Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"ready": false,
"shift_id": "019fd4e7-8dae-73bd-8647-588dbb86c1a6",
"shift_date": "2026-08-05",
"scheduled_start_time": "19:33:00",
"scheduled_end_time": "06:36:00",
"blockers": [
"invalid_status",
"contract_unsigned",
"rahmenvertrag_unsigned",
"ecard_missing",
"not_today",
"outside_clock_in_window"
]
}
}
Example response (403):
{
"status": "ERROR",
"message": "Diese Schicht gehört nicht zu deinem Konto."
}
Example response (404):
{
"status": "ERROR",
"message": "Schicht nicht gefunden."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Shift
requires authentication
Everything the shift screen needs while a shift is running: the booking itself, where it is, who to ask for, and the clock.
Until now a shift could be listed and acted on but not fetched, so a screen opened on one had to keep whatever the list gave it and could not refresh after a clock-in or a break.
attendance.worked_seconds is time on the clock with breaks already
deducted — the client counts on from it rather than polling. While a
break is open, current_break_seconds does the same for the break, and
worked_seconds stops advancing.
actions says which of the controls apply right now, decided by the
same rules the clock-in, clock-out and break endpoints enforce, so the
screen does not have to reimplement them and then disagree.
contract is the Überlassungsvertrag for this shift alone. Each
shift is agreed to separately, because a company can set terms on a
single shift, so a worker taking three days signs three contracts and
each has its own sign_deadline. Its id is what
GET /mobile/contracts/{contractId} and POST .../sign take, so the
screen can open or sign the right one without searching the worker's
contract list. It is null before the company has selected the worker.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"shift": {
"id": "019fd4e7-8dae-73bd-8647-588dbb86c1a6",
"status": "awaiting_signature",
"status_label": "Unterschrift ausstehend",
"shift_date": "2026-08-05",
"scheduled_start_time": "19:33:00",
"scheduled_end_time": "06:36:00",
"shift_type": "day",
"confirmation_deadline": "2026-08-23T19:02:29+00:00",
"notes": null,
"location": {
"name": "Marvin and Sons",
"address": "886 Schimmel Plaza Suite 357",
"lat": 48.035945,
"lng": 14.889039
},
"compensation": {
"hourly_rate_gross": 16.24,
"estimated_gross": 132.68,
"currency": "EUR",
"supplements": {
"night": 0,
"weekend": 0
}
},
"can_confirm": true,
"can_clock_in": false,
"contact_person_name": null,
"contact_person_phone": null,
"contact_person_avatar_url": null,
"meeting_point": null,
"dress_code": "Vero amet fugiat quaerat odit.",
"job": {
"id": "019fd4e7-8da0-718d-8b0a-7fa0f29523e2",
"title": "Loan Interviewer",
"category": "retail"
},
"organization": {
"id": "019fd4e7-5633-700f-ad54-9f03c0661fd1",
"name": "Caritas",
"logo_url": null,
"average_rating": null
},
"contract": {
"id": "019fd4e7-8db1-7290-97a1-e17bfbb64a4d",
"contract_number": "UEVG-556708",
"status": "pending_signature",
"status_label": "Unterschrift ausstehend",
"is_signed": false,
"can_sign": true,
"signed_at": null,
"sign_deadline": "2026-08-07T02:29:32+00:00",
"is_overdue": false
},
"planned_break_minutes": 0,
"paid_break_minutes": 30,
"attendance": {
"clock_in_at": null,
"clock_out_at": null,
"worked_seconds": 0,
"break_minutes_taken": 0,
"is_on_break": false,
"current_break_started_at": null,
"current_break_seconds": 0
},
"actions": {
"can_clock_in": false,
"can_clock_out": false,
"can_start_break": false,
"can_end_break": false,
"can_report_incident": false,
"can_change_workplace": false,
"can_sign_contract": true
}
}
}
}
Example response (404, Not the caller's shift):
{
"status": "RESOURCE_NOT_FOUND",
"message": "Die Schicht wurde nicht gefunden."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Report Shift Incident
requires authentication
Allows an employee to report a workplace incident that occurred during
an active or recently completed shift (injury, safety concern, equipment
failure, etc.). Creates a support ticket of category shift linked to
the given shift.
The incident report is sent to the internal team for follow-up. Austrian ASchG §15 obliges employers/employees to report workplace injuries.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/9c3f5f3d-0123-4abc-b456-426614174000/incident" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"incident_type\": \"injury\",
\"description\": \"I slipped on a wet floor near the loading bay.\",
\"occurred_at\": \"2026-06-27T14:30:00Z\",
\"lat\": 48.2082,
\"lng\": 16.3738
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/9c3f5f3d-0123-4abc-b456-426614174000/incident"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"incident_type": "injury",
"description": "I slipped on a wet floor near the loading bay.",
"occurred_at": "2026-06-27T14:30:00Z",
"lat": 48.2082,
"lng": 16.3738
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/shifts/9c3f5f3d-0123-4abc-b456-426614174000/incident';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'incident_type' => 'injury',
'description' => 'I slipped on a wet floor near the loading bay.',
'occurred_at' => '2026-06-27T14:30:00Z',
'lat' => 48.2082,
'lng' => 16.3738,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/shifts/9c3f5f3d-0123-4abc-b456-426614174000/incident');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"incident_type": "injury",
"description": "I slipped on a wet floor near the loading bay.",
"occurred_at": "2026-06-27T14:30:00Z",
"lat": 48.2082,
"lng": 16.3738
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"ticket_id": "019fd2b8-3a07-70e6-be52-a12bdc110c54",
"ticket_number": "TKT-202608-00001",
"message": "Vorfall wurde gemeldet."
}
}
Example response (403):
{
"status": "ERROR",
"message": "Diese Schicht gehört nicht zu deinem Konto."
}
Example response (404):
{
"status": "ERROR",
"message": "Schicht nicht gefunden."
}
Example response (422):
{
"status": "ERROR",
"message": "The description field is required."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Confirm My Hours
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/hours-confirmation" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/hours-confirmation"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/hours-confirmation';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/hours-confirmation');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"clock_in_at": "2026-08-06T02:30:01+00:00",
"clock_out_at": "2026-08-06T10:30:01+00:00",
"break_minutes": 480,
"scheduled_end_time": "10:30:00",
"payable_minutes": 30,
"unclaimed_overtime_minutes": 0,
"confirmed_at": null
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Confirm My Hours
requires authentication
The worker's sign-off on what they will be paid for, after clocking out.
A GET returns the figures the screen shows: when they actually clocked in and out, how many of those minutes are payable, and how many fall outside the cap and would need an overtime request. The POST records their agreement, with an optional signature.
Confirming does not settle anything — the company still confirms the hours in its own Hours screen, and that is what reaches payroll. This records the worker's side of the story so a later disagreement has both.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/hours-confirmation" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/hours-confirmation"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/hours-confirmation';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/hours-confirmation');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Your hours have been confirmed.",
"data": {
"clock_in_at": "2026-08-05T16:19:02+00:00",
"clock_out_at": "2026-08-06T00:19:02+00:00",
"break_minutes": 480,
"scheduled_end_time": "00:19:00",
"payable_minutes": 30,
"unclaimed_overtime_minutes": 0,
"confirmed_at": "2026-08-06T00:19:02+00:00"
}
}
Example response (422, Not clocked out):
{
"status": "INVALID_OPERATION",
"message": "You have not clocked out of this shift yet."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List My Shift Requests
requires authentication
Every request the authenticated worker has raised, newest first, optionally narrowed to one shift or one status.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/requests?shift_id=019f9939-c4c3-70fb-a54e-5ebf63db36d2&status=pending" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"shift_id\": \"6ff8f7f6-1eb3-3525-be4a-3932c805afed\",
\"status\": \"withdrawn\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/requests"
);
const params = {
"shift_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"status": "pending",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"shift_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed",
"status": "withdrawn"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/requests';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'shift_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'status' => 'pending',
],
'json' => [
'shift_id' => '6ff8f7f6-1eb3-3525-be4a-3932c805afed',
'status' => 'withdrawn',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/requests')
.replace(queryParameters: {
'shift_id': '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'status': 'pending',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"shift_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed",
"status": "withdrawn"
};
final response = await http.get(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"requests": [
{
"id": "019fd2b8-a28b-7060-8491-a3fa2aee9676",
"assignment_id": "019fd2b8-a219-710c-9a2a-91af501576cd",
"type": "overtime",
"type_label": "Überstunden",
"affects_pay": true,
"status": "pending",
"status_label": "Offen",
"reason_code": null,
"reason_note": "Die Lieferung musste noch fertig verräumt werden.",
"claimed_minutes": 45,
"evidence": [],
"requested_at": "2026-08-06T00:19:03+00:00",
"decision": null,
"escalated_at": null,
"conversation_id": null
},
{
"id": "019fd2b8-a252-73da-94fd-15b16c76b745",
"assignment_id": "019fd2b8-a219-710c-9a2a-91af501576cd",
"type": "manual_check_in",
"type_label": "Manuelle Anmeldung",
"affects_pay": false,
"status": "pending",
"status_label": "Offen",
"reason_code": "no_qr_scan",
"reason_note": null,
"claimed_minutes": null,
"evidence": [],
"requested_at": "2026-08-05T16:19:03+00:00",
"decision": null,
"escalated_at": null,
"conversation_id": null
}
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Raise a Shift Request
requires authentication
Asks the company to decide something about a shift the worker was assigned to — extra time worked, an early departure, a correction to the recorded hours, or evidence excusing an absence.
Nothing here blocks the worker: an overtime request is raised after they have already clocked out, and the recorded clock-out time is never altered by it. What the request can change is how many of those minutes are paid.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/requests" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"type\": \"overtime\",
\"reason_code\": \"covered_for_colleague\",
\"reason_note\": \"Stayed to finish the late delivery.\",
\"claimed_minutes\": 45,
\"evidence\": [
\"019f9939-c4c3-70fb-a54e-5ebf63db36d2\"
]
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/requests"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"type": "overtime",
"reason_code": "covered_for_colleague",
"reason_note": "Stayed to finish the late delivery.",
"claimed_minutes": 45,
"evidence": [
"019f9939-c4c3-70fb-a54e-5ebf63db36d2"
]
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/requests';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'type' => 'overtime',
'reason_code' => 'covered_for_colleague',
'reason_note' => 'Stayed to finish the late delivery.',
'claimed_minutes' => 45,
'evidence' => ['019f9939-c4c3-70fb-a54e-5ebf63db36d2'],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/requests');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"type": "overtime",
"reason_code": "covered_for_colleague",
"reason_note": "Stayed to finish the late delivery.",
"claimed_minutes": 45,
"evidence": [
"019f9939-c4c3-70fb-a54e-5ebf63db36d2"
]
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Your request has been sent to the company.",
"data": {
"id": "019fd2b8-a28b-7060-8491-a3fa2aee9676",
"assignment_id": "019fd2b8-a219-710c-9a2a-91af501576cd",
"type": "overtime",
"type_label": "Überstunden",
"affects_pay": true,
"status": "pending",
"status_label": "Offen",
"reason_code": null,
"reason_note": "Die Lieferung musste noch fertig verräumt werden.",
"claimed_minutes": 45,
"evidence": [],
"requested_at": "2026-08-06T00:19:03+00:00",
"decision": null,
"escalated_at": null,
"conversation_id": null
}
}
Example response (422, Already open):
{
"status": "VALIDATION_ERROR",
"message": "A request of this type is already open for this shift."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Withdraw a Shift Request
requires authentication
Takes back a request the company has not decided yet. Once decided it stands — the record of what was asked and what was answered is part of the pay trail and is not erasable by either side.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/mobile/requests/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/requests/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/requests/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/requests/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (409, Already decided):
{
"status": "INVALID_OPERATION",
"message": "This request has already been decided."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Record Workplace Change
requires authentication
Records a mid-shift workplace change discovered by the employee (different employer, different location, or different working conditions than those agreed in the Überlassungsbestätigung).
Per BUAG §3 and AÜG §11, employees must be informed about and consent to
workplace changes. This action stores the change event in the workplace_changes
JSONB column added by migration M1.
The employee must be actively clocked in for this endpoint to accept changes.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/9c3f5f3d-0123-4abc-b456-426614174000/workplace-change" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"change_type\": \"location\",
\"old_value\": \"Hauptstraße 1, 1010 Wien\",
\"new_value\": \"Mariahilfer Str. 50, 1060 Wien\",
\"reason\": \"Production line moved.\",
\"consent_given\": true
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/9c3f5f3d-0123-4abc-b456-426614174000/workplace-change"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"change_type": "location",
"old_value": "Hauptstraße 1, 1010 Wien",
"new_value": "Mariahilfer Str. 50, 1060 Wien",
"reason": "Production line moved.",
"consent_given": true
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/shifts/9c3f5f3d-0123-4abc-b456-426614174000/workplace-change';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'change_type' => 'location',
'old_value' => 'Hauptstraße 1, 1010 Wien',
'new_value' => 'Mariahilfer Str. 50, 1060 Wien',
'reason' => 'Production line moved.',
'consent_given' => true,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/shifts/9c3f5f3d-0123-4abc-b456-426614174000/workplace-change');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"change_type": "location",
"old_value": "Hauptstraße 1, 1010 Wien",
"new_value": "Mariahilfer Str. 50, 1060 Wien",
"reason": "Production line moved.",
"consent_given": true
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200):
{
"status": "SUCCESS",
"data": {
"message": "Arbeitsortänderung wurde erfasst.",
"total_changes": 1
}
}
Example response (400):
{
"status": "ERROR",
"message": "Du bist nicht eingestempelt."
}
Example response (403):
{
"status": "ERROR",
"message": "Diese Schicht gehört nicht zu deinem Konto."
}
Example response (404):
{
"status": "ERROR",
"message": "Schicht nicht gefunden."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Cancel Shift
requires authentication
The worker cancels their own shift. What that costs depends on whether they had signed:
Unsigned (awaiting_signature) — declining. The worker is refusing
to sign, not breaking a commitment, so it is free at any time: no 24-hour
window, no Stornopauschale, no reliability entry. Letting the sign
deadline lapse costs nothing, and saying no outright cannot cost more.
Signed — cancelling. Within 24 hours of start it is refused
(DEADLINE_PASSED — contact support); 24–48 hours' notice carries the
Stornopauschale and a reliability penalty; more than 48 hours is
penalty-free.
Either way the shift's own Überlassungsvertrag is revoked with it, so nothing signable (or in force) survives on a cancelled shift.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/cancel" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Krankheitsbedingt kurzfristig abgesagt.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/cancel"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/cancel';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'Krankheitsbedingt kurzfristig abgesagt.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/cancel');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The shift has been cancelled. Your reliability score may be affected.",
"data": {
"shift_id": "019fd359-b78c-730d-810e-166b221166a5",
"cancelled_at": "2026-08-05 19:15",
"notice_hours": 0,
"reliability_impact": 0
}
}
Example response (422, Signed, under 24 hours to start):
{
"status": "DEADLINE_PASSED",
"message": "Diese Schicht kann weniger als 24 Stunden vor Beginn nicht mehr selbst storniert werden. Bitte kontaktieren Sie den Support."
}
Example response (422, Already cancelled or completed):
{
"status": "INVALID_OPERATION",
"message": "Diese Schicht kann nicht storniert werden."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Clock In
requires authentication
Clock in to a shift.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2
A QR scan proves presence by itself. A **manual or GPS check-in** must
bring its own proof: `lat`/`lng` are required and checked against the
workplace — beyond the configured radius (500 m) the check-in is
refused with `LOCATION_OUT_OF_RANGE` — and at least one photo taken on
site must accompany the request. The photos are stored as shift
attachments and put in front of the company together with the
check-in review.
With `gps_unavailable: true` the position requirement is waived, the
check-in is flagged for support, and the photos remain mandatory./clock-in" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"lat\": 48.2082,
\"lng\": 16.3738,
\"method\": \"manual\",
\"signature\": \"Beispieltext\",
\"photos\": null,
\"gps_unavailable\": false
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2
A QR scan proves presence by itself. A **manual or GPS check-in** must
bring its own proof: `lat`/`lng` are required and checked against the
workplace — beyond the configured radius (500 m) the check-in is
refused with `LOCATION_OUT_OF_RANGE` — and at least one photo taken on
site must accompany the request. The photos are stored as shift
attachments and put in front of the company together with the
check-in review.
With `gps_unavailable: true` the position requirement is waived, the
check-in is flagged for support, and the photos remain mandatory./clock-in"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"lat": 48.2082,
"lng": 16.3738,
"method": "manual",
"signature": "Beispieltext",
"photos": null,
"gps_unavailable": false
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2
A QR scan proves presence by itself. A **manual or GPS check-in** must
bring its own proof: `lat`/`lng` are required and checked against the
workplace — beyond the configured radius (500 m) the check-in is
refused with `LOCATION_OUT_OF_RANGE` — and at least one photo taken on
site must accompany the request. The photos are stored as shift
attachments and put in front of the company together with the
check-in review.
With `gps_unavailable: true` the position requirement is waived, the
check-in is flagged for support, and the photos remain mandatory./clock-in';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'lat' => 48.2082,
'lng' => 16.3738,
'method' => 'manual',
'signature' => 'Beispieltext',
'photos' => null,
'gps_unavailable' => false,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2
A QR scan proves presence by itself. A **manual or GPS check-in** must
bring its own proof: `lat`/`lng` are required and checked against the
workplace — beyond the configured radius (500 m) the check-in is
refused with `LOCATION_OUT_OF_RANGE` — and at least one photo taken on
site must accompany the request. The photos are stored as shift
attachments and put in front of the company together with the
check-in review.
With `gps_unavailable: true` the position requirement is waived, the
check-in is flagged for support, and the photos remain mandatory./clock-in');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"lat": 48.2082,
"lng": 16.3738,
"method": "manual",
"signature": "Beispieltext",
"photos": null,
"gps_unavailable": false
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "You have successfully clocked in.",
"data": {
"attendance": {
"id": "019fd515-53b8-73b9-8f04-c3758917dbf3",
"clock_in_at": "2026-08-06T03:19:32+00:00",
"clock_in_method": "manual"
},
"shift": {
"id": "019fd515-5399-73cd-ba1c-6d51fdd33ee7",
"status": "checked_in"
},
"conversation_id": "019fd515-53c3-70a6-93d3-1451aec0adfa",
"gps_fallback": false,
"support_notified": false
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Clock Out
requires authentication
Clock out from a shift.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/clock-out" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"lat\": 1,
\"lng\": 1,
\"method\": \"qr\",
\"break_minutes\": 1,
\"signature\": \"Beispieltext\",
\"early_checkout_reason\": \"Krankheitsbedingt kurzfristig abgesagt.\",
\"early_checkout_category\": \"sickness\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/clock-out"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"lat": 1,
"lng": 1,
"method": "qr",
"break_minutes": 1,
"signature": "Beispieltext",
"early_checkout_reason": "Krankheitsbedingt kurzfristig abgesagt.",
"early_checkout_category": "sickness"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/clock-out';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'lat' => 1,
'lng' => 1,
'method' => 'qr',
'break_minutes' => 1,
'signature' => 'Beispieltext',
'early_checkout_reason' => 'Krankheitsbedingt kurzfristig abgesagt.',
'early_checkout_category' => 'sickness',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/clock-out');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"lat": 1,
"lng": 1,
"method": "qr",
"break_minutes": 1,
"signature": "Beispieltext",
"early_checkout_reason": "Krankheitsbedingt kurzfristig abgesagt.",
"early_checkout_category": "sickness"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "You have successfully clocked out.",
"data": {
"attendance": {
"id": "019fd2b8-9e87-7131-9457-cc5bea1d6e78",
"clock_in_at": "2026-08-05T16:19:02+00:00",
"clock_out_at": "2026-08-06T00:19:02+00:00",
"total_hours_worked": 8,
"break_minutes": 480,
"overtime_hours": 0,
"actual_gross_amount": 0
},
"shift": {
"id": "019fd2b8-9e68-73ba-aff1-e1ff0de2c556",
"status": "completed"
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Toggle Break
requires authentication
Employee starts or ends a break with a simple button tap.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/break" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/break"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/break';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/break');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"action": "break_started",
"break_id": "019fd2b8-9e9d-724c-8182-9d92c82b5d24",
"started_at": "2026-08-05T16:19:02+00:00",
"break_type": "standard",
"message": "Pause gestartet"
},
"meta": {
"is_on_break": true,
"total_break_minutes": 0,
"mandatory_break_taken": false
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Upload a photo / document attached to a shift (evidence, handover, …).
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/architecto/attachments" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "caption=Übergabeprotokoll"\
--form "file=@/tmp/phpr29e3bd3d8h38azIbXa" const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/architecto/attachments"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('caption', 'Übergabeprotokoll');
body.append('file', document.querySelector('input[name="file"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/shifts/architecto/attachments';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'multipart/form-data',
'Accept' => 'application/json',
],
'multipart' => [
[
'name' => 'caption',
'contents' => 'Übergabeprotokoll'
],
[
'name' => 'file',
'contents' => fopen('/tmp/phpr29e3bd3d8h38azIbXa', 'r')
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/shifts/architecto/attachments');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'multipart/form-data',
'Accept': 'application/json',
};
final request = http.MultipartRequest('POST', uri);
request.headers.addAll(headers);
request.fields['caption'] = 'Übergabeprotokoll';
request.files.add(await http.MultipartFile.fromPath('file', '/tmp/phpr29e3bd3d8h38azIbXa'));
final streamed = await request.send();
final response = await http.Response.fromStream(streamed);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The attachment has been uploaded.",
"data": {
"attachment": {
"id": "019fd2b8-3a7e-7235-9631-d728b029f2ea",
"original_filename": "beispiel.pdf",
"mime_type": "application/pdf",
"file_size": 65536,
"caption": "Übergabeprotokoll",
"created_at": "2026-08-05T16:18:36+00:00"
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Generate Check In Qr
requires authentication
Generate a QR code payload for shift check-in/check-out.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/qr?action=architecto" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"action\": \"clock_in\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/qr"
);
const params = {
"action": "architecto",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"action": "clock_in"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/qr';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'action' => 'architecto',
],
'json' => [
'action' => 'clock_in',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/qr')
.replace(queryParameters: {
'action': 'architecto',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"action": "clock_in"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "messages.qr_generated",
"data": {
"qr_payload": "eyJpdiI6IkxPQXdSYmJ4akVDZGRldzhseWNTVnc9PSIsInZhbHVlIjoiaWNZc1FaMzk4QWRHN0RFR0M5WkNKU2NKcTNzN2tRSVZtSUJOcEdSLzR1TnAwUUxTamY0V0pWWWc2ZkNhQUYzak9NZzlnb0tVc1E0bXhIN1BXa2ZwZUR1SzlTTjZvUlpNSENUcWdZcGFUZFJsdVZZZldnOTFNNmRPa3JWYkJoUzZiTzFJR3Z2dFVDMlMyVnNENFpMMXViU2w2VGtYdWx1TnljWGZZQUlLZEo1UytvOHZ0OTVUZndJa0FvZnMrV28wIiwibWFjIjoiNTc4ZjhlZWQ1MTdhYTNhOTMzOGQ3MDAzMDU4YmYyMDNjNjgwYWMxNTZhZWE5YmI4MjYwOTc5MjljNzkxYTUxNiIsInRhZyI6IiJ9",
"expires_at": "2026-08-05T16:19:36+00:00",
"action": "clock_in",
"action_label": "Einchecken"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Dienstzettel
requires authentication
Stream the per-shift Dienstzettel as a PDF.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/dienstzettel" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/dienstzettel"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/dienstzettel';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/dienstzettel');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "43ecbfa4-7afc-4a80-8897-2927ce9ef626",
"timestamp": "2026-08-21T05:14:34.017781Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Earnings Statement
requires authentication
Stream our own per-shift earnings statement (Verdienstabrechnung) as a PDF.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/earnings-statement" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/earnings-statement"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/earnings-statement';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/earnings-statement');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "7cd5c56f-d7e8-4b71-9899-3087a486211c",
"timestamp": "2026-08-21T05:14:34.030330Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Rate Company
requires authentication
Employee submits a rating for a company after shift completion.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/rate" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"overall_score\": 1,
\"punctuality_score\": 1,
\"professionalism_score\": 1,
\"communication_score\": 1,
\"work_environment_score\": 1,
\"comment\": \"Beispieltext\",
\"is_anonymous\": true
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/rate"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"overall_score": 1,
"punctuality_score": 1,
"professionalism_score": 1,
"communication_score": 1,
"work_environment_score": 1,
"comment": "Beispieltext",
"is_anonymous": true
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/rate';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'overall_score' => 1,
'punctuality_score' => 1,
'professionalism_score' => 1,
'communication_score' => 1,
'work_environment_score' => 1,
'comment' => 'Beispieltext',
'is_anonymous' => true,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/rate');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"overall_score": 1,
"punctuality_score": 1,
"professionalism_score": 1,
"communication_score": 1,
"work_environment_score": 1,
"comment": "Beispieltext",
"is_anonymous": true
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Your rating has been submitted successfully.",
"data": {
"rating": {
"id": "019fd2b8-3ad6-716f-9be2-5f73c4f494f2",
"overall_score": 1,
"created_at": "2026-08-05 16:18"
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Ratings
List Received Ratings
requires authentication
List the ratings a worker has received from companies.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/ratings/received" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/ratings/received"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/ratings/received';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/ratings/received');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"average_overall": null,
"count": 0,
"ratings": []
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Notifications
Register (or refresh) the authenticated user's push-notification device token.
requires authentication
The Firebase Cloud Messaging token is unique per device install; re-posting an existing token re-binds it to the current user (e.g. after an account switch) and refreshes its platform/name. Idempotent by token.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/devices/register" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"token\": \"fADc...9x\",
\"platform\": \"ios\",
\"device_name\": \"iPhone 15 Pro\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/devices/register"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"token": "fADc...9x",
"platform": "ios",
"device_name": "iPhone 15 Pro"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/devices/register';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'token' => 'fADc...9x',
'platform' => 'ios',
'device_name' => 'iPhone 15 Pro',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/devices/register');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"token": "fADc...9x",
"platform": "ios",
"device_name": "iPhone 15 Pro"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Device registered for push notifications.",
"data": {
"id": "019fd2b8-3240-70a0-be56-989736211eff",
"platform": "ios"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Unregister a push-notification device token
requires authentication
Removes the token so this device stops receiving notifications for the authenticated user. Idempotent: unregistering a token that is already gone, or one belonging to someone else, reports success without touching another account's registration.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/devices/unregister" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"token\": \"fADc...9x\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/devices/unregister"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"token": "fADc...9x"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/devices/unregister';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'token' => 'fADc...9x',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/devices/unregister');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"token": "fADc...9x"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Device unregistered from push notifications.",
"data": {
"removed": false
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Notifications
requires authentication
Paginated list of notifications for the authenticated user.
Includes an unread_count in meta for the inbox badge.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/notifications?page=16&per_page=16&unread_only=" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/notifications"
);
const params = {
"page": "16",
"per_page": "16",
"unread_only": "0",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/notifications';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'page' => '16',
'per_page' => '16',
'unread_only' => '0',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/notifications')
.replace(queryParameters: {
'page': '16',
'per_page': '16',
'unread_only': '',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Notifications retrieved successfully.",
"data": [],
"errors": null,
"meta": {
"request_id": "c7eb899a-5227-4d81-bdbb-845ed39a9963",
"timestamp": "2026-08-05T16:18:36.098962Z",
"current_page": 16,
"per_page": 16,
"total": 0,
"last_page": 1,
"unread_count": 0
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Unread Notification Count
requires authentication
Returns the count of unread notifications for badge display.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/notifications/unread-count" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/notifications/unread-count"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/notifications/unread-count';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/notifications/unread-count');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"unread_count": 0
},
"errors": null,
"meta": {
"request_id": "d37f478c-4c14-45ab-ac14-23580ddfa706",
"timestamp": "2026-08-05T16:18:36.105987Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Mark Notification Read
requires authentication
Marks a single notification as read.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/notifications/550e8400-e29b-41d4-a716-446655440000/read" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/notifications/550e8400-e29b-41d4-a716-446655440000/read"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/notifications/550e8400-e29b-41d4-a716-446655440000/read';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/notifications/550e8400-e29b-41d4-a716-446655440000/read');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Success):
{
"status": "SUCCESS",
"message": "Notification marked as read.",
"data": null,
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-06-10T12:00:00.000000Z"
}
}
Example response (404, Not Found):
{
"status": "NOT_FOUND",
"message": "Notification not found.",
"data": null,
"errors": [
{
"field": null,
"message": "Notification not found."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-06-10T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Mark All Notifications Read
requires authentication
Marks all unread notifications as read.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/notifications/read-all" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/notifications/read-all"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/notifications/read-all';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/notifications/read-all');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "All notifications have been marked as read.",
"data": {
"marked_count": 0
},
"errors": null,
"meta": {
"request_id": "431882ec-4bb8-4d4c-9b72-39376ca1eaa1",
"timestamp": "2026-08-05T16:18:36.115293Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Legal
List Legal Documents
Returns URLs and versions for all legal documents.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/legal/documents" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/legal/documents"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/legal/documents';
$response = $client->get(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/legal/documents');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"privacy_policy": {
"key": "privacy_policy",
"url": "http://localhost:8001/legal/privacy_policy",
"version": "1",
"title": "Datenschutzerklärung",
"required": true
},
"terms_of_service": {
"key": "terms_of_service",
"url": "http://localhost:8001/legal/terms_of_service",
"version": "1",
"title": "Allgemeine Geschäftsbedingungen (AGB)",
"required": true
},
"employment_terms": {
"key": "employment_terms",
"url": "http://localhost:8001/legal/aug_info",
"version": "1",
"title": "Information gemäß AÜG (Arbeitskräfteüberlassungsgesetz)",
"required": true
},
"cookie_policy": {
"key": "cookie_policy",
"url": "http://localhost:8001/legal/cookie_policy",
"version": "1",
"title": "Cookie-Richtlinie",
"required": false
},
"data_processing_agreement": {
"key": "dpa",
"url": "http://localhost:8001/legal/dpa",
"version": "2026-06-01",
"title": "Data Processing Agreement",
"required": false
}
},
"errors": null,
"meta": {
"request_id": "e90e4da8-5533-4b6a-8c64-eee968de3e53",
"timestamp": "2026-08-05T16:18:34.398969Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Employee Profile
Reference Data
The permitted values for the choices on the profile screens: genders, residence bases, document types and countries. Labels are German, which is the language of the documents these describe.
Safe to cache for a day — these change only when the platform does.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/reference-data" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/reference-data"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/reference-data';
$response = $client->get(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/reference-data');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"genders": [
{
"value": "male",
"label": "Männlich"
},
{
"value": "female",
"label": "Weiblich"
},
{
"value": "diverse",
"label": "Divers"
},
{
"value": "not_specified",
"label": "Keine Angabe"
}
],
"residence_statuses": [
{
"value": "AT_CITIZEN",
"label": "Österreichische Staatsbürgerschaft"
},
{
"value": "EU_EEA",
"label": "EU/EWR-Bürger"
},
{
"value": "THIRD_COUNTRY",
"label": "Drittstaatsangehörige(r)"
}
],
"document_types": [
{
"value": "passport",
"label": "Passport",
"requires_expiry": true,
"is_work_authorisation": false
},
{
"value": "id_card",
"label": "ID card",
"requires_expiry": true,
"is_work_authorisation": false
},
{
"value": "driver_license",
"label": "Driver's licence",
"requires_expiry": true,
"is_work_authorisation": false
},
{
"value": "work_permit",
"label": "Work permit",
"requires_expiry": true,
"is_work_authorisation": true
},
{
"value": "residence_permit",
"label": "Residence permit",
"requires_expiry": true,
"is_work_authorisation": true
},
{
"value": "rot_weiss_rot_karte",
"label": "Rot-Weiß-Rot card",
"requires_expiry": true,
"is_work_authorisation": true
},
{
"value": "blue_card",
"label": "EU Blue Card",
"requires_expiry": true,
"is_work_authorisation": true
},
{
"value": "bank_statement",
"label": "Bank statement",
"requires_expiry": false,
"is_work_authorisation": false
},
{
"value": "proof_of_address",
"label": "Proof of address",
"requires_expiry": false,
"is_work_authorisation": false
},
{
"value": "social_insurance_card",
"label": "Social insurance record",
"requires_expiry": false,
"is_work_authorisation": false
},
{
"value": "tax_document",
"label": "Tax document",
"requires_expiry": false,
"is_work_authorisation": false
},
{
"value": "certification",
"label": "Certification",
"requires_expiry": true,
"is_work_authorisation": false
},
{
"value": "health_certificate",
"label": "Health certificate",
"requires_expiry": true,
"is_work_authorisation": false
},
{
"value": "criminal_record_check",
"label": "Criminal record check",
"requires_expiry": false,
"is_work_authorisation": false
},
{
"value": "other",
"label": "Other",
"requires_expiry": false,
"is_work_authorisation": false
}
],
"countries": [
{
"code": "AF",
"name": "Afghanistan",
"dial_code": "+93"
},
{
"code": "AL",
"name": "Albania",
"dial_code": "+355"
},
{
"code": "DZ",
"name": "Algeria",
"dial_code": "+213"
},
{
"code": "AS",
"name": "American Samoa",
"dial_code": "+1"
},
{
"code": "AD",
"name": "Andorra",
"dial_code": "+376"
},
{
"code": "AO",
"name": "Angola",
"dial_code": "+244"
},
{
"code": "AI",
"name": "Anguilla",
"dial_code": "+1"
},
{
"code": "AQ",
"name": "Antarctica",
"dial_code": null
},
{
"code": "AG",
"name": "Antigua and Barbuda",
"dial_code": "+1"
},
{
"code": "AR",
"name": "Argentina",
"dial_code": "+54"
},
{
"code": "AM",
"name": "Armenia",
"dial_code": "+374"
},
{
"code": "AW",
"name": "Aruba",
"dial_code": "+297"
},
{
"code": "AU",
"name": "Australia",
"dial_code": "+61"
},
{
"code": "AT",
"name": "Austria",
"dial_code": "+43"
},
{
"code": "AZ",
"name": "Azerbaijan",
"dial_code": "+994"
},
{
"code": "BS",
"name": "Bahamas",
"dial_code": "+1"
},
{
"code": "BH",
"name": "Bahrain",
"dial_code": "+973"
},
{
"code": "BD",
"name": "Bangladesh",
"dial_code": "+880"
},
{
"code": "BB",
"name": "Barbados",
"dial_code": "+1"
},
{
"code": "BY",
"name": "Belarus",
"dial_code": "+375"
},
{
"code": "BE",
"name": "Belgium",
"dial_code": "+32"
},
{
"code": "BZ",
"name": "Belize",
"dial_code": "+501"
},
{
"code": "BJ",
"name": "Benin",
"dial_code": "+229"
},
{
"code": "BM",
"name": "Bermuda",
"dial_code": "+1"
},
{
"code": "BT",
"name": "Bhutan",
"dial_code": "+975"
},
{
"code": "BO",
"name": "Bolivia",
"dial_code": "+591"
},
{
"code": "BQ",
"name": "Bonaire, Sint Eustatius and Saba",
"dial_code": "+599"
},
{
"code": "BA",
"name": "Bosnia and Herzegovina",
"dial_code": "+387"
},
{
"code": "BW",
"name": "Botswana",
"dial_code": "+267"
},
{
"code": "BV",
"name": "Bouvet Island",
"dial_code": null
},
{
"code": "BR",
"name": "Brazil",
"dial_code": "+55"
},
{
"code": "IO",
"name": "British Indian Ocean Territory",
"dial_code": "+246"
},
{
"code": "VG",
"name": "British Virgin Islands",
"dial_code": "+1"
},
{
"code": "BN",
"name": "Brunei",
"dial_code": "+673"
},
{
"code": "BG",
"name": "Bulgaria",
"dial_code": "+359"
},
{
"code": "BF",
"name": "Burkina Faso",
"dial_code": "+226"
},
{
"code": "BI",
"name": "Burundi",
"dial_code": "+257"
},
{
"code": "CV",
"name": "Cabo Verde",
"dial_code": "+238"
},
{
"code": "KH",
"name": "Cambodia",
"dial_code": "+855"
},
{
"code": "CM",
"name": "Cameroon",
"dial_code": "+237"
},
{
"code": "CA",
"name": "Canada",
"dial_code": "+1"
},
{
"code": "KY",
"name": "Cayman Islands",
"dial_code": "+1"
},
{
"code": "CF",
"name": "Central African Republic",
"dial_code": "+236"
},
{
"code": "TD",
"name": "Chad",
"dial_code": "+235"
},
{
"code": "CL",
"name": "Chile",
"dial_code": "+56"
},
{
"code": "CN",
"name": "China",
"dial_code": "+86"
},
{
"code": "CX",
"name": "Christmas Island",
"dial_code": "+61"
},
{
"code": "CC",
"name": "Cocos (Keeling) Islands",
"dial_code": "+61"
},
{
"code": "CO",
"name": "Colombia",
"dial_code": "+57"
},
{
"code": "KM",
"name": "Comoros",
"dial_code": "+269"
},
{
"code": "CD",
"name": "Congo, Democratic Republic",
"dial_code": "+243"
},
{
"code": "CG",
"name": "Congo, Republic",
"dial_code": "+242"
},
{
"code": "CK",
"name": "Cook Islands",
"dial_code": "+682"
},
{
"code": "CR",
"name": "Costa Rica",
"dial_code": "+506"
},
{
"code": "HR",
"name": "Croatia",
"dial_code": "+385"
},
{
"code": "CU",
"name": "Cuba",
"dial_code": "+53"
},
{
"code": "CW",
"name": "Curaçao",
"dial_code": "+599"
},
{
"code": "CY",
"name": "Cyprus",
"dial_code": "+357"
},
{
"code": "CZ",
"name": "Czech Republic",
"dial_code": "+420"
},
{
"code": "CI",
"name": "Côte d'Ivoire",
"dial_code": "+225"
},
{
"code": "DK",
"name": "Denmark",
"dial_code": "+45"
},
{
"code": "DJ",
"name": "Djibouti",
"dial_code": "+253"
},
{
"code": "DM",
"name": "Dominica",
"dial_code": "+1"
},
{
"code": "DO",
"name": "Dominican Republic",
"dial_code": "+1"
},
{
"code": "EC",
"name": "Ecuador",
"dial_code": "+593"
},
{
"code": "EG",
"name": "Egypt",
"dial_code": "+20"
},
{
"code": "SV",
"name": "El Salvador",
"dial_code": "+503"
},
{
"code": "GQ",
"name": "Equatorial Guinea",
"dial_code": "+240"
},
{
"code": "ER",
"name": "Eritrea",
"dial_code": "+291"
},
{
"code": "EE",
"name": "Estonia",
"dial_code": "+372"
},
{
"code": "SZ",
"name": "Eswatini",
"dial_code": "+268"
},
{
"code": "ET",
"name": "Ethiopia",
"dial_code": "+251"
},
{
"code": "FK",
"name": "Falkland Islands",
"dial_code": "+500"
},
{
"code": "FO",
"name": "Faroe Islands",
"dial_code": "+298"
},
{
"code": "FJ",
"name": "Fiji",
"dial_code": "+679"
},
{
"code": "FI",
"name": "Finland",
"dial_code": "+358"
},
{
"code": "FR",
"name": "France",
"dial_code": "+33"
},
{
"code": "GF",
"name": "French Guiana",
"dial_code": "+594"
},
{
"code": "PF",
"name": "French Polynesia",
"dial_code": "+689"
},
{
"code": "TF",
"name": "French Southern Territories",
"dial_code": null
},
{
"code": "GA",
"name": "Gabon",
"dial_code": "+241"
},
{
"code": "GM",
"name": "Gambia",
"dial_code": "+220"
},
{
"code": "GE",
"name": "Georgia",
"dial_code": "+995"
},
{
"code": "DE",
"name": "Germany",
"dial_code": "+49"
},
{
"code": "GH",
"name": "Ghana",
"dial_code": "+233"
},
{
"code": "GI",
"name": "Gibraltar",
"dial_code": "+350"
},
{
"code": "GR",
"name": "Greece",
"dial_code": "+30"
},
{
"code": "GL",
"name": "Greenland",
"dial_code": "+299"
},
{
"code": "GD",
"name": "Grenada",
"dial_code": "+1"
},
{
"code": "GP",
"name": "Guadeloupe",
"dial_code": "+590"
},
{
"code": "GU",
"name": "Guam",
"dial_code": "+1"
},
{
"code": "GT",
"name": "Guatemala",
"dial_code": "+502"
},
{
"code": "GG",
"name": "Guernsey",
"dial_code": "+44"
},
{
"code": "GN",
"name": "Guinea",
"dial_code": "+224"
},
{
"code": "GW",
"name": "Guinea-Bissau",
"dial_code": "+245"
},
{
"code": "GY",
"name": "Guyana",
"dial_code": "+592"
},
{
"code": "HT",
"name": "Haiti",
"dial_code": "+509"
},
{
"code": "HM",
"name": "Heard Island and McDonald Islands",
"dial_code": null
},
{
"code": "HN",
"name": "Honduras",
"dial_code": "+504"
},
{
"code": "HK",
"name": "Hong Kong",
"dial_code": "+852"
},
{
"code": "HU",
"name": "Hungary",
"dial_code": "+36"
},
{
"code": "IS",
"name": "Iceland",
"dial_code": "+354"
},
{
"code": "IN",
"name": "India",
"dial_code": "+91"
},
{
"code": "ID",
"name": "Indonesia",
"dial_code": "+62"
},
{
"code": "IR",
"name": "Iran",
"dial_code": "+98"
},
{
"code": "IQ",
"name": "Iraq",
"dial_code": "+964"
},
{
"code": "IE",
"name": "Ireland",
"dial_code": "+353"
},
{
"code": "IM",
"name": "Isle of Man",
"dial_code": "+44"
},
{
"code": "IL",
"name": "Israel",
"dial_code": "+972"
},
{
"code": "IT",
"name": "Italy",
"dial_code": "+39"
},
{
"code": "JM",
"name": "Jamaica",
"dial_code": "+1"
},
{
"code": "JP",
"name": "Japan",
"dial_code": "+81"
},
{
"code": "JE",
"name": "Jersey",
"dial_code": "+44"
},
{
"code": "JO",
"name": "Jordan",
"dial_code": "+962"
},
{
"code": "KZ",
"name": "Kazakhstan",
"dial_code": "+7"
},
{
"code": "KE",
"name": "Kenya",
"dial_code": "+254"
},
{
"code": "KI",
"name": "Kiribati",
"dial_code": "+686"
},
{
"code": "XK",
"name": "Kosovo",
"dial_code": "+383"
},
{
"code": "KW",
"name": "Kuwait",
"dial_code": "+965"
},
{
"code": "KG",
"name": "Kyrgyzstan",
"dial_code": "+996"
},
{
"code": "LA",
"name": "Laos",
"dial_code": "+856"
},
{
"code": "LV",
"name": "Latvia",
"dial_code": "+371"
},
{
"code": "LB",
"name": "Lebanon",
"dial_code": "+961"
},
{
"code": "LS",
"name": "Lesotho",
"dial_code": "+266"
},
{
"code": "LR",
"name": "Liberia",
"dial_code": "+231"
},
{
"code": "LY",
"name": "Libya",
"dial_code": "+218"
},
{
"code": "LI",
"name": "Liechtenstein",
"dial_code": "+423"
},
{
"code": "LT",
"name": "Lithuania",
"dial_code": "+370"
},
{
"code": "LU",
"name": "Luxembourg",
"dial_code": "+352"
},
{
"code": "MO",
"name": "Macao",
"dial_code": "+853"
},
{
"code": "MG",
"name": "Madagascar",
"dial_code": "+261"
},
{
"code": "MW",
"name": "Malawi",
"dial_code": "+265"
},
{
"code": "MY",
"name": "Malaysia",
"dial_code": "+60"
},
{
"code": "MV",
"name": "Maldives",
"dial_code": "+960"
},
{
"code": "ML",
"name": "Mali",
"dial_code": "+223"
},
{
"code": "MT",
"name": "Malta",
"dial_code": "+356"
},
{
"code": "MH",
"name": "Marshall Islands",
"dial_code": "+692"
},
{
"code": "MQ",
"name": "Martinique",
"dial_code": "+596"
},
{
"code": "MR",
"name": "Mauritania",
"dial_code": "+222"
},
{
"code": "MU",
"name": "Mauritius",
"dial_code": "+230"
},
{
"code": "YT",
"name": "Mayotte",
"dial_code": "+262"
},
{
"code": "MX",
"name": "Mexico",
"dial_code": "+52"
},
{
"code": "FM",
"name": "Micronesia",
"dial_code": "+691"
},
{
"code": "MD",
"name": "Moldova",
"dial_code": "+373"
},
{
"code": "MC",
"name": "Monaco",
"dial_code": "+377"
},
{
"code": "MN",
"name": "Mongolia",
"dial_code": "+976"
},
{
"code": "ME",
"name": "Montenegro",
"dial_code": "+382"
},
{
"code": "MS",
"name": "Montserrat",
"dial_code": "+1"
},
{
"code": "MA",
"name": "Morocco",
"dial_code": "+212"
},
{
"code": "MZ",
"name": "Mozambique",
"dial_code": "+258"
},
{
"code": "MM",
"name": "Myanmar",
"dial_code": "+95"
},
{
"code": "NA",
"name": "Namibia",
"dial_code": "+264"
},
{
"code": "NR",
"name": "Nauru",
"dial_code": "+674"
},
{
"code": "NP",
"name": "Nepal",
"dial_code": "+977"
},
{
"code": "NL",
"name": "Netherlands",
"dial_code": "+31"
},
{
"code": "NC",
"name": "New Caledonia",
"dial_code": "+687"
},
{
"code": "NZ",
"name": "New Zealand",
"dial_code": "+64"
},
{
"code": "NI",
"name": "Nicaragua",
"dial_code": "+505"
},
{
"code": "NE",
"name": "Niger",
"dial_code": "+227"
},
{
"code": "NG",
"name": "Nigeria",
"dial_code": "+234"
},
{
"code": "NU",
"name": "Niue",
"dial_code": "+683"
},
{
"code": "NF",
"name": "Norfolk Island",
"dial_code": "+672"
},
{
"code": "KP",
"name": "North Korea",
"dial_code": "+850"
},
{
"code": "MK",
"name": "North Macedonia",
"dial_code": "+389"
},
{
"code": "MP",
"name": "Northern Mariana Islands",
"dial_code": "+1"
},
{
"code": "NO",
"name": "Norway",
"dial_code": "+47"
},
{
"code": "OM",
"name": "Oman",
"dial_code": "+968"
},
{
"code": "PK",
"name": "Pakistan",
"dial_code": "+92"
},
{
"code": "PW",
"name": "Palau",
"dial_code": "+680"
},
{
"code": "PS",
"name": "Palestine",
"dial_code": "+970"
},
{
"code": "PA",
"name": "Panama",
"dial_code": "+507"
},
{
"code": "PG",
"name": "Papua New Guinea",
"dial_code": "+675"
},
{
"code": "PY",
"name": "Paraguay",
"dial_code": "+595"
},
{
"code": "PE",
"name": "Peru",
"dial_code": "+51"
},
{
"code": "PH",
"name": "Philippines",
"dial_code": "+63"
},
{
"code": "PN",
"name": "Pitcairn Islands",
"dial_code": "+64"
},
{
"code": "PL",
"name": "Poland",
"dial_code": "+48"
},
{
"code": "PT",
"name": "Portugal",
"dial_code": "+351"
},
{
"code": "PR",
"name": "Puerto Rico",
"dial_code": "+1"
},
{
"code": "QA",
"name": "Qatar",
"dial_code": "+974"
},
{
"code": "RO",
"name": "Romania",
"dial_code": "+40"
},
{
"code": "RU",
"name": "Russia",
"dial_code": "+7"
},
{
"code": "RW",
"name": "Rwanda",
"dial_code": "+250"
},
{
"code": "RE",
"name": "Réunion",
"dial_code": "+262"
},
{
"code": "BL",
"name": "Saint Barthélemy",
"dial_code": "+590"
},
{
"code": "SH",
"name": "Saint Helena",
"dial_code": "+290"
},
{
"code": "KN",
"name": "Saint Kitts and Nevis",
"dial_code": "+1"
},
{
"code": "LC",
"name": "Saint Lucia",
"dial_code": "+1"
},
{
"code": "MF",
"name": "Saint Martin",
"dial_code": "+590"
},
{
"code": "PM",
"name": "Saint Pierre and Miquelon",
"dial_code": "+508"
},
{
"code": "VC",
"name": "Saint Vincent and the Grenadines",
"dial_code": "+1"
},
{
"code": "WS",
"name": "Samoa",
"dial_code": "+685"
},
{
"code": "SM",
"name": "San Marino",
"dial_code": "+378"
},
{
"code": "SA",
"name": "Saudi Arabia",
"dial_code": "+966"
},
{
"code": "SN",
"name": "Senegal",
"dial_code": "+221"
},
{
"code": "RS",
"name": "Serbia",
"dial_code": "+381"
},
{
"code": "SC",
"name": "Seychelles",
"dial_code": "+248"
},
{
"code": "SL",
"name": "Sierra Leone",
"dial_code": "+232"
},
{
"code": "SG",
"name": "Singapore",
"dial_code": "+65"
},
{
"code": "SX",
"name": "Sint Maarten",
"dial_code": "+1"
},
{
"code": "SK",
"name": "Slovakia",
"dial_code": "+421"
},
{
"code": "SI",
"name": "Slovenia",
"dial_code": "+386"
},
{
"code": "SB",
"name": "Solomon Islands",
"dial_code": "+677"
},
{
"code": "SO",
"name": "Somalia",
"dial_code": "+252"
},
{
"code": "ZA",
"name": "South Africa",
"dial_code": "+27"
},
{
"code": "GS",
"name": "South Georgia and South Sandwich",
"dial_code": null
},
{
"code": "KR",
"name": "South Korea",
"dial_code": "+82"
},
{
"code": "SS",
"name": "South Sudan",
"dial_code": "+211"
},
{
"code": "ES",
"name": "Spain",
"dial_code": "+34"
},
{
"code": "LK",
"name": "Sri Lanka",
"dial_code": "+94"
},
{
"code": "SD",
"name": "Sudan",
"dial_code": "+249"
},
{
"code": "SR",
"name": "Suriname",
"dial_code": "+597"
},
{
"code": "SJ",
"name": "Svalbard and Jan Mayen",
"dial_code": "+47"
},
{
"code": "SE",
"name": "Sweden",
"dial_code": "+46"
},
{
"code": "CH",
"name": "Switzerland",
"dial_code": "+41"
},
{
"code": "SY",
"name": "Syria",
"dial_code": "+963"
},
{
"code": "ST",
"name": "São Tomé and Príncipe",
"dial_code": "+239"
},
{
"code": "TW",
"name": "Taiwan",
"dial_code": "+886"
},
{
"code": "TJ",
"name": "Tajikistan",
"dial_code": "+992"
},
{
"code": "TZ",
"name": "Tanzania",
"dial_code": "+255"
},
{
"code": "TH",
"name": "Thailand",
"dial_code": "+66"
},
{
"code": "TL",
"name": "Timor-Leste",
"dial_code": "+670"
},
{
"code": "TG",
"name": "Togo",
"dial_code": "+228"
},
{
"code": "TK",
"name": "Tokelau",
"dial_code": "+690"
},
{
"code": "TO",
"name": "Tonga",
"dial_code": "+676"
},
{
"code": "TT",
"name": "Trinidad and Tobago",
"dial_code": "+1"
},
{
"code": "TN",
"name": "Tunisia",
"dial_code": "+216"
},
{
"code": "TR",
"name": "Turkey",
"dial_code": "+90"
},
{
"code": "TM",
"name": "Turkmenistan",
"dial_code": "+993"
},
{
"code": "TC",
"name": "Turks and Caicos Islands",
"dial_code": "+1"
},
{
"code": "TV",
"name": "Tuvalu",
"dial_code": "+688"
},
{
"code": "UM",
"name": "U.S. Minor Outlying Islands",
"dial_code": "+1"
},
{
"code": "VI",
"name": "U.S. Virgin Islands",
"dial_code": "+1"
},
{
"code": "UG",
"name": "Uganda",
"dial_code": "+256"
},
{
"code": "UA",
"name": "Ukraine",
"dial_code": "+380"
},
{
"code": "AE",
"name": "United Arab Emirates",
"dial_code": "+971"
},
{
"code": "GB",
"name": "United Kingdom",
"dial_code": "+44"
},
{
"code": "US",
"name": "United States",
"dial_code": "+1"
},
{
"code": "UY",
"name": "Uruguay",
"dial_code": "+598"
},
{
"code": "UZ",
"name": "Uzbekistan",
"dial_code": "+998"
},
{
"code": "VU",
"name": "Vanuatu",
"dial_code": "+678"
},
{
"code": "VA",
"name": "Vatican City",
"dial_code": "+39"
},
{
"code": "VE",
"name": "Venezuela",
"dial_code": "+58"
},
{
"code": "VN",
"name": "Vietnam",
"dial_code": "+84"
},
{
"code": "WF",
"name": "Wallis and Futuna",
"dial_code": "+681"
},
{
"code": "EH",
"name": "Western Sahara",
"dial_code": "+212"
},
{
"code": "YE",
"name": "Yemen",
"dial_code": "+967"
},
{
"code": "ZM",
"name": "Zambia",
"dial_code": "+260"
},
{
"code": "ZW",
"name": "Zimbabwe",
"dial_code": "+263"
},
{
"code": "AX",
"name": "Åland Islands",
"dial_code": "+358"
}
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Profile Completion
requires authentication
What the onboarding UI should drive off: an overall percentage plus the state of each section, so the app can show exactly what is outstanding rather than guessing from the profile payload.
A profile is complete only when every required section is — personal,
address, tax, bank and documents. The emergency contact is collected but
never required. Once all of them are satisfied and the email is verified,
the profile moves itself to pending_approval and the framework
agreement is minted for signing; an admin approval is what finally makes
it active.
correction_fields is populated when a reviewer sent the profile back,
and names the fields they want changed.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/completion" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/completion"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/completion';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/completion');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"completion_percentage": 50,
"sections": [
{
"key": "personal",
"complete": false,
"missing_fields": [
"legal_first_name",
"legal_last_name",
"gender",
"citizenship_primary",
"residence_status"
],
"required": true
},
{
"key": "contact",
"complete": true,
"missing_fields": [],
"required": true
},
{
"key": "address",
"complete": true,
"missing_fields": [],
"required": true
},
{
"key": "tax",
"complete": true,
"missing_fields": [],
"required": true
},
{
"key": "bank",
"complete": false,
"missing_fields": [
"bank_account"
],
"required": true
},
{
"key": "documents",
"complete": false,
"missing_fields": [
"address_proof",
"social_insurance",
"bank"
],
"missing_documents": [
{
"key": "address_proof",
"label": "Meldezettel",
"accepts": [
"proof_of_address"
]
},
{
"key": "social_insurance",
"label": "e-card (Sozialversicherung)",
"accepts": [
"social_insurance_card"
]
},
{
"key": "bank",
"label": "Kontoauszug",
"accepts": [
"bank_statement"
]
}
],
"required": true
},
{
"key": "emergency",
"complete": false,
"missing_fields": [
"emergency_contact_name",
"emergency_contact_phone"
],
"required": false
}
],
"correction_fields": null
},
"errors": null,
"meta": {
"request_id": "d4f66e1d-1c44-4c19-94d8-3bc9146f913f",
"timestamp": "2026-08-05T16:18:35.700301Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Personal Details
requires authentication
Identity as it must appear on the employment contract, so the values here are matched against the uploaded ID during review — a mismatch sends the profile back for correction rather than failing silently.
Every field is optional on its own: the section is saved incrementally as
the worker fills the wizard, and completion is judged separately by
GET /employee-profile/completion.
Saving this while the profile is pending_approval, rejected or
archived is refused — a record under review cannot move beneath the
reviewer.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/personal" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"legal_first_name\": \"Jonas\",
\"legal_last_name\": \"Brunner\",
\"middle_names\": \"Maria\",
\"previous_last_names\": \"Huber\",
\"date_of_birth\": \"1995-04-12\",
\"place_of_birth\": \"Graz\",
\"country_of_birth\": \"AT\",
\"gender\": \"M\",
\"citizenship_primary\": \"AT\",
\"citizenship_additional\": [
\"DE\"
],
\"residence_status\": \"AT_CITIZEN\",
\"has_driver_license\": true,
\"has_car\": false
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/personal"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"legal_first_name": "Jonas",
"legal_last_name": "Brunner",
"middle_names": "Maria",
"previous_last_names": "Huber",
"date_of_birth": "1995-04-12",
"place_of_birth": "Graz",
"country_of_birth": "AT",
"gender": "M",
"citizenship_primary": "AT",
"citizenship_additional": [
"DE"
],
"residence_status": "AT_CITIZEN",
"has_driver_license": true,
"has_car": false
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/personal';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'legal_first_name' => 'Jonas',
'legal_last_name' => 'Brunner',
'middle_names' => 'Maria',
'previous_last_names' => 'Huber',
'date_of_birth' => '1995-04-12',
'place_of_birth' => 'Graz',
'country_of_birth' => 'AT',
'gender' => 'M',
'citizenship_primary' => 'AT',
'citizenship_additional' => ['DE'],
'residence_status' => 'AT_CITIZEN',
'has_driver_license' => true,
'has_car' => false,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/personal');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"legal_first_name": "Jonas",
"legal_last_name": "Brunner",
"middle_names": "Maria",
"previous_last_names": "Huber",
"date_of_birth": "1995-04-12",
"place_of_birth": "Graz",
"country_of_birth": "AT",
"gender": "M",
"citizenship_primary": "AT",
"citizenship_additional": [
"DE"
],
"residence_status": "AT_CITIZEN",
"has_driver_license": true,
"has_car": false
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (422, Under 18):
{
"status": "VALIDATION_ERROR",
"message": "The date of birth must be at least 18 years ago."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Contact Details
requires authentication
Secondary contact details only. The primary email and phone are changed
through POST /profile/email/request-change and
POST /profile/phone/request-change, which verify ownership first —
neither can be overwritten here.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/contact" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"alternate_email\": \"jonas.privat@example.com\",
\"country_code\": \"+43\",
\"phone_number\": \"6641234567\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/contact"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"alternate_email": "jonas.privat@example.com",
"country_code": "+43",
"phone_number": "6641234567"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/contact';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'alternate_email' => 'jonas.privat@example.com',
'country_code' => '+43',
'phone_number' => '6641234567',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/contact');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"alternate_email": "jonas.privat@example.com",
"country_code": "+43",
"phone_number": "6641234567"
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Address
requires authentication
The worker's residential address, which the platform treats as their registered (gemeldete) address — the two are assumed to be the same.
Changing the address invalidates any proof-of-address document already on
file: it is set back to reupload_requested, and an already-approved
profile returns to pending_approval. That is deliberate — the old
document no longer evidences where the worker lives.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/address" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"address_line_1\": \"Hauptstrasse\",
\"house_number\": \"12\",
\"apartment\": \"Top 4\",
\"postal_code\": \"1010\",
\"city\": \"Wien\",
\"country\": \"AT\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/address"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"address_line_1": "Hauptstrasse",
"house_number": "12",
"apartment": "Top 4",
"postal_code": "1010",
"city": "Wien",
"country": "AT"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/address';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'address_line_1' => 'Hauptstrasse',
'house_number' => '12',
'apartment' => 'Top 4',
'postal_code' => '1010',
'city' => 'Wien',
'country' => 'AT',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/address');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"address_line_1": "Hauptstrasse",
"house_number": "12",
"apartment": "Top 4",
"postal_code": "1010",
"city": "Wien",
"country": "AT"
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Profile section updated successfully.",
"data": {
"status": "pending_approval",
"completion_percentage": 50,
"correction_fields": null
},
"errors": null,
"meta": {
"request_id": "873b0a88-e989-4e03-b42d-1dbb7f620553",
"timestamp": "2026-08-05T16:18:35.741770Z"
}
}
Example response (422, Invalid Austrian postal code):
{
"status": "VALIDATION_ERROR",
"message": "An Austrian postal code must be four digits."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Tax and Social Insurance
requires authentication
The Sozialversicherungsnummer is the one field payroll cannot proceed without: it identifies the worker to the Austrian social insurance system and is validated by checksum here, not merely by length.
Three refusals are worth distinguishing, because the app should do something different for each:
VALIDATION_ERROR(422) — the number is malformed or fails its checksum. Ask the worker to correct it.FIELD_LOCKED(403) — a number is already on file and the profile has been verified. It cannot be changed from the app.SVS_NUMBER_ALREADY_REGISTERED(409) — the number is valid and the field is not locked, but another profile already holds it. Re-entering it cannot help: either the worker already has an account, or the number belongs to somebody else. Route them to support with the returnedticket_category.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/tax" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"svs_number\": \"1234010195\",
\"tax_number\": \"12 345\\/6789\",
\"finanz_online_registered\": false
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/tax"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"svs_number": "1234010195",
"tax_number": "12 345\/6789",
"finanz_online_registered": false
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/tax';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'svs_number' => '1234010195',
'tax_number' => '12 345/6789',
'finanz_online_registered' => false,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/tax');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"svs_number": "1234010195",
"tax_number": "12 345\/6789",
"finanz_online_registered": false
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (409, Number already held by another profile):
{
"status": "SVS_NUMBER_ALREADY_REGISTERED",
"message": "This social-insurance number is already registered.",
"data": {
"ticket_category": "profile_change"
},
"errors": [
{
"field": "svs_number",
"message": "This social-insurance number is already registered."
}
]
}
Example response (422, Checksum failed):
{
"status": "VALIDATION_ERROR",
"message": "The social insurance number is not valid."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Emergency Contact
requires authentication
Who to call if something happens on site. Collected for every worker but never required for profile completion, so leaving it empty does not hold up approval.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/emergency" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"emergency_contact_name\": \"Maria Brunner\",
\"emergency_contact_country_code\": \"+43\",
\"emergency_contact_phone\": \"6641234567\",
\"emergency_contact_relationship\": \"Schwester\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/emergency"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"emergency_contact_name": "Maria Brunner",
"emergency_contact_country_code": "+43",
"emergency_contact_phone": "6641234567",
"emergency_contact_relationship": "Schwester"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/emergency';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'emergency_contact_name' => 'Maria Brunner',
'emergency_contact_country_code' => '+43',
'emergency_contact_phone' => '6641234567',
'emergency_contact_relationship' => 'Schwester',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/emergency');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"emergency_contact_name": "Maria Brunner",
"emergency_contact_country_code": "+43",
"emergency_contact_phone": "6641234567",
"emergency_contact_relationship": "Schwester"
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Profile section updated successfully.",
"data": {
"status": "active",
"completion_percentage": 50,
"correction_fields": null
},
"errors": null,
"meta": {
"request_id": "6be59063-d244-479e-bd91-343b9cbd343d",
"timestamp": "2026-08-05T16:18:35.766541Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Language Skills
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/languages" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/languages"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/languages';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/languages');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"languages": []
},
"errors": null,
"meta": {
"request_id": "526335a2-9a99-4e27-940a-4d597f30c1f5",
"timestamp": "2026-08-05T16:18:35.774502Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Replace Language Skills
requires authentication
Sends the complete list — whatever is posted becomes the worker's languages, so omitting an entry removes it. Jobs that require a language are matched against these.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/languages" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"languages\": [
{
\"code\": \"de\",
\"level\": \"c1\"
}
]
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/languages"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"languages": [
{
"code": "de",
"level": "c1"
}
]
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/languages';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'languages' => [
['code' => 'de', 'level' => 'c1'],
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/employee-profile/languages');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"languages": [
{
"code": "de",
"level": "c1"
}
]
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Saved):
{
"status": "SUCCESS",
"data": {
"languages": [
{
"code": "de",
"level": "c1"
},
{
"code": "en",
"level": "b2"
}
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Employee Profile
requires authentication
The worker's full employment record — identity, address, tax, bank and
document state — as opposed to GET /profile, which is the user account
behind the login.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/employee-profile" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/employee-profile"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/employee-profile';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/employee-profile');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"user": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"first_name": "Anna",
"last_name": "Neuling",
"email": "pending@demo.flexxr.at",
"phone": "+436769876543",
"country_code": "+43",
"phone_number": "6769876543",
"email_verified": true,
"phone_verified": true,
"pending_phone": "+436641239876"
},
"profile": {
"id": "019fd2b7-f279-7142-a68d-0d4563a06070",
"status": "active",
"status_label": "Aktiv",
"completion_percentage": 0,
"svs_number_set": true,
"tax_id_set": false,
"tax_number_set": false,
"nationality": "AT",
"date_of_birth": "1995-08-20",
"place_of_birth": null,
"gender": null,
"legal_first_name": null,
"legal_last_name": null,
"middle_names": null,
"previous_last_names": null,
"country_of_birth": null,
"residence_status": null,
"citizenship_primary": null,
"citizenship_additional": null,
"has_driver_license": false,
"has_car": false,
"finanz_online_registered": false,
"alternate_email": null,
"correction_fields": null,
"address": {
"line_1": "Neugasse 5",
"line_2": null,
"house_number": null,
"apartment": null,
"postal_code": "4020",
"city": "Linz",
"country": "AT"
},
"emergency_contact": {
"name": null,
"country_code": null,
"phone": null,
"phone_e164": null,
"relationship": null
},
"is_eu_citizen": false,
"requires_work_permit": false,
"work_permit_expires_at": null,
"work_permit_expiring_soon": false,
"work_permit_expired": false,
"onboarding_completed_at": "2026-08-05 16:18:32",
"rejection_reason": null,
"suspended_reason": null,
"suspended_until": null
},
"consents": {
"terms_of_service": {
"accepted": true,
"version": "1.0",
"document_id": null,
"accepted_at": "2026-08-05T16:18:17+00:00"
},
"privacy_policy": {
"accepted": false,
"version": null,
"document_id": null,
"accepted_at": null
},
"data_processing": {
"accepted": false,
"version": null,
"document_id": null,
"accepted_at": null
},
"marketing_email": {
"accepted": false,
"version": null,
"document_id": null,
"accepted_at": null
}
},
"needs_onboarding": false,
"can_apply_for_jobs": true
}
}
Example response (404, No profile yet):
{
"status": "NOT_FOUND",
"message": "Please complete your employee profile."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Privacy & GDPR
Download Data Export
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/gdpr/export/019febec-0321-7368-9b4e-d906c6855bac/download" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/gdpr/export/019febec-0321-7368-9b4e-d906c6855bac/download"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/gdpr/export/019febec-0321-7368-9b4e-d906c6855bac/download';
$response = $client->get(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/gdpr/export/019febec-0321-7368-9b4e-d906c6855bac/download');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "eb800bbb-4c83-4588-b389-7c02b8fdd66d",
"timestamp": "2026-08-21T05:14:32.739710Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Consent History
requires authentication
Returns a paginated list of consent decisions recorded for the authenticated user, including consents captured during registration.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/gdpr/consent-history?per_page=25" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/gdpr/consent-history"
);
const params = {
"per_page": "25",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/gdpr/consent-history';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'per_page' => '25',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/gdpr/consent-history')
.replace(queryParameters: {
'per_page': '25',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [],
"errors": null,
"meta": {
"request_id": "1e5faf19-0862-4e67-9563-a92fdc0f1f7c",
"timestamp": "2026-08-05T16:18:36.169396Z",
"total": 0,
"current_page": 1,
"last_page": 1,
"per_page": 25
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Record Consent
requires authentication
Records a consent decision for a legal document.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/gdpr/consent" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"consent_type\": \"privacy_policy\",
\"version\": \"2026-06-01\",
\"is_granted\": true,
\"client_timestamp\": \"2026-07-26T09:00:00Z\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/gdpr/consent"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"consent_type": "privacy_policy",
"version": "2026-06-01",
"is_granted": true,
"client_timestamp": "2026-07-26T09:00:00Z"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/gdpr/consent';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'consent_type' => 'privacy_policy',
'version' => '2026-06-01',
'is_granted' => true,
'client_timestamp' => '2026-07-26T09:00:00Z',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/gdpr/consent');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"consent_type": "privacy_policy",
"version": "2026-06-01",
"is_granted": true,
"client_timestamp": "2026-07-26T09:00:00Z"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Your consent has been recorded successfully.",
"data": {
"consent_type": "privacy_policy",
"version": "2026-06-01",
"is_granted": true,
"recorded_at": "2026-08-05T16:18:36+00:00"
},
"errors": null,
"meta": {
"request_id": "2672f5c3-f949-4ea6-87f4-f965aef850be",
"timestamp": "2026-08-05T16:18:36.181527Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Export My Data (Art. 15 DSGVO)
requires authentication
Returns all personal data held about the authenticated user. Rate-limited to once per 5 minutes.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/gdpr/export" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/gdpr/export"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/gdpr/export';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/gdpr/export');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Data export has been generated.",
"data": {
"user": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"first_name": "Anna",
"last_name": "Neuling",
"email": "pending@demo.flexxr.at",
"email_verified_at": "2026-08-05T16:18:32+00:00",
"phone": "+436769876543",
"date_of_birth": null,
"status": "active",
"notify_push": true,
"notify_email": true,
"notify_sms": true,
"notify_marketing": false,
"created_at": "2026-08-05T16:18:18+00:00"
},
"employee_profile": {
"status": "active",
"svs_number": "****0895",
"tax_id": null,
"tax_number": null,
"nationality": "AT",
"date_of_birth": "1995-08-20",
"place_of_birth": null,
"gender": null,
"legal_first_name": null,
"legal_last_name": null,
"middle_names": null,
"previous_last_names": null,
"country_of_birth": null,
"citizenship_primary": null,
"citizenship_additional": null,
"residence_status": null,
"alternate_email": null,
"address": "Neugasse 5",
"address_line_2": null,
"house_number": null,
"apartment": null,
"city": "Linz",
"postal_code": "4020",
"country": "AT",
"finanz_online_registered": false,
"is_eu_citizen": false,
"requires_work_permit": false,
"work_permit_expires_at": null,
"onboarding_completed_at": "2026-08-05T16:18:32+00:00"
},
"documents": [
{
"type": "id_card",
"status": "pending",
"expires_at": null,
"uploaded_at": "2026-08-05T16:18:18+00:00"
},
{
"type": "passport",
"status": "verified",
"expires_at": "2033-05-22",
"uploaded_at": "2026-08-05T16:18:32+00:00"
}
],
"attachments": [
{
"label": "voluptas nihil",
"original_filename": "est.pdf",
"file_size": 293696,
"uploaded_at": "2026-08-05T16:18:32+00:00"
}
],
"qualifications": [],
"bank_accounts": [],
"applications": [
{
"job_title": "Accountant",
"status": "selected",
"applied_at": "2026-08-05T16:18:32+00:00"
}
],
"shifts": [
{
"date": null,
"start_time": null,
"end_time": null,
"status": "completed",
"clock_in_at": null,
"clock_out_at": null
},
{
"date": null,
"start_time": null,
"end_time": null,
"status": "awaiting_signature",
"clock_in_at": null,
"clock_out_at": null
},
{
"date": null,
"start_time": null,
"end_time": null,
"status": "checked_in",
"clock_in_at": null,
"clock_out_at": null
},
{
"date": null,
"start_time": null,
"end_time": null,
"status": "signed",
"clock_in_at": null,
"clock_out_at": null
}
],
"contracts": [],
"ratings_given": [],
"ratings_received": [],
"consents": [
{
"consent_type": "terms_of_service",
"version": "1.0",
"is_granted": true,
"recorded_at": "2026-08-05T16:18:17+00:00"
}
],
"exported_at": "2026-08-05T16:18:36+00:00"
},
"errors": null,
"meta": {
"request_id": "aa451d65-823a-4848-850b-ff7a4caf66e2",
"timestamp": "2026-08-05T16:18:36.201637Z"
}
}
Example response (429, Rate Limited):
{
"status": "TOO_MANY_REQUESTS",
"message": "Please wait before requesting another export.",
"data": null,
"errors": [
{
"field": null,
"message": "Please wait 5 minute(s) before requesting another export."
}
],
"meta": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Request Data Export (Art. 20 DSGVO)
requires authentication
Queues an asynchronous export of all personal data (JSON + copies of uploaded documents) as a ZIP. Poll the returned status URL until the export is ready, then download it within 48 hours.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/gdpr/export" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/gdpr/export"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/gdpr/export';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/gdpr/export');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (202, Recorded from a live call):
{
"status": "ACCEPTED",
"message": "Data export started. You will be notified once it is ready.",
"data": {
"export_id": "019fd2b8-3830-7193-a147-36d8a971a236",
"status": "pending",
"status_url": "http://localhost:8001/api/v1/mobile/gdpr/export/019fd2b8-3830-7193-a147-36d8a971a236",
"expires_at": "2026-08-07T16:18:36+00:00"
},
"errors": null,
"meta": {
"request_id": "9dc62923-ca91-4a86-a867-3be0ff085aef",
"timestamp": "2026-08-05T16:18:36.211284Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Data Export Status
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/gdpr/export/019febec-0321-7368-9b4e-d906c6855bac" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/gdpr/export/019febec-0321-7368-9b4e-d906c6855bac"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/gdpr/export/019febec-0321-7368-9b4e-d906c6855bac';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/gdpr/export/019febec-0321-7368-9b4e-d906c6855bac');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Ready):
{
"status": "SUCCESS",
"message": null,
"data": {
"export_id": "exp-uuid",
"status": "ready",
"download_url": "https://api.flexxr.at/api/v1/mobile/gdpr/export/exp-uuid/download?signature=...",
"expires_at": "2026-06-18T12:00:00+00:00",
"file_size": 20480
},
"errors": null,
"meta": {}
}
Example response (404, Not Found):
{
"status": "NOT_FOUND",
"message": "Export not found.",
"data": null,
"errors": [
{
"field": null,
"message": "Export not found."
}
],
"meta": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Account Deletion Status
requires authentication
Returns the scheduled deletion date and cancel window, or null when no deletion is pending.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/gdpr/delete-request" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/gdpr/delete-request"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/gdpr/delete-request';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/gdpr/delete-request');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Pending):
{
"status": "SUCCESS",
"message": null,
"data": {
"scheduled_at": "2026-08-09T12:00:00+00:00",
"can_cancel_until": "2026-08-09T12:00:00+00:00"
},
"errors": null,
"meta": {}
}
Example response (200, None):
{
"status": "SUCCESS",
"message": null,
"data": null,
"errors": null,
"meta": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Request Account Deletion (Art. 17 DSGVO)
requires authentication
Creates a deletion request for the user's account. The account will be scheduled for deletion after a 30-day grace period.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/gdpr/delete-request" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"No longer using the service\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/gdpr/delete-request"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "No longer using the service"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/gdpr/delete-request';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'No longer using the service',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/gdpr/delete-request');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "No longer using the service"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (400, Already Requested):
{
"status": "BAD_REQUEST",
"message": "Account deletion already requested.",
"data": null,
"errors": [
{
"field": null,
"message": "Account deletion already requested."
}
],
"meta": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Cancel Account Deletion
requires authentication
Cancels a pending account deletion request during the grace period.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/mobile/gdpr/delete-request" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/gdpr/delete-request"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/gdpr/delete-request';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/gdpr/delete-request');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Success):
{
"status": "SUCCESS",
"message": "Account deletion cancelled.",
"data": null,
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-06-10T12:00:00.000000Z"
}
}
Example response (400, No Request):
{
"status": "BAD_REQUEST",
"message": "No pending deletion request.",
"data": null,
"errors": [
{
"field": null,
"message": "No pending deletion request."
}
],
"meta": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Withdraw GDPR Request
requires authentication
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/mobile/gdpr/requests/019fe6e4-bbcd-71fd-918b-effe04df4ff9" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/gdpr/requests/019fe6e4-bbcd-71fd-918b-effe04df4ff9"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/gdpr/requests/019fe6e4-bbcd-71fd-918b-effe04df4ff9';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/gdpr/requests/019fe6e4-bbcd-71fd-918b-effe04df4ff9');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (409, Already being handled):
{
"status": "INVALID_OPERATION",
"message": "Only a pending request can be withdrawn."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Auth
Biometric Login
requires authentication
Exchange a device's biometric credential for a fresh session.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/biometric/login" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/biometric/login"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/biometric/login';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/biometric/login');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Signed in):
{
"status": "SUCCESS",
"message": "Signed in.",
"data": {
"token": "12|plain-access-token",
"refresh_token": "13|plain-refresh-token",
"biometric_token": "14|plain-biometric-token",
"expires_in": 900
},
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-07-28T10:00:00.000000Z"
}
}
Example response (401, Credential rejected):
{
"status": "UNAUTHORIZED",
"message": "This device is no longer enrolled.",
"data": null,
"errors": [
{
"field": null,
"message": "This device is no longer enrolled."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-07-28T10:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Confirm Password
requires authentication
Verifies the authenticated user's current password. Throttled to resist brute-force guessing.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/confirm-password" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"password\": \"S3cure-Passw0rd!\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/confirm-password"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"password": "S3cure-Passw0rd!"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/confirm-password';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'password' => 'S3cure-Passw0rd!',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/confirm-password');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"password": "S3cure-Passw0rd!"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (422, Wrong Password):
{
"status": "UNPROCESSABLE_ENTITY",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "password",
"message": "The provided password does not match our records."
}
],
"meta": {}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Enable Biometric
requires authentication
Opt in to biometric login from an already password-authenticated session.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/biometric/enable" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/biometric/enable"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/biometric/enable';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/biometric/enable');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Biometric login has been enabled on this device.",
"data": {
"biometric_token": "7|JjeW6QZpkQSEcPVxm2mduqTTTLqTnGMKVjO9MfWs2aa6a6ac"
},
"errors": null,
"meta": {
"request_id": "db4a283c-ee3b-42b8-9998-7e0ab3a0e9a4",
"timestamp": "2026-08-05T16:18:36.051090Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Disable Biometric
requires authentication
Turn off biometric login and revoke the device's biometric credential.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/biometric/disable" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/biometric/disable"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/biometric/disable';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/biometric/disable');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Biometric login has been disabled.",
"data": null,
"errors": null,
"meta": {
"request_id": "e38b6ebe-f8fa-40ae-8a87-8667f88c7582",
"timestamp": "2026-08-05T16:18:36.064570Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Dashboard
Get Employee Dashboard (Home Screen)
requires authentication
Returns the employee home screen data including:
- Next upcoming shift (if any)
- Profile completion progress
- Popular jobs this week
- Recently added jobs
- Personalized recommendations
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/dashboard" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/dashboard"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/dashboard';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/dashboard');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"user": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"first_name": null,
"full_name": null,
"avatar_url": null
},
"next_shift": {
"id": "019fd2b8-28d3-70d7-92eb-f1bb1577acaf",
"status": "signed",
"status_label": "Unterschrieben",
"date": "2026-08-06",
"start_time": "08:00:00",
"end_time": "16:00:00",
"location_name": "Nolan-Roberts",
"location_address": "4309 O'Reilly Way Suite 012",
"job": {
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant",
"category": {
"id": "019fd2b7-f39f-73e6-870b-fe7584e4f9bc",
"slug": "office",
"name": "Büro",
"name_localized": "Office",
"icon": "briefcase",
"color": null
}
},
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"logo_url": null
}
},
"profile_completion": {
"documents_percent": 25,
"legal_info_percent": 50,
"total_percent": 50,
"is_complete": false
},
"popular_jobs": [
{
"id": "019fd2b8-22cf-71c5-8edd-5e3ce9d29e8b",
"title": "Promoter*in Vienna Marathon",
"description": "Für ein großes Outdoor-Event suchen wir Promoter*innen und Koordinator*innen. Teamgeist und Flexibilität sind gefragt.",
"status": "published",
"is_featured": false,
"category": {
"id": "019fd2b7-f398-7300-a216-c64584fea8f7",
"slug": "event",
"name": "Events",
"name_localized": "Events",
"icon": "calendar-star",
"color": null
},
"tags": [
"Events",
"Tagschicht",
"Veranstaltungserfahrung",
"Teamfähigkeit"
],
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Promoter*in Vienna Marathon",
"address": "Hauptstraße 48, 1010 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2082,
"lng": 16.3738,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-26",
"end_date": "2026-08-28",
"shift_start_time": "09:00:00",
"shift_end_time": "17:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 13.5,
"supplements": null,
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 20,
"filled": 0,
"available": 20
},
"deadlines": {
"application": "2026-08-23T00:00:00+00:00"
},
"created_at": "2026-08-05T16:18:30+00:00",
"is_saved": false,
"can_apply": false,
"rate": null
},
{
"id": "019fd2b8-2599-7355-a7f1-dcb185b05faa",
"title": "Rezeptionist*in Hotel Sacher",
"description": "Für unser Haus suchen wir freundliche und belastbare Mitarbeiter*innen für den Front- und Back-Office-Bereich.",
"status": "published",
"is_featured": false,
"category": {
"id": "019fd2b7-f375-724e-84b8-4f9647ef6419",
"slug": "hotel",
"name": "Hotellerie",
"name_localized": "Hospitality",
"icon": "hotel",
"color": null
},
"tags": [
"Hospitality",
"Tagschicht",
"Hotellerie-Erfahrung",
"Deutsch B2"
],
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Rezeptionist*in Hotel Sacher",
"address": "Hauptstraße 87, 1010 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2034,
"lng": 16.3694,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-17",
"end_date": "2026-08-19",
"shift_start_time": "09:00:00",
"shift_end_time": "17:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 17.5,
"supplements": null,
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 4,
"filled": 0,
"available": 4
},
"deadlines": {
"application": "2026-08-14T00:00:00+00:00"
},
"created_at": "2026-08-05T16:18:31+00:00",
"is_saved": false,
"can_apply": false,
"rate": null
},
{
"id": "019fd2b8-1f86-7376-9a3a-c072ab5675cb",
"title": "Service-Mitarbeiter*in Wiener Prater Festival",
"description": "Wir suchen engagierte Service-Mitarbeiter*innen für unser Team. Du bringst Freude am Umgang mit Gästen mit und arbeitest gerne im Team.",
"status": "published",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Tagschicht",
"Serviceerfahrung",
"Deutsch B2"
],
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Service-Mitarbeiter*in Wiener Prater Festival",
"address": "Hauptstraße 91, 1020 Wien",
"city": "Wien",
"postal_code": "1020",
"lat": 48.2117,
"lng": 16.3969,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-19",
"end_date": "2026-08-21",
"shift_start_time": "09:00:00",
"shift_end_time": "17:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 15.5,
"supplements": null,
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 12,
"filled": 0,
"available": 12
},
"deadlines": {
"application": "2026-08-16T00:00:00+00:00"
},
"created_at": "2026-08-05T16:18:29+00:00",
"is_saved": false,
"can_apply": false,
"rate": null
},
{
"id": "019fd2b8-21c8-72cc-80b1-47fd13450522",
"title": "Barkeeper*in Sommernacht Open Air",
"description": "Wir suchen engagierte Service-Mitarbeiter*innen für unser Team. Du bringst Freude am Umgang mit Gästen mit und arbeitest gerne im Team.",
"status": "published",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Nachtschicht",
"Serviceerfahrung",
"Deutsch B2"
],
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Barkeeper*in Sommernacht Open Air",
"address": "Hauptstraße 35, 1060 Wien",
"city": "Wien",
"postal_code": "1060",
"lat": 48.1953,
"lng": 16.356,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-15",
"end_date": "2026-08-17",
"shift_start_time": "22:00:00",
"shift_end_time": "06:00:00",
"shift_type": "night",
"shift_type_label": "Nachtschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 16,
"supplements": null,
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 8,
"filled": 0,
"available": 8
},
"deadlines": {
"application": "2026-08-12T00:00:00+00:00"
},
"created_at": "2026-08-05T16:18:30+00:00",
"is_saved": false,
"can_apply": false,
"rate": null
},
{
"id": "019fd2b8-24b0-700a-ae2a-142f5e48aead",
"title": "Lagerhelfer*in Logistikzentrum Inzersdorf",
"description": "Für unser Logistikzentrum suchen wir zuverlässige Helfer*innen. Körperliche Belastbarkeit und Pünktlichkeit sind Voraussetzung.",
"status": "published",
"is_featured": false,
"category": {
"id": "019fd2b7-f38b-7209-8b83-b345b172def2",
"slug": "warehouse",
"name": "Lager",
"name_localized": "Warehouse",
"icon": "industry",
"color": null
},
"tags": [
"Warehouse",
"Nachtschicht",
"Staplerführerschein von Vorteil",
"Körperliche Belastbarkeit"
],
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Lagerhelfer*in Logistikzentrum Inzersdorf",
"address": "Hauptstraße 28, 1230 Wien",
"city": "Wien",
"postal_code": "1230",
"lat": 48.1454,
"lng": 16.3499,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-12",
"end_date": "2026-08-14",
"shift_start_time": "22:00:00",
"shift_end_time": "06:00:00",
"shift_type": "night",
"shift_type_label": "Nachtschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 14.8,
"supplements": null,
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 15,
"filled": 0,
"available": 15
},
"deadlines": {
"application": "2026-08-09T00:00:00+00:00"
},
"created_at": "2026-08-05T16:18:31+00:00",
"is_saved": false,
"can_apply": false,
"rate": null
}
],
"recent_jobs": [
{
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant",
"description": "Ut nostrum rerum ut alias quia libero excepturi. Voluptatum et aut non quia quisquam molestias. Perferendis qui hic unde.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f39f-73e6-870b-fe7584e4f9bc",
"slug": "office",
"name": "Büro",
"name_localized": "Office",
"icon": "briefcase",
"color": null
},
"tags": [
"Office",
"Nachtschicht"
],
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Barrows, Christiansen and Jones",
"address": "586 Tremaine Row",
"city": "East Eliseo",
"postal_code": "10547-3697",
"lat": 46.931383,
"lng": 11.998284,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-12",
"end_date": "2026-08-19",
"shift_start_time": "01:49:00",
"shift_end_time": "18:57:00",
"shift_type": "night",
"shift_type_label": "Nachtschicht",
"duration_hours": 17.133333333333333
},
"compensation": {
"hourly_rate_gross": 32.08,
"supplements": {
"night": 0.7,
"weekend": 3.86
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 5,
"filled": 0,
"available": 5
},
"deadlines": {
"application": "2026-09-05T16:18:32+00:00"
},
"created_at": "2026-08-05T16:18:32+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
{
"id": "019fd2b8-1405-709f-bca9-b0a418fb6a75",
"title": "Silvesternacht Service",
"description": "Wir suchen motivierte Silvesternacht Service für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Nachtschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-fe56-70d1-bb3a-641339ce636a",
"name": "Lagerhaus Steiermark",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Hotel Imperial Wien",
"address": "Kärntner Ring 16, 1015 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2082,
"lng": 16.3739,
"distance_km": null
},
"schedule": {
"start_date": "2027-02-09",
"end_date": "2027-02-10",
"shift_start_time": "22:00:00",
"shift_end_time": "06:00:00",
"shift_type": "night",
"shift_type_label": "Nachtschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 25,
"supplements": {
"night_bonus": 50,
"holiday_bonus": 100,
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 12,
"filled": 0,
"available": 12
},
"deadlines": {
"application": "2027-02-04T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
{
"id": "019fd2b8-15b5-7019-8521-6ea79edc4ba5",
"title": "Garderobenservice Ball",
"description": "Für unsere bevorstehende Veranstaltung suchen wir tatkräftige Unterstützung. Als Garderobenservice Ball sind Sie das Aushängeschild unserer Veranstaltung und sorgen für einen reibungslosen Ablauf.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f398-7300-a216-c64584fea8f7",
"slug": "event",
"name": "Events",
"name_localized": "Events",
"icon": "calendar-star",
"color": null
},
"tags": [
"Events",
"Tagschicht"
],
"organization": {
"id": "019fd2b7-ff32-7117-ab28-06e2d3082002",
"name": "Bildungszentrum Mitte",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Wiener Rathaus",
"address": "Friedrich-Schmidt-Platz 1, 1010 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2082,
"lng": 16.3739,
"distance_km": null
},
"schedule": {
"start_date": "2027-01-22",
"end_date": "2027-01-23",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 14.5,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 10,
"filled": 0,
"available": 10
},
"deadlines": {
"application": "2027-01-19T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:27+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
{
"id": "019fd2b8-18d3-718f-bbe2-32c97903f559",
"title": "Verkaufshilfe Weihnachtsgeschäft",
"description": "Für unser Retail-Team suchen wir freundliche und kundenorientierte Verkaufshilfe Weihnachtsgeschäft. Sie beraten unsere Kunden, wickeln Kassiervorgänge ab und sorgen für eine ansprechende Warenpräsentation.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f37d-712d-92b3-aa5540f6b2a7",
"slug": "retail",
"name": "Einzelhandel",
"name_localized": "Retail",
"icon": "shopping-cart",
"color": null
},
"tags": [
"Retail",
"Tagschicht"
],
"organization": {
"id": "019fd2b7-fca6-71cf-8683-c97f6f50a24a",
"name": "Reinigungsservice Alpin",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Wiener Innenstadt",
"address": "Kärntner Straße 15, 1010 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2082,
"lng": 16.3739,
"distance_km": null
},
"schedule": {
"start_date": "2027-01-12",
"end_date": "2027-02-01",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 13.5,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 10,
"filled": 0,
"available": 10
},
"deadlines": {
"application": "2027-01-08T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:28+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
{
"id": "019fd2b8-13e2-7390-a987-e12b987cdbb8",
"title": "Weihnachtsmarkt Servicekraft",
"description": "Wir suchen motivierte Weihnachtsmarkt Servicekraft für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Tagschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-f91f-70cb-8409-8632db9df3c7",
"name": "Sicherheitsdienst Österreich",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Christkindlmarkt Rathausplatz",
"address": "Rathausplatz 1, 1010 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2082,
"lng": 16.3739,
"distance_km": null
},
"schedule": {
"start_date": "2027-01-02",
"end_date": "2027-02-01",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 14,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 30,
"filled": 0,
"available": 30
},
"deadlines": {
"application": "2026-12-29T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
}
],
"recommended_jobs": [
{
"job": {
"id": "019fd2b8-1a90-7125-af02-72f37fef65ea",
"title": "Backoffice Assistenz",
"description": "Wir suchen engagierte Backoffice Assistenz zur Verstärkung unseres Teams. Sie erwartet ein abwechslungsreiches Aufgabengebiet in einem dynamischen Umfeld.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f39f-73e6-870b-fe7584e4f9bc",
"slug": "office",
"name": "Büro",
"name_localized": "Office",
"icon": "briefcase",
"color": null
},
"tags": [
"Office",
"Tagschicht"
],
"organization": {
"id": "019fd2b7-f768-7325-b254-280a67b1a995",
"name": "Retail Services GmbH",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Steuerberatung Wien",
"address": "Margaretenstraße 90, 1050 Wien",
"city": "Wien",
"postal_code": "1050",
"lat": 48.1944,
"lng": 16.3585,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-15",
"end_date": "2026-09-04",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 16,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 1,
"filled": 0,
"available": 1
},
"deadlines": {
"application": "2026-08-10T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:28+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 61.5,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 10,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-1265-737c-ae21-e5265dc709d8",
"title": "Servicekraft Restaurant Mitte",
"description": "Wir suchen motivierte Servicekraft Restaurant Mitte für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Tagschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-ff32-7117-ab28-06e2d3082002",
"name": "Bildungszentrum Mitte",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Brasserie Mitte",
"address": "Schwarzenbergplatz 3, 1010 Wien",
"city": "Wien",
"postal_code": "1010",
"lat": 48.2082,
"lng": 16.3739,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-10",
"end_date": "2026-09-09",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 14.5,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 8,
"filled": 0,
"available": 8
},
"deadlines": {
"application": "2026-08-07T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-1287-7146-a673-6798f3d03acc",
"title": "Barkeeper Spätschicht Club",
"description": "Wir suchen motivierte Barkeeper Spätschicht Club für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Nachtschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-f5ae-7390-a778-c08c8d56cdc0",
"name": "Event Solutions Austria",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Club Passage",
"address": "Babenbergerstraße 9, 1010 Wien",
"city": "Wien",
"postal_code": "1070",
"lat": 48.2003,
"lng": 16.3465,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-08",
"end_date": "2026-11-03",
"shift_start_time": "22:00:00",
"shift_end_time": "06:00:00",
"shift_type": "night",
"shift_type_label": "Nachtschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 16,
"supplements": {
"night_bonus": 15,
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 4,
"filled": 0,
"available": 4
},
"deadlines": {
"application": "2026-08-06T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-1298-737e-bbfd-295992feb4db",
"title": "Küchenhilfe Großküche",
"description": "Wir suchen motivierte Küchenhilfe Großküche für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Tagschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-fad7-719c-887a-a0f510bbd31d",
"name": "IT Solutions GmbH",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "SV Gastronomie Wien",
"address": "Gablenzgasse 11, 1150 Wien",
"city": "Wien",
"postal_code": "1150",
"lat": 48.196,
"lng": 16.3268,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-12",
"end_date": "2026-12-03",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 13.5,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 10,
"filled": 0,
"available": 10
},
"deadlines": {
"application": "2026-08-07T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-12b2-72ff-8be7-dadbf8e167b6",
"title": "Kellner*in Haubenrestaurant",
"description": "Wir suchen motivierte Kellner*in Haubenrestaurant für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Tagschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-fca6-71cf-8683-c97f6f50a24a",
"name": "Reinigungsservice Alpin",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Restaurant Steirereck",
"address": "Am Heumarkt 2a, 1030 Wien",
"city": "Wien",
"postal_code": "1030",
"lat": 48.2014,
"lng": 16.387,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-15",
"end_date": "2026-10-04",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 15.5,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 3,
"filled": 0,
"available": 3
},
"deadlines": {
"application": "2026-08-10T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
},
{
"job": {
"id": "019fd2b8-12c7-72ab-bd18-53060b989f57",
"title": "Buffetkraft Messe",
"description": "Wir suchen motivierte Buffetkraft Messe für unser engagiertes Team. Sie unterstützen uns bei der professionellen Gästebetreuung und sorgen für ein unvergessliches Erlebnis. Vorkenntnisse in der Gastronomie sind von Vorteil, aber nicht zwingend erforderlich.",
"status": "active",
"is_featured": false,
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"color": null
},
"tags": [
"Gastronomy",
"Tagschicht",
"HACCP Kenntnisse von Vorteil"
],
"organization": {
"id": "019fd2b7-fe56-70d1-bb3a-641339ce636a",
"name": "Lagerhaus Steiermark",
"logo_url": null,
"average_rating": null
},
"location": {
"name": "Reed Messe Wien",
"address": "Messeplatz 1, 1021 Wien",
"city": "Wien",
"postal_code": "1020",
"lat": 48.2176,
"lng": 16.4138,
"distance_km": null
},
"schedule": {
"start_date": "2026-08-19",
"end_date": "2026-08-21",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"shift_type": "day",
"shift_type_label": "Tagschicht",
"duration_hours": 8
},
"compensation": {
"hourly_rate_gross": 13.8,
"supplements": {
"weekend_bonus": 8
},
"estimated_total_gross": null,
"currency": "EUR"
},
"vacancies": {
"total": 15,
"filled": 0,
"available": 15
},
"deadlines": {
"application": "2026-08-15T16:18:26+00:00"
},
"created_at": "2026-08-05T16:18:26+00:00",
"is_saved": false,
"can_apply": true,
"rate": null
},
"recommendation": {
"score": 60,
"reasons": [
"Passt zu Ihren Qualifikationen"
],
"breakdown": {
"location": 50,
"qualifications": 100,
"category_history": 0,
"company_rating": 50,
"reliability": 100
}
}
}
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Qualifications
List My Qualifications
requires authentication
Each with its verification state and expiry. An expired qualification is kept on the record but no longer counts towards a job that requires it.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/qualifications" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/qualifications"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/qualifications';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/qualifications');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"qualifications": [],
"counts": {
"total": 0,
"verified": 0,
"pending": 0,
"expiring_soon": 0,
"expired": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Add a Qualification
requires authentication
A certificate or licence the worker holds — a Staplerschein, a food hygiene certificate, a first-aid course. Jobs can require these, and an unverified or expired qualification does not satisfy the requirement.
Attach the supporting scan by uploading it via POST /documents first
and passing the resulting id as document_id; a qualification with no
evidence cannot be verified.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/qualifications" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Staplerschein\",
\"description\": \"Gabelstapler bis 5t\",
\"issuing_organization\": \"WIFI Wien\",
\"credential_id\": \"ST-2024-8891\",
\"document_id\": \"019f9939-c4c3-70fb-a54e-5ebf63db36d2\",
\"issued_at\": \"2024-03-01\",
\"expires_at\": \"2029-03-01\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/qualifications"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Staplerschein",
"description": "Gabelstapler bis 5t",
"issuing_organization": "WIFI Wien",
"credential_id": "ST-2024-8891",
"document_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"issued_at": "2024-03-01",
"expires_at": "2029-03-01"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/qualifications';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'name' => 'Staplerschein',
'description' => 'Gabelstapler bis 5t',
'issuing_organization' => 'WIFI Wien',
'credential_id' => 'ST-2024-8891',
'document_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'issued_at' => '2024-03-01',
'expires_at' => '2029-03-01',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/qualifications');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"name": "Staplerschein",
"description": "Gabelstapler bis 5t",
"issuing_organization": "WIFI Wien",
"credential_id": "ST-2024-8891",
"document_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"issued_at": "2024-03-01",
"expires_at": "2029-03-01"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The qualification has been added successfully.",
"data": {
"qualification": {
"id": "019fd41b-85f2-713f-88ff-c02f3cca8cb7",
"name": "Staplerschein",
"description": "Gabelstapler bis 5t",
"issuing_organization": "WIFI Wien",
"credential_id": "ST-2024-8891",
"issued_at": "2024-03-01",
"expires_at": "2029-03-01",
"is_verified": false,
"created_at": "2026-08-05 22:46:41"
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update a Qualification
requires authentication
Editing a verified qualification returns it to review — the details a reviewer checked are no longer the details on file.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/mobile/qualifications/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Beispieltext\",
\"description\": \"Beispieltext\",
\"issuing_organization\": \"Beispieltext\",
\"credential_id\": \"Beispieltext\",
\"document_id\": \"019f9939-c4c3-70fb-a54e-5ebf63db36d2\",
\"issued_at\": \"2026-09-30\",
\"expires_at\": \"2026-09-30\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/qualifications/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Beispieltext",
"description": "Beispieltext",
"issuing_organization": "Beispieltext",
"credential_id": "Beispieltext",
"document_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"issued_at": "2026-09-30",
"expires_at": "2026-09-30"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/qualifications/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'name' => 'Beispieltext',
'description' => 'Beispieltext',
'issuing_organization' => 'Beispieltext',
'credential_id' => 'Beispieltext',
'document_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'issued_at' => '2026-09-30',
'expires_at' => '2026-09-30',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/qualifications/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"name": "Beispieltext",
"description": "Beispieltext",
"issuing_organization": "Beispieltext",
"credential_id": "Beispieltext",
"document_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"issued_at": "2026-09-30",
"expires_at": "2026-09-30"
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete a Qualification
requires authentication
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/mobile/qualifications/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/qualifications/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/qualifications/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/qualifications/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Bank Accounts
List My Bank Accounts
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/bank-accounts" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/bank-accounts"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/bank-accounts';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/bank-accounts');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"bank_accounts": [],
"has_primary": false
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Add a Bank Account
requires authentication
Where wages are paid. A bank account is one of the sections a profile needs before it can be submitted for approval.
The IBAN is checksum-validated, not merely length-checked, and the BIC is derived from the Austrian bank code when it is not supplied.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/bank-accounts" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"account_holder\": \"Jonas Brunner\",
\"iban\": \"AT611904300234573201\",
\"bic\": \"GIBAATWWXXX\",
\"bank_name\": \"Erste Bank\",
\"is_primary\": true,
\"verification_document_id\": \"019f9939-c4c3-70fb-a54e-5ebf63db36d2\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/bank-accounts"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"account_holder": "Jonas Brunner",
"iban": "AT611904300234573201",
"bic": "GIBAATWWXXX",
"bank_name": "Erste Bank",
"is_primary": true,
"verification_document_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/bank-accounts';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'account_holder' => 'Jonas Brunner',
'iban' => 'AT611904300234573201',
'bic' => 'GIBAATWWXXX',
'bank_name' => 'Erste Bank',
'is_primary' => true,
'verification_document_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/bank-accounts');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"account_holder": "Jonas Brunner",
"iban": "AT611904300234573201",
"bic": "GIBAATWWXXX",
"bank_name": "Erste Bank",
"is_primary": true,
"verification_document_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (422, Invalid IBAN):
{
"status": "VALIDATION_ERROR",
"message": "The IBAN is not valid."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Set the Primary Bank Account
requires authentication
Chooses which account wages are paid into. Exactly one account is primary at a time; promoting one demotes the other.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/bank-accounts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/primary" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/bank-accounts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/primary"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/bank-accounts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/primary';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/bank-accounts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/primary');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete a Bank Account
requires authentication
The primary account cannot be removed while it is the only one on file — a worker with no account cannot be paid.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/mobile/bank-accounts/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/bank-accounts/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/bank-accounts/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/bank-accounts/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Security
Get Two-Factor State
requires authentication
Returns the current 2FA configuration for the authenticated user.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/security/two-factor" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/security/two-factor"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/security/two-factor';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/security/two-factor');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, 2FA Disabled):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"enabled": false,
"method": null,
"confirmed_at": null,
"recovery_codes_remaining": 0
},
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-06-10T12:00:00.000000Z"
}
}
Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"enabled": true,
"method": "totp",
"confirmed_at": "2026-08-05T16:18:32+00:00",
"recovery_codes_remaining": 2
},
"errors": null,
"meta": {
"request_id": "4bb5ce3f-11eb-4ddd-b32e-09a6493765be",
"timestamp": "2026-08-05T16:18:36.072911Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Login History
requires authentication
Returns recent login attempts for the authenticated user.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/security/login-history?limit=20" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/security/login-history"
);
const params = {
"limit": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/security/login-history';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'limit' => '20',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/security/login-history')
.replace(queryParameters: {
'limit': '20',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [],
"errors": null,
"meta": {
"request_id": "0e90e127-69d7-4ef7-9364-6d17d1842b2c",
"timestamp": "2026-08-05T16:18:36.080326Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Regenerate Recovery Codes
requires authentication
Generates new recovery codes, invalidating all previous ones. User must have 2FA enabled.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/security/recovery-codes/regenerate" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/security/recovery-codes/regenerate"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/security/recovery-codes/regenerate';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/security/recovery-codes/regenerate');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "New recovery codes have been generated.",
"data": {
"recovery_codes": [
"HB2T0-PKB9V",
"RMEKC-3DIJH",
"C3VY7-WKMA1",
"DWBQ6-EOGR1",
"USUS6-PPZO7",
"6M3U3-5CG0V",
"HCSH0-CYUBB",
"MSNEO-XIOLK"
]
},
"errors": null,
"meta": {
"request_id": "1ed862c5-9edb-4fb3-9167-c4f0a29ed7f5",
"timestamp": "2026-08-05T16:18:36.089383Z"
}
}
Example response (400, 2FA Not Enabled):
{
"status": "BAD_REQUEST",
"message": "Two-factor authentication is not enabled.",
"data": null,
"errors": [
{
"field": null,
"message": "Two-factor authentication is not enabled."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-06-10T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Settings
Get Notification Settings
requires authentication
Get user notification settings.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/settings/notifications" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/settings/notifications"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/settings/notifications';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/settings/notifications');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"global": {
"email_enabled": true,
"push_enabled": true,
"sms_enabled": true,
"marketing_enabled": false
},
"categories": {
"security": [
{
"type": "registration_welcome",
"label": "Willkommen bei Flexxr",
"description": "Willkommensnachricht nach der Registrierung mit Link zur E-Mail-Bestätigung",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "new_device_login",
"label": "Anmeldung von neuem Gerät",
"description": "Benachrichtigung wenn sich jemand von einem neuen Gerät anmeldet",
"can_disable": false,
"supports_push": true,
"supports_sms": true,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "password_changed",
"label": "Passwort geändert",
"description": "Benachrichtigung bei Passwortänderung",
"can_disable": false,
"supports_push": true,
"supports_sms": true,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "two_factor_enabled",
"label": "Zwei-Faktor-Authentifizierung aktiviert",
"description": "Benachrichtigung wenn 2FA aktiviert wird",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "two_factor_disabled",
"label": "Zwei-Faktor-Authentifizierung deaktiviert",
"description": "Benachrichtigung wenn 2FA deaktiviert wird",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "account_suspended",
"label": "Konto gesperrt",
"description": "Benachrichtigung wenn Ihr Konto gesperrt wird",
"can_disable": false,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "account_reactivated",
"label": "Konto reaktiviert",
"description": "Benachrichtigung wenn Ihr Konto reaktiviert wird",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
}
],
"profile": [
{
"type": "profile_approved",
"label": "Profil genehmigt",
"description": "Benachrichtigung wenn Ihr Profil genehmigt wird",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "profile_rejected",
"label": "Profil abgelehnt",
"description": "Benachrichtigung wenn Ihr Profil abgelehnt wird",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "document_verified",
"label": "Dokument verifiziert",
"description": "Benachrichtigung wenn ein Dokument verifiziert wird",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "document_rejected",
"label": "Dokument abgelehnt",
"description": "Benachrichtigung wenn ein Dokument abgelehnt wird",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "document_expiring",
"label": "Dokument läuft ab",
"description": "Erinnerung wenn ein Dokument bald abläuft",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "correction_required",
"label": "Korrektur erforderlich",
"description": "Benachrichtigung wenn Korrekturen erforderlich sind",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "review_taking_longer",
"label": "Prüfung dauert länger",
"description": "Benachrichtigung wenn die Profilprüfung länger dauert als erwartet",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "profile_incomplete_reminder",
"label": "Profil unvollständig – Erinnerung",
"description": "Erinnerung wenn Ihr Profil seit mehreren Tagen unvollständig ist",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "work_permit_expiring",
"label": "Arbeitserlaubnis läuft ab",
"description": "Erinnerung wenn Ihre Arbeitserlaubnis bald abläuft",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "work_permit_expired_suspension",
"label": "Konto gesperrt – Arbeitserlaubnis abgelaufen",
"description": "Benachrichtigung wenn Ihr Konto aufgrund einer abgelaufenen Arbeitserlaubnis gesperrt wurde",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "profile_submitted",
"label": "Unterlagen werden geprüft",
"description": "Benachrichtigung wenn Ihre Unterlagen zur Prüfung eingereicht wurden",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
}
],
"jobs": [
{
"type": "new_job_match",
"label": "Neuer passender Job",
"description": "Benachrichtigung über neue passende Jobs",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "saved_job_deadline",
"label": "Bewerbungsfrist endet bald",
"description": "Erinnerung, bevor die Bewerbungsfrist eines gemerkten Jobs endet",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "application_received",
"label": "Bewerbung eingegangen",
"description": "Bestätigung über eingegangene Bewerbungen",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "application_accepted",
"label": "Bewerbung angenommen",
"description": "Benachrichtigung wenn eine Bewerbung angenommen wird",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "application_rejected",
"label": "Bewerbung abgelehnt",
"description": "Benachrichtigung wenn eine Bewerbung abgelehnt wird",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "application_waitlisted",
"label": "Auf Warteliste gesetzt",
"description": "Benachrichtigung wenn Sie auf die Warteliste gesetzt werden",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "shift_assigned",
"label": "Schicht zugewiesen",
"description": "Benachrichtigung wenn Ihnen eine Schicht zugewiesen wird",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "shift_reminder",
"label": "Schicht-Erinnerung",
"description": "Erinnerung vor Schichtbeginn",
"can_disable": true,
"supports_push": true,
"supports_sms": true,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "shift_cancelled",
"label": "Schicht storniert",
"description": "Benachrichtigung wenn eine Schicht storniert wird",
"can_disable": true,
"supports_push": true,
"supports_sms": true,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "shift_modified",
"label": "Schicht geändert",
"description": "Benachrichtigung wenn eine Schicht geändert wird",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "shift_location_changed",
"label": "Einsatzort geändert",
"description": "Benachrichtigung wenn der Einsatzort einer Schicht geändert wird",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "shift_extended",
"label": "Schicht verlängert",
"description": "Benachrichtigung wenn eine Schicht verlängert wird",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "shift_time_disputed",
"label": "Arbeitszeit bestritten",
"description": "Benachrichtigung wenn die erfasste Arbeitszeit bestritten wird",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "no_show_detected",
"label": "No-Show erkannt",
"description": "Benachrichtigung wenn ein Mitarbeiter nicht erscheint",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "no_show_recorded",
"label": "No-Show vermerkt",
"description": "Mitteilung über vermerkte Abwesenheit",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "emergency_shift_available",
"label": "Notfall-Schicht verfügbar",
"description": "Benachrichtigung über kurzfristig verfügbare Schichten",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "emergency_shift_assigned",
"label": "Notfall-Schicht zugewiesen",
"description": "Bestätigung einer Notfall-Schichtzuweisung",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "replacement_found",
"label": "Ersatz gefunden",
"description": "Benachrichtigung wenn Ersatz gefunden wurde",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
}
],
"finance": [
{
"type": "payslip_available",
"label": "Lohnzettel verfügbar",
"description": "Benachrichtigung wenn ein neuer Lohnzettel verfügbar ist",
"can_disable": true,
"supports_push": false,
"supports_sms": false,
"email_enabled": true,
"push_enabled": false,
"sms_enabled": false
},
{
"type": "payment_sent",
"label": "Zahlung gesendet",
"description": "Benachrichtigung wenn eine Zahlung gesendet wird",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "payment_processing",
"label": "Auszahlung in Bearbeitung",
"description": "Benachrichtigung wenn eine Auszahlung in Bearbeitung ist",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "invoice_issued",
"label": "Rechnung ausgestellt",
"description": "Benachrichtigung wenn eine Rechnung ausgestellt wird",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "payment_due",
"label": "Zahlung fällig",
"description": "Erinnerung wenn eine Zahlung fällig wird",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "payment_overdue",
"label": "Zahlung überfällig",
"description": "Benachrichtigung wenn eine Zahlung überfällig ist",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "wallet_topped_up",
"label": "Wallet aufgeladen",
"description": "Benachrichtigung wenn Ihr Wallet erfolgreich aufgeladen wurde",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "withdrawal_requested",
"label": "Auszahlung angefordert",
"description": "Benachrichtigung wenn eine Auszahlung zur Prüfung eingereicht wurde",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "withdrawal_completed",
"label": "Auszahlung abgeschlossen",
"description": "Benachrichtigung wenn eine Auszahlung erfolgreich abgeschlossen wurde",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "withdrawal_failed",
"label": "Auszahlung fehlgeschlagen",
"description": "Benachrichtigung wenn eine Auszahlung fehlgeschlagen ist",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "withdrawal_rejected",
"label": "Auszahlung abgelehnt",
"description": "Benachrichtigung wenn eine Auszahlung abgelehnt wurde",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "withdrawal_cancelled",
"label": "Auszahlung storniert",
"description": "Benachrichtigung wenn eine Auszahlung storniert wurde",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "platform_fee_charged",
"label": "Plattformgebühr berechnet",
"description": "Benachrichtigung wenn eine Plattformgebühr berechnet wurde",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "payslip_ready",
"label": "Lohnzettel bereit",
"description": "Benachrichtigung wenn der Lohnzettel bereit ist",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "invoice_created",
"label": "Rechnung erstellt",
"description": "Benachrichtigung über neue Rechnungen",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
}
],
"communication": [
{
"type": "new_message",
"label": "Neue Nachricht",
"description": "Benachrichtigung über neue Nachrichten",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "new_rating",
"label": "Neue Bewertung",
"description": "Benachrichtigung über neue Bewertungen",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "support_ticket_update",
"label": "Support-Ticket aktualisiert",
"description": "Aktualisierungen zu Ihren Support-Tickets",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "support_ticket_reply",
"label": "Support hat geantwortet",
"description": "Benachrichtigung wenn der Support auf Ihr Ticket antwortet",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "support_ticket_resolved",
"label": "Support-Ticket gelöst",
"description": "Benachrichtigung wenn Ihr Support-Ticket gelöst wurde",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
}
],
"system": [
{
"type": "compliance_violation",
"label": "Compliance-Verstoß",
"description": "Benachrichtigung über Arbeitszeitverstöße",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
},
{
"type": "system_notification",
"label": "System-Benachrichtigung",
"description": "Allgemeine System-Benachrichtigungen",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
}
],
"marketing": [
{
"type": "marketing_email",
"label": "Marketing E-Mails",
"description": "Werbliche E-Mails und Angebote",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": false,
"push_enabled": false,
"sms_enabled": false
},
{
"type": "marketing_push",
"label": "Marketing Push-Nachrichten",
"description": "Werbliche Push-Nachrichten",
"can_disable": true,
"supports_push": true,
"supports_sms": false,
"email_enabled": false,
"push_enabled": false,
"sms_enabled": false
},
{
"type": "newsletter",
"label": "Newsletter",
"description": "Regelmäßiger Newsletter mit Neuigkeiten",
"can_disable": true,
"supports_push": false,
"supports_sms": false,
"email_enabled": false,
"push_enabled": false,
"sms_enabled": false
}
]
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Notification Setting
requires authentication
Update user notification settings.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/mobile/settings/notifications" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"notification_type\": \"architecto\",
\"email_enabled\": true,
\"push_enabled\": true,
\"sms_enabled\": false
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/settings/notifications"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"notification_type": "architecto",
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/settings/notifications';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'notification_type' => 'architecto',
'email_enabled' => true,
'push_enabled' => true,
'sms_enabled' => false,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/settings/notifications');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"notification_type": "architecto",
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Global Notification Settings
requires authentication
Update global notification settings.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/mobile/settings/notifications/global" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email_enabled\": true,
\"push_enabled\": true,
\"sms_enabled\": false,
\"marketing_enabled\": true
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/settings/notifications/global"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false,
"marketing_enabled": true
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/settings/notifications/global';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email_enabled' => true,
'push_enabled' => true,
'sms_enabled' => false,
'marketing_enabled' => true,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/settings/notifications/global');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email_enabled": true,
"push_enabled": true,
"sms_enabled": false,
"marketing_enabled": true
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"email_enabled": false,
"push_enabled": false,
"sms_enabled": true,
"marketing_enabled": true
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get App Settings
requires authentication
Returns user's app settings (language, theme, biometric auth).
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/settings/app" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/settings/app"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/settings/app';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/settings/app');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"settings": {
"language": "de",
"theme": "system",
"biometric_enabled": false,
"push_notifications_enabled": true,
"location_tracking_enabled": false,
"email_notifications_enabled": true
},
"available_languages": [
{
"code": "de",
"label": "Deutsch"
},
{
"code": "en",
"label": "English"
}
],
"available_themes": [
{
"value": "system",
"label": "System"
},
{
"value": "light",
"label": "Hell"
},
{
"value": "dark",
"label": "Dunkel"
}
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update App Settings
requires authentication
Updates user's app settings (language, theme, biometric auth).
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/mobile/settings/app" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"language\": \"de\",
\"theme\": \"dark\",
\"biometric_enabled\": true,
\"push_notifications_enabled\": true,
\"location_tracking_enabled\": false,
\"email_notifications_enabled\": true
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/settings/app"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"language": "de",
"theme": "dark",
"biometric_enabled": true,
"push_notifications_enabled": true,
"location_tracking_enabled": false,
"email_notifications_enabled": true
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/settings/app';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'language' => 'de',
'theme' => 'dark',
'biometric_enabled' => true,
'push_notifications_enabled' => true,
'location_tracking_enabled' => false,
'email_notifications_enabled' => true,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/settings/app');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"language": "de",
"theme": "dark",
"biometric_enabled": true,
"push_notifications_enabled": true,
"location_tracking_enabled": false,
"email_notifications_enabled": true
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"settings": {
"language": "de",
"theme": "dark",
"biometric_enabled": true,
"push_notifications_enabled": true,
"location_tracking_enabled": false,
"email_notifications_enabled": true
},
"message": "settings.updated"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Job Alerts
List Job Alerts
requires authentication
Returns all job alerts for the authenticated employee.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/job-alerts" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/job-alerts"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/job-alerts';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/job-alerts');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": [
{
"id": "019fd2b8-2e42-73c3-89fd-86a26426e4ba",
"name": "Lager Wien",
"category": null,
"location_city": null,
"location_state": null,
"min_hourly_rate": null,
"max_hourly_rate": null,
"shift_type": null,
"max_distance_km": null,
"keywords": null,
"is_active": true,
"notification_frequency": "instant",
"push_enabled": true,
"email_enabled": false,
"last_matched_at": null,
"total_matches": 0,
"created_at": "2026-08-05T16:18:33+00:00"
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create Job Alert
requires authentication
Creates a new job alert for the authenticated employee. Maximum 10 active alerts per user.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/job-alerts" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Gastro Jobs Wien\",
\"category_id\": \"019abcd-1234\",
\"location_city\": \"Wien\",
\"location_state\": \"wien\",
\"min_hourly_rate\": 14,
\"max_hourly_rate\": 25,
\"shift_type\": \"day\",
\"max_distance_km\": 25,
\"location_lat\": 48.2082,
\"location_lng\": 16.3738,
\"keywords\": [
\"kellner\",
\"service\"
],
\"notification_frequency\": \"instant\",
\"push_enabled\": true,
\"email_enabled\": false
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/job-alerts"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Gastro Jobs Wien",
"category_id": "019abcd-1234",
"location_city": "Wien",
"location_state": "wien",
"min_hourly_rate": 14,
"max_hourly_rate": 25,
"shift_type": "day",
"max_distance_km": 25,
"location_lat": 48.2082,
"location_lng": 16.3738,
"keywords": [
"kellner",
"service"
],
"notification_frequency": "instant",
"push_enabled": true,
"email_enabled": false
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/job-alerts';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'name' => 'Gastro Jobs Wien',
'category_id' => '019abcd-1234',
'location_city' => 'Wien',
'location_state' => 'wien',
'min_hourly_rate' => 14.0,
'max_hourly_rate' => 25.0,
'shift_type' => 'day',
'max_distance_km' => 25,
'location_lat' => 48.2082,
'location_lng' => 16.3738,
'keywords' => ['kellner', 'service'],
'notification_frequency' => 'instant',
'push_enabled' => true,
'email_enabled' => false,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/job-alerts');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"name": "Gastro Jobs Wien",
"category_id": "019abcd-1234",
"location_city": "Wien",
"location_state": "wien",
"min_hourly_rate": 14,
"max_hourly_rate": 25,
"shift_type": "day",
"max_distance_km": 25,
"location_lat": 48.2082,
"location_lng": 16.3738,
"keywords": [
"kellner",
"service"
],
"notification_frequency": "instant",
"push_enabled": true,
"email_enabled": false
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Created):
{
"status": "SUCCESS",
"data": {}
}
Example response (422, Too many alerts):
{
"status": "ERROR",
"message": "Maximum 10 active alerts allowed"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Job Alert
requires authentication
Updates an existing job alert for the authenticated employee.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/mobile/job-alerts/019abcd-5678" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Gastro Jobs Wien\",
\"category_id\": \"019abcd-1234\",
\"location_city\": \"Wien\",
\"location_state\": \"wien\",
\"min_hourly_rate\": 14,
\"max_hourly_rate\": 25,
\"shift_type\": \"day\",
\"max_distance_km\": 25,
\"location_lat\": 48.2082,
\"location_lng\": 16.3738,
\"keywords\": [
\"kellner\",
\"service\"
],
\"is_active\": true,
\"notification_frequency\": \"instant\",
\"push_enabled\": true,
\"email_enabled\": false
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/job-alerts/019abcd-5678"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Gastro Jobs Wien",
"category_id": "019abcd-1234",
"location_city": "Wien",
"location_state": "wien",
"min_hourly_rate": 14,
"max_hourly_rate": 25,
"shift_type": "day",
"max_distance_km": 25,
"location_lat": 48.2082,
"location_lng": 16.3738,
"keywords": [
"kellner",
"service"
],
"is_active": true,
"notification_frequency": "instant",
"push_enabled": true,
"email_enabled": false
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/job-alerts/019abcd-5678';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'name' => 'Gastro Jobs Wien',
'category_id' => '019abcd-1234',
'location_city' => 'Wien',
'location_state' => 'wien',
'min_hourly_rate' => 14.0,
'max_hourly_rate' => 25.0,
'shift_type' => 'day',
'max_distance_km' => 25,
'location_lat' => 48.2082,
'location_lng' => 16.3738,
'keywords' => ['kellner', 'service'],
'is_active' => true,
'notification_frequency' => 'instant',
'push_enabled' => true,
'email_enabled' => false,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/job-alerts/019abcd-5678');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"name": "Gastro Jobs Wien",
"category_id": "019abcd-1234",
"location_city": "Wien",
"location_state": "wien",
"min_hourly_rate": 14,
"max_hourly_rate": 25,
"shift_type": "day",
"max_distance_km": 25,
"location_lat": 48.2082,
"location_lng": 16.3738,
"keywords": [
"kellner",
"service"
],
"is_active": true,
"notification_frequency": "instant",
"push_enabled": true,
"email_enabled": false
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Updated):
{
"status": "SUCCESS",
"data": {}
}
Example response (404, Not found):
{
"status": "ERROR",
"message": "Job alert not found"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete Job Alert
requires authentication
Deletes a job alert for the authenticated employee.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/mobile/job-alerts/019abcd-5678" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/job-alerts/019abcd-5678"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/job-alerts/019abcd-5678';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/job-alerts/019abcd-5678');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Job alert deleted"
}
Example response (404, Not found):
{
"status": "ERROR",
"message": "Job alert not found"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Badges
List Badges
requires authentication
List all available badges with their status for the authenticated employee.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/badges" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/badges"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/badges';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/badges');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"summary": {
"total_badges": 0,
"earned_badges": 0,
"total_points": 0,
"completion_percent": 0
},
"badges": []
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Earned Badges
requires authentication
List the authenticated employee's earned badges.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/badges/earned" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/badges/earned"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/badges/earned';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/badges/earned');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"total_badges": 0,
"total_points": 0,
"badges": []
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Earnings
Get Earnings Summary
requires authentication
Returns earnings breakdown from completed shifts. Supports period filtering (week/month/year/all).
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/earnings?period=month&start_date=2026-01-01&end_date=2026-06-30" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/earnings"
);
const params = {
"period": "month",
"start_date": "2026-01-01",
"end_date": "2026-06-30",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/earnings';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'period' => 'month',
'start_date' => '2026-01-01',
'end_date' => '2026-06-30',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/earnings')
.replace(queryParameters: {
'period': 'month',
'start_date': '2026-01-01',
'end_date': '2026-06-30',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"period": {
"type": "month",
"start": "2026-01-01",
"end": "2026-06-30",
"label": "01.01.2026 - 30.06.2026"
},
"summary": {
"total_gross": 0,
"total_net_estimated": 0,
"total_hours": 0,
"shifts_count": 0,
"avg_hourly_rate": 0
},
"breakdown": {
"paid": {
"amount": 0,
"hours": 0,
"shifts_count": 0
},
"pending": {
"amount": 0,
"hours": 0,
"shifts_count": 0
}
},
"by_category": [],
"by_organization": [],
"chart_data": [
{
"date": "2026-01-01",
"label": "01",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-02",
"label": "02",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-03",
"label": "03",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-04",
"label": "04",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-05",
"label": "05",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-06",
"label": "06",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-07",
"label": "07",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-08",
"label": "08",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-09",
"label": "09",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-10",
"label": "10",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-11",
"label": "11",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-12",
"label": "12",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-13",
"label": "13",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-14",
"label": "14",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-15",
"label": "15",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-16",
"label": "16",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-17",
"label": "17",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-18",
"label": "18",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-19",
"label": "19",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-20",
"label": "20",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-21",
"label": "21",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-22",
"label": "22",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-23",
"label": "23",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-24",
"label": "24",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-25",
"label": "25",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-26",
"label": "26",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-27",
"label": "27",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-28",
"label": "28",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-29",
"label": "29",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-30",
"label": "30",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-01-31",
"label": "31",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-01",
"label": "01",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-02",
"label": "02",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-03",
"label": "03",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-04",
"label": "04",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-05",
"label": "05",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-06",
"label": "06",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-07",
"label": "07",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-08",
"label": "08",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-09",
"label": "09",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-10",
"label": "10",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-11",
"label": "11",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-12",
"label": "12",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-13",
"label": "13",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-14",
"label": "14",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-15",
"label": "15",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-16",
"label": "16",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-17",
"label": "17",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-18",
"label": "18",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-19",
"label": "19",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-20",
"label": "20",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-21",
"label": "21",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-22",
"label": "22",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-23",
"label": "23",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-24",
"label": "24",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-25",
"label": "25",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-26",
"label": "26",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-27",
"label": "27",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-02-28",
"label": "28",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-01",
"label": "01",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-02",
"label": "02",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-03",
"label": "03",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-04",
"label": "04",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-05",
"label": "05",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-06",
"label": "06",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-07",
"label": "07",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-08",
"label": "08",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-09",
"label": "09",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-10",
"label": "10",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-11",
"label": "11",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-12",
"label": "12",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-13",
"label": "13",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-14",
"label": "14",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-15",
"label": "15",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-16",
"label": "16",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-17",
"label": "17",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-18",
"label": "18",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-19",
"label": "19",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-20",
"label": "20",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-21",
"label": "21",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-22",
"label": "22",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-23",
"label": "23",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-24",
"label": "24",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-25",
"label": "25",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-26",
"label": "26",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-27",
"label": "27",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-28",
"label": "28",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-29",
"label": "29",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-30",
"label": "30",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-03-31",
"label": "31",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-01",
"label": "01",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-02",
"label": "02",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-03",
"label": "03",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-04",
"label": "04",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-05",
"label": "05",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-06",
"label": "06",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-07",
"label": "07",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-08",
"label": "08",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-09",
"label": "09",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-10",
"label": "10",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-11",
"label": "11",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-12",
"label": "12",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-13",
"label": "13",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-14",
"label": "14",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-15",
"label": "15",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-16",
"label": "16",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-17",
"label": "17",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-18",
"label": "18",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-19",
"label": "19",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-20",
"label": "20",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-21",
"label": "21",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-22",
"label": "22",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-23",
"label": "23",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-24",
"label": "24",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-25",
"label": "25",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-26",
"label": "26",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-27",
"label": "27",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-28",
"label": "28",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-29",
"label": "29",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-04-30",
"label": "30",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-01",
"label": "01",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-02",
"label": "02",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-03",
"label": "03",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-04",
"label": "04",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-05",
"label": "05",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-06",
"label": "06",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-07",
"label": "07",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-08",
"label": "08",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-09",
"label": "09",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-10",
"label": "10",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-11",
"label": "11",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-12",
"label": "12",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-13",
"label": "13",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-14",
"label": "14",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-15",
"label": "15",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-16",
"label": "16",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-17",
"label": "17",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-18",
"label": "18",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-19",
"label": "19",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-20",
"label": "20",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-21",
"label": "21",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-22",
"label": "22",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-23",
"label": "23",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-24",
"label": "24",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-25",
"label": "25",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-26",
"label": "26",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-27",
"label": "27",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-28",
"label": "28",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-29",
"label": "29",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-30",
"label": "30",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-05-31",
"label": "31",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-01",
"label": "01",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-02",
"label": "02",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-03",
"label": "03",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-04",
"label": "04",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-05",
"label": "05",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-06",
"label": "06",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-07",
"label": "07",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-08",
"label": "08",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-09",
"label": "09",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-10",
"label": "10",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-11",
"label": "11",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-12",
"label": "12",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-13",
"label": "13",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-14",
"label": "14",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-15",
"label": "15",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-16",
"label": "16",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-17",
"label": "17",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-18",
"label": "18",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-19",
"label": "19",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-20",
"label": "20",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-21",
"label": "21",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-22",
"label": "22",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-23",
"label": "23",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-24",
"label": "24",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-25",
"label": "25",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-26",
"label": "26",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-27",
"label": "27",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-28",
"label": "28",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-29",
"label": "29",
"gross": 0,
"hours": 0,
"shifts": 0
},
{
"date": "2026-06-30",
"label": "30",
"gross": 0,
"hours": 0,
"shifts": 0
}
],
"navigation": {
"prev": "2025-12",
"next": "2026-02"
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reliability
Get Reliability Score
requires authentication
Get the employee's reliability score and history.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/reliability" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/reliability"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/reliability';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/reliability');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"reliability": {
"score": 100,
"tier": "excellent",
"tier_label": "Excellent",
"window_start": "2026-02-05",
"window_end": "2026-08-05"
},
"punctuality": {
"percentage": null
},
"activity": {
"hours_worked": 0,
"shifts_completed": 1
},
"breakdown": {
"shift_cancellation": 0,
"no_show": 0,
"shift_completion": 0,
"positive_feedback": 0
},
"recent_negative": [],
"improvement_tips": [
"Build your work history by completing more shifts."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Contracts
List Contracts
requires authentication
List all contracts for the authenticated employee.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/contracts" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/contracts"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/contracts';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/contracts');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"contracts": [],
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 20,
"total": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Contract
requires authentication
Get contract details and download URL.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/contracts/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/contracts/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/contracts/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/contracts/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "1b3b99d9-6927-4218-9edf-6c81f2bb5ebf",
"timestamp": "2026-08-21T05:14:34.095638Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Sign Contract
requires authentication
The worker signs a contract — the framework agreement before applying to anything, or an Überlassungsvertrag.
A selection produces one Überlassungsvertrag per shift, not one for
the batch: a company can set contract terms on a single shift, so each
shift is agreed to on its own. A worker selected for three days has
three to sign, and signing one readies that shift alone — the others
stay pending_signature with their own deadlines.
Two things are required together: an explicit consent flag, and the signature they drew. The drawing is stamped onto the PDF and bound into its hash, so a contract cannot later be altered without the signature ceasing to match.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/contracts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/sign" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"signature_consent\": true,
\"signature_data\": \"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/contracts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/sign"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"signature_consent": true,
"signature_data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/contracts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/sign';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'signature_consent' => true,
'signature_data' => 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/contracts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/sign');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"signature_consent": true,
"signature_data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Support
List Tickets
requires authentication
List all support tickets for the authenticated user.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/support/tickets" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/support/tickets"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/support/tickets';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/support/tickets');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"tickets": [
{
"id": "019fd2b8-2e3b-7096-97f9-96d4a481c803",
"ticket_number": "TKT-969367",
"category": "complaint",
"category_label": "Beschwerde",
"status": "open",
"status_label": "Offen",
"subject": "Totam autem repellendus quasi iste debitis fugiat.",
"priority": 2,
"created_at": "2026-08-05 16:18",
"resolved_at": null,
"has_unread": false
}
],
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 20,
"total": 1
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create Ticket
requires authentication
Create a new support ticket (worker requester).
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/support/tickets" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"category\": \"general\",
\"subject\": \"Frage zur Abrechnung\",
\"description\": \"Beispieltext\",
\"related_entity_type\": \"shift\",
\"related_entity_id\": \"019f9939-c4c3-70fb-a54e-5ebf63db36d2\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/support/tickets"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"category": "general",
"subject": "Frage zur Abrechnung",
"description": "Beispieltext",
"related_entity_type": "shift",
"related_entity_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/support/tickets';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'category' => 'general',
'subject' => 'Frage zur Abrechnung',
'description' => 'Beispieltext',
'related_entity_type' => 'shift',
'related_entity_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/support/tickets');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"category": "general",
"subject": "Frage zur Abrechnung",
"description": "Beispieltext",
"related_entity_type": "shift",
"related_entity_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Ticket
requires authentication
Get a support ticket with messages.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "605f390a-b139-4dc7-838f-1ae2277ef187",
"timestamp": "2026-08-21T05:14:34.145889Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Add Ticket Message
requires authentication
Add a message to an existing ticket.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/messages" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"message\": \"Bitte um Rueckmeldung zur naechsten Schicht.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/messages"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"message": "Bitte um Rueckmeldung zur naechsten Schicht."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/messages';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'message' => 'Bitte um Rueckmeldung zur naechsten Schicht.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/messages');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"message": "Bitte um Rueckmeldung zur naechsten Schicht."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Messages
List Conversations
requires authentication
List conversations for the authenticated mobile user.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/messages/conversations" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/messages/conversations"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/messages/conversations';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/messages/conversations');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"conversations": [
{
"id": "64c3f8d8-55d2-4457-b394-c3277a378bac",
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"logo_url": null
},
"job": null,
"last_message": null,
"unread_count": 0,
"last_message_at": "2026-08-05T16:18:32+00:00"
}
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Messages
requires authentication
Get messages for a conversation (mobile user perspective).
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/messages/conversations/019fd51d-53c7-73d0-880d-8edee1800329" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/messages/conversations/019fd51d-53c7-73d0-880d-8edee1800329"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/messages/conversations/019fd51d-53c7-73d0-880d-8edee1800329';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/messages/conversations/019fd51d-53c7-73d0-880d-8edee1800329');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"messages": [],
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 50,
"total": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reply To Conversation
requires authentication
Reply to an existing conversation (mobile user perspective).
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/messages/conversations/019fd51d-53c7-73d0-880d-8edee1800329" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"content\": \"Beispieltext\",
\"attachments\": null
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/messages/conversations/019fd51d-53c7-73d0-880d-8edee1800329"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"content": "Beispieltext",
"attachments": null
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/messages/conversations/019fd51d-53c7-73d0-880d-8edee1800329';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'content' => 'Beispieltext',
'attachments' => null,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/messages/conversations/019fd51d-53c7-73d0-880d-8edee1800329');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"content": "Beispieltext",
"attachments": null
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"message": {
"id": "019fd2b8-3b63-72cd-84f1-aeb06cd822ba",
"conversation_id": "64c3f8d8-55d2-4457-b394-c3277a378bac",
"content": "Beispieltext",
"is_from_user": true,
"created_at": "2026-08-05T16:18:37+00:00"
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Upload a Message Attachment
requires authentication
Upload a file attachment ahead of sending it with a message. The returned attachment id is bound to a message when that message is sent.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/messages/conversations/019f9939-c4c3-70fb-a54e-5ebf63db36d2/attachments" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "file=@/tmp/phpau36t4abcslnf4xzzmv" const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/messages/conversations/019f9939-c4c3-70fb-a54e-5ebf63db36d2/attachments"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('file', document.querySelector('input[name="file"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/messages/conversations/019f9939-c4c3-70fb-a54e-5ebf63db36d2/attachments';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'multipart/form-data',
'Accept' => 'application/json',
],
'multipart' => [
[
'name' => 'file',
'contents' => fopen('/tmp/phpau36t4abcslnf4xzzmv', 'r')
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/messages/conversations/019f9939-c4c3-70fb-a54e-5ebf63db36d2/attachments');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'multipart/form-data',
'Accept': 'application/json',
};
final request = http.MultipartRequest('POST', uri);
request.headers.addAll(headers);
request.files.add(await http.MultipartFile.fromPath('file', '/tmp/phpau36t4abcslnf4xzzmv'));
final streamed = await request.send();
final response = await http.Response.fromStream(streamed);
print(jsonDecode(response.body));
}Example response (201, Uploaded):
{
"status": "SUCCESS",
"data": {
"attachment": {
"id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"name": "beleg.pdf",
"mime_type": "application/pdf",
"file_size": 48213
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Send Message
requires authentication
Send a message to an organization from the mobile user.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/messages" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"organization_id\": \"019f9939-c4c3-70fb-a54e-5ebf63db36d2\",
\"content\": \"Beispieltext\",
\"job_id\": \"019f9939-c4c3-70fb-a54e-5ebf63db36d2\",
\"shift_id\": \"019f9939-c4c3-70fb-a54e-5ebf63db36d2\",
\"attachments\": null
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/messages"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"organization_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"content": "Beispieltext",
"job_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"shift_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"attachments": null
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/messages';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'organization_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'content' => 'Beispieltext',
'job_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'shift_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'attachments' => null,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/messages');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"organization_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"content": "Beispieltext",
"job_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"shift_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"attachments": null
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"message": {
"id": "019fd2b8-3b7b-706f-9077-c559f02b838a",
"conversation_id": "019fd2b8-3b78-703e-bc22-0286223114aa",
"content": "Beispieltext",
"created_at": "2026-08-05T16:18:37+00:00"
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Admin API
Admin dashboard endpoints for platform management. Requires admin-level Bearer token authentication.
Authentication
Login Admin
Authenticates an administrator against the admin guard and issues a Sanctum token. Inactive admin accounts are rejected before credential verification to prevent timing-based enumeration of deactivated accounts.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/auth/login" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"admin@flexxr.at\",
\"country_code\": \"+43\",
\"phone_number\": \"6641234567\",
\"password\": \"AdminSecure123\",
\"code\": \"123456\",
\"recovery_code\": \"ABCD-1234-EFGH\",
\"remember_me\": true
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/auth/login"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "admin@flexxr.at",
"country_code": "+43",
"phone_number": "6641234567",
"password": "AdminSecure123",
"code": "123456",
"recovery_code": "ABCD-1234-EFGH",
"remember_me": true
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/auth/login';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'admin@flexxr.at',
'country_code' => '+43',
'phone_number' => '6641234567',
'password' => 'AdminSecure123',
'code' => '123456',
'recovery_code' => 'ABCD-1234-EFGH',
'remember_me' => true,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/auth/login');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "admin@flexxr.at",
"country_code": "+43",
"phone_number": "6641234567",
"password": "AdminSecure123",
"code": "123456",
"recovery_code": "ABCD-1234-EFGH",
"remember_me": true
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Login successful.",
"data": {
"token": "14|Qd0Pxqa8ulXyaGJEB8Ylpxe6EUYq02DMJzPtUTV5e9f2582f",
"admin": {
"id": "019fd2b7-edab-7280-b09f-b18f58a272ee",
"name": "Super Admin",
"email": "office@flexxr.at",
"role": "super_admin",
"is_active": true,
"last_login_at": "2026-08-05T16:18:40.000000Z",
"created_at": "2026-08-05T16:18:17.000000Z"
}
},
"errors": null,
"meta": {
"request_id": "46530e7b-851c-4aab-b7fe-66d6253aeabb",
"timestamp": "2026-08-05T16:18:40.986452Z"
}
}
Example response (401, 2FA Required):
{
"status": "TWO_FACTOR_REQUIRED",
"message": "Two-factor authentication is required.",
"data": {
"token": "2|challenge-token...",
"two_factor_method": "totp"
},
"errors": [
{
"field": null,
"message": "Two-factor authentication is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (401, Invalid Credentials):
{
"status": "INVALID_CREDENTIALS",
"message": "The provided credentials are incorrect.",
"data": null,
"errors": [
{
"field": "email",
"message": "The provided credentials are incorrect."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "email",
"message": "The email field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (423, Account Temporarily Locked):
{
"status": "ACCOUNT_TEMPORARILY_LOCKED",
"message": "Account temporarily locked. Try again in 15 minutes.",
"data": null,
"errors": [
{
"field": "email",
"message": "Account temporarily locked. Try again in 15 minutes."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Dashboard
Get Admin Dashboard Stats
requires authentication
Aggregate counts for the admin dashboard's KPI tiles.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/dashboard/stats" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/dashboard/stats"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/dashboard/stats';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/dashboard/stats');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"pending_employees": 1,
"pending_companies": 1,
"active_jobs": 109,
"ongoing_assignments": 1,
"overdue_invoices": 0,
"open_tickets": 2,
"fraud_alerts": 0
},
"errors": null,
"meta": {
"request_id": "3a5fb11c-8caa-4c3e-8d97-0efd8c8c83bc",
"timestamp": "2026-08-05T16:18:41.679890Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Users
List Users
requires authentication
Returns a paginated list of all users, optionally filtered by a search term (matched against name and email) and/or a status value.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/users?search=test&status=active&per_page=15&sort=first_name&order=asc" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/users"
);
const params = {
"search": "test",
"status": "active",
"per_page": "15",
"sort": "first_name",
"order": "asc",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/users';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'search' => 'test',
'status' => 'active',
'per_page' => '15',
'sort' => 'first_name',
'order' => 'asc',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/users')
.replace(queryParameters: {
'search': 'test',
'status': 'active',
'per_page': '15',
'sort': 'first_name',
'order': 'asc',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [],
"errors": null,
"meta": {
"request_id": "b0862681-9b77-4cd1-bf0b-b07077be4ce1",
"timestamp": "2026-08-05T16:18:41.691650Z",
"current_page": 1,
"last_page": 1,
"per_page": 15,
"total": 0
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Returns the full profile of a single user, identified by route-model binding.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "User retrieved successfully.",
"data": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"first_name": "Anna",
"last_name": "Neuling",
"email": "pending@demo.flexxr.at",
"country_code": "+43",
"phone_number": "6769876543",
"status": "active",
"avatar_url": null,
"bio": null,
"date_of_birth": null,
"country": null,
"city": null,
"notify_push": true,
"notify_email": true,
"notify_sms": true,
"notify_marketing": false,
"email_verified_at": "2026-08-05T16:18:32+00:00",
"phone_verified_at": "2026-08-05T16:18:32+00:00",
"created_at": "2026-08-05T16:18:18+00:00",
"updated_at": "2026-08-05T16:18:33+00:00",
"employee_profile": null
},
"errors": null,
"meta": {
"request_id": "f29df2ed-2159-4b94-a318-cb28112ce82a",
"timestamp": "2026-08-05T16:18:41.701057Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Updates an employee's profile fields (identity, contact, address) on behalf of an admin.
requires authentication
Status transitions, password rotations, anonymisation and email-change confirmations all have dedicated endpoints with their own audit events and are intentionally not handled here.
Address fields (address_line_1, address_line_2, postal_code) are stored on the employee_profiles table, while identity and basic location (city, country) remain on the users table.
GDPR Art. 30 record-of-processing is satisfied by writing a
user.updated_by_admin audit event listing only the names of the
fields that changed — never the cleartext values themselves. The new
values remain authoritative on the User/EmployeeProfile rows, the
previous values can be reconstructed from immutable backups if a
forensic review is needed.
Example request:
curl --request PATCH \
"https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"first_name\": \"Beispieltext\",
\"last_name\": \"Beispieltext\",
\"bio\": \"Beispieltext\",
\"date_of_birth\": \"2026-09-30\",
\"country_code\": \"AT\",
\"phone_number\": \"6641234567\",
\"address_line_1\": \"Beispieltext\",
\"address_line_2\": \"Beispieltext\",
\"postal_code\": \"AT\",
\"city\": \"Beispieltext\",
\"country\": \"Beispieltext\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"first_name": "Beispieltext",
"last_name": "Beispieltext",
"bio": "Beispieltext",
"date_of_birth": "2026-09-30",
"country_code": "AT",
"phone_number": "6641234567",
"address_line_1": "Beispieltext",
"address_line_2": "Beispieltext",
"postal_code": "AT",
"city": "Beispieltext",
"country": "Beispieltext"
};
fetch(url, {
method: "PATCH",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f';
$response = $client->patch(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'first_name' => 'Beispieltext',
'last_name' => 'Beispieltext',
'bio' => 'Beispieltext',
'date_of_birth' => '2026-09-30',
'country_code' => 'AT',
'phone_number' => '6641234567',
'address_line_1' => 'Beispieltext',
'address_line_2' => 'Beispieltext',
'postal_code' => 'AT',
'city' => 'Beispieltext',
'country' => 'Beispieltext',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"first_name": "Beispieltext",
"last_name": "Beispieltext",
"bio": "Beispieltext",
"date_of_birth": "2026-09-30",
"country_code": "AT",
"phone_number": "6641234567",
"address_line_1": "Beispieltext",
"address_line_2": "Beispieltext",
"postal_code": "AT",
"city": "Beispieltext",
"country": "Beispieltext"
};
final response = await http.patch(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Updates the status of an existing user account.
requires authentication
Delegates the status transition (including token revocation for
deactivated/banned users) to UserService. * @group Admin API
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/status" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"status\": \"active\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/status"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"status": "active"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/status';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'status' => 'active',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/status');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"status": "active"
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "User status updated successfully.",
"data": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"first_name": "Anna",
"last_name": "Neuling",
"email": "pending@demo.flexxr.at",
"country_code": "+43",
"phone_number": "6769876543",
"status": "active",
"avatar_url": null,
"bio": null,
"date_of_birth": null,
"country": null,
"city": null,
"notify_push": true,
"notify_email": true,
"notify_sms": true,
"notify_marketing": false,
"email_verified_at": "2026-08-05T16:18:32+00:00",
"phone_verified_at": "2026-08-05T16:18:32+00:00",
"created_at": "2026-08-05T16:18:18+00:00",
"updated_at": "2026-08-05T16:18:33+00:00",
"employee_profile": null
},
"errors": null,
"meta": {
"request_id": "b855ec49-4087-41ca-8107-b867ec67bdb0",
"timestamp": "2026-08-05T16:18:41.723038Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Admin-triggered user password reset email.
requires authentication
Sends the user a 6-digit code using the same code-based flow as self-service forgot-password. The mobile app handles the code entry.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/send-reset" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/send-reset"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/send-reset';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/send-reset');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Password reset email sent.",
"data": null,
"errors": null,
"meta": {
"request_id": "95f42427-a958-4322-af06-e36c986887c8",
"timestamp": "2026-08-05T16:18:41.738923Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Admin Users
Creates a new admin account.
requires authentication
The super-admin route middleware enforces the role restriction. The newly created admin is active by default; they must log in and optionally enable 2FA themselves. No welcome email is sent — the
super admin communicates credentials out-of-band. * @group Admin API
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/admins" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Beispieltext\",
\"email\": \"name@example.at\",
\"password\": \"S3cure-Passw0rd!\",
\"role\": \"super_admin\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/admins"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Beispieltext",
"email": "name@example.at",
"password": "S3cure-Passw0rd!",
"role": "super_admin"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/admins';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'name' => 'Beispieltext',
'email' => 'name@example.at',
'password' => 'S3cure-Passw0rd!',
'role' => 'super_admin',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/admins');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"name": "Beispieltext",
"email": "name@example.at",
"password": "S3cure-Passw0rd!",
"role": "super_admin"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "CREATED",
"message": "Admin created successfully.",
"data": {
"id": "019fd2b8-520f-7027-b522-08e9a33b49b3",
"name": "Beispieltext",
"email": "name@example.at",
"role": "super_admin",
"is_active": true,
"last_login_at": null,
"created_at": "2026-08-05T16:18:42.000000Z"
},
"errors": null,
"meta": {
"request_id": "8cdc19e4-93ff-4e3f-b229-fee0e489d02b",
"timestamp": "2026-08-05T16:18:42.843825Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Returns the profile of a single admin, identified by route-model binding. * @group Admin API
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Admin retrieved successfully.",
"data": {
"id": "019fd2b7-edab-7280-b09f-b18f58a272ee",
"name": "Super Admin",
"email": "office@flexxr.at",
"role": "super_admin",
"is_active": true,
"last_login_at": null,
"created_at": "2026-08-05T16:18:17.000000Z"
},
"errors": null,
"meta": {
"request_id": "b038e712-95bd-458e-89ed-02e96b78f138",
"timestamp": "2026-08-05T16:18:42.853899Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Changes the role of an existing admin account.
requires authentication
Guards against self-demotion: a super admin cannot downgrade their own role, preventing accidental lock-out when they are the only super admin.
On every successful role change, the matching ACL preset is also swapped
so the legacy admin.role column and the acl_actor_presets pivot stay
in sync. The role update and the preset swap run inside one transaction.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/role" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"role\": \"super_admin\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/role"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"role": "super_admin"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/role';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'role' => 'super_admin',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/role');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"role": "super_admin"
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Admin role updated successfully.",
"data": {
"id": "019fd2b7-edab-7280-b09f-b18f58a272ee",
"name": "Super Admin",
"email": "office@flexxr.at",
"role": "super_admin",
"is_active": true,
"last_login_at": null,
"created_at": "2026-08-05T16:18:17.000000Z"
},
"errors": null,
"meta": {
"request_id": "cc178b32-00a9-4fb3-8c59-eeeb3d3fb9c5",
"timestamp": "2026-08-05T16:18:42.871916Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Deactivates an admin account and revokes all their Sanctum tokens.
requires authentication
Guards against self-deactivation to prevent a super admin from
accidentally locking themselves out of the dashboard. * @group Admin API
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/deactivate" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/deactivate"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "PUT",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/deactivate';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/deactivate');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.put(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Admin deactivated successfully.",
"data": {
"id": "019fd2b8-29c6-70eb-b55e-61878b3ad363",
"name": "Timothy Goyette I",
"email": "klein.jeffrey@example.com",
"role": "support_agent",
"is_active": false,
"last_login_at": null,
"created_at": "2026-08-05T16:18:32.000000Z"
},
"errors": null,
"meta": {
"request_id": "043c8f6f-b451-4f1f-8aa3-a1b9ad17ee99",
"timestamp": "2026-08-05T16:18:42.890951Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reactivates a previously deactivated admin account.
requires authentication
Tokens are not restored — the admin must log in fresh to obtain a new token. * @group Admin API
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/reactivate" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/reactivate"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "PUT",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/reactivate';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/reactivate');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.put(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Admin reactivated successfully.",
"data": {
"id": "019fd2b7-edab-7280-b09f-b18f58a272ee",
"name": "Super Admin",
"email": "office@flexxr.at",
"role": "super_admin",
"is_active": true,
"last_login_at": null,
"created_at": "2026-08-05T16:18:17.000000Z"
},
"errors": null,
"meta": {
"request_id": "3be88090-98cd-49d7-91f3-780bc1ad10a4",
"timestamp": "2026-08-05T16:18:42.902995Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Resets (disables) the 2FA setting for a target admin account.
requires authentication
Mirrors the mechanism used by DisableTwoFactorAction: deletes the TwoFactorSetting morph record for the target authenticatable. Also revokes all Sanctum tokens so the current session cannot coast on the 2fa.verified state.
Guards against self-reset — super admins must use the self-service
DELETE /admin/auth/two-factor/disable endpoint instead. * @group Admin API
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/reset-two-factor" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/reset-two-factor"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/reset-two-factor';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/reset-two-factor');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Two-factor authentication reset successfully.",
"data": {
"id": "019fd2b8-29c6-70eb-b55e-61878b3ad363",
"name": "Timothy Goyette I",
"email": "klein.jeffrey@example.com",
"role": "support_agent",
"is_active": true,
"last_login_at": null,
"created_at": "2026-08-05T16:18:32.000000Z"
},
"errors": null,
"meta": {
"request_id": "5b6c0487-98b5-47e0-9beb-af10a7656f0a",
"timestamp": "2026-08-05T16:18:42.919563Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Resets (disables) the 2FA setting for a target admin account.
requires authentication
Mirrors the mechanism used by DisableTwoFactorAction: deletes the TwoFactorSetting morph record for the target authenticatable. Also revokes all Sanctum tokens so the current session cannot coast on the 2fa.verified state.
Guards against self-reset — super admins must use the self-service
DELETE /admin/auth/two-factor/disable endpoint instead. * @group Admin API
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/reset-2fa" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/reset-2fa"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/reset-2fa';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/reset-2fa');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Two-factor authentication reset successfully.",
"data": {
"id": "019fd2b8-29c6-70eb-b55e-61878b3ad363",
"name": "Timothy Goyette I",
"email": "klein.jeffrey@example.com",
"role": "support_agent",
"is_active": true,
"last_login_at": null,
"created_at": "2026-08-05T16:18:32.000000Z"
},
"errors": null,
"meta": {
"request_id": "5b6c0487-98b5-47e0-9beb-af10a7656f0a",
"timestamp": "2026-08-05T16:18:42.919563Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Scoped Admin Presets
requires authentication
Returns the preset keys currently active for a single admin in the given
organisation context (union of global + org-scoped assignments). Omitting
organization_id returns the same result as the global endpoint.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/presets/scoped?organization_id=018f1234-abcd-7000-0000-000000000001" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"organization_id\": \"6ff8f7f6-1eb3-3525-be4a-3932c805afed\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/presets/scoped"
);
const params = {
"organization_id": "018f1234-abcd-7000-0000-000000000001",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"organization_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/presets/scoped';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'organization_id' => '018f1234-abcd-7000-0000-000000000001',
],
'json' => [
'organization_id' => '6ff8f7f6-1eb3-3525-be4a-3932c805afed',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/presets/scoped')
.replace(queryParameters: {
'organization_id': '018f1234-abcd-7000-0000-000000000001',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"organization_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed"
};
final response = await http.get(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"admin_id": "019fd2b7-edab-7280-b09f-b18f58a272ee",
"organization_id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"presets": [
"super-admin"
]
},
"errors": null,
"meta": {
"request_id": "f5f405f3-eeec-4e79-abc8-7b8920e1b156",
"timestamp": "2026-08-05T16:18:42.948008Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Scoped Admin Presets
requires authentication
Bulk-replaces the org-scoped preset assignments for an admin. Only rows
matching the supplied organization_id context are diffed; global
assignments are never touched. Presets absent from the request body are
revoked (soft); new ones are assigned. The diff and writes run inside a
single DB transaction.
Required permission: admin.admins.manage (super-admin only by default).
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/presets/scoped" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"organization_id\": \"018f1234-abcd-7000-0000-000000000001\",
\"presets\": [
\"admin\",
\"admin-finance\"
]
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/presets/scoped"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"organization_id": "018f1234-abcd-7000-0000-000000000001",
"presets": [
"admin",
"admin-finance"
]
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/presets/scoped';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'organization_id' => '018f1234-abcd-7000-0000-000000000001',
'presets' => ['admin', 'admin-finance'],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/presets/scoped');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"organization_id": "018f1234-abcd-7000-0000-000000000001",
"presets": [
"admin",
"admin-finance"
]
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Scoped admin presets updated.",
"data": {
"admin_id": "019fd2b7-edab-7280-b09f-b18f58a272ee",
"organization_id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"presets": [
"super-admin"
]
},
"errors": null,
"meta": {
"request_id": "dc0fa735-54c1-46d5-9457-cc38dd13b0e1",
"timestamp": "2026-08-05T16:18:42.969201Z"
}
}
Example response (422, Unknown preset):
{
"status": "VALIDATION_ERROR",
"message": "Unknown preset 'foo'."
}
Example response (422, Out of scope):
{
"status": "VALIDATION_ERROR",
"message": "Unknown preset 'co-admin'."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Admin Presets
requires authentication
Returns the preset keys currently assigned to a single admin. Used by the "Manage roles" dialog to pre-check the right boxes.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/presets" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/presets"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/presets';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/presets');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"admin_id": "019fd2b7-edab-7280-b09f-b18f58a272ee",
"presets": [
"super-admin"
]
},
"errors": null,
"meta": {
"request_id": "e65c3abe-ffe9-4fee-8269-dea01f566b5b",
"timestamp": "2026-08-05T16:18:42.981025Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Admin Presets
requires authentication
Bulk-replaces the presets assigned to an admin. Presets currently held but absent from the request body are revoked; presets in the request body but not yet held are added. The diff and the assign / revoke writes execute inside a single transaction so a partial failure cannot leave the actor with a half-updated preset set.
Required permission: admin.admins.manage (super-admin only by default).
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/presets" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"presets\": [
\"admin\",
\"admin-finance\"
]
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/presets"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"presets": [
"admin",
"admin-finance"
]
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/presets';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'presets' => ['admin', 'admin-finance'],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/presets');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"presets": [
"admin",
"admin-finance"
]
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Admin presets updated.",
"data": {
"admin_id": "019fd2b7-edab-7280-b09f-b18f58a272ee",
"presets": [
"super-admin"
]
},
"errors": null,
"meta": {
"request_id": "8204b89c-9e5a-4051-b179-15d96a9f9b75",
"timestamp": "2026-08-05T16:18:42.991244Z"
}
}
Example response (422, Unknown preset):
{
"status": "VALIDATION_ERROR",
"message": "Unknown preset 'foo'."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Scoped Admin Presets
requires authentication
Returns the preset keys currently active for a single admin in the given
organisation context (union of global + org-scoped assignments). Omitting
organization_id returns the same result as the global endpoint.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/scoped-presets?organization_id=018f1234-abcd-7000-0000-000000000001" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"organization_id\": \"6ff8f7f6-1eb3-3525-be4a-3932c805afed\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/scoped-presets"
);
const params = {
"organization_id": "018f1234-abcd-7000-0000-000000000001",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"organization_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/scoped-presets';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'organization_id' => '018f1234-abcd-7000-0000-000000000001',
],
'json' => [
'organization_id' => '6ff8f7f6-1eb3-3525-be4a-3932c805afed',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/scoped-presets')
.replace(queryParameters: {
'organization_id': '018f1234-abcd-7000-0000-000000000001',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"organization_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed"
};
final response = await http.get(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"admin_id": "019fd2b7-edab-7280-b09f-b18f58a272ee",
"organization_id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"presets": [
"super-admin"
]
},
"errors": null,
"meta": {
"request_id": "f5f405f3-eeec-4e79-abc8-7b8920e1b156",
"timestamp": "2026-08-05T16:18:42.948008Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Scoped Admin Presets
requires authentication
Bulk-replaces the org-scoped preset assignments for an admin. Only rows
matching the supplied organization_id context are diffed; global
assignments are never touched. Presets absent from the request body are
revoked (soft); new ones are assigned. The diff and writes run inside a
single DB transaction.
Required permission: admin.admins.manage (super-admin only by default).
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/scoped-presets" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"organization_id\": \"018f1234-abcd-7000-0000-000000000001\",
\"presets\": [
\"admin\",
\"admin-finance\"
]
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/scoped-presets"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"organization_id": "018f1234-abcd-7000-0000-000000000001",
"presets": [
"admin",
"admin-finance"
]
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/scoped-presets';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'organization_id' => '018f1234-abcd-7000-0000-000000000001',
'presets' => ['admin', 'admin-finance'],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/admins/019f0593-c378-72f0-84b7-8adf1820207f/scoped-presets');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"organization_id": "018f1234-abcd-7000-0000-000000000001",
"presets": [
"admin",
"admin-finance"
]
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Scoped admin presets updated.",
"data": {
"admin_id": "019fd2b7-edab-7280-b09f-b18f58a272ee",
"organization_id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"presets": [
"super-admin"
]
},
"errors": null,
"meta": {
"request_id": "dc0fa735-54c1-46d5-9457-cc38dd13b0e1",
"timestamp": "2026-08-05T16:18:42.969201Z"
}
}
Example response (422, Unknown preset):
{
"status": "VALIDATION_ERROR",
"message": "Unknown preset 'foo'."
}
Example response (422, Out of scope):
{
"status": "VALIDATION_ERROR",
"message": "Unknown preset 'co-admin'."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Admin Presets
requires authentication
Returns the catalog of admin-scope presets (roles) that a super admin may assign to other admin accounts. Used by the admin dashboard's "Manage roles" dialog.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/admin-presets" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/admin-presets"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/admin-presets';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/admin-presets');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [
{
"key": "super-admin",
"label": "Super Admin",
"description": "Unrestricted admin access including GDPR operations, app secrets, and admin account management.",
"permissions": [
"admin.admins.create",
"admin.admins.deactivate",
"admin.admins.reactivate",
"admin.admins.reset-2fa",
"admin.admins.update",
"admin.admins.update-presets",
"admin.admins.update-role",
"admin.admins.view",
"admin.app-settings.reveal-secret",
"admin.app-settings.update",
"admin.app-settings.view",
"admin.assignments.manage",
"admin.assignments.view",
"admin.audit.view",
"admin.billing.update",
"admin.billing.view",
"admin.compliance.aueg-monitor",
"admin.compliance.minimum-wage-warnings",
"admin.compliance.view",
"admin.compliance.working-time-warnings",
"admin.contracts.manage",
"admin.contracts.view",
"admin.employees.approve",
"admin.employees.flag-high-risk",
"admin.employees.reactivate",
"admin.employees.reject",
"admin.employees.request-correction",
"admin.employees.review-documents",
"admin.employees.suspend",
"admin.employees.validate-svs",
"admin.employees.view",
"admin.finance.manage-dunning",
"admin.finance.manage-invoices",
"admin.finance.view-invoices",
"admin.finance.view-payments",
"admin.gdpr.anonymize",
"admin.gdpr.export",
"admin.gdpr.restrict",
"admin.jobs.approve",
"admin.jobs.emergency-close",
"admin.jobs.emergency-reassign",
"admin.jobs.manage-categories",
"admin.jobs.manage-document-types",
"admin.jobs.reject",
"admin.jobs.view",
"admin.legal.manage",
"admin.legal.view",
"admin.organizations.reactivate",
"admin.organizations.reject",
"admin.organizations.reset-password",
"admin.organizations.review-documents",
"admin.organizations.suspend",
"admin.organizations.update",
"admin.organizations.verify",
"admin.organizations.view",
"admin.payroll.download-payslips",
"admin.payroll.sync",
"admin.payroll.trigger",
"admin.payroll.view",
"admin.ratings.moderate",
"admin.ratings.view",
"admin.reports.export",
"admin.reports.view",
"admin.security.detect-duplicates",
"admin.security.manual-review",
"admin.support.assign-tickets",
"admin.support.escalate-tickets",
"admin.support.resolve-tickets",
"admin.support.update",
"admin.support.view",
"admin.support.view-tickets",
"admin.system.view-health",
"admin.system.view-metrics",
"admin.users.change-status",
"admin.users.reset-password",
"admin.users.update",
"admin.users.update-by-admin",
"admin.users.view"
],
"category": "platform_admin",
"highlights": [
"presets.super-admin.highlights.full_access",
"presets.super-admin.highlights.manage_admins",
"presets.super-admin.highlights.platform_settings"
],
"risk_level": "high"
},
{
"key": "payroll-admin",
"label": "Payroll Admin",
"description": "Manage payroll calculations, payslip generation, and ELDA submissions.",
"permissions": [
"admin.contracts.view",
"admin.employees.view",
"admin.payroll.download-payslips",
"admin.payroll.sync",
"admin.payroll.trigger",
"admin.payroll.view",
"admin.reports.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "compliance-officer",
"label": "Compliance Officer",
"description": "Employee/company document review, compliance monitoring (AÜG/AZG/ARG), audit log access.",
"permissions": [
"admin.audit.view",
"admin.compliance.aueg-monitor",
"admin.compliance.minimum-wage-warnings",
"admin.compliance.view",
"admin.compliance.working-time-warnings",
"admin.employees.approve",
"admin.employees.flag-high-risk",
"admin.employees.reactivate",
"admin.employees.reject",
"admin.employees.request-correction",
"admin.employees.review-documents",
"admin.employees.suspend",
"admin.employees.validate-svs",
"admin.employees.view",
"admin.legal.manage",
"admin.legal.view",
"admin.organizations.reject",
"admin.organizations.review-documents",
"admin.organizations.verify",
"admin.organizations.view",
"admin.reports.view",
"admin.security.detect-duplicates",
"admin.security.manual-review"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "operations-manager",
"label": "Operations Manager",
"description": "Platform operations: employee/company review, support tickets, system health monitoring.",
"permissions": [
"admin.assignments.manage",
"admin.assignments.view",
"admin.employees.approve",
"admin.employees.reject",
"admin.employees.request-correction",
"admin.employees.review-documents",
"admin.employees.view",
"admin.jobs.approve",
"admin.jobs.emergency-close",
"admin.jobs.emergency-reassign",
"admin.jobs.manage-categories",
"admin.jobs.manage-document-types",
"admin.jobs.reject",
"admin.jobs.view",
"admin.organizations.reject",
"admin.organizations.review-documents",
"admin.organizations.verify",
"admin.organizations.view",
"admin.reports.view",
"admin.support.assign-tickets",
"admin.support.escalate-tickets",
"admin.support.resolve-tickets",
"admin.support.update",
"admin.support.view",
"admin.support.view-tickets",
"admin.system.view-health",
"admin.system.view-metrics"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "finance-admin",
"label": "Finance Admin",
"description": "Manage invoices, payments, and dunning processes.",
"permissions": [
"admin.billing.update",
"admin.billing.view",
"admin.finance.manage-dunning",
"admin.finance.manage-invoices",
"admin.finance.view-invoices",
"admin.finance.view-payments",
"admin.reports.export",
"admin.reports.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "payroll-agent",
"label": "Payroll Agent",
"description": "View payroll status and download payslips. Cannot trigger runs or sync.",
"permissions": [
"admin.employees.view",
"admin.payroll.download-payslips",
"admin.payroll.view",
"admin.reports.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "compliance-agent",
"label": "Compliance Agent",
"description": "Monitor AZG/ARG warnings and review documents. Cannot verify/reject organisations.",
"permissions": [
"admin.audit.view",
"admin.compliance.minimum-wage-warnings",
"admin.compliance.view",
"admin.compliance.working-time-warnings",
"admin.employees.review-documents",
"admin.employees.view",
"admin.organizations.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "support-supervisor",
"label": "Support Supervisor",
"description": "Full support-ticket control including assignment and escalation.",
"permissions": [
"admin.employees.view",
"admin.organizations.view",
"admin.reports.view",
"admin.support.assign-tickets",
"admin.support.escalate-tickets",
"admin.support.resolve-tickets",
"admin.support.update",
"admin.support.view",
"admin.support.view-tickets",
"admin.users.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "ops-agent",
"label": "Operations Agent",
"description": "Review employee/company applications and monitor jobs. Cannot approve or reject.",
"permissions": [
"admin.assignments.view",
"admin.employees.review-documents",
"admin.employees.view",
"admin.jobs.view",
"admin.organizations.review-documents",
"admin.organizations.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "finance-agent",
"label": "Finance Agent",
"description": "View invoices and payments. Cannot finalize invoices or manage dunning.",
"permissions": [
"admin.billing.view",
"admin.finance.view-invoices",
"admin.finance.view-payments",
"admin.reports.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "support-agent",
"label": "Support Agent",
"description": "Handle support tickets, view user and organization information for context.",
"permissions": [
"admin.employees.view",
"admin.organizations.view",
"admin.support.resolve-tickets",
"admin.support.update",
"admin.support.view",
"admin.support.view-tickets",
"admin.users.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "admin",
"label": "Admin",
"description": "Standard admin: org/user management, audit log, settings. Use SRS roles instead.",
"permissions": [
"admin.admins.view",
"admin.app-settings.update",
"admin.app-settings.view",
"admin.audit.view",
"admin.employees.approve",
"admin.employees.flag-high-risk",
"admin.employees.reactivate",
"admin.employees.reject",
"admin.employees.request-correction",
"admin.employees.review-documents",
"admin.employees.suspend",
"admin.employees.validate-svs",
"admin.employees.view",
"admin.organizations.reactivate",
"admin.organizations.reject",
"admin.organizations.reset-password",
"admin.organizations.review-documents",
"admin.organizations.suspend",
"admin.organizations.update",
"admin.organizations.verify",
"admin.organizations.view",
"admin.reports.view",
"admin.users.change-status",
"admin.users.reset-password",
"admin.users.update",
"admin.users.update-by-admin",
"admin.users.view"
],
"category": "platform_admin",
"highlights": [
"presets.admin.highlights.review_orgs",
"presets.admin.highlights.moderate_campaigns",
"presets.admin.highlights.approve_payouts",
"presets.admin.highlights.no_admin_management"
],
"risk_level": "high"
},
{
"key": "moderator",
"label": "Moderator",
"description": "Read-only: view organisations, users, audit log. Use \"support-agent\" instead.",
"permissions": [
"admin.audit.view",
"admin.employees.view",
"admin.organizations.view",
"admin.users.view"
],
"category": "content",
"highlights": [
"presets.moderator.highlights.view_organizations",
"presets.moderator.highlights.view_users",
"presets.moderator.highlights.no_money_actions"
],
"risk_level": "medium"
}
],
"errors": null,
"meta": {
"request_id": "2762271f-0d07-4368-802a-e50e0d9f8403",
"timestamp": "2026-08-05T16:18:43.032923Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Admin Presets
requires authentication
Returns the catalog of admin-scope presets (roles) that a super admin may assign to other admin accounts. Used by the admin dashboard's "Manage roles" dialog.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/acl/presets" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/acl/presets"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/acl/presets';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/acl/presets');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [
{
"key": "super-admin",
"label": "Super Admin",
"description": "Unrestricted admin access including GDPR operations, app secrets, and admin account management.",
"permissions": [
"admin.admins.create",
"admin.admins.deactivate",
"admin.admins.reactivate",
"admin.admins.reset-2fa",
"admin.admins.update",
"admin.admins.update-presets",
"admin.admins.update-role",
"admin.admins.view",
"admin.app-settings.reveal-secret",
"admin.app-settings.update",
"admin.app-settings.view",
"admin.assignments.manage",
"admin.assignments.view",
"admin.audit.view",
"admin.billing.update",
"admin.billing.view",
"admin.compliance.aueg-monitor",
"admin.compliance.minimum-wage-warnings",
"admin.compliance.view",
"admin.compliance.working-time-warnings",
"admin.contracts.manage",
"admin.contracts.view",
"admin.employees.approve",
"admin.employees.flag-high-risk",
"admin.employees.reactivate",
"admin.employees.reject",
"admin.employees.request-correction",
"admin.employees.review-documents",
"admin.employees.suspend",
"admin.employees.validate-svs",
"admin.employees.view",
"admin.finance.manage-dunning",
"admin.finance.manage-invoices",
"admin.finance.view-invoices",
"admin.finance.view-payments",
"admin.gdpr.anonymize",
"admin.gdpr.export",
"admin.gdpr.restrict",
"admin.jobs.approve",
"admin.jobs.emergency-close",
"admin.jobs.emergency-reassign",
"admin.jobs.manage-categories",
"admin.jobs.manage-document-types",
"admin.jobs.reject",
"admin.jobs.view",
"admin.legal.manage",
"admin.legal.view",
"admin.organizations.reactivate",
"admin.organizations.reject",
"admin.organizations.reset-password",
"admin.organizations.review-documents",
"admin.organizations.suspend",
"admin.organizations.update",
"admin.organizations.verify",
"admin.organizations.view",
"admin.payroll.download-payslips",
"admin.payroll.sync",
"admin.payroll.trigger",
"admin.payroll.view",
"admin.ratings.moderate",
"admin.ratings.view",
"admin.reports.export",
"admin.reports.view",
"admin.security.detect-duplicates",
"admin.security.manual-review",
"admin.support.assign-tickets",
"admin.support.escalate-tickets",
"admin.support.resolve-tickets",
"admin.support.update",
"admin.support.view",
"admin.support.view-tickets",
"admin.system.view-health",
"admin.system.view-metrics",
"admin.users.change-status",
"admin.users.reset-password",
"admin.users.update",
"admin.users.update-by-admin",
"admin.users.view"
],
"category": "platform_admin",
"highlights": [
"presets.super-admin.highlights.full_access",
"presets.super-admin.highlights.manage_admins",
"presets.super-admin.highlights.platform_settings"
],
"risk_level": "high"
},
{
"key": "payroll-admin",
"label": "Payroll Admin",
"description": "Manage payroll calculations, payslip generation, and ELDA submissions.",
"permissions": [
"admin.contracts.view",
"admin.employees.view",
"admin.payroll.download-payslips",
"admin.payroll.sync",
"admin.payroll.trigger",
"admin.payroll.view",
"admin.reports.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "compliance-officer",
"label": "Compliance Officer",
"description": "Employee/company document review, compliance monitoring (AÜG/AZG/ARG), audit log access.",
"permissions": [
"admin.audit.view",
"admin.compliance.aueg-monitor",
"admin.compliance.minimum-wage-warnings",
"admin.compliance.view",
"admin.compliance.working-time-warnings",
"admin.employees.approve",
"admin.employees.flag-high-risk",
"admin.employees.reactivate",
"admin.employees.reject",
"admin.employees.request-correction",
"admin.employees.review-documents",
"admin.employees.suspend",
"admin.employees.validate-svs",
"admin.employees.view",
"admin.legal.manage",
"admin.legal.view",
"admin.organizations.reject",
"admin.organizations.review-documents",
"admin.organizations.verify",
"admin.organizations.view",
"admin.reports.view",
"admin.security.detect-duplicates",
"admin.security.manual-review"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "operations-manager",
"label": "Operations Manager",
"description": "Platform operations: employee/company review, support tickets, system health monitoring.",
"permissions": [
"admin.assignments.manage",
"admin.assignments.view",
"admin.employees.approve",
"admin.employees.reject",
"admin.employees.request-correction",
"admin.employees.review-documents",
"admin.employees.view",
"admin.jobs.approve",
"admin.jobs.emergency-close",
"admin.jobs.emergency-reassign",
"admin.jobs.manage-categories",
"admin.jobs.manage-document-types",
"admin.jobs.reject",
"admin.jobs.view",
"admin.organizations.reject",
"admin.organizations.review-documents",
"admin.organizations.verify",
"admin.organizations.view",
"admin.reports.view",
"admin.support.assign-tickets",
"admin.support.escalate-tickets",
"admin.support.resolve-tickets",
"admin.support.update",
"admin.support.view",
"admin.support.view-tickets",
"admin.system.view-health",
"admin.system.view-metrics"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "finance-admin",
"label": "Finance Admin",
"description": "Manage invoices, payments, and dunning processes.",
"permissions": [
"admin.billing.update",
"admin.billing.view",
"admin.finance.manage-dunning",
"admin.finance.manage-invoices",
"admin.finance.view-invoices",
"admin.finance.view-payments",
"admin.reports.export",
"admin.reports.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "payroll-agent",
"label": "Payroll Agent",
"description": "View payroll status and download payslips. Cannot trigger runs or sync.",
"permissions": [
"admin.employees.view",
"admin.payroll.download-payslips",
"admin.payroll.view",
"admin.reports.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "compliance-agent",
"label": "Compliance Agent",
"description": "Monitor AZG/ARG warnings and review documents. Cannot verify/reject organisations.",
"permissions": [
"admin.audit.view",
"admin.compliance.minimum-wage-warnings",
"admin.compliance.view",
"admin.compliance.working-time-warnings",
"admin.employees.review-documents",
"admin.employees.view",
"admin.organizations.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "support-supervisor",
"label": "Support Supervisor",
"description": "Full support-ticket control including assignment and escalation.",
"permissions": [
"admin.employees.view",
"admin.organizations.view",
"admin.reports.view",
"admin.support.assign-tickets",
"admin.support.escalate-tickets",
"admin.support.resolve-tickets",
"admin.support.update",
"admin.support.view",
"admin.support.view-tickets",
"admin.users.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "ops-agent",
"label": "Operations Agent",
"description": "Review employee/company applications and monitor jobs. Cannot approve or reject.",
"permissions": [
"admin.assignments.view",
"admin.employees.review-documents",
"admin.employees.view",
"admin.jobs.view",
"admin.organizations.review-documents",
"admin.organizations.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "finance-agent",
"label": "Finance Agent",
"description": "View invoices and payments. Cannot finalize invoices or manage dunning.",
"permissions": [
"admin.billing.view",
"admin.finance.view-invoices",
"admin.finance.view-payments",
"admin.reports.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "support-agent",
"label": "Support Agent",
"description": "Handle support tickets, view user and organization information for context.",
"permissions": [
"admin.employees.view",
"admin.organizations.view",
"admin.support.resolve-tickets",
"admin.support.update",
"admin.support.view",
"admin.support.view-tickets",
"admin.users.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "admin",
"label": "Admin",
"description": "Standard admin: org/user management, audit log, settings. Use SRS roles instead.",
"permissions": [
"admin.admins.view",
"admin.app-settings.update",
"admin.app-settings.view",
"admin.audit.view",
"admin.employees.approve",
"admin.employees.flag-high-risk",
"admin.employees.reactivate",
"admin.employees.reject",
"admin.employees.request-correction",
"admin.employees.review-documents",
"admin.employees.suspend",
"admin.employees.validate-svs",
"admin.employees.view",
"admin.organizations.reactivate",
"admin.organizations.reject",
"admin.organizations.reset-password",
"admin.organizations.review-documents",
"admin.organizations.suspend",
"admin.organizations.update",
"admin.organizations.verify",
"admin.organizations.view",
"admin.reports.view",
"admin.users.change-status",
"admin.users.reset-password",
"admin.users.update",
"admin.users.update-by-admin",
"admin.users.view"
],
"category": "platform_admin",
"highlights": [
"presets.admin.highlights.review_orgs",
"presets.admin.highlights.moderate_campaigns",
"presets.admin.highlights.approve_payouts",
"presets.admin.highlights.no_admin_management"
],
"risk_level": "high"
},
{
"key": "moderator",
"label": "Moderator",
"description": "Read-only: view organisations, users, audit log. Use \"support-agent\" instead.",
"permissions": [
"admin.audit.view",
"admin.employees.view",
"admin.organizations.view",
"admin.users.view"
],
"category": "content",
"highlights": [
"presets.moderator.highlights.view_organizations",
"presets.moderator.highlights.view_users",
"presets.moderator.highlights.no_money_actions"
],
"risk_level": "medium"
}
],
"errors": null,
"meta": {
"request_id": "2762271f-0d07-4368-802a-e50e0d9f8403",
"timestamp": "2026-08-05T16:18:43.032923Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Organizations
List Organizations
requires authentication
Returns a paginated list of all organisations, optionally filtered by a search term (matched against name and email) and/or a status value.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/organizations?search=test&status=active&per_page=15&sort=name&order=asc" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/organizations"
);
const params = {
"search": "test",
"status": "active",
"per_page": "15",
"sort": "name",
"order": "asc",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/organizations';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'search' => 'test',
'status' => 'active',
'per_page' => '15',
'sort' => 'name',
'order' => 'asc',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/organizations')
.replace(queryParameters: {
'search': 'test',
'status': 'active',
'per_page': '15',
'sort': 'name',
'order': 'asc',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [],
"errors": null,
"meta": {
"request_id": "fe7a27ad-e2c9-4825-af4a-7df8fb6beaaf",
"timestamp": "2026-08-05T16:18:42.087462Z",
"current_page": 1,
"last_page": 1,
"per_page": 15,
"total": 0
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Export Organizations
requires authentication
Streams the full organisation list as a CSV file.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/organizations/export" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/organizations/export"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/organizations/export';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/organizations/export');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "09d5c681-e3a5-46ed-9a4d-9a3c9dbabc73",
"timestamp": "2026-08-21T05:14:35.938874Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Returns the full profile of a single organisation, identified by
requires authentication
route-model binding. * @group Admin API
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Organisation retrieved successfully.",
"data": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"slug": "caritas-4v1ues",
"email": "caritas-portal@flexxr.eu.cc",
"country_code": "+43",
"phone_number": "6641234567",
"contact_person_name": null,
"contact_person_phone": null,
"iso_country_code": "AT",
"phone_e164": "+436641234567",
"description": "Caritas test organisation used for end-to-end portal QA. Safe to delete.",
"logo_url": null,
"website": "https://www.caritas.at",
"address": "Albrechtskreithgasse 19-21",
"address_line2": null,
"postal_code": null,
"city": "Vienna",
"country": "Austria",
"status": "active",
"verified_at": "2026-08-05T16:18:17.000000Z",
"is_verified": true,
"total_raised": null,
"created_at": "2026-08-05T16:18:17.000000Z",
"platform_fee_flat_cents": null,
"firmenbuchnummer": null,
"uid_number": null,
"uid_validation_status": null,
"gisa_status": "pending",
"payout_method": null,
"stripe_connect_account_id": null,
"connect_charges_enabled": null,
"connect_payouts_enabled": null,
"connect_details_submitted": null,
"connect_requirements_due": null,
"connect_country_code": null
},
"errors": null,
"meta": {
"request_id": "5f3a0146-cc1c-4a3d-832d-77df0c4cec1f",
"timestamp": "2026-08-05T16:18:42.101496Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Verify Organization
requires authentication
Verifies a pending organisation, transitioning it to Active status.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/verify" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/verify"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "PUT",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/verify';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/verify');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.put(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Organisation verified successfully.",
"data": {
"id": "019fd2b8-2abb-7347-a732-5c2c2ee4f03c",
"name": "Feeney, Howell and Stehr",
"slug": "feeney-howell-and-stehr-bfcdiz",
"email": "gunnar90@hahn.com",
"country_code": "+1",
"phone_number": "2025550275",
"contact_person_name": null,
"contact_person_phone": null,
"iso_country_code": null,
"phone_e164": "+12025550275",
"description": "Dolor aspernatur eligendi nam enim tempore. Possimus est unde quia dignissimos dolore unde eos. Est quos quam enim voluptatem ut molestiae.",
"logo_url": null,
"website": null,
"address": null,
"address_line2": null,
"postal_code": null,
"city": null,
"country": null,
"status": "active",
"verified_at": "2026-08-05T16:18:42.000000Z",
"is_verified": true,
"total_raised": null,
"created_at": "2026-08-05T16:18:32.000000Z",
"platform_fee_flat_cents": null,
"firmenbuchnummer": null,
"uid_number": null,
"uid_validation_status": null,
"payout_method": null,
"stripe_connect_account_id": null,
"connect_charges_enabled": null,
"connect_payouts_enabled": null,
"connect_details_submitted": null,
"connect_requirements_due": null,
"connect_country_code": null
},
"errors": null,
"meta": {
"request_id": "1e3ae433-1435-4a4b-8cd3-6c871aa8c9ea",
"timestamp": "2026-08-05T16:18:42.117609Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reject Organization
requires authentication
Rejects a pending organisation application.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/reject" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Krankheitsbedingt kurzfristig abgesagt.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/reject"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt."
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/reject';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'Krankheitsbedingt kurzfristig abgesagt.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/reject');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt."
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Organisation rejected.",
"data": {
"id": "019fd2b8-2abb-7347-a732-5c2c2ee4f03c",
"name": "Feeney, Howell and Stehr",
"slug": "feeney-howell-and-stehr-bfcdiz",
"email": "gunnar90@hahn.com",
"country_code": "+1",
"phone_number": "2025550275",
"contact_person_name": null,
"contact_person_phone": null,
"iso_country_code": null,
"phone_e164": "+12025550275",
"description": "Dolor aspernatur eligendi nam enim tempore. Possimus est unde quia dignissimos dolore unde eos. Est quos quam enim voluptatem ut molestiae.",
"logo_url": null,
"website": null,
"address": null,
"address_line2": null,
"postal_code": null,
"city": null,
"country": null,
"status": "rejected",
"verified_at": null,
"is_verified": false,
"total_raised": null,
"created_at": "2026-08-05T16:18:32.000000Z",
"platform_fee_flat_cents": null,
"firmenbuchnummer": null,
"uid_number": null,
"uid_validation_status": null,
"payout_method": null,
"stripe_connect_account_id": null,
"connect_charges_enabled": null,
"connect_payouts_enabled": null,
"connect_details_submitted": null,
"connect_requirements_due": null,
"connect_country_code": null
},
"errors": null,
"meta": {
"request_id": "628391df-a753-4ffc-b5aa-8eb743ba49ba",
"timestamp": "2026-08-05T16:18:42.132018Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Suspends an active organisation and immediately revokes all active tokens.
requires authentication
Business-rule enforcement (active-only guard) is handled inside
OrganizationService::suspend(). * @group Admin API
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/suspend" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Krankheitsbedingt kurzfristig abgesagt.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/suspend"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt."
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/suspend';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'Krankheitsbedingt kurzfristig abgesagt.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/suspend');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt."
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Organisation suspended successfully.",
"data": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"slug": "caritas-4v1ues",
"email": "caritas-portal@flexxr.eu.cc",
"country_code": "+43",
"phone_number": "6641234567",
"contact_person_name": null,
"contact_person_phone": null,
"iso_country_code": "AT",
"phone_e164": "+436641234567",
"description": "Caritas test organisation used for end-to-end portal QA. Safe to delete.",
"logo_url": null,
"website": "https://www.caritas.at",
"address": "Albrechtskreithgasse 19-21",
"address_line2": null,
"postal_code": null,
"city": "Vienna",
"country": "Austria",
"status": "suspended",
"verified_at": "2026-08-05T16:18:17.000000Z",
"is_verified": true,
"total_raised": null,
"created_at": "2026-08-05T16:18:17.000000Z",
"platform_fee_flat_cents": null,
"firmenbuchnummer": null,
"uid_number": null,
"uid_validation_status": null,
"payout_method": null,
"stripe_connect_account_id": null,
"connect_charges_enabled": null,
"connect_payouts_enabled": null,
"connect_details_submitted": null,
"connect_requirements_due": null,
"connect_country_code": null
},
"errors": null,
"meta": {
"request_id": "55ed4c84-a8de-451b-a958-d4747f155cd0",
"timestamp": "2026-08-05T16:18:42.146772Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reactivates a suspended organisation, restoring its ability to operate.
requires authentication
The original verification metadata (verified_at, verified_by) is preserved unchanged. Business-rule enforcement (suspended-only guard) is handled inside
OrganizationService::reactivate(). * @group Admin API
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/reactivate" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/reactivate"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "PUT",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/reactivate';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/reactivate');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.put(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Organisation reactivated successfully.",
"data": {
"id": "019fd2b8-2b93-70ff-9a0a-ef0bb511b558",
"name": "Cormier and Sons",
"slug": "cormier-and-sons-vnw4vm",
"email": "wisozk.agustin@pacocha.org",
"country_code": "+1",
"phone_number": "2025550634",
"contact_person_name": null,
"contact_person_phone": null,
"iso_country_code": null,
"phone_e164": "+12025550634",
"description": "Maxime omnis maxime autem aliquid voluptas magni consequatur nesciunt. Sapiente quam quae laudantium culpa reiciendis repellat dolores. Exercitationem expedita et eum modi.",
"logo_url": null,
"website": null,
"address": null,
"address_line2": null,
"postal_code": null,
"city": null,
"country": null,
"status": "active",
"verified_at": null,
"is_verified": false,
"total_raised": null,
"created_at": "2026-08-05T16:18:32.000000Z",
"platform_fee_flat_cents": null,
"firmenbuchnummer": null,
"uid_number": null,
"uid_validation_status": null,
"payout_method": null,
"stripe_connect_account_id": null,
"connect_charges_enabled": null,
"connect_payouts_enabled": null,
"connect_details_submitted": null,
"connect_requirements_due": null,
"connect_country_code": null
},
"errors": null,
"meta": {
"request_id": "c586e4b9-d8d2-4f0f-b3a1-d4339de77df8",
"timestamp": "2026-08-05T16:18:42.159248Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Updates mutable profile fields on an organisation as an admin.
requires authentication
Only the fields present in the request are applied; absent keys leave existing values untouched (PATCH semantics). Status transitions, bank-detail
changes, and verification metadata are handled by dedicated endpoints. * @group Admin API
Example request:
curl --request PATCH \
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Beispieltext\",
\"description\": \"Beispieltext\",
\"logo_url\": \"Beispieltext\",
\"website\": \"Beispieltext\",
\"address\": \"Beispieltext\",
\"address_line2\": \"Beispieltext\",
\"postal_code\": \"AT\",
\"city\": \"Beispieltext\",
\"country\": \"Beispieltext\",
\"iso_country_code\": \"AT\",
\"platform_fee_flat_cents\": 1,
\"country_code\": \"AT\",
\"phone_number\": \"6641234567\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Beispieltext",
"description": "Beispieltext",
"logo_url": "Beispieltext",
"website": "Beispieltext",
"address": "Beispieltext",
"address_line2": "Beispieltext",
"postal_code": "AT",
"city": "Beispieltext",
"country": "Beispieltext",
"iso_country_code": "AT",
"platform_fee_flat_cents": 1,
"country_code": "AT",
"phone_number": "6641234567"
};
fetch(url, {
method: "PATCH",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d';
$response = $client->patch(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'name' => 'Beispieltext',
'description' => 'Beispieltext',
'logo_url' => 'Beispieltext',
'website' => 'Beispieltext',
'address' => 'Beispieltext',
'address_line2' => 'Beispieltext',
'postal_code' => 'AT',
'city' => 'Beispieltext',
'country' => 'Beispieltext',
'iso_country_code' => 'AT',
'platform_fee_flat_cents' => 1,
'country_code' => 'AT',
'phone_number' => '6641234567',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"name": "Beispieltext",
"description": "Beispieltext",
"logo_url": "Beispieltext",
"website": "Beispieltext",
"address": "Beispieltext",
"address_line2": "Beispieltext",
"postal_code": "AT",
"city": "Beispieltext",
"country": "Beispieltext",
"iso_country_code": "AT",
"platform_fee_flat_cents": 1,
"country_code": "AT",
"phone_number": "6641234567"
};
final response = await http.patch(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Admin-triggered organisation password reset code.
requires authentication
Dispatches the same 6-digit code the org would receive via the public
/api/v1/org/auth/forgot-password endpoint — keeping the reset flow
identical regardless of who initiated it. The admin never sees the code
itself; the org follows the standard forgot-password → verify-code → reset-password path on the company portal.
Use case: an org owner who cannot log in (lost device, lost access to their inbox, etc.) phones Flexxr support, the operator confirms identity out-of-band, and then triggers this endpoint to push a fresh code to the org's primary email — without exposing the code to the operator.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/send-reset" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/send-reset"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/send-reset';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/send-reset');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Password reset email sent.",
"data": null,
"errors": null,
"meta": {
"request_id": "5fdc2a18-95f3-4f95-9f60-dd08aa90ef1a",
"timestamp": "2026-08-05T16:18:42.182780Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Upload Organisation Logo (Admin)
requires authentication
Stores a new logo file for the given organisation and returns the updated profile.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/logo" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "logo=@/tmp/phpnci5g6cgjg6edlqqDWn" const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/logo"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('logo', document.querySelector('input[name="logo"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/logo';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'multipart/form-data',
'Accept' => 'application/json',
],
'multipart' => [
[
'name' => 'logo',
'contents' => fopen('/tmp/phpnci5g6cgjg6edlqqDWn', 'r')
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/logo');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'multipart/form-data',
'Accept': 'application/json',
};
final request = http.MultipartRequest('POST', uri);
request.headers.addAll(headers);
request.files.add(await http.MultipartFile.fromPath('logo', '/tmp/phpnci5g6cgjg6edlqqDWn'));
final streamed = await request.send();
final response = await http.Response.fromStream(streamed);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Logo uploaded successfully.",
"data": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"slug": "caritas-4v1ues",
"email": "caritas-portal@flexxr.eu.cc",
"country_code": "+43",
"phone_number": "6641234567",
"contact_person_name": null,
"contact_person_phone": null,
"iso_country_code": "AT",
"phone_e164": "+436641234567",
"description": "Caritas test organisation used for end-to-end portal QA. Safe to delete.",
"logo_url": "/storage/logos/organizations/QWGcqEq0WGb4VTvFnrdZJoIvCxZThaklKavUGS4l.jpg",
"website": "https://www.caritas.at",
"address": "Albrechtskreithgasse 19-21",
"address_line2": null,
"postal_code": null,
"city": "Vienna",
"country": "Austria",
"status": "active",
"verified_at": "2026-08-05T16:18:17.000000Z",
"is_verified": true,
"total_raised": null,
"created_at": "2026-08-05T16:18:17.000000Z",
"platform_fee_flat_cents": null,
"firmenbuchnummer": null,
"uid_number": null,
"uid_validation_status": null,
"payout_method": null,
"stripe_connect_account_id": null,
"connect_charges_enabled": null,
"connect_payouts_enabled": null,
"connect_details_submitted": null,
"connect_requirements_due": null,
"connect_country_code": null
},
"errors": null,
"meta": {
"request_id": "57d1c22e-3512-4367-8950-b4df2bd39ae3",
"timestamp": "2026-08-05T16:18:42.194784Z"
}
}
Example response (404, Organisation Not Found):
{
"status": "NOT_FOUND",
"message": "No query results for model [Organization].",
"data": null,
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-05-01T10:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "Validation failed.",
"data": null,
"errors": [
{
"field": "logo",
"message": "The logo field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-05-01T10:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Lists the team members of a specific organisation for the admin detail page.
requires authentication
Phase-1 mirrors {@see ListOrgTeamAction}:
the only seat is the organisation principal itself. The shape is
frozen so the admin UI renders today and switches to multi-user
mode the day the organization_members pivot lands.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/team" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/team"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/team';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/team');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [
{
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"organization_id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"email": "caritas-portal@flexxr.eu.cc",
"role": "owner",
"status": "active",
"avatar_url": null,
"is_principal": true,
"joined_at": "2026-08-05T16:18:17+00:00",
"last_active_at": "2026-08-05T16:18:33+00:00"
}
],
"errors": null,
"meta": {
"request_id": "99d177f8-4686-4277-8f80-b2a436581fb7",
"timestamp": "2026-08-05T16:18:42.213358Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Lists every team invitation (pending, accepted, revoked, expired) for a specific organisation. Powers the admin organisation detail page so support can see the invitation funnel without logging in as the org.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/invitations" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/invitations"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/invitations';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/invitations');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [],
"errors": null,
"meta": {
"request_id": "0c3a868f-3ae6-4436-836f-837c0d3bc51b",
"timestamp": "2026-08-05T16:18:42.226051Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Organization Documents
requires authentication
Returns all KYC documents for a given organisation for admin review.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/documents" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/documents"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/documents';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/documents');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Dokumente erfolgreich abgerufen.",
"data": [],
"errors": null,
"meta": {
"request_id": "e0d196cb-4f23-427c-9c6a-50729a4b0ded",
"timestamp": "2026-08-05T16:18:42.237423Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Download Organization Document
requires authentication
Streams an organisation's KYC document for admin review. Streaming works on any disk (local in dev, S3 in prod), unlike temporary signed URLs which the local driver cannot generate.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/documents/019f34d3-5029-7158-a549-910ae39abad5/download" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/documents/019f34d3-5029-7158-a549-910ae39abad5/download"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/documents/019f34d3-5029-7158-a549-910ae39abad5/download';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/documents/019f34d3-5029-7158-a549-910ae39abad5/download');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "970f18dd-d6d1-4695-8764-f8d8a246be22",
"timestamp": "2026-08-21T05:14:36.064793Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Approve Organization Document
requires authentication
Approves a KYC document submitted by an organisation.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/documents/019f34d3-5029-7158-a549-910ae39abad5/approve" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/documents/019f34d3-5029-7158-a549-910ae39abad5/approve"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/documents/019f34d3-5029-7158-a549-910ae39abad5/approve';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/documents/019f34d3-5029-7158-a549-910ae39abad5/approve');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reject Organization Document
requires authentication
Rejects a KYC document submitted by an organisation, with a mandatory reason.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/documents/019f34d3-5029-7158-a549-910ae39abad5/reject" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Krankheitsbedingt kurzfristig abgesagt.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/documents/019f34d3-5029-7158-a549-910ae39abad5/reject"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/documents/019f34d3-5029-7158-a549-910ae39abad5/reject';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'Krankheitsbedingt kurzfristig abgesagt.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/documents/019f34d3-5029-7158-a549-910ae39abad5/reject');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Organization Document Requests
requires authentication
Lists all document requests raised for a given organisation.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/document-requests" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/document-requests"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/document-requests';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/document-requests');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Dokumentanforderungen erfolgreich abgerufen.",
"data": [],
"errors": null,
"meta": {
"request_id": "56675c8c-b427-4505-84a4-47ecf293ff7c",
"timestamp": "2026-08-05T16:18:42.280175Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Request Organization Documents
requires authentication
Raises a new document request for an organisation, optionally specifying a message and due date.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/document-requests" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"document_types\": null,
\"message\": \"Bitte um Rueckmeldung zur naechsten Schicht.\",
\"due_at\": \"2026-09-30\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/document-requests"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"document_types": null,
"message": "Bitte um Rueckmeldung zur naechsten Schicht.",
"due_at": "2026-09-30"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/document-requests';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'document_types' => null,
'message' => 'Bitte um Rueckmeldung zur naechsten Schicht.',
'due_at' => '2026-09-30',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/document-requests');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"document_types": null,
"message": "Bitte um Rueckmeldung zur naechsten Schicht.",
"due_at": "2026-09-30"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Cancel Organization Document Request
requires authentication
Withdraws an open document request before the organisation fulfils it.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/document-requests/019f37d2-a096-72da-ba50-ba5a5a9674fe" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/document-requests/019f37d2-a096-72da-ba50-ba5a5a9674fe"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/document-requests/019f37d2-a096-72da-ba50-ba5a5a9674fe';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/organizations/019f0593-c95d-73f3-aced-b962c9664f8d/document-requests/019f37d2-a096-72da-ba50-ba5a5a9674fe');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Employees
List Pending Employees
requires authentication
List employees pending approval.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/employees/pending" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/employees/pending"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/employees/pending';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/employees/pending');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"employees": [
{
"id": "019fd2b8-29d1-7181-a321-e1d4deee8590",
"user_id": "019fd2b8-29cf-7133-8ff2-ec12d31edb4d",
"status": "pending_approval",
"status_label": "Genehmigung ausstehend",
"profile_completion_percentage": 100,
"svs_number": "1706010190",
"nationality": "AT",
"city": "West Ignatius",
"user": {
"id": "019fd2b8-29cf-7133-8ff2-ec12d31edb4d",
"name": "Chelsey Larkin",
"email": "umurphy@example.net",
"phone": null
},
"created_at": "2026-08-05 16:18",
"updated_at": "2026-08-05 16:18"
}
],
"summary": {
"pending_approval": 1,
"correction_required": 0
},
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 20,
"total": 1
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Show Employee Review
requires authentication
Show an employee's profile for admin review.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/employees/019f9939-c4c3-70fb-a54e-5ebf63db36d2/review" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/employees/019f9939-c4c3-70fb-a54e-5ebf63db36d2/review"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/employees/019f9939-c4c3-70fb-a54e-5ebf63db36d2/review';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/employees/019f9939-c4c3-70fb-a54e-5ebf63db36d2/review');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"profile": {
"id": "019fd2b7-f279-7142-a68d-0d4563a06070",
"user_id": "019fd2b7-f271-73fd-8268-848be381e136",
"status": "active",
"status_label": "Aktiv",
"status_reason": null,
"suspended_reason": null,
"suspended_until": null,
"profile_completion_percentage": 0,
"svs_number": "5678200895",
"date_of_birth": "1995-08-20",
"place_of_birth": null,
"nationality": "AT",
"gender": null,
"legal_first_name": null,
"legal_last_name": null,
"middle_names": null,
"previous_last_names": null,
"citizenship_primary": null,
"citizenship_additional": null,
"residence_status": null,
"residence_status_label": null,
"country_of_birth": null,
"tax_id_set": false,
"tax_number_set": false,
"finanz_online_registered": false,
"alternate_email": null,
"street": "Neugasse 5",
"house_number": null,
"postal_code": "4020",
"city": "Linz",
"country": "AT",
"correction_fields": null,
"profile_picture_url": null,
"preferred_radius_km": null,
"bio": null,
"marketing_consent": null,
"gdpr_consent": null,
"created_at": "2026-08-05 16:18",
"updated_at": "2026-08-05 16:18"
},
"user": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"first_name": "Anna",
"last_name": "Neuling",
"email": "pending@demo.flexxr.at",
"phone": "+436769876543",
"email_verified": true
},
"documents": [
{
"id": "019fd2b7-f280-73fe-83af-4fdd5f9db332",
"type": "id_card",
"type_label": "ID card",
"filename": "ausweis.pdf",
"file_url": "/storage/documents/demo/ausweis.pdf",
"thumbnail_url": null,
"status": "pending",
"status_label": "Ausstehend",
"rejection_reason": null,
"expires_at": null,
"is_expired": false,
"virus_scanned_at": null,
"ocr_name_match_score": null,
"ocr_confidence": null,
"needs_review": false,
"discrepancies": [],
"created_at": "2026-08-05 16:18"
},
{
"id": "019fd2b8-28ce-735c-aa32-c03c49655e69",
"type": "passport",
"type_label": "Passport",
"filename": "veniam.pdf",
"file_url": "/storage/employee/917d038a-c64d-30e4-8416-39aca59dc516/passport/2026/06/13/29374d0b-28b0-36d0-9ee2-bac06a7bb554.pdf",
"thumbnail_url": null,
"status": "verified",
"status_label": "Verifiziert",
"rejection_reason": null,
"expires_at": "2033-05-22",
"is_expired": false,
"virus_scanned_at": null,
"ocr_name_match_score": null,
"ocr_confidence": null,
"needs_review": false,
"discrepancies": [],
"created_at": "2026-08-05 16:18"
}
],
"qualifications": [],
"bank_accounts": [],
"emergency_contacts": [],
"checklist": {
"email_verified": true,
"id_document_uploaded": true,
"bank_account_added": false,
"svs_number_provided": true,
"profile_complete": false,
"work_permit_valid": true
},
"work_permit": {
"required": false,
"expires_at": null,
"is_expired": false,
"days_until_expiry": null
},
"shifts": [
{
"assignment": {
"id": "019fd2b8-28d3-70d7-92eb-f1bb1577acaf",
"status": "signed",
"status_label": "Unterschrieben",
"shift_date": "2026-08-06",
"scheduled_start_time": "08:00:00",
"scheduled_end_time": "16:00:00",
"location_name": "Nolan-Roberts",
"location_address": "4309 O'Reilly Way Suite 012",
"hourly_rate_gross": "34.72",
"started_at": null,
"completed_at": null,
"job": {
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant"
},
"employee": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"name": "Anna Neuling"
},
"contract": null,
"attendance": null,
"rating": null
},
"timeline": [
{
"event_type": "assignment.created",
"actor": "system",
"title": "Assignment created",
"description": "Assignment was created from job selection.",
"occurred_at": "2026-08-05T16:18:32+00:00",
"path": "/hours"
}
]
},
{
"assignment": {
"id": "019fd2b8-28d8-728d-a447-8de1a42eec83",
"status": "checked_in",
"status_label": "Eingecheckt",
"shift_date": "2026-08-05",
"scheduled_start_time": "11:58:00",
"scheduled_end_time": "12:13:00",
"location_name": "Goldner and Sons",
"location_address": "30005 Prosacco Orchard",
"hourly_rate_gross": "18.57",
"started_at": null,
"completed_at": null,
"job": {
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant"
},
"employee": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"name": "Anna Neuling"
},
"contract": null,
"attendance": null,
"rating": null
},
"timeline": [
{
"event_type": "assignment.created",
"actor": "system",
"title": "Assignment created",
"description": "Assignment was created from job selection.",
"occurred_at": "2026-08-05T16:18:32+00:00",
"path": "/hours"
}
]
},
{
"assignment": {
"id": "019fd2b8-28d1-7112-b8e9-68bd79fbafb9",
"status": "awaiting_signature",
"status_label": "Unterschrift ausstehend",
"shift_date": "2026-08-04",
"scheduled_start_time": "16:57:00",
"scheduled_end_time": "09:21:00",
"location_name": "Buckridge-Collier",
"location_address": "661 Cayla Unions Suite 344",
"hourly_rate_gross": "27.68",
"started_at": null,
"completed_at": null,
"job": {
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant"
},
"employee": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"name": "Anna Neuling"
},
"contract": null,
"attendance": null,
"rating": null
},
"timeline": [
{
"event_type": "assignment.created",
"actor": "system",
"title": "Assignment created",
"description": "Assignment was created from job selection.",
"occurred_at": "2026-08-05T16:18:32+00:00",
"path": "/hours"
}
]
},
{
"assignment": {
"id": "019fd2b8-28df-7265-8b1e-cb5de026e4d7",
"status": "completed",
"status_label": "Abgeschlossen",
"shift_date": "2026-08-03",
"scheduled_start_time": "08:31:00",
"scheduled_end_time": "05:12:00",
"location_name": "Wehner Inc",
"location_address": "45222 Hansen Gardens",
"hourly_rate_gross": "18.25",
"started_at": null,
"completed_at": null,
"job": {
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant"
},
"employee": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"name": "Anna Neuling"
},
"contract": null,
"attendance": null,
"rating": null
},
"timeline": [
{
"event_type": "assignment.created",
"actor": "system",
"title": "Assignment created",
"description": "Assignment was created from job selection.",
"occurred_at": "2026-08-05T16:18:32+00:00",
"path": "/hours"
}
]
}
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Approve Employee
requires authentication
Approve an employee's profile.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/employees/019f9939-c4c3-70fb-a54e-5ebf63db36d2/approve" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"note\": \"Beispieltext\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/employees/019f9939-c4c3-70fb-a54e-5ebf63db36d2/approve"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"note": "Beispieltext"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/employees/019f9939-c4c3-70fb-a54e-5ebf63db36d2/approve';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'note' => 'Beispieltext',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/employees/019f9939-c4c3-70fb-a54e-5ebf63db36d2/approve');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"note": "Beispieltext"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The employee has been approved successfully.",
"data": {
"employee_id": "019fd2b8-29d1-7181-a321-e1d4deee8590",
"status": "active"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reject Employee
requires authentication
Reject an employee's application.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/employees/019f9939-c4c3-70fb-a54e-5ebf63db36d2/reject" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Krankheitsbedingt kurzfristig abgesagt.\",
\"reason_code\": \"documents_invalid\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/employees/019f9939-c4c3-70fb-a54e-5ebf63db36d2/reject"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt.",
"reason_code": "documents_invalid"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/employees/019f9939-c4c3-70fb-a54e-5ebf63db36d2/reject';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'Krankheitsbedingt kurzfristig abgesagt.',
'reason_code' => 'documents_invalid',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/employees/019f9939-c4c3-70fb-a54e-5ebf63db36d2/reject');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt.",
"reason_code": "documents_invalid"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The employee application has been rejected.",
"data": {
"employee_id": "019fd2b8-29d1-7181-a321-e1d4deee8590",
"status": "rejected"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Request Correction
requires authentication
Request correction from employee before approval.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/employees/019f9939-c4c3-70fb-a54e-5ebf63db36d2/request-correction" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Krankheitsbedingt kurzfristig abgesagt.\",
\"fields_requiring_correction\": null
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/employees/019f9939-c4c3-70fb-a54e-5ebf63db36d2/request-correction"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt.",
"fields_requiring_correction": null
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/employees/019f9939-c4c3-70fb-a54e-5ebf63db36d2/request-correction';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'Krankheitsbedingt kurzfristig abgesagt.',
'fields_requiring_correction' => null,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/employees/019f9939-c4c3-70fb-a54e-5ebf63db36d2/request-correction');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt.",
"fields_requiring_correction": null
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Correction request has been sent to the employee.",
"data": {
"employee_id": "019fd2b8-29d1-7181-a321-e1d4deee8590",
"status": "correction_required"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Approve Document
requires authentication
Approve (verify) an employee document during admin review.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/employees/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2/approve" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/employees/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2/approve"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/employees/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2/approve';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/employees/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2/approve');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The document has been verified.",
"data": {
"document_id": "019fd2b8-6103-7134-bdc4-ac4ec15c8ab5",
"status": "verified"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reject Document
requires authentication
Reject an employee document during admin review. A reason is mandatory and is surfaced to the employee so they know what to fix.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/employees/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2/reject" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Krankheitsbedingt kurzfristig abgesagt.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/employees/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2/reject"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/employees/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2/reject';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'Krankheitsbedingt kurzfristig abgesagt.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/employees/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2/reject');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The document has been rejected.",
"data": {
"document_id": "019fd2b8-6352-7026-9ee5-f2087fc25f75",
"status": "rejected",
"rejection_reason": "Das Dokument ist unleserlich. Bitte erneut hochladen."
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Verify Qualification
requires authentication
Marks a worker's self-reported qualification as verified. Until an admin does this the qualification counts as the worker's own claim — the mobile app shows it without the verified badge.
An expired qualification cannot be verified: what would be confirmed is no longer in force.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/employees/qualifications/019f9939-c4c3-70fb-a54e-5ebf63db36d2/verify" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/employees/qualifications/019f9939-c4c3-70fb-a54e-5ebf63db36d2/verify"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/employees/qualifications/019f9939-c4c3-70fb-a54e-5ebf63db36d2/verify';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/employees/qualifications/019f9939-c4c3-70fb-a54e-5ebf63db36d2/verify');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The qualification has been verified.",
"data": {
"qualification_id": "019fd41b-439a-727b-bdab-d37f8d7ca5f0",
"is_verified": true
}
}
Example response (422, Already expired):
{
"status": "INVALID_OPERATION",
"message": "Diese Qualifikation ist abgelaufen. Bitte erneuern Sie sie."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reject Qualification
requires authentication
Refuses to verify a qualification — or withdraws a verification already given, when it turns out to have been wrong. The row stays on the worker's profile as their own claim; the reason is sent to them so they know what to fix.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/employees/qualifications/019f9939-c4c3-70fb-a54e-5ebf63db36d2/reject" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Der Nachweis ist nicht lesbar.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/employees/qualifications/019f9939-c4c3-70fb-a54e-5ebf63db36d2/reject"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Der Nachweis ist nicht lesbar."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/employees/qualifications/019f9939-c4c3-70fb-a54e-5ebf63db36d2/reject';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'Der Nachweis ist nicht lesbar.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/employees/qualifications/019f9939-c4c3-70fb-a54e-5ebf63db36d2/reject');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "Der Nachweis ist nicht lesbar."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Verification of the qualification has been declined.",
"data": {
"qualification_id": "019fd41b-439a-727b-bdab-d37f8d7ca5f0",
"is_verified": false
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Jobs
List All Jobs
requires authentication
List all job listings across all organizations for admin oversight.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/jobs" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/jobs"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/jobs';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/jobs');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"jobs": [
{
"id": "019fd2b8-28e8-73a4-94d6-5a423c21f064",
"title": "Foundry Mold and Coremaker",
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"status": "active"
},
"category": "software",
"category_label": "Software",
"status": "draft",
"status_label": "Entwurf",
"status_color": "gray",
"location_city": "South Zachery",
"start_date": "2026-08-29",
"end_date": "2026-09-25",
"shift_start_time": "16:30:00",
"shift_end_time": "14:33:00",
"total_vacancies": 10,
"filled_vacancies": 0,
"hourly_rate_gross": 29.86,
"applications_count": 0,
"shifts_count": 0,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:32+00:00"
},
{
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant",
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"status": "active"
},
"category": "office",
"category_label": "Büro",
"status": "active",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "East Eliseo",
"start_date": "2026-08-12",
"end_date": "2026-08-19",
"shift_start_time": "01:49:00",
"shift_end_time": "18:57:00",
"total_vacancies": 5,
"filled_vacancies": 0,
"hourly_rate_gross": 32.08,
"applications_count": 1,
"shifts_count": 4,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:32+00:00"
},
{
"id": "019fd2b8-28ee-71e0-b50d-2c303c17f728",
"title": "Kindergarten Teacher",
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"status": "active"
},
"category": "warehouse",
"category_label": "Lager",
"status": "pending_review",
"status_label": "In Prüfung",
"status_color": "yellow",
"location_city": "Eldahaven",
"start_date": "2026-08-21",
"end_date": "2026-09-15",
"shift_start_time": "06:44:00",
"shift_end_time": "06:04:00",
"total_vacancies": 1,
"filled_vacancies": 0,
"hourly_rate_gross": 18.4,
"applications_count": 0,
"shifts_count": 0,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:32+00:00"
},
{
"id": "019fd2b8-2705-73fd-a401-002956f1f401",
"title": "Fahrer*in Zustelldienst Wien Nord",
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"status": "active"
},
"category": "logistics",
"category_label": "Logistik",
"status": "published",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-14",
"end_date": "2026-08-15",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"total_vacancies": 4,
"filled_vacancies": 0,
"hourly_rate_gross": 15,
"applications_count": 0,
"shifts_count": 0,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:31+00:00"
},
{
"id": "019fd2b8-2599-7355-a7f1-dcb185b05faa",
"title": "Rezeptionist*in Hotel Sacher",
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"status": "active"
},
"category": "hotel",
"category_label": "Hotellerie",
"status": "published",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-17",
"end_date": "2026-08-19",
"shift_start_time": "09:00:00",
"shift_end_time": "17:00:00",
"total_vacancies": 4,
"filled_vacancies": 0,
"hourly_rate_gross": 17.5,
"applications_count": 51,
"shifts_count": 0,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:31+00:00"
},
{
"id": "019fd2b8-24b0-700a-ae2a-142f5e48aead",
"title": "Lagerhelfer*in Logistikzentrum Inzersdorf",
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"status": "active"
},
"category": "warehouse",
"category_label": "Lager",
"status": "published",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-12",
"end_date": "2026-08-14",
"shift_start_time": "22:00:00",
"shift_end_time": "06:00:00",
"total_vacancies": 15,
"filled_vacancies": 0,
"hourly_rate_gross": 14.8,
"applications_count": 29,
"shifts_count": 0,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:31+00:00"
},
{
"id": "019fd2b8-270a-71f9-a13c-ef188105041c",
"title": "Reinigungskraft Hotel Ibis Mariahilf",
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"status": "active"
},
"category": "cleaning",
"category_label": "Reinigung",
"status": "published",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-16",
"end_date": "2026-08-17",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"total_vacancies": 3,
"filled_vacancies": 0,
"hourly_rate_gross": 13.2,
"applications_count": 0,
"shifts_count": 0,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:31+00:00"
},
{
"id": "019fd2b8-26fb-7142-b3a3-df10c3591584",
"title": "Küchenhilfe Streetfood Festival Naschmarkt",
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"status": "active"
},
"category": "catering",
"category_label": "Catering",
"status": "published",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-13",
"end_date": "2026-08-14",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"total_vacancies": 6,
"filled_vacancies": 0,
"hourly_rate_gross": 13,
"applications_count": 0,
"shifts_count": 0,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:31+00:00"
},
{
"id": "019fd2b8-270f-715d-a3a0-76c4c314e3ff",
"title": "Verkäufer*in Elektronik Mediamarkt Vösendorf",
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"status": "active"
},
"category": "retail",
"category_label": "Einzelhandel",
"status": "published",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Vösendorf",
"start_date": "2026-08-20",
"end_date": "2026-08-21",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"total_vacancies": 7,
"filled_vacancies": 0,
"hourly_rate_gross": 14,
"applications_count": 0,
"shifts_count": 0,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:31+00:00"
},
{
"id": "019fd2b8-2700-724b-adc5-2be8957e0590",
"title": "Kassierer*in Supermarkt Floridsdorf",
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"status": "active"
},
"category": "supermarket",
"category_label": "Lebensmittelhandel",
"status": "published",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-11",
"end_date": "2026-08-12",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"total_vacancies": 5,
"filled_vacancies": 0,
"hourly_rate_gross": 13.5,
"applications_count": 0,
"shifts_count": 0,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:31+00:00"
},
{
"id": "019fd2b8-21c8-72cc-80b1-47fd13450522",
"title": "Barkeeper*in Sommernacht Open Air",
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"status": "active"
},
"category": "gastro",
"category_label": "Gastronomie",
"status": "published",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-15",
"end_date": "2026-08-17",
"shift_start_time": "22:00:00",
"shift_end_time": "06:00:00",
"total_vacancies": 8,
"filled_vacancies": 0,
"hourly_rate_gross": 16,
"applications_count": 38,
"shifts_count": 0,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:30+00:00"
},
{
"id": "019fd2b8-22cf-71c5-8edd-5e3ce9d29e8b",
"title": "Promoter*in Vienna Marathon",
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"status": "active"
},
"category": "event",
"category_label": "Events",
"status": "published",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-26",
"end_date": "2026-08-28",
"shift_start_time": "09:00:00",
"shift_end_time": "17:00:00",
"total_vacancies": 20,
"filled_vacancies": 0,
"hourly_rate_gross": 13.5,
"applications_count": 62,
"shifts_count": 0,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:30+00:00"
},
{
"id": "019fd2b8-1f86-7376-9a3a-c072ab5675cb",
"title": "Service-Mitarbeiter*in Wiener Prater Festival",
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"status": "active"
},
"category": "gastro",
"category_label": "Gastronomie",
"status": "published",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-19",
"end_date": "2026-08-21",
"shift_start_time": "09:00:00",
"shift_end_time": "17:00:00",
"total_vacancies": 12,
"filled_vacancies": 0,
"hourly_rate_gross": 15.5,
"applications_count": 45,
"shifts_count": 0,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:29+00:00"
},
{
"id": "019fd2b8-1dcd-734a-a041-f809f58e95fb",
"title": "IT Supportkraft Vertretung",
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"status": "active"
},
"category": "it_services",
"category_label": "IT Services",
"status": "pending_review",
"status_label": "In Prüfung",
"status_color": "yellow",
"location_city": "Wien",
"start_date": "2026-08-20",
"end_date": "2026-09-04",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"total_vacancies": 2,
"filled_vacancies": 0,
"hourly_rate_gross": 22,
"applications_count": 0,
"shifts_count": 0,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:29+00:00"
},
{
"id": "019fd2b8-1dc8-7078-bcc2-07c7297ffa47",
"title": "Nachtschicht Lager Q4",
"organization": {
"id": "019fd2b7-f91f-70cb-8409-8632db9df3c7",
"name": "Sicherheitsdienst Österreich",
"status": "active"
},
"category": "logistics",
"category_label": "Logistik",
"status": "draft",
"status_label": "Entwurf",
"status_color": "gray",
"location_city": "Graz",
"start_date": "2026-12-03",
"end_date": "2027-02-01",
"shift_start_time": "22:00:00",
"shift_end_time": "06:00:00",
"total_vacancies": 20,
"filled_vacancies": 0,
"hourly_rate_gross": 15.5,
"applications_count": 0,
"shifts_count": 0,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:29+00:00"
},
{
"id": "019fd2b8-1d92-7277-aa77-7172270002a5",
"title": "Qualitätskontrolle Lebensmittel",
"organization": {
"id": "019fd2b7-f4d3-71a1-89d4-ca7d5731b32a",
"name": "Wiener Gastro GmbH",
"status": "active"
},
"category": "production",
"category_label": "Produktion",
"status": "active",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Graz",
"start_date": "2026-08-08",
"end_date": "2026-10-04",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"total_vacancies": 4,
"filled_vacancies": 0,
"hourly_rate_gross": 15.5,
"applications_count": 8,
"shifts_count": 2,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:29+00:00"
},
{
"id": "019fd2b8-1dc6-72cc-acac-502231efcb6b",
"title": "Messehostess Herbstmesse",
"organization": {
"id": "019fd2b7-f91f-70cb-8409-8632db9df3c7",
"name": "Sicherheitsdienst Österreich",
"status": "active"
},
"category": "event",
"category_label": "Events",
"status": "draft",
"status_label": "Entwurf",
"status_color": "gray",
"location_city": "Wien",
"start_date": "2026-11-03",
"end_date": "2026-11-08",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"total_vacancies": 10,
"filled_vacancies": 0,
"hourly_rate_gross": 14,
"applications_count": 0,
"shifts_count": 0,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:29+00:00"
},
{
"id": "019fd2b8-1dcb-73f4-9257-e7fa42fe8514",
"title": "Sommerfest Catering",
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"status": "active"
},
"category": "catering",
"category_label": "Catering",
"status": "pending_review",
"status_label": "In Prüfung",
"status_color": "yellow",
"location_city": "Wien",
"start_date": "2026-09-24",
"end_date": "2026-09-25",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"total_vacancies": 12,
"filled_vacancies": 0,
"hourly_rate_gross": 15,
"applications_count": 0,
"shifts_count": 0,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:29+00:00"
},
{
"id": "019fd2b8-1d1e-7188-9438-b0d6050c492a",
"title": "Kursleiter*in Deutschkurs",
"organization": {
"id": "019fd2b8-00e8-7186-8fa6-5b042a30b10d",
"name": "Transport & Spedition GmbH",
"status": "active"
},
"category": "education",
"category_label": "Bildung",
"status": "active",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-12",
"end_date": "2026-11-03",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"total_vacancies": 3,
"filled_vacancies": 0,
"hourly_rate_gross": 18,
"applications_count": 6,
"shifts_count": 2,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:29+00:00"
},
{
"id": "019fd2b8-1d4e-71d9-aad9-3d9f47a96e48",
"title": "Ausstellungsführer Museum",
"organization": {
"id": "019fd2b7-fbb4-73fa-b801-e0c8a8de2651",
"name": "Bauwerk GmbH",
"status": "active"
},
"category": "education",
"category_label": "Bildung",
"status": "active",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-15",
"end_date": "2027-02-01",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"total_vacancies": 4,
"filled_vacancies": 0,
"hourly_rate_gross": 15,
"applications_count": 7,
"shifts_count": 1,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:29+00:00"
},
{
"id": "019fd2b8-1ce9-736a-9a61-22cea78283c9",
"title": "Support-Techniker Außeneinsatz",
"organization": {
"id": "019fd2b7-f91f-70cb-8409-8632db9df3c7",
"name": "Sicherheitsdienst Österreich",
"status": "active"
},
"category": "it_services",
"category_label": "IT Services",
"status": "active",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Graz",
"start_date": "2026-08-12",
"end_date": "2026-10-04",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"total_vacancies": 2,
"filled_vacancies": 0,
"hourly_rate_gross": 20,
"applications_count": 4,
"shifts_count": 2,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:29+00:00"
},
{
"id": "019fd2b8-1d3f-7297-8384-35d386f1454b",
"title": "Schulassistenz Volksschule",
"organization": {
"id": "019fd2b7-f5ae-7390-a778-c08c8d56cdc0",
"name": "Event Solutions Austria",
"status": "active"
},
"category": "education",
"category_label": "Bildung",
"status": "active",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-08",
"end_date": "2026-11-03",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"total_vacancies": 2,
"filled_vacancies": 0,
"hourly_rate_gross": 15.5,
"applications_count": 3,
"shifts_count": 1,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:29+00:00"
},
{
"id": "019fd2b8-1ccb-7322-8d33-448afd9b027b",
"title": "Testingenieur Vertretung",
"organization": {
"id": "019fd2b7-f842-71ba-a318-a919a24d4bcf",
"name": "Hotel & Spa Imperial",
"status": "active"
},
"category": "it_services",
"category_label": "IT Services",
"status": "active",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-15",
"end_date": "2026-09-04",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"total_vacancies": 1,
"filled_vacancies": 0,
"hourly_rate_gross": 25,
"applications_count": 6,
"shifts_count": 1,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:29+00:00"
},
{
"id": "019fd2b8-1dad-7375-b680-f51dcff486d0",
"title": "Verpackungshelfer*in",
"organization": {
"id": "019fd2b8-00e8-7186-8fa6-5b042a30b10d",
"name": "Transport & Spedition GmbH",
"status": "active"
},
"category": "production",
"category_label": "Produktion",
"status": "filled",
"status_label": "Besetzt",
"status_color": "purple",
"location_city": "Wien",
"start_date": "2026-07-29",
"end_date": "2026-08-03",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"total_vacancies": 8,
"filled_vacancies": 8,
"hourly_rate_gross": 14.5,
"applications_count": 4,
"shifts_count": 1,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:29+00:00"
},
{
"id": "019fd2b8-1d03-71ce-9e17-21e92ae7b9d7",
"title": "Netzwerktechniker Hotline",
"organization": {
"id": "019fd2b7-fbb4-73fa-b801-e0c8a8de2651",
"name": "Bauwerk GmbH",
"status": "active"
},
"category": "software",
"category_label": "Software",
"status": "filled",
"status_label": "Besetzt",
"status_color": "purple",
"location_city": "Wien",
"start_date": "2026-07-31",
"end_date": "2026-08-03",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"total_vacancies": 3,
"filled_vacancies": 3,
"hourly_rate_gross": 21,
"applications_count": 3,
"shifts_count": 1,
"has_compliance_warning": false,
"is_deleted": false,
"created_at": "2026-08-05T16:18:29+00:00"
}
],
"pagination": {
"current_page": 1,
"last_page": 6,
"per_page": 25,
"total": 133
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Show Job
requires authentication
Show detailed job information for admin review.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"job": {
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant",
"description": "Ut nostrum rerum ut alias quia libero excepturi. Voluptatum et aut non quia quisquam molestias. Perferendis qui hic unde.",
"category": "office",
"category_label": "Büro",
"status": "active",
"status_label": "Aktiv",
"status_color": "green",
"shift_type": "night",
"shift_type_label": "Nachtschicht",
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"status": "active",
"email": "caritas-portal@flexxr.eu.cc"
},
"location": {
"name": "Barrows, Christiansen and Jones",
"address": "586 Tremaine Row",
"city": "East Eliseo",
"postal_code": "10547-3697",
"lat": 46.931383,
"lng": 11.998284
},
"schedule": {
"start_date": "2026-08-12",
"end_date": "2026-08-19",
"shift_start_time": "01:49:00",
"shift_end_time": "18:57:00",
"application_deadline": "2026-09-05",
"confirmation_deadline": "2026-08-16",
"sign_window_hours": 24
},
"vacancies": {
"total": 5,
"filled": 0,
"available": 5
},
"compensation": {
"hourly_rate_gross": 32.08,
"supplements": {
"night": 0.7,
"weekend": 3.86
},
"estimated_total_gross": null
},
"requirements": {
"qualifications": [],
"dress_code": "Tempore necessitatibus quia illo suscipit.",
"equipment_provided": "Adipisci fugiat doloremque atque consectetur necessitatibus sunt cumque.",
"job_requirements": [
{
"type": "document",
"code": "passport",
"name": "Reisepass",
"is_mandatory": true
},
{
"type": "document",
"code": "driver_license",
"name": "Führerschein",
"is_mandatory": true
}
]
},
"contact": {
"parking_info": null,
"special_instructions": null
},
"review": {
"submitted_at": null,
"reviewed_at": null,
"rejection_note": null,
"submit_count": 0
},
"compliance": {
"has_warning": false,
"warnings": []
},
"timestamps": {
"published_at": null,
"filled_at": null,
"cancelled_at": null,
"deleted_at": null,
"created_at": "2026-08-05T16:18:32+00:00",
"updated_at": "2026-08-05T16:18:32+00:00"
},
"cancellation_reason": null,
"is_deleted": false,
"stats": {
"applications_count": 1,
"shifts_count": 4
},
"applications": [
{
"id": "019fd2b8-28c6-73d1-b719-dae19c4d443c",
"user": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"name": "Anna Neuling",
"email": "pending@demo.flexxr.at"
},
"status": "selected",
"applied_at": "2026-08-05T16:18:32+00:00"
}
],
"shifts": [
{
"id": "019fd2b8-28df-7265-8b1e-cb5de026e4d7",
"user_id": "019fd2b7-f271-73fd-8268-848be381e136",
"status": "completed",
"date": "2026-08-03",
"clock_in_at": null,
"clock_out_at": null
},
{
"id": "019fd2b8-28d1-7112-b8e9-68bd79fbafb9",
"user_id": "019fd2b7-f271-73fd-8268-848be381e136",
"status": "awaiting_signature",
"date": "2026-08-04",
"clock_in_at": null,
"clock_out_at": null
},
{
"id": "019fd2b8-28d8-728d-a447-8de1a42eec83",
"user_id": "019fd2b7-f271-73fd-8268-848be381e136",
"status": "checked_in",
"date": "2026-08-05",
"clock_in_at": null,
"clock_out_at": null
},
{
"id": "019fd2b8-28d3-70d7-92eb-f1bb1577acaf",
"user_id": "019fd2b7-f271-73fd-8268-848be381e136",
"status": "signed",
"date": "2026-08-06",
"clock_in_at": null,
"clock_out_at": null
}
],
"planned_shifts": [
{
"id": "019fd2b8-28d5-7103-b951-9f6ff1d94556",
"shift_date": "2026-08-05",
"start_time": "08:00",
"end_time": "16:00",
"break_minutes": 30,
"workers_needed": 2,
"shift_manager_name": null,
"notes": null,
"dress_code": null,
"contact_person_name": null,
"contact_person_phone": null,
"meeting_point": null,
"geofence": null,
"application_deadline": null
}
]
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Approve Job
requires authentication
POST /admin/jobs/{job}/approve
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/approve" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/approve"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/approve';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/approve');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The job has been approved and published.",
"data": {
"id": "019fd2b8-6bb5-7113-b62c-7434d5f44733",
"status": "active",
"status_label": "Aktiv",
"published_at": "2026-08-05 16:18"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reject Job
requires authentication
POST /admin/jobs/{job}/reject
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/reject" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"note\": \"Beispieltext\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/reject"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"note": "Beispieltext"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/reject';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'note' => 'Beispieltext',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/reject');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"note": "Beispieltext"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The job has been rejected. The company can edit and resubmit it.",
"data": {
"id": "019fd2b8-70e9-7002-b15b-8db7f766386d",
"status": "rejected",
"status_label": "Abgelehnt",
"rejection_note": "Der Stundensatz liegt unter dem Kollektivvertrag."
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Force Close Job
requires authentication
Emergency close a job listing by admin.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/force-close" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Krankheitsbedingt kurzfristig abgesagt.\",
\"notify_employees\": true,
\"notify_organization\": true
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/force-close"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt.",
"notify_employees": true,
"notify_organization": true
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/force-close';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'Krankheitsbedingt kurzfristig abgesagt.',
'notify_employees' => true,
'notify_organization' => true,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/force-close');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt.",
"notify_employees": true,
"notify_organization": true
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "messages.job_force_closed",
"data": {
"job_id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"affected_shifts_count": 2,
"affected_shifts": [
{
"shift_id": "019fd2b8-28d1-7112-b8e9-68bd79fbafb9",
"user_id": "019fd2b7-f271-73fd-8268-848be381e136",
"user_email": "pending@demo.flexxr.at"
},
{
"shift_id": "019fd2b8-28d3-70d7-92eb-f1bb1577acaf",
"user_id": "019fd2b7-f271-73fd-8268-848be381e136",
"user_email": "pending@demo.flexxr.at"
}
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Toggle Job Featured
requires authentication
Sets or flips whether a job is featured on the home screen. Pass
is_featured to set an explicit value, or omit it to flip the
current value.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/admin/jobs/019f1584-1555-72af-96c3-88f3f979d25c/featured" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"is_featured\": true
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/jobs/019f1584-1555-72af-96c3-88f3f979d25c/featured"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"is_featured": true
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/jobs/019f1584-1555-72af-96c3-88f3f979d25c/featured';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'is_featured' => true,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/jobs/019f1584-1555-72af-96c3-88f3f979d25c/featured');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"is_featured": true
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Settings
List Settings
requires authentication
Returns all application settings, optionally filtered by group.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/settings?group=general&per_page=15" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/settings"
);
const params = {
"group": "general",
"per_page": "15",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/settings';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'group' => 'general',
'per_page' => '15',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/settings')
.replace(queryParameters: {
'group': 'general',
'per_page': '15',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [],
"errors": null,
"meta": {
"request_id": "4e6a4f9a-ecc4-4ca9-b4ea-292f901c07e7",
"timestamp": "2026-08-05T16:18:42.512221Z",
"current_page": 1,
"last_page": 1,
"per_page": 15,
"total": 0
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Bulk-update application settings in a single transactional request.
requires authentication
Used by the admin Settings page to save a whole tab (e.g. "Stripe", "Mail")
at once. Per-row payloads are individually validated against each setting's
validation rules, and the entire batch is rolled back if any row fails
authorisation or validation.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/admin/settings" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"settings\": null
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/settings"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"settings": null
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/settings';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'settings' => null,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/settings');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"settings": null
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Bulk-update application settings in a single transactional request.
requires authentication
Used by the admin Settings page to save a whole tab (e.g. "Stripe", "Mail")
at once. Per-row payloads are individually validated against each setting's
validation rules, and the entire batch is rolled back if any row fails
authorisation or validation.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/settings/bulk" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"settings\": null
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/settings/bulk"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"settings": null
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/settings/bulk';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'settings' => null,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/settings/bulk');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"settings": null
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reveal the cleartext value of a secret setting.
requires authentication
Super-admin only; every reveal is audit-logged with admin id, ip, user-agent, and timestamp. Clients should treat the returned value as one-shot — re-displaying it requires another reveal call.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/settings/app.name/reveal" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/settings/app.name/reveal"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/settings/app.name/reveal';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/settings/app.name/reveal');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Setting value revealed.",
"data": {
"key": "app.name",
"value": "Flexxer Backend"
},
"errors": null,
"meta": {
"request_id": "df0d0749-d201-42cf-aa40-f250f25d2b49",
"timestamp": "2026-08-05T16:18:42.552956Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reveal the cleartext value of a secret setting.
requires authentication
Super-admin only; every reveal is audit-logged with admin id, ip, user-agent, and timestamp. Clients should treat the returned value as one-shot — re-displaying it requires another reveal call.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/settings/app.name/reveal" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/settings/app.name/reveal"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/settings/app.name/reveal';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/settings/app.name/reveal');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Setting value revealed.",
"data": {
"key": "app.name",
"value": "Flexxer Backend"
},
"errors": null,
"meta": {
"request_id": "df0d0749-d201-42cf-aa40-f250f25d2b49",
"timestamp": "2026-08-05T16:18:42.552956Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Returns a single application setting identified by its key via
requires authentication
route-model binding ({setting:key}). * @group Admin API
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/settings/app.name" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/settings/app.name"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/settings/app.name';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/settings/app.name');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Setting retrieved successfully.",
"data": {
"id": "019fd2b7-eea2-7183-91ff-569d302b80a5",
"key": "app.name",
"value": "Flexxer Backend",
"has_value": true,
"type": "string",
"group": "application",
"label": "Application name",
"description": null,
"is_secret": false,
"is_encrypted": false,
"is_public": true,
"config_path": "app.name",
"validation": [
"max:100"
],
"sort_order": 10
},
"errors": null,
"meta": {
"request_id": "6bc74203-0d37-4005-acc7-4ca85f5ae75b",
"timestamp": "2026-08-05T16:18:42.572305Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update a single application setting identified by its key via route-model binding ({setting:key}).
requires authentication
- Authorisation is enforced through AppSettingPolicy::update so secret / privileged-group keys (stripe, mail, oauth, ...) require super_admin.
- Validation rules are derived dynamically from the setting's own
validationJSON column plus its declaredtype. - Encryption (when is_encrypted=true) is handled transparently by AppSetting::writeValue().
- The settings cache is invalidated through SettingsService::set so the next request observes the new value.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/admin/settings/app.name" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"value\": \"Beispieltext\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/settings/app.name"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"value": "Beispieltext"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/settings/app.name';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'value' => 'Beispieltext',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/settings/app.name');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"value": "Beispieltext"
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Setting updated successfully.",
"data": {
"id": "019fd2b7-eea2-7183-91ff-569d302b80a5",
"key": "app.name",
"value": "Beispieltext",
"has_value": true,
"type": "string",
"group": "application",
"label": "Application name",
"description": null,
"is_secret": false,
"is_encrypted": false,
"is_public": true,
"config_path": "app.name",
"validation": [
"max:100"
],
"sort_order": 10
},
"errors": null,
"meta": {
"request_id": "0d7997b1-efd3-4632-bc1f-9579037fc828",
"timestamp": "2026-08-05T16:18:42.584365Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update a single application setting identified by its key via route-model binding ({setting:key}).
requires authentication
- Authorisation is enforced through AppSettingPolicy::update so secret / privileged-group keys (stripe, mail, oauth, ...) require super_admin.
- Validation rules are derived dynamically from the setting's own
validationJSON column plus its declaredtype. - Encryption (when is_encrypted=true) is handled transparently by AppSetting::writeValue().
- The settings cache is invalidated through SettingsService::set so the next request observes the new value.
Example request:
curl --request PATCH \
"https://backend-dev.flexxr.at/api/v1/admin/settings/app.name" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"value\": \"Beispieltext\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/settings/app.name"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"value": "Beispieltext"
};
fetch(url, {
method: "PATCH",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/settings/app.name';
$response = $client->patch(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'value' => 'Beispieltext',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/settings/app.name');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"value": "Beispieltext"
};
final response = await http.patch(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Setting updated successfully.",
"data": {
"id": "019fd2b7-eea2-7183-91ff-569d302b80a5",
"key": "app.name",
"value": "Beispieltext",
"has_value": true,
"type": "string",
"group": "application",
"label": "Application name",
"description": null,
"is_secret": false,
"is_encrypted": false,
"is_public": true,
"config_path": "app.name",
"validation": [
"max:100"
],
"sort_order": 10
},
"errors": null,
"meta": {
"request_id": "0d7997b1-efd3-4632-bc1f-9579037fc828",
"timestamp": "2026-08-05T16:18:42.584365Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Audit Logs
Shortcut endpoint that returns the audit history for a specific mobile user. Equivalent to calling ListAuditLogsAction with
requires authentication
actor_type=User and actor_id={user}, but more ergonomic. * @group Admin API
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/audit-logs" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/audit-logs"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/audit-logs';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/audit-logs');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [],
"errors": null,
"meta": {
"request_id": "986148e1-fff0-482e-aaa0-5d41090efc2f",
"timestamp": "2026-08-05T16:18:41.836956Z",
"current_page": 1,
"last_page": 1,
"per_page": 25,
"total": 0
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Lists audit logs with filters on actor, event, IP, and date range.
requires authentication
Results are paginated and sorted by occurred_at descending so the
admin UI shows the most recent events first. * @group Admin API
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/audit-logs" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/audit-logs"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/audit-logs';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/audit-logs');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [
{
"id": "019fd2b7-f16f-722a-a17a-a0e1db7deb06",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Employee\\Models\\EmployeeBankAccount",
"subject_id": "019fd2b7-f16e-704c-b219-414a49a200c8",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"user_id": "019fd2b7-f153-7131-a03e-8f1096bf7eeb",
"is_primary": true,
"iban": "***MASKED***",
"bic": "RLNWATWW",
"bank_name": "Raiffeisen Bank",
"account_holder": "M*************",
"verified_at": "2026-03-05 16:18:18",
"is_verified": true,
"id": "019fd2b7-f16e-704c-b219-414a49a200c8",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f174-723d-9443-de112a7d144a",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Employee\\Models\\EmployeeDocument",
"subject_id": "019fd2b7-f173-70ee-8312-3dfc81345d78",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"user_id": "019fd2b7-f153-7131-a03e-8f1096bf7eeb",
"type": "id_card",
"original_filename": "p*****************f",
"storage_path": "c0ecb9801dd5592ab1d5b796b45cf183ae7a3b2a00154bd87cd0d0f39f71b787",
"file_size": 306900,
"mime_type": "application/pdf",
"status": "verified",
"document_number": "P******6",
"expires_at": "2031-08-05 16:18:18",
"reviewed_at": "2026-02-05 16:18:18",
"id": "019fd2b7-f173-70ee-8312-3dfc81345d78",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f177-7063-a530-e7b1cbb65fe0",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Employee\\Models\\EmployeeDocument",
"subject_id": "019fd2b7-f176-71df-a915-724d63fbbf7b",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"user_id": "019fd2b7-f153-7131-a03e-8f1096bf7eeb",
"type": "residence_permit",
"original_filename": "a******************f",
"storage_path": "a1a163d574e16f564d36030b921157863ae59a9359cc46f01fc02abaebafac5f",
"file_size": 158747,
"mime_type": "application/pdf",
"status": "verified",
"document_number": "A***********5",
"expires_at": "2028-08-05 16:18:18",
"reviewed_at": "2026-02-05 16:18:18",
"id": "019fd2b7-f176-71df-a915-724d63fbbf7b",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f17b-71b8-8ce8-d07f4bac6cb2",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Employee\\Models\\EmployeeDocument",
"subject_id": "019fd2b7-f17a-711b-a732-08f306e90713",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"user_id": "019fd2b7-f153-7131-a03e-8f1096bf7eeb",
"type": "social_insurance_card",
"original_filename": "e********f",
"storage_path": "bd958714cff13dfbfeb1e81751a841391dfe7cfb351ea518bf39f9b74b6a8751",
"file_size": 118449,
"mime_type": "application/pdf",
"status": "verified",
"document_number": null,
"expires_at": null,
"reviewed_at": "2026-02-05 16:18:18",
"id": "019fd2b7-f17a-711b-a732-08f306e90713",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f180-7174-a1df-07c27ea86e09",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Employee\\Models\\EmployeeQualification",
"subject_id": "019fd2b7-f17e-71c4-9e83-3bfb364ee6f5",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"user_id": "019fd2b7-f153-7131-a03e-8f1096bf7eeb",
"name": "Lebensmittelhygiene-Schulung",
"description": "HACCP-konform",
"issuing_organization": "Wifi Wien",
"credential_id": "CERT-VSMQAWJD",
"issued_at": "2024-08-05 16:18:18",
"expires_at": "2029-08-05 16:18:18",
"is_verified": true,
"verified_at": "2026-03-05 16:18:18",
"id": "019fd2b7-f17e-71c4-9e83-3bfb364ee6f5",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f183-72de-8fa6-ba8cb8c97a5e",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Employee\\Models\\EmployeeQualification",
"subject_id": "019fd2b7-f182-7351-9c68-f8069cc2b654",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"user_id": "019fd2b7-f153-7131-a03e-8f1096bf7eeb",
"name": "Erste-Hilfe-Kurs (16h)",
"description": "Betrieblicher Ersthelfer",
"issuing_organization": "Rotes Kreuz",
"credential_id": "CERT-0GX09TN6",
"issued_at": "2025-08-05 16:18:18",
"expires_at": "2027-08-05 16:18:18",
"is_verified": true,
"verified_at": "2026-03-05 16:18:18",
"id": "019fd2b7-f182-7351-9c68-f8069cc2b654",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f186-7171-9186-ecc5291b5720",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Employee\\Models\\EmployeeQualification",
"subject_id": "019fd2b7-f184-705f-902c-e3fe336e4696",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"user_id": "019fd2b7-f153-7131-a03e-8f1096bf7eeb",
"name": "Führerschein Klasse B",
"description": "PKW",
"issuing_organization": "Magistrat Wien",
"credential_id": "CERT-MMURVRZ9",
"issued_at": "2018-08-05 16:18:18",
"expires_at": "2033-08-05 16:18:18",
"is_verified": true,
"verified_at": "2026-03-05 16:18:18",
"id": "019fd2b7-f184-705f-902c-e3fe336e4696",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f18a-7051-a1a0-f69915c7b971",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Employee\\Models\\LegalConsent",
"subject_id": "019fd2b7-f189-70a8-90e2-a0cd3bea33f9",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"user_id": "019fd2b7-f153-7131-a03e-8f1096bf7eeb",
"consent_type": "terms_of_service",
"version": "1.0",
"is_granted": true,
"ip_address": "192.168.1.1",
"user_agent": "Mozilla/5.0 Flexxr/1.0",
"id": "019fd2b7-f189-70a8-90e2-a0cd3bea33f9"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f18f-713a-8653-ba9b92ae4893",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Employee\\Models\\LegalConsent",
"subject_id": "019fd2b7-f18d-7173-b3c9-a930482056cc",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"user_id": "019fd2b7-f153-7131-a03e-8f1096bf7eeb",
"consent_type": "privacy_policy",
"version": "1.0",
"is_granted": true,
"ip_address": "192.168.1.1",
"user_agent": "Mozilla/5.0 Flexxr/1.0",
"id": "019fd2b7-f18d-7173-b3c9-a930482056cc"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f193-730e-9ea9-dc287d5a2138",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Employee\\Models\\LegalConsent",
"subject_id": "019fd2b7-f192-70a0-ad38-e7249a9072e9",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"user_id": "019fd2b7-f153-7131-a03e-8f1096bf7eeb",
"consent_type": "data_processing",
"version": "1.0",
"is_granted": true,
"ip_address": "192.168.1.1",
"user_agent": "Mozilla/5.0 Flexxr/1.0",
"id": "019fd2b7-f192-70a0-ad38-e7249a9072e9"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f196-7342-8b80-22a97ced07f8",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Employee\\Models\\LegalConsent",
"subject_id": "019fd2b7-f195-70c4-8789-2a049d2c90e0",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"user_id": "019fd2b7-f153-7131-a03e-8f1096bf7eeb",
"consent_type": "framework_contract",
"version": "1.0",
"is_granted": true,
"ip_address": "192.168.1.1",
"user_agent": "Mozilla/5.0 Flexxr/1.0",
"id": "019fd2b7-f195-70c4-8789-2a049d2c90e0"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f27c-72ac-b5bb-02c51b40af7b",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Employee\\Models\\EmployeeProfile",
"subject_id": "019fd2b7-f279-7142-a68d-0d4563a06070",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"user_id": "019fd2b7-f271-73fd-8268-848be381e136",
"status": "pending_approval",
"date_of_birth": "1*****************0",
"nationality": "AT",
"address_line_1": "***REDACTED***",
"postal_code": "4**0",
"city": "Linz",
"country": "AT",
"svs_number": "***MASKED***",
"id": "019fd2b7-f279-7142-a68d-0d4563a06070",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f283-701d-a54c-158235363ec0",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Employee\\Models\\EmployeeDocument",
"subject_id": "019fd2b7-f280-73fe-83af-4fdd5f9db332",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"user_id": "019fd2b7-f271-73fd-8268-848be381e136",
"type": "id_card",
"original_filename": "a*********f",
"storage_path": "9155853482e609f840bdc816663625331d19feca66fdea30517b2e836a5078f8",
"file_size": 245000,
"mime_type": "application/pdf",
"status": "pending",
"id": "019fd2b7-f280-73fe-83af-4fdd5f9db332",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f288-7040-a457-b028861470d3",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Employee\\Models\\LegalConsent",
"subject_id": "019fd2b7-f286-701b-a4b6-2c2aff8e2daf",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"user_id": "019fd2b7-f271-73fd-8268-848be381e136",
"consent_type": "terms_of_service",
"version": "1.0",
"is_granted": true,
"ip_address": "192.168.1.100",
"id": "019fd2b7-f286-701b-a4b6-2c2aff8e2daf"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f369-7004-afff-8a69186dc602",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Employee\\Models\\EmployeeProfile",
"subject_id": "019fd2b7-f367-70e0-95e4-16a395c2b4ec",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"user_id": "019fd2b7-f362-705a-bd7d-66b2f8394aa2",
"status": "suspended",
"date_of_birth": "1*****************0",
"nationality": "AT",
"address_line_1": "***REDACTED***",
"postal_code": "1**0",
"city": "Wien",
"country": "AT",
"suspended_reason": "Wiederholte No-Shows bei bestätigten Schichten",
"id": "019fd2b7-f367-70e0-95e4-16a395c2b4ec",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f373-73e1-9170-f39694b52605",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Job\\Models\\JobCategory",
"subject_id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"slug": "gastro",
"name": "Gastronomie",
"name_en": "Gastronomy",
"icon": "utensils",
"kollektivvertrag": "Gastgewerbe",
"sort_order": 1,
"is_active": true,
"is_featured": true,
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f375-724e-84b8-4f964842107a",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Job\\Models\\JobCategory",
"subject_id": "019fd2b7-f375-724e-84b8-4f9647ef6419",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"slug": "hotel",
"name": "Hotellerie",
"name_en": "Hospitality",
"icon": "hotel",
"kollektivvertrag": "Hotel- und Gastgewerbe",
"sort_order": 2,
"is_active": true,
"is_featured": true,
"id": "019fd2b7-f375-724e-84b8-4f9647ef6419",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f378-72e4-b49e-cfb1fc2a49b0",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Job\\Models\\JobCategory",
"subject_id": "019fd2b7-f377-7108-8400-efa89715a39f",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"slug": "food_service",
"name": "Food Service",
"name_en": "Food Service",
"icon": "utensils",
"kollektivvertrag": "Gastgewerbe",
"sort_order": 3,
"is_active": true,
"is_featured": false,
"id": "019fd2b7-f377-7108-8400-efa89715a39f",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f37b-70a0-9864-944852d41e9f",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Job\\Models\\JobCategory",
"subject_id": "019fd2b7-f37a-72a9-84a9-7862f636e2fd",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"slug": "catering",
"name": "Catering",
"name_en": "Catering",
"icon": "utensils",
"kollektivvertrag": "Gastgewerbe",
"sort_order": 4,
"is_active": true,
"is_featured": false,
"id": "019fd2b7-f37a-72a9-84a9-7862f636e2fd",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f37e-73e1-8bb1-161448fd23cd",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Job\\Models\\JobCategory",
"subject_id": "019fd2b7-f37d-712d-92b3-aa5540f6b2a7",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"slug": "retail",
"name": "Einzelhandel",
"name_en": "Retail",
"icon": "shopping-cart",
"kollektivvertrag": "Handel",
"sort_order": 5,
"is_active": true,
"is_featured": false,
"id": "019fd2b7-f37d-712d-92b3-aa5540f6b2a7",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f381-70ee-b46d-57a550a4104d",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Job\\Models\\JobCategory",
"subject_id": "019fd2b7-f380-7300-91c6-75c968e6d045",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"slug": "supermarket",
"name": "Lebensmittelhandel",
"name_en": "Grocery",
"icon": "shopping-cart",
"kollektivvertrag": "Handel",
"sort_order": 6,
"is_active": true,
"is_featured": false,
"id": "019fd2b7-f380-7300-91c6-75c968e6d045",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f385-7167-a529-4245dd301d44",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Job\\Models\\JobCategory",
"subject_id": "019fd2b7-f384-7071-b096-674d16b4ad00",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"slug": "pharmacy",
"name": "Apotheke",
"name_en": "Pharmacy",
"icon": "heart-pulse",
"kollektivvertrag": "Pharmazeutischer Großhandel",
"sort_order": 7,
"is_active": true,
"is_featured": false,
"id": "019fd2b7-f384-7071-b096-674d16b4ad00",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f389-7022-8c5e-bf2ea9173fe3",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Job\\Models\\JobCategory",
"subject_id": "019fd2b7-f388-7098-b463-ae170338e60f",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"slug": "production",
"name": "Produktion",
"name_en": "Production",
"icon": "industry",
"kollektivvertrag": "Industrie",
"sort_order": 8,
"is_active": true,
"is_featured": false,
"id": "019fd2b7-f388-7098-b463-ae170338e60f",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f38c-7393-918e-19b1ae541bf2",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Job\\Models\\JobCategory",
"subject_id": "019fd2b7-f38b-7209-8b83-b345b172def2",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"slug": "warehouse",
"name": "Lager",
"name_en": "Warehouse",
"icon": "industry",
"kollektivvertrag": "Industrie",
"sort_order": 9,
"is_active": true,
"is_featured": false,
"id": "019fd2b7-f38b-7209-8b83-b345b172def2",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
{
"id": "019fd2b7-f165-7231-8be6-f3c0c9d9acd0",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Employee\\Models\\EmployeeProfile",
"subject_id": "019fd2b7-f161-73ae-875c-d74efc63d8bb",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"user_id": "019fd2b7-f153-7131-a03e-8f1096bf7eeb",
"status": "active",
"date_of_birth": "1*****************0",
"nationality": "AT",
"address_line_1": "***REDACTED***",
"address_line_2": "***REDACTED***",
"postal_code": "1**0",
"city": "Wien",
"country": "AT",
"svs_number": "***MASKED***",
"tax_id": "e******************************************************************************************************************************************************************************************************9",
"emergency_contact_name": "M***************",
"emergency_contact_phone": "********5678",
"emergency_contact_relationship": "Ehefrau",
"approved_at": "2026-02-05 16:18:18",
"id": "019fd2b7-f161-73ae-875c-d74efc63d8bb",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
}
],
"errors": null,
"meta": {
"request_id": "af080157-9260-4732-8976-5e113b9c26d2",
"timestamp": "2026-08-05T16:18:42.488489Z",
"current_page": 1,
"last_page": 72,
"per_page": 25,
"total": 1790
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Export Audit Logs
requires authentication
Streams audit logs as a CSV download, honoring the same filters as the list endpoint.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/audit-logs/export?actor_type=App%5C%5CDomain%5C%5CUser%5C%5CModels%5C%5CUser&actor_id=9b2c3d4e-5f6a-7b8c-9d0e-1f2a3b4c5d6e&subject_type=App%5C%5CDomain%5C%5COrganization%5C%5CModels%5C%5COrganization&subject_id=9b2c3d4e-5f6a-7b8c-9d0e-1f2a3b4c5d6e&event=login.failed&from=2026-04-01T00%3A00%3A00Z&to=2026-04-30T23%3A59%3A59Z&ip_address=203.0.113.42" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/audit-logs/export"
);
const params = {
"actor_type": "App\\Domain\\User\\Models\\User",
"actor_id": "9b2c3d4e-5f6a-7b8c-9d0e-1f2a3b4c5d6e",
"subject_type": "App\\Domain\\Organization\\Models\\Organization",
"subject_id": "9b2c3d4e-5f6a-7b8c-9d0e-1f2a3b4c5d6e",
"event": "login.failed",
"from": "2026-04-01T00:00:00Z",
"to": "2026-04-30T23:59:59Z",
"ip_address": "203.0.113.42",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/audit-logs/export';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'actor_type' => 'App\\Domain\\User\\Models\\User',
'actor_id' => '9b2c3d4e-5f6a-7b8c-9d0e-1f2a3b4c5d6e',
'subject_type' => 'App\\Domain\\Organization\\Models\\Organization',
'subject_id' => '9b2c3d4e-5f6a-7b8c-9d0e-1f2a3b4c5d6e',
'event' => 'login.failed',
'from' => '2026-04-01T00:00:00Z',
'to' => '2026-04-30T23:59:59Z',
'ip_address' => '203.0.113.42',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/audit-logs/export')
.replace(queryParameters: {
'actor_type': 'App\\Domain\\User\\Models\\User',
'actor_id': '9b2c3d4e-5f6a-7b8c-9d0e-1f2a3b4c5d6e',
'subject_type': 'App\\Domain\\Organization\\Models\\Organization',
'subject_id': '9b2c3d4e-5f6a-7b8c-9d0e-1f2a3b4c5d6e',
'event': 'login.failed',
'from': '2026-04-01T00:00:00Z',
'to': '2026-04-30T23:59:59Z',
'ip_address': '203.0.113.42',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "6e0665b2-afbf-4bce-b235-2956571a8731",
"timestamp": "2026-08-21T05:14:36.328392Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Returns a single audit log row by id. * @group Admin API
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/audit-logs/019f0593-c66e-7141-a832-edbf690fced6" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/audit-logs/019f0593-c66e-7141-a832-edbf690fced6"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/audit-logs/019f0593-c66e-7141-a832-edbf690fced6';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/audit-logs/019f0593-c66e-7141-a832-edbf690fced6');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"id": "019fd2b7-f165-7231-8be6-f3c0c9d9acd0",
"event": "model.created",
"actor_type": null,
"actor_id": null,
"actor_guard": null,
"subject_type": "App\\Domain\\Employee\\Models\\EmployeeProfile",
"subject_id": "019fd2b7-f161-73ae-875c-d74efc63d8bb",
"ip_address": "127.0.0.1",
"user_agent": "Symfony",
"session_token_id": null,
"metadata": {
"old_values": null,
"new_values": {
"user_id": "019fd2b7-f153-7131-a03e-8f1096bf7eeb",
"status": "active",
"date_of_birth": "1*****************0",
"nationality": "AT",
"address_line_1": "***REDACTED***",
"address_line_2": "***REDACTED***",
"postal_code": "1**0",
"city": "Wien",
"country": "AT",
"svs_number": "***MASKED***",
"tax_id": "e******************************************************************************************************************************************************************************************************9",
"emergency_contact_name": "M***************",
"emergency_contact_phone": "********5678",
"emergency_contact_relationship": "Ehefrau",
"approved_at": "2026-02-05 16:18:18",
"id": "019fd2b7-f161-73ae-875c-d74efc63d8bb",
"updated_at": "2026-08-05 16:18:18",
"created_at": "2026-08-05 16:18:18"
},
"correlation_id": null
},
"occurred_at": "2026-08-05T16:18:17.000000Z"
},
"errors": null,
"meta": {
"request_id": "6ad4d966-cec8-4745-a221-d1cb548a92f5",
"timestamp": "2026-08-05T16:18:42.503197Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
GDPR
Admin-triggered GDPR Art. 17 (Right to Erasure) anonymization.
requires authentication
Overwrites all PII on the user with non-identifying placeholders, deactivates the account, and revokes all active Sanctum tokens. A mandatory reason is required and is recorded in the audit log.
This operation is irreversible. Foreign-key relationships (donations,
favourites) are preserved for legal and accounting purposes. * @group Admin API
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/anonymize" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Krankheitsbedingt kurzfristig abgesagt.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/anonymize"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/anonymize';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'Krankheitsbedingt kurzfristig abgesagt.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/anonymize');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "User anonymised successfully.",
"data": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"first_name": "Anonymized",
"last_name": "User",
"email": "anonymized-019fd2b7-f271-73fd-8268-848be381e136@flexxr.invalid",
"country_code": null,
"phone_number": null,
"status": "deactivated",
"avatar_url": null,
"bio": null,
"date_of_birth": null,
"country": null,
"city": null,
"notify_push": true,
"notify_email": true,
"notify_sms": true,
"notify_marketing": false,
"email_verified_at": "2026-08-05T16:18:32+00:00",
"phone_verified_at": "2026-08-05T16:18:32+00:00",
"created_at": "2026-08-05T16:18:18+00:00",
"updated_at": "2026-08-05T16:18:41+00:00",
"employee_profile": null
},
"errors": null,
"meta": {
"request_id": "942e6a6d-9d0c-4a4f-bc5e-e1de244412e6",
"timestamp": "2026-08-05T16:18:41.761914Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Admin-triggered GDPR Art. 15 (Right of Access) data export.
requires authentication
Compiles everything the platform holds about a user into a single JSON envelope. The frontend handles the JSON → file download step
client-side; no streaming is required for v1. * @group Admin API
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/export" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/export"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/export';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/export');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "User data exported successfully.",
"data": {
"export_metadata": {
"schema_version": "2.1",
"export_type": "admin_assisted",
"exported_at": "2026-08-05T16:18:41.777945Z",
"exported_by_admin_id": "019fd2b7-edab-7280-b09f-b18f58a272ee",
"data_subject_id": "019fd2b7-f271-73fd-8268-848be381e136",
"controller": {
"name": "Flexxer",
"address": "Musterstraße 1, 1010 Wien, Österreich",
"fn": "FN 123456x",
"uid": "ATU12345678",
"privacy_contact": "privacy@flexxr.at",
"support_contact": "support@flexxr.at"
},
"legal_basis": {
"access": "GDPR Art. 15 (Right of access)",
"portability": "GDPR Art. 20 (Right to data portability)"
},
"rights_summary": {
"access": "Art. 15 — request a copy of your data (this export)",
"rectification": "Art. 16 — request correction of inaccurate data",
"erasure": "Art. 17 — request deletion / anonymisation of your account",
"portability": "Art. 20 — receive your data in a machine-readable format",
"objection": "Art. 21 — object to processing based on legitimate interests"
},
"retention_periods": {
"account_data": "3 years after last activity",
"audit_logs": "7 years",
"donation_receipts": "7 years (fiscal obligation)",
"session_tokens": "90 days from last use"
}
},
"profile": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"email": "pending@demo.flexxr.at",
"first_name": "Anna",
"last_name": "Neuling",
"phone_number": "6769876543",
"email_verified_at": "2026-08-05T16:18:32.000000Z",
"created_at": "2026-08-05T16:18:18.000000Z"
},
"consents": {
"notify_push": true,
"notify_email": true,
"notify_sms": true,
"notify_marketing": false
},
"audit_trail": [],
"notifications": [],
"sessions": [
{
"name": "docs",
"created_at": "2026-08-05 16:18:33"
}
],
"social_accounts": [],
"two_factor": {
"method": "totp",
"is_enabled": true,
"confirmed_at": "2026-08-05T16:18:32.000000Z",
"recovery_codes_remaining": 2
},
"donations": [],
"recurring_donations": [],
"donation_receipts": [],
"favourites": [],
"contact_messages": [],
"support_tickets": [],
"legal_acceptances": [],
"exported_at": "2026-08-05T16:18:41.778035Z",
"exported_by_admin_id": "019fd2b7-edab-7280-b09f-b18f58a272ee",
"exported_by_self": false
},
"errors": null,
"meta": {
"request_id": "5fa38b28-b605-4d05-80c8-464f916d5eb5",
"timestamp": "2026-08-05T16:18:41.783098Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Restrict User Processing
requires authentication
Flags the user's data as processing-restricted under GDPR Art. 18.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/restrict" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/restrict"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/restrict';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/restrict');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Lift User Processing Restriction
requires authentication
Clears the processing-restricted flag on the user.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/restrict" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/restrict"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/restrict';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/restrict');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Org GDPR Requests
requires authentication
Paginated queue of GDPR requests forwarded by organisations on behalf of a donor/data subject, optionally filtered by status, request type, or organisation.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/gdpr/org-requests?status=pending&type=access&organization_id=019f9939-c4c3-70fb-a54e-5ebf63db36d2&per_page=20" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"status\": \"rejected\",
\"type\": \"restriction\",
\"organization_id\": \"6ff8f7f6-1eb3-3525-be4a-3932c805afed\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/gdpr/org-requests"
);
const params = {
"status": "pending",
"type": "access",
"organization_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"per_page": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"status": "rejected",
"type": "restriction",
"organization_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/gdpr/org-requests';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'status' => 'pending',
'type' => 'access',
'organization_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'per_page' => '20',
],
'json' => [
'status' => 'rejected',
'type' => 'restriction',
'organization_id' => '6ff8f7f6-1eb3-3525-be4a-3932c805afed',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/gdpr/org-requests')
.replace(queryParameters: {
'status': 'pending',
'type': 'access',
'organization_id': '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'per_page': '20',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"status": "rejected",
"type": "restriction",
"organization_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed"
};
final response = await http.get(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "07ec46f6-66c0-43dd-ae6d-08ad888de3cb",
"timestamp": "2026-08-21T05:14:35.638439Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Org GDPR Request Status
requires authentication
Move an org-forwarded GDPR request into progress, resolve it, or reject it with an optional platform note.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/gdpr/org-requests/architecto/status" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"status\": \"resolved\",
\"platform_note\": \"Deletion completed and confirmed to the organisation.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/gdpr/org-requests/architecto/status"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"status": "resolved",
"platform_note": "Deletion completed and confirmed to the organisation."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/gdpr/org-requests/architecto/status';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'status' => 'resolved',
'platform_note' => 'Deletion completed and confirmed to the organisation.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/gdpr/org-requests/architecto/status');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"status": "resolved",
"platform_note": "Deletion completed and confirmed to the organisation."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (422, Invalid status):
{
"status": "VALIDATION_ERROR",
"message": "The status field is invalid."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Worker GDPR Requests
requires authentication
Paginated queue of GDPR rights requests raised directly by workers,
optionally filtered by status, request type, or user. Each row
includes sla_days_remaining against the Art. 12(3) one-month
response deadline.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/gdpr/user-requests?status=pending&type=restriction&user_id=019f9939-c4c3-70fb-a54e-5ebf63db36d2&per_page=20" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"status\": \"in_progress\",
\"type\": \"rectification\",
\"user_id\": \"6ff8f7f6-1eb3-3525-be4a-3932c805afed\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/gdpr/user-requests"
);
const params = {
"status": "pending",
"type": "restriction",
"user_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"per_page": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"status": "in_progress",
"type": "rectification",
"user_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/gdpr/user-requests';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'status' => 'pending',
'type' => 'restriction',
'user_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'per_page' => '20',
],
'json' => [
'status' => 'in_progress',
'type' => 'rectification',
'user_id' => '6ff8f7f6-1eb3-3525-be4a-3932c805afed',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/gdpr/user-requests')
.replace(queryParameters: {
'status': 'pending',
'type': 'restriction',
'user_id': '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'per_page': '20',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"status": "in_progress",
"type": "rectification",
"user_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed"
};
final response = await http.get(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "50b4baf4-7a3c-40a6-9fe6-009be5467bba",
"timestamp": "2026-08-21T05:14:35.661280Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Worker GDPR Request Status
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/gdpr/user-requests/019fe6e4-bbcd-71fd-918b-effe04df4ff9/status" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"status\": \"resolved\",
\"platform_note\": \"Adresse wurde korrigiert.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/gdpr/user-requests/019fe6e4-bbcd-71fd-918b-effe04df4ff9/status"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"status": "resolved",
"platform_note": "Adresse wurde korrigiert."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/gdpr/user-requests/019fe6e4-bbcd-71fd-918b-effe04df4ff9/status';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'status' => 'resolved',
'platform_note' => 'Adresse wurde korrigiert.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/gdpr/user-requests/019fe6e4-bbcd-71fd-918b-effe04df4ff9/status');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"status": "resolved",
"platform_note": "Adresse wurde korrigiert."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (422, Invalid status):
{
"status": "VALIDATION_ERROR",
"message": "The status field is invalid."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List GDPR Deletion Requests
requires authentication
Users with a scheduled data-retention horizon, ordered by how soon it falls due.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/gdpr/deletion-requests?per_page=20" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/gdpr/deletion-requests"
);
const params = {
"per_page": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/gdpr/deletion-requests';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'per_page' => '20',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/gdpr/deletion-requests')
.replace(queryParameters: {
'per_page': '20',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "fce2f915-1e78-4278-97ce-28b10af4dac9",
"timestamp": "2026-08-21T05:14:35.679123Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List GDPR Data Exports
requires authentication
Paginated queue of asynchronous GDPR data-export requests, optionally filtered by status or user.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/gdpr/exports?status=ready&user_id=019f9939-c4c3-70fb-a54e-5ebf63db36d2&per_page=20" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"status\": \"expired\",
\"user_id\": \"6ff8f7f6-1eb3-3525-be4a-3932c805afed\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/gdpr/exports"
);
const params = {
"status": "ready",
"user_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"per_page": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"status": "expired",
"user_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/gdpr/exports';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'status' => 'ready',
'user_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'per_page' => '20',
],
'json' => [
'status' => 'expired',
'user_id' => '6ff8f7f6-1eb3-3525-be4a-3932c805afed',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/gdpr/exports')
.replace(queryParameters: {
'status': 'ready',
'user_id': '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'per_page': '20',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"status": "expired",
"user_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed"
};
final response = await http.get(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "1670e81f-0fee-45e8-9a49-ae2afa5ee569",
"timestamp": "2026-08-21T05:14:35.689876Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Auth
Change Admin Password
requires authentication
Allows an authenticated, 2FA-verified admin to change their own password.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/auth/change-password" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"current_password\": \"S3cure-Passw0rd!\",
\"new_password\": \"S3cure-Passw0rd!\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/auth/change-password"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"current_password": "S3cure-Passw0rd!",
"new_password": "S3cure-Passw0rd!"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/auth/change-password';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'current_password' => 'S3cure-Passw0rd!',
'new_password' => 'S3cure-Passw0rd!',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/auth/change-password');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"current_password": "S3cure-Passw0rd!",
"new_password": "S3cure-Passw0rd!"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Password updated.",
"data": null,
"errors": null,
"meta": {
"request_id": "d2eb3161-d050-4812-80a5-90564e5b4161",
"timestamp": "2026-08-05T16:18:41.650210Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "current_password",
"message": "The password is incorrect."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Password Reuse):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "password",
"message": "You cannot reuse your last 3 passwords."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Current Admin
requires authentication
Returns the authenticated admin's profile alongside their resolved ACL manifest (scope, presets, flat permission list, conditional markers).
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/auth/me" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/auth/me"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/auth/me';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/auth/me');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"profile": {
"id": "019fd2b7-edab-7280-b09f-b18f58a272ee",
"name": "Super Admin",
"email": "office@flexxr.at",
"role": "super_admin",
"is_active": true
},
"acl": {
"scope": "admin",
"presets": [
"super-admin"
],
"permissions": [
"admin.admins.create",
"admin.admins.deactivate",
"admin.admins.reactivate",
"admin.admins.reset-2fa",
"admin.admins.update",
"admin.admins.update-presets",
"admin.admins.update-role",
"admin.admins.view",
"admin.app-settings.reveal-secret",
"admin.app-settings.update",
"admin.app-settings.view",
"admin.assignments.manage",
"admin.assignments.view",
"admin.audit.view",
"admin.billing.update",
"admin.billing.view",
"admin.compliance.aueg-monitor",
"admin.compliance.minimum-wage-warnings",
"admin.compliance.view",
"admin.compliance.working-time-warnings",
"admin.contracts.manage",
"admin.contracts.view",
"admin.employees.approve",
"admin.employees.flag-high-risk",
"admin.employees.reactivate",
"admin.employees.reject",
"admin.employees.request-correction",
"admin.employees.review-documents",
"admin.employees.suspend",
"admin.employees.validate-svs",
"admin.employees.view",
"admin.finance.manage-dunning",
"admin.finance.manage-invoices",
"admin.finance.view-invoices",
"admin.finance.view-payments",
"admin.gdpr.anonymize",
"admin.gdpr.export",
"admin.gdpr.restrict",
"admin.jobs.approve",
"admin.jobs.emergency-close",
"admin.jobs.emergency-reassign",
"admin.jobs.manage-categories",
"admin.jobs.manage-document-types",
"admin.jobs.reject",
"admin.jobs.view",
"admin.legal.manage",
"admin.legal.view",
"admin.organizations.reactivate",
"admin.organizations.reject",
"admin.organizations.reset-password",
"admin.organizations.review-documents",
"admin.organizations.suspend",
"admin.organizations.update",
"admin.organizations.verify",
"admin.organizations.view",
"admin.payroll.download-payslips",
"admin.payroll.sync",
"admin.payroll.trigger",
"admin.payroll.view",
"admin.ratings.moderate",
"admin.ratings.view",
"admin.reports.export",
"admin.reports.view",
"admin.security.detect-duplicates",
"admin.security.manual-review",
"admin.support.assign-tickets",
"admin.support.escalate-tickets",
"admin.support.resolve-tickets",
"admin.support.update",
"admin.support.view",
"admin.support.view-tickets",
"admin.system.view-health",
"admin.system.view-metrics",
"admin.users.change-status",
"admin.users.reset-password",
"admin.users.update",
"admin.users.update-by-admin",
"admin.users.view"
],
"conditional": {},
"computed_at": "2026-08-05T16:18:41+00:00"
},
"two_factor": {
"confirmed": true,
"required": false,
"setup_required": false
}
},
"errors": null,
"meta": {
"request_id": "bbcf7f74-310a-47c7-9394-09d385e741df",
"timestamp": "2026-08-05T16:18:41.662797Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Admin Two-Factor State
requires authentication
Returns the current 2FA configuration for the authenticated admin.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, 2FA Disabled):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"enabled": false,
"method": null,
"confirmed_at": null,
"recovery_codes_remaining": 0
},
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-06-10T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
User Sessions
List a user's active Sanctum sessions (personal access tokens).
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/sessions" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/sessions"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/sessions';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/sessions');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Sessions retrieved successfully.",
"data": [
{
"id": "4",
"name": "docs",
"abilities": [
"*"
],
"last_used_at": null,
"expires_at": null,
"created_at": "2026-08-05T16:18:33.000000Z",
"is_expired": false
}
],
"errors": null,
"meta": {
"request_id": "0c9f5eef-9166-4173-9389-17d6cc662596",
"timestamp": "2026-08-05T16:18:41.792412Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Revoke ALL Sanctum sessions for a user. Used by admins responding to suspected account compromise or following a privacy support request.
requires authentication
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/sessions" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/sessions"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/sessions';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/sessions');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "All sessions revoked.",
"data": {
"revoked_count": 1
},
"errors": null,
"meta": {
"request_id": "0ab9f276-3175-4f5e-88f2-017b0affb509",
"timestamp": "2026-08-05T16:18:41.808950Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Revoke a single Sanctum session (personal access token) belonging to a user.
requires authentication
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/sessions/architecto" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/sessions/architecto"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/sessions/architecto';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/users/019f0593-c75f-7265-bb3d-278a77f5a95f/sessions/architecto');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Session revoked.",
"data": {
"id": "4"
},
"errors": null,
"meta": {
"request_id": "a50d1a40-7b5b-4de9-865c-d54b38b6fc2e",
"timestamp": "2026-08-05T16:18:41.826845Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Employee Approval
Suspend an ACTIVE employee.
requires authentication
Suspend Employee
Suspension immediately cancels all future scheduled shifts so the suspended worker can neither appear on rosters nor accrue wages while restricted. The employee keeps login access but sees a restriction notice; the generic reason category is shared, investigation details are not.
After the transaction commits, each affected organisation receives a single ShiftCancelled notification (one per org, deduplicated). A notification failure never aborts the suspension.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/employees/architecto/suspend" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"compliance_violation\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/employees/architecto/suspend"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "compliance_violation"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/employees/architecto/suspend';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'compliance_violation',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/employees/architecto/suspend');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "compliance_violation"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Employee suspended.",
"data": {
"employee_id": "019fd2b7-f279-7142-a68d-0d4563a06070",
"status": "suspended",
"cancelled_shifts": 1
}
}
Example response (404, Not Found):
{
"status": "ERROR",
"message": "Employee not found."
}
Example response (422, Not Active):
{
"status": "ERROR",
"message": "Only active employees can be suspended."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reactivate a SUSPENDED employee.
requires authentication
Reactivate Employee
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/employees/architecto/reactivate" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"note\": \"Investigation closed, no violation found.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/employees/architecto/reactivate"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"note": "Investigation closed, no violation found."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/employees/architecto/reactivate';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'note' => 'Investigation closed, no violation found.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/employees/architecto/reactivate');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"note": "Investigation closed, no violation found."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Employee reactivated.",
"data": {
"employee_id": "019fd2b8-29d8-7088-aaea-ffda7ed96710",
"status": "active"
}
}
Example response (404, Not Found):
{
"status": "ERROR",
"message": "Employee not found."
}
Example response (422, Not Suspended):
{
"status": "ERROR",
"message": "Only suspended employees can be reactivated."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Employee Documents
Resolve a document discrepancy after admin review.
requires authentication
Discrepancies are advisory flags created by OCR when extracted data doesn't match the profile (name, DOB, IBAN). Admins can resolve them after verifying the document is legitimate.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/employees/discrepancies/architecto/resolve" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/employees/discrepancies/architecto/resolve"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/employees/discrepancies/architecto/resolve';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/employees/discrepancies/architecto/resolve');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Success):
{
"status": "SUCCESS",
"message": "Discrepancy resolved.",
"data": {
"discrepancy_id": "uuid",
"resolved_at": "2026-06-20 12:00"
}
}
Example response (404, Not Found):
{
"status": "NOT_FOUND",
"message": "Discrepancy not found."
}
Example response (422, Already Resolved):
{
"status": "INVALID_OPERATION",
"message": "Discrepancy already resolved."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
No-Shows
List No-Shows
requires authentication
Platform-wide list of no-show incidents, with reliability/fraud relevant summary counts computed across every filtered row, not just the current page.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/no-shows?organization_id=019f9939-c4c3-70fb-a54e-5ebf63db36d2&date_from=2026-01-01&date_to=2026-01-31&status=detected&is_excused=" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"organization_id\": \"6ff8f7f6-1eb3-3525-be4a-3932c805afed\",
\"date_from\": \"2026-08-21T05:14:35\",
\"date_to\": \"2026-08-21T05:14:35\",
\"status\": \"excused\",
\"is_excused\": false
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/no-shows"
);
const params = {
"organization_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"date_from": "2026-01-01",
"date_to": "2026-01-31",
"status": "detected",
"is_excused": "0",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"organization_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed",
"date_from": "2026-08-21T05:14:35",
"date_to": "2026-08-21T05:14:35",
"status": "excused",
"is_excused": false
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/no-shows';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'organization_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'date_from' => '2026-01-01',
'date_to' => '2026-01-31',
'status' => 'detected',
'is_excused' => '0',
],
'json' => [
'organization_id' => '6ff8f7f6-1eb3-3525-be4a-3932c805afed',
'date_from' => '2026-08-21T05:14:35',
'date_to' => '2026-08-21T05:14:35',
'status' => 'excused',
'is_excused' => false,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/no-shows')
.replace(queryParameters: {
'organization_id': '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'date_from': '2026-01-01',
'date_to': '2026-01-31',
'status': 'detected',
'is_excused': '',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"organization_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed",
"date_from": "2026-08-21T05:14:35",
"date_to": "2026-08-21T05:14:35",
"status": "excused",
"is_excused": false
};
final response = await http.get(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "4dd51c7f-725f-4721-9e34-00899c8d6bd6",
"timestamp": "2026-08-21T05:14:35.839287Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Excuse No-Show
requires authentication
Marks a no-show incident as excused with an optional note. Refused when the incident is already excused or is past the stage where an excuse still applies.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/no-shows/019f34c2-b7a3-7144-96fa-ba76afffcf1e/excuse" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"note\": \"Employee provided a medical certificate.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/no-shows/019f34c2-b7a3-7144-96fa-ba76afffcf1e/excuse"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"note": "Employee provided a medical certificate."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/no-shows/019f34c2-b7a3-7144-96fa-ba76afffcf1e/excuse';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'note' => 'Employee provided a medical certificate.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/no-shows/019f34c2-b7a3-7144-96fa-ba76afffcf1e/excuse');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"note": "Employee provided a medical certificate."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (409, Cannot be excused):
{
"status": "CONFLICT",
"message": "This incident can no longer be excused."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Badges
List Badges
requires authentication
The full badge catalog (including hidden/inactive), with the number of workers who have earned each badge.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/badges" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/badges"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/badges';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/badges');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "5b167a2f-b8ad-43a0-8c3c-562d7aaf84e8",
"timestamp": "2026-08-21T05:14:35.857334Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create Badge
requires authentication
Adds a new badge to the catalog.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/badges" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"slug\": \"perfect-month\",
\"name\": \"Perfekter Monat\",
\"description\": \"Keine Ausfälle einen Monat lang.\",
\"icon\": \"mdi-star\",
\"color\": \"gold\",
\"category\": \"reliability\",
\"tier\": 2,
\"criteria_type\": \"shifts_completed\",
\"criteria_threshold\": 10,
\"points\": 50,
\"is_active\": true,
\"is_hidden\": false,
\"sort_order\": 10
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/badges"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"slug": "perfect-month",
"name": "Perfekter Monat",
"description": "Keine Ausfälle einen Monat lang.",
"icon": "mdi-star",
"color": "gold",
"category": "reliability",
"tier": 2,
"criteria_type": "shifts_completed",
"criteria_threshold": 10,
"points": 50,
"is_active": true,
"is_hidden": false,
"sort_order": 10
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/badges';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'slug' => 'perfect-month',
'name' => 'Perfekter Monat',
'description' => 'Keine Ausfälle einen Monat lang.',
'icon' => 'mdi-star',
'color' => 'gold',
'category' => 'reliability',
'tier' => 2,
'criteria_type' => 'shifts_completed',
'criteria_threshold' => 10,
'points' => 50,
'is_active' => true,
'is_hidden' => false,
'sort_order' => 10,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/badges');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"slug": "perfect-month",
"name": "Perfekter Monat",
"description": "Keine Ausfälle einen Monat lang.",
"icon": "mdi-star",
"color": "gold",
"category": "reliability",
"tier": 2,
"criteria_type": "shifts_completed",
"criteria_threshold": 10,
"points": 50,
"is_active": true,
"is_hidden": false,
"sort_order": 10
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Badge
requires authentication
Updates a catalog badge's definition.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/admin/badges/019fe42b-65dc-722e-a4c6-9768028255ff" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Perfekter Monat\",
\"description\": \"Keine Ausfälle einen Monat lang.\",
\"icon\": \"mdi-star\",
\"color\": \"gold\",
\"category\": \"reliability\",
\"tier\": 2,
\"criteria_type\": \"shifts_completed\",
\"criteria_threshold\": 10,
\"points\": 50,
\"is_active\": true,
\"is_hidden\": false,
\"sort_order\": 10
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/badges/019fe42b-65dc-722e-a4c6-9768028255ff"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Perfekter Monat",
"description": "Keine Ausfälle einen Monat lang.",
"icon": "mdi-star",
"color": "gold",
"category": "reliability",
"tier": 2,
"criteria_type": "shifts_completed",
"criteria_threshold": 10,
"points": 50,
"is_active": true,
"is_hidden": false,
"sort_order": 10
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/badges/019fe42b-65dc-722e-a4c6-9768028255ff';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'name' => 'Perfekter Monat',
'description' => 'Keine Ausfälle einen Monat lang.',
'icon' => 'mdi-star',
'color' => 'gold',
'category' => 'reliability',
'tier' => 2,
'criteria_type' => 'shifts_completed',
'criteria_threshold' => 10,
'points' => 50,
'is_active' => true,
'is_hidden' => false,
'sort_order' => 10,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/badges/019fe42b-65dc-722e-a4c6-9768028255ff');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"name": "Perfekter Monat",
"description": "Keine Ausfälle einen Monat lang.",
"icon": "mdi-star",
"color": "gold",
"category": "reliability",
"tier": 2,
"criteria_type": "shifts_completed",
"criteria_threshold": 10,
"points": 50,
"is_active": true,
"is_hidden": false,
"sort_order": 10
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete Badge
requires authentication
Soft-deletes a catalog badge. Existing awards are unaffected.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/admin/badges/019fe42b-65dc-722e-a4c6-9768028255ff" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/badges/019fe42b-65dc-722e-a4c6-9768028255ff"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/badges/019fe42b-65dc-722e-a4c6-9768028255ff';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/badges/019fe42b-65dc-722e-a4c6-9768028255ff');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Award Badge
requires authentication
Manually awards a badge to a worker with a reason.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/badges/019fe42b-65dc-722e-a4c6-9768028255ff/award" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"user_id\": \"019f9939-c4c3-70fb-a54e-5ebf63db36d2\",
\"reason\": \"Herausragende Leistung im Juni.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/badges/019fe42b-65dc-722e-a4c6-9768028255ff/award"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"user_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"reason": "Herausragende Leistung im Juni."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/badges/019fe42b-65dc-722e-a4c6-9768028255ff/award';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'user_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'reason' => 'Herausragende Leistung im Juni.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/badges/019fe42b-65dc-722e-a4c6-9768028255ff/award');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"user_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"reason": "Herausragende Leistung im Juni."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (409, Already awarded):
{
"status": "DUPLICATE_ENTRY",
"message": "This worker already has this badge."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Revoke Badge Award
requires authentication
Revokes a badge from the worker who was awarded it.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/admin/badges/019fe42b-65dc-722e-a4c6-9768028255ff/awards/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/badges/019fe42b-65dc-722e-a4c6-9768028255ff/awards/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/badges/019fe42b-65dc-722e-a4c6-9768028255ff/awards/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/badges/019fe42b-65dc-722e-a4c6-9768028255ff/awards/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (404, Not awarded):
{
"status": "NOT_FOUND",
"message": "This worker does not have this badge."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Job Categories
List Job Categories
requires authentication
Returns all job categories with optional filtering.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/job-categories?active=1&featured=1&parent_id=null+%28for+root+categories%29&search=gastro" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/job-categories"
);
const params = {
"active": "1",
"featured": "1",
"parent_id": "null (for root categories)",
"search": "gastro",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/job-categories';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'active' => '1',
'featured' => '1',
'parent_id' => 'null (for root categories)',
'search' => 'gastro',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/job-categories')
.replace(queryParameters: {
'active': '1',
'featured': '1',
'parent_id': 'null (for root categories)',
'search': 'gastro',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"categories": [
{
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"kollektivvertrag": "Gastgewerbe",
"color": null,
"is_featured": true,
"parent_id": null,
"children": []
}
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create Job Category
requires authentication
Creates a new job category for the platform.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/job-categories" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Gastronomie\",
\"name_en\": \"Gastronomy\",
\"slug\": \"gastro\",
\"icon\": \"utensils\",
\"description\": \"Restaurant and hotel jobs\",
\"kollektivvertrag\": \"Gastgewerbe KV\",
\"parent_id\": null,
\"sort_order\": 10,
\"is_active\": true,
\"is_featured\": false,
\"color\": \"#FF5733\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/job-categories"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Gastronomie",
"name_en": "Gastronomy",
"slug": "gastro",
"icon": "utensils",
"description": "Restaurant and hotel jobs",
"kollektivvertrag": "Gastgewerbe KV",
"parent_id": null,
"sort_order": 10,
"is_active": true,
"is_featured": false,
"color": "#FF5733"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/job-categories';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'name' => 'Gastronomie',
'name_en' => 'Gastronomy',
'slug' => 'gastro',
'icon' => 'utensils',
'description' => 'Restaurant and hotel jobs',
'kollektivvertrag' => 'Gastgewerbe KV',
'parent_id' => null,
'sort_order' => 10,
'is_active' => true,
'is_featured' => false,
'color' => '#FF5733',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/job-categories');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"name": "Gastronomie",
"name_en": "Gastronomy",
"slug": "gastro",
"icon": "utensils",
"description": "Restaurant and hotel jobs",
"kollektivvertrag": "Gastgewerbe KV",
"parent_id": null,
"sort_order": 10,
"is_active": true,
"is_featured": false,
"color": "#FF5733"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Success):
{
"status": "SUCCESS",
"data": {
"category": {}
}
}
Example response (422, Validation Error):
{
"status": "ERROR",
"message": "Validation failed"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Job Category
requires authentication
Updates an existing job category.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/admin/job-categories/550e8400-e29b-41d4-a716-446655440000" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Gastronomie\",
\"name_en\": \"Gastronomy\",
\"slug\": \"gastro\",
\"icon\": \"utensils\",
\"description\": \"Restaurant and hotel jobs\",
\"kollektivvertrag\": \"Gastgewerbe KV\",
\"parent_id\": null,
\"sort_order\": 10,
\"is_active\": true,
\"is_featured\": false,
\"color\": \"#FF5733\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/job-categories/550e8400-e29b-41d4-a716-446655440000"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Gastronomie",
"name_en": "Gastronomy",
"slug": "gastro",
"icon": "utensils",
"description": "Restaurant and hotel jobs",
"kollektivvertrag": "Gastgewerbe KV",
"parent_id": null,
"sort_order": 10,
"is_active": true,
"is_featured": false,
"color": "#FF5733"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/job-categories/550e8400-e29b-41d4-a716-446655440000';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'name' => 'Gastronomie',
'name_en' => 'Gastronomy',
'slug' => 'gastro',
'icon' => 'utensils',
'description' => 'Restaurant and hotel jobs',
'kollektivvertrag' => 'Gastgewerbe KV',
'parent_id' => null,
'sort_order' => 10,
'is_active' => true,
'is_featured' => false,
'color' => '#FF5733',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/job-categories/550e8400-e29b-41d4-a716-446655440000');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"name": "Gastronomie",
"name_en": "Gastronomy",
"slug": "gastro",
"icon": "utensils",
"description": "Restaurant and hotel jobs",
"kollektivvertrag": "Gastgewerbe KV",
"parent_id": null,
"sort_order": 10,
"is_active": true,
"is_featured": false,
"color": "#FF5733"
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"category": {
"id": "019fd2b7-f371-732c-8cdb-6de13be42891",
"slug": "gastro",
"name": "Gastronomie",
"name_localized": "Gastronomy",
"icon": "utensils",
"kollektivvertrag": "Gastgewerbe KV",
"color": "#FF5733",
"is_featured": false,
"parent_id": null
}
}
}
Example response (404, Not Found):
{
"status": "ERROR",
"message": "Category not found"
}
Example response (422, Validation Error):
{
"status": "ERROR",
"message": "Validation failed"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete Job Category
requires authentication
Soft-deletes a job category. Categories with active jobs cannot be deleted.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/admin/job-categories/550e8400-e29b-41d4-a716-446655440000?force=" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/job-categories/550e8400-e29b-41d4-a716-446655440000"
);
const params = {
"force": "0",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/job-categories/550e8400-e29b-41d4-a716-446655440000';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'force' => '0',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/job-categories/550e8400-e29b-41d4-a716-446655440000')
.replace(queryParameters: {
'force': '',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Success):
{
"status": "SUCCESS",
"message": "Category deleted"
}
Example response (404, Not Found):
{
"status": "ERROR",
"message": "Category not found"
}
Example response (409, Conflict):
{
"status": "ERROR",
"message": "Category has active jobs"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Job Document Types
List Job Document Types
requires authentication
List every system document type with its company-visibility flag so an admin can choose which the companies may require when authoring a job.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/job-document-types" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/job-document-types"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/job-document-types';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/job-document-types');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"document_types": [
{
"id": "d10619da-fd23-4dab-bcd1-73f8b2387be5",
"code": "passport",
"label": "Passport",
"company_selectable": true,
"sort_order": 10
},
{
"id": "9ee56a86-9282-45b4-b735-f218aae16759",
"code": "id_card",
"label": "ID card",
"company_selectable": true,
"sort_order": 20
},
{
"id": "f5348f1b-2f15-4c41-a5fe-b2f99c775ee2",
"code": "driver_license",
"label": "Driver's licence",
"company_selectable": true,
"sort_order": 30
},
{
"id": "7d395af4-f896-46df-bbc4-671ae40f4f8a",
"code": "work_permit",
"label": "Work permit",
"company_selectable": true,
"sort_order": 40
},
{
"id": "84af4d09-035f-43e6-bd53-2ab18370338a",
"code": "residence_permit",
"label": "Residence permit",
"company_selectable": true,
"sort_order": 50
},
{
"id": "2f3704b2-e39a-4eeb-8864-56bf52f3ed28",
"code": "rot_weiss_rot_karte",
"label": "Rot-Weiß-Rot card",
"company_selectable": true,
"sort_order": 60
},
{
"id": "9f171c88-d0da-4d68-ba57-87402c4a0a2c",
"code": "blue_card",
"label": "EU Blue Card",
"company_selectable": true,
"sort_order": 70
},
{
"id": "bedbfb30-1731-4887-9a3e-b01d77eb0577",
"code": "bank_statement",
"label": "Bank statement",
"company_selectable": true,
"sort_order": 80
},
{
"id": "45eff414-51e3-4c74-9f12-5b7b600ea715",
"code": "proof_of_address",
"label": "Proof of address",
"company_selectable": true,
"sort_order": 90
},
{
"id": "7da8605b-3108-41b7-ae37-57b6fba26ef5",
"code": "social_insurance_card",
"label": "Social insurance record",
"company_selectable": true,
"sort_order": 100
},
{
"id": "004dcced-7dc0-41b5-86dc-ebe2d5098fe2",
"code": "tax_document",
"label": "Tax document",
"company_selectable": true,
"sort_order": 110
},
{
"id": "88d1719e-fd3f-47f7-bfe9-418db3353b6a",
"code": "certification",
"label": "Certification",
"company_selectable": true,
"sort_order": 120
},
{
"id": "9c528cb6-5ed6-418d-85ee-98d5087c90cf",
"code": "health_certificate",
"label": "Health certificate",
"company_selectable": true,
"sort_order": 130
},
{
"id": "04ebe252-d4c3-40e2-b4e4-ee8a9f636d1b",
"code": "criminal_record_check",
"label": "Criminal record check",
"company_selectable": true,
"sort_order": 140
},
{
"id": "fe6ae84f-7733-49c9-a8de-20672765d2bf",
"code": "other",
"label": "Other",
"company_selectable": true,
"sort_order": 150
}
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Job Document Type
requires authentication
Toggle whether companies may pick a document type (and its ordering). The set of types is fixed by the system enum, so only visibility and order are editable — not the code or creation of new types.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/admin/job-document-types/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"company_selectable\": true,
\"sort_order\": 1
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/job-document-types/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"company_selectable": true,
"sort_order": 1
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/job-document-types/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'company_selectable' => true,
'sort_order' => 1,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/job-document-types/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"company_selectable": true,
"sort_order": 1
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Contracts
List Contracts
requires authentication
Paginated, platform-wide list of contracts, filterable by type, status, organisation, worker, or contract number.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/contracts?type=ueberlassungsvertrag&status=signed&organization_id=019f9939-c4c3-70fb-a54e-5ebf63db36d2&user_id=019f9939-c4c3-70fb-a54e-5ebf63db36d2&contract_number=UEV-2026-000123&per_page=20" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"type\": \"ueberlassungsvertrag\",
\"status\": \"signed\",
\"organization_id\": \"6ff8f7f6-1eb3-3525-be4a-3932c805afed\",
\"user_id\": \"6b72fe4a-5b40-307c-bc24-f79acf9a1bb9\",
\"contract_number\": \"m\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/contracts"
);
const params = {
"type": "ueberlassungsvertrag",
"status": "signed",
"organization_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"user_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"contract_number": "UEV-2026-000123",
"per_page": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"type": "ueberlassungsvertrag",
"status": "signed",
"organization_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed",
"user_id": "6b72fe4a-5b40-307c-bc24-f79acf9a1bb9",
"contract_number": "m"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/contracts';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'type' => 'ueberlassungsvertrag',
'status' => 'signed',
'organization_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'user_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'contract_number' => 'UEV-2026-000123',
'per_page' => '20',
],
'json' => [
'type' => 'ueberlassungsvertrag',
'status' => 'signed',
'organization_id' => '6ff8f7f6-1eb3-3525-be4a-3932c805afed',
'user_id' => '6b72fe4a-5b40-307c-bc24-f79acf9a1bb9',
'contract_number' => 'm',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/contracts')
.replace(queryParameters: {
'type': 'ueberlassungsvertrag',
'status': 'signed',
'organization_id': '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'user_id': '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'contract_number': 'UEV-2026-000123',
'per_page': '20',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"type": "ueberlassungsvertrag",
"status": "signed",
"organization_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed",
"user_id": "6b72fe4a-5b40-307c-bc24-f79acf9a1bb9",
"contract_number": "m"
};
final response = await http.get(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "f605c85b-dbfe-4bd5-a2d9-3e642710bcbd",
"timestamp": "2026-08-21T05:14:36.264377Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Show Contract
requires authentication
Contract detail including the signed shift assignments it covers and a null-safe download URL.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/contracts/019fdbed-1326-732f-8e9c-68bd4a59d120" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/contracts/019fdbed-1326-732f-8e9c-68bd4a59d120"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/contracts/019fdbed-1326-732f-8e9c-68bd4a59d120';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/contracts/019fdbed-1326-732f-8e9c-68bd4a59d120');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "6b72b314-73fd-45bb-ae86-1dbcd3058f40",
"timestamp": "2026-08-21T05:14:36.276577Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Messaging
List Conversations
requires authentication
Paginated, platform-wide list of conversations, optionally filtered by organisation, user, or a free-text search against the subject.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/messages/conversations?organization_id=019f9939-c4c3-70fb-a54e-5ebf63db36d2&user_id=019f9939-c4c3-70fb-a54e-5ebf63db36d2&q=Schicht&per_page=20" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"organization_id\": \"6ff8f7f6-1eb3-3525-be4a-3932c805afed\",
\"user_id\": \"6b72fe4a-5b40-307c-bc24-f79acf9a1bb9\",
\"q\": \"m\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/messages/conversations"
);
const params = {
"organization_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"user_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"q": "Schicht",
"per_page": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"organization_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed",
"user_id": "6b72fe4a-5b40-307c-bc24-f79acf9a1bb9",
"q": "m"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/messages/conversations';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'organization_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'user_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'q' => 'Schicht',
'per_page' => '20',
],
'json' => [
'organization_id' => '6ff8f7f6-1eb3-3525-be4a-3932c805afed',
'user_id' => '6b72fe4a-5b40-307c-bc24-f79acf9a1bb9',
'q' => 'm',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/messages/conversations')
.replace(queryParameters: {
'organization_id': '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'user_id': '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'q': 'Schicht',
'per_page': '20',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"organization_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed",
"user_id": "6b72fe4a-5b40-307c-bc24-f79acf9a1bb9",
"q": "m"
};
final response = await http.get(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "312f42e4-0d24-4b77-b40b-c08cbc8cb1e2",
"timestamp": "2026-08-21T05:14:36.300932Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Show Conversation Thread
requires authentication
Paginated, read-only message history for a conversation. Sender names are resolved via bulk join queries rather than per-message lookups.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/messages/conversations/019fd51d-53c7-73d0-880d-8edee1800329?per_page=50&before=2026-06-01T00%3A00%3A00Z" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"per_page\": 1,
\"before\": \"2026-08-21T05:14:36\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/messages/conversations/019fd51d-53c7-73d0-880d-8edee1800329"
);
const params = {
"per_page": "50",
"before": "2026-06-01T00:00:00Z",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"per_page": 1,
"before": "2026-08-21T05:14:36"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/messages/conversations/019fd51d-53c7-73d0-880d-8edee1800329';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'per_page' => '50',
'before' => '2026-06-01T00:00:00Z',
],
'json' => [
'per_page' => 1,
'before' => '2026-08-21T05:14:36',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/messages/conversations/019fd51d-53c7-73d0-880d-8edee1800329')
.replace(queryParameters: {
'per_page': '50',
'before': '2026-06-01T00:00:00Z',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"per_page": 1,
"before": "2026-08-21T05:14:36"
};
final response = await http.get(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "db671b12-e2fc-457e-b129-8de92ac9460f",
"timestamp": "2026-08-21T05:14:36.315491Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
System
Get System Health
requires authentication
Latest result per health check and the overall derived status (healthy, degraded, or unhealthy).
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/system/health" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/system/health"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/system/health';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/system/health');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "d067ae32-0f50-4752-8381-87f0a057109e",
"timestamp": "2026-08-21T05:14:36.361872Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Fraud
Show Fraud Case
requires authentication
Full detail of a fraud case: the entities involved, the evidence the signal collected, and its review history.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/fraud/cases/019ffe44-1675-717e-a552-4f410e68ac0f" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/fraud/cases/019ffe44-1675-717e-a552-4f410e68ac0f"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/fraud/cases/019ffe44-1675-717e-a552-4f410e68ac0f';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/fraud/cases/019ffe44-1675-717e-a552-4f410e68ac0f');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "bd6c8605-e0fc-4a2c-9735-10a25d924945",
"timestamp": "2026-08-21T05:14:36.378810Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Fraud Case Status
requires authentication
Move a fraud case into review, confirm it, or dismiss it with
resolution notes. A dismissed case is left untouched by the nightly
fraud:evaluate sweep until a reviewer reopens it.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/fraud/cases/019ffe44-1675-717e-a552-4f410e68ac0f/status" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"status\": \"confirmed\",
\"resolution_notes\": \"Confirmed — same person operating two accounts.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/fraud/cases/019ffe44-1675-717e-a552-4f410e68ac0f/status"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"status": "confirmed",
"resolution_notes": "Confirmed — same person operating two accounts."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/fraud/cases/019ffe44-1675-717e-a552-4f410e68ac0f/status';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'status' => 'confirmed',
'resolution_notes' => 'Confirmed — same person operating two accounts.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/fraud/cases/019ffe44-1675-717e-a552-4f410e68ac0f/status');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"status": "confirmed",
"resolution_notes": "Confirmed — same person operating two accounts."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (422, Invalid status):
{
"status": "VALIDATION_ERROR",
"message": "The status field is invalid."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Fraud Rule
requires authentication
Enable/disable a fraud signal or update its threshold/window config. The signal key and severity are fixed at the code level and cannot be changed here.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/admin/fraud/rules/019fe183-5843-7311-9ead-2251ec85b3f1" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"is_active\": true,
\"config\": {
\"min_shared_users\": 3
}
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/fraud/rules/019fe183-5843-7311-9ead-2251ec85b3f1"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"is_active": true,
"config": {
"min_shared_users": 3
}
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/fraud/rules/019fe183-5843-7311-9ead-2251ec85b3f1';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'is_active' => true,
'config' => ['min_shared_users' => 3],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/fraud/rules/019fe183-5843-7311-9ead-2251ec85b3f1');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"is_active": true,
"config": {
"min_shared_users": 3
}
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Admins
List Admins
requires authentication
Returns a paginated list of all admin accounts, with optional filters.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/admins?search=john&role=admin&is_active=1&per_page=15&sort=name&order=asc" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/admins"
);
const params = {
"search": "john",
"role": "admin",
"is_active": "1",
"per_page": "15",
"sort": "name",
"order": "asc",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/admins';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'search' => 'john',
'role' => 'admin',
'is_active' => '1',
'per_page' => '15',
'sort' => 'name',
'order' => 'asc',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/admins')
.replace(queryParameters: {
'search': 'john',
'role': 'admin',
'is_active': '1',
'per_page': '15',
'sort': 'name',
'order': 'asc',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [],
"errors": null,
"meta": {
"request_id": "864a4b86-aeb4-4ca0-b5dc-29ebed259c97",
"timestamp": "2026-08-05T16:18:42.604748Z",
"current_page": 1,
"last_page": 1,
"per_page": 15,
"total": 0
}
}
Example response (403, Forbidden):
{
"status": "FORBIDDEN",
"message": "Forbidden.",
"data": null,
"errors": [
{
"field": null,
"message": "Forbidden."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Export Admins
requires authentication
Streams the full admin roster as a CSV file.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/admins/export" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/admins/export"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/admins/export';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/admins/export');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "faad9a42-9a68-459c-b2a7-61c6d335c075",
"timestamp": "2026-08-21T05:14:36.475427Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Invoices
List Invoices
requires authentication
List invoices with filtering and pagination.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/invoices" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/invoices"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/invoices';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/invoices');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"invoices": [
{
"id": "3257a732-8d8a-4de5-8dee-a54e85c7e111",
"invoice_number": "RE-2026-055747",
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas"
},
"period": "2026-08",
"status": "draft",
"status_label": "Draft",
"subtotal_cents": 55952,
"vat_amount_cents": 11190,
"total_cents": 67142,
"vat_rate_percent": 20,
"line_items_count": 0,
"invoice_date": "2026-08-05",
"due_date": "2026-08-19",
"paid_at": null,
"created_at": "2026-08-05T16:18:32+00:00"
}
],
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 20,
"total": 1
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Show Invoice
requires authentication
Show detailed invoice information for an admin, across any organisation.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/invoices/019f1bd5-82b2-7341-abb8-e8f08fd445c3" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/invoices/019f1bd5-82b2-7341-abb8-e8f08fd445c3"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/invoices/019f1bd5-82b2-7341-abb8-e8f08fd445c3';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/invoices/019f1bd5-82b2-7341-abb8-e8f08fd445c3');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"invoice": {
"id": "3257a732-8d8a-4de5-8dee-a54e85c7e111",
"invoice_number": "RE-2026-055747",
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas"
},
"period": "2026-08",
"status": "draft",
"status_label": "Draft",
"reference": null,
"notes": null,
"summary": {
"subtotal_cents": 55952,
"vat_rate_percent": 20,
"vat_amount_cents": 11190,
"platform_fee_cents": 0,
"total_cents": 67142,
"paid_amount_cents": 0,
"remaining_cents": 67142
},
"dates": {
"invoice_date": "2026-08-05",
"due_date": "2026-08-19",
"sent_at": null,
"paid_at": null
},
"payment_reference": null,
"pdf_path": null,
"line_items": [],
"created_at": "2026-08-05T16:18:32+00:00",
"updated_at": "2026-08-05T16:18:32+00:00"
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Wallet
GET /admin/wallet/withdrawals — every company's withdrawal requests, newest first, so admins can find the ones awaiting review instead of relying on each company's own history endpoint. Optional `?status=` filter.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/wallet/withdrawals" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"status\": \"architecto\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/wallet/withdrawals"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"status": "architecto"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/wallet/withdrawals';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'status' => 'architecto',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/wallet/withdrawals');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"status": "architecto"
};
final response = await http.get(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"withdrawals": [],
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 20,
"total": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
POST /admin/wallet/withdrawals/{withdrawal}/approve — approve a pending, over-threshold withdrawal and run the card refund.
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/wallet/withdrawals/architecto/approve" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/wallet/withdrawals/architecto/approve"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/wallet/withdrawals/architecto/approve';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/wallet/withdrawals/architecto/approve');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
POST /admin/wallet/withdrawals/{withdrawal}/reject — reject a pending withdrawal and release its reserved funds back to the company.
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/wallet/withdrawals/architecto/reject" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Krankheitsbedingt kurzfristig abgesagt.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/wallet/withdrawals/architecto/reject"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/wallet/withdrawals/architecto/reject';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'Krankheitsbedingt kurzfristig abgesagt.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/wallet/withdrawals/architecto/reject');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Assignments
List Assignments
requires authentication
Every assignment across all organisations, for operations oversight — the platform-wide view of who is working where, which the per-company endpoint cannot give because it is scoped to one organisation.
Unfiltered this spans the whole history, newest first, since the rows an operator acts on are the ones nearest to now.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/assignments?status=checked_in&organization_id=019f9939-c4c3-70fb-a54e-5ebf63db36d2&date_from=2026-07-01&date_to=2026-07-31&search=Brunner&per_page=25" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"status\": \"hours_confirmed\",
\"organization_id\": \"6ff8f7f6-1eb3-3525-be4a-3932c805afed\",
\"date_from\": \"2026-08-21T05:14:36\",
\"date_to\": \"2026-08-21T05:14:36\",
\"search\": \"g\",
\"per_page\": 16
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/assignments"
);
const params = {
"status": "checked_in",
"organization_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"date_from": "2026-07-01",
"date_to": "2026-07-31",
"search": "Brunner",
"per_page": "25",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"status": "hours_confirmed",
"organization_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed",
"date_from": "2026-08-21T05:14:36",
"date_to": "2026-08-21T05:14:36",
"search": "g",
"per_page": 16
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/assignments';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'status' => 'checked_in',
'organization_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'date_from' => '2026-07-01',
'date_to' => '2026-07-31',
'search' => 'Brunner',
'per_page' => '25',
],
'json' => [
'status' => 'hours_confirmed',
'organization_id' => '6ff8f7f6-1eb3-3525-be4a-3932c805afed',
'date_from' => '2026-08-21T05:14:36',
'date_to' => '2026-08-21T05:14:36',
'search' => 'g',
'per_page' => 16,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/assignments')
.replace(queryParameters: {
'status': 'checked_in',
'organization_id': '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'date_from': '2026-07-01',
'date_to': '2026-07-31',
'search': 'Brunner',
'per_page': '25',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"status": "hours_confirmed",
"organization_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed",
"date_from": "2026-08-21T05:14:36",
"date_to": "2026-08-21T05:14:36",
"search": "g",
"per_page": 16
};
final response = await http.get(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"assignments": [],
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 16,
"total": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Decide a Shift Request (Admin Override)
requires authentication
Approve or decline a worker's shift request on behalf of the company — used when a company is unresponsive or a decision needs correcting.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/shift-requests/019fdd1b-c901-7051-b2ed-3a96150483ed/decide" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"approve\": true,
\"note\": \"Overtime was not authorised on site.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/shift-requests/019fdd1b-c901-7051-b2ed-3a96150483ed/decide"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"approve": true,
"note": "Overtime was not authorised on site."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/shift-requests/019fdd1b-c901-7051-b2ed-3a96150483ed/decide';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'approve' => true,
'note' => 'Overtime was not authorised on site.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/shift-requests/019fdd1b-c901-7051-b2ed-3a96150483ed/decide');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"approve": true,
"note": "Overtime was not authorised on site."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (409, Already decided):
{
"status": "INVALID_OPERATION",
"message": "This request has already been decided."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Ratings
List Ratings
requires authentication
Ratings exchanged between companies and workers, newest first, for moderation oversight.
Anonymity is a promise made to the rater in the apps, not a rule for this endpoint: moderation is impossible without knowing who wrote what, so the identities are returned here and the obligation moves to who may call it.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/ratings?min_score=2&has_comment=1&per_page=25" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"min_score\": 1,
\"has_comment\": false,
\"per_page\": 22
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/ratings"
);
const params = {
"min_score": "2",
"has_comment": "1",
"per_page": "25",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"min_score": 1,
"has_comment": false,
"per_page": 22
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/ratings';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'min_score' => '2',
'has_comment' => '1',
'per_page' => '25',
],
'json' => [
'min_score' => 1,
'has_comment' => false,
'per_page' => 22,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/ratings')
.replace(queryParameters: {
'min_score': '2',
'has_comment': '1',
'per_page': '25',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"min_score": 1,
"has_comment": false,
"per_page": 22
};
final response = await http.get(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"ratings": [],
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 22,
"total": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Compliance
List Compliance Violations
requires authentication
List compliance violations with filtering.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/compliance/violations" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/compliance/violations"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/compliance/violations';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/compliance/violations');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"violations": [],
"summary": {
"total_unresolved": 0,
"critical_unresolved": 0
},
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 20,
"total": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Resolve Compliance Violation
requires authentication
Resolve a compliance violation.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/compliance/violations/architecto/resolve" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"notes\": \"Beispieltext\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/compliance/violations/architecto/resolve"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"notes": "Beispieltext"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/compliance/violations/architecto/resolve';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'notes' => 'Beispieltext',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/compliance/violations/architecto/resolve');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"notes": "Beispieltext"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Generate Compliance Report
requires authentication
Generate compliance report for a period.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/compliance/reports" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"organization_id\": \"019f9939-c4c3-70fb-a54e-5ebf63db36d2\",
\"from\": \"2026-09-30\",
\"to\": \"2026-09-30\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/compliance/reports"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"organization_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"from": "2026-09-30",
"to": "2026-09-30"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/compliance/reports';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'organization_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'from' => '2026-09-30',
'to' => '2026-09-30',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/compliance/reports');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"organization_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"from": "2026-09-30",
"to": "2026-09-30"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"report": {
"period": {
"from": "2026-09-30",
"to": "2026-09-30"
},
"total_violations": 0,
"resolved": 0,
"unresolved": 0,
"by_severity": [],
"by_type": [],
"compliance_score": 100
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Fallweise Flags
requires authentication
List fallweise-Beschäftigung Ampel flags (yellow/red engagements) with filtering — the audit trail proving casual employment is monitored for regularity (Beschäftigungskonzept §3).
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/compliance/fallweise-flags" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/compliance/fallweise-flags"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/compliance/fallweise-flags';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/compliance/fallweise-flags');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"flags": [],
"summary": {
"yellow": 0,
"red": 0
},
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 20,
"total": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reports
Get Reports Summary
requires authentication
Platform-wide KPI groups — assignments, hours, money, growth, compliance, ratings — for a date range. Defaults to the current calendar month.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/reports/summary?date_from=2026-05-01&date_to=2026-05-31" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"date_from\": \"2026-08-21T05:14:36\",
\"date_to\": \"2026-08-21T05:14:36\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/reports/summary"
);
const params = {
"date_from": "2026-05-01",
"date_to": "2026-05-31",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"date_from": "2026-08-21T05:14:36",
"date_to": "2026-08-21T05:14:36"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/reports/summary';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'date_from' => '2026-05-01',
'date_to' => '2026-05-31',
],
'json' => [
'date_from' => '2026-08-21T05:14:36',
'date_to' => '2026-08-21T05:14:36',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/reports/summary')
.replace(queryParameters: {
'date_from': '2026-05-01',
'date_to': '2026-05-31',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"date_from": "2026-08-21T05:14:36",
"date_to": "2026-08-21T05:14:36"
};
final response = await http.get(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "2ef084b4-a17b-462a-8e18-7786504d90af",
"timestamp": "2026-08-21T05:14:36.739104Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Reports Series
requires authentication
Weekly time-series of completed assignments, top-up volume, new workers, and compliance violations for a date range. Defaults to the current calendar month.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/reports/series?date_from=2026-05-01&date_to=2026-05-31" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"date_from\": \"2026-08-21T05:14:36\",
\"date_to\": \"2026-08-21T05:14:36\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/reports/series"
);
const params = {
"date_from": "2026-05-01",
"date_to": "2026-05-31",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"date_from": "2026-08-21T05:14:36",
"date_to": "2026-08-21T05:14:36"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/reports/series';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'date_from' => '2026-05-01',
'date_to' => '2026-05-31',
],
'json' => [
'date_from' => '2026-08-21T05:14:36',
'date_to' => '2026-08-21T05:14:36',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/reports/series')
.replace(queryParameters: {
'date_from': '2026-05-01',
'date_to': '2026-05-31',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"date_from": "2026-08-21T05:14:36",
"date_to": "2026-08-21T05:14:36"
};
final response = await http.get(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "9d489aaf-a4e2-4696-a234-1eca78e8cb4f",
"timestamp": "2026-08-21T05:14:36.753892Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Export Reports
requires authentication
Streams one reports section — assignments, money, growth, or compliance — as a CSV download for the given date range.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/reports/export?section=assignments&date_from=2026-05-01&date_to=2026-05-31" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"section\": \"architecto\",
\"date_from\": \"2026-08-21T05:14:36\",
\"date_to\": \"2026-08-21T05:14:36\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/reports/export"
);
const params = {
"section": "assignments",
"date_from": "2026-05-01",
"date_to": "2026-05-31",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"section": "architecto",
"date_from": "2026-08-21T05:14:36",
"date_to": "2026-08-21T05:14:36"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/reports/export';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'section' => 'assignments',
'date_from' => '2026-05-01',
'date_to' => '2026-05-31',
],
'json' => [
'section' => 'architecto',
'date_from' => '2026-08-21T05:14:36',
'date_to' => '2026-08-21T05:14:36',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/reports/export')
.replace(queryParameters: {
'section': 'assignments',
'date_from': '2026-05-01',
'date_to': '2026-05-31',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"section": "architecto",
"date_from": "2026-08-21T05:14:36",
"date_to": "2026-08-21T05:14:36"
};
final response = await http.get(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "9cd044c7-a95b-4c30-994a-cd26f220e034",
"timestamp": "2026-08-21T05:14:36.768364Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Legal
List Legal Document Versions
requires authentication
List legal document versions (terms, privacy/Datenschutz, AÜG info, …).
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/legal/documents" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/legal/documents"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/legal/documents';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/legal/documents');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": [
{
"id": "019fd2b7-ef68-7312-a1a3-6b14820cf9e2",
"document_type": "privacy_policy",
"document_label": "Privacy Policy",
"version": 1,
"locale": "de",
"title": "Datenschutzerklärung",
"public_url": null,
"requires_reacceptance": true,
"is_active": true,
"requires_consent": true,
"accepted_count": 1,
"pending_count": 15,
"published_at": "2026-08-05T16:18:17+00:00",
"created_at": "2026-08-05T16:18:17+00:00"
},
{
"id": "019fd2b7-ef6c-7272-a1a7-6eebcd113ec1",
"document_type": "privacy_policy",
"document_label": "Privacy Policy",
"version": 1,
"locale": "en",
"title": "Privacy Policy",
"public_url": null,
"requires_reacceptance": true,
"is_active": true,
"requires_consent": true,
"accepted_count": 0,
"pending_count": 16,
"published_at": "2026-08-05T16:18:17+00:00",
"created_at": "2026-08-05T16:18:17+00:00"
},
{
"id": "019fd2b7-ef6f-72ae-8c86-d9977da26ec0",
"document_type": "terms_of_service",
"document_label": "Terms and Conditions",
"version": 1,
"locale": "de",
"title": "Allgemeine Geschäftsbedingungen (AGB)",
"public_url": null,
"requires_reacceptance": true,
"is_active": true,
"requires_consent": true,
"accepted_count": 1,
"pending_count": 15,
"published_at": "2026-08-05T16:18:17+00:00",
"created_at": "2026-08-05T16:18:17+00:00"
},
{
"id": "019fd2b7-ef73-7323-9eea-ef440b63f842",
"document_type": "terms_of_service",
"document_label": "Terms and Conditions",
"version": 1,
"locale": "en",
"title": "Terms of Service",
"public_url": null,
"requires_reacceptance": true,
"is_active": true,
"requires_consent": true,
"accepted_count": 0,
"pending_count": 16,
"published_at": "2026-08-05T16:18:17+00:00",
"created_at": "2026-08-05T16:18:17+00:00"
},
{
"id": "019fd2b7-ef76-73b5-a9c5-d7cca778324b",
"document_type": "data_processing",
"document_label": "Data Processing",
"version": 1,
"locale": "de",
"title": "Einwilligung zur Datenverarbeitung",
"public_url": null,
"requires_reacceptance": true,
"is_active": true,
"requires_consent": true,
"accepted_count": 1,
"pending_count": 15,
"published_at": "2026-08-05T16:18:17+00:00",
"created_at": "2026-08-05T16:18:17+00:00"
},
{
"id": "019fd2b7-ef79-7064-b74c-069b159b28f9",
"document_type": "data_processing",
"document_label": "Data Processing",
"version": 1,
"locale": "en",
"title": "Data Processing Consent",
"public_url": null,
"requires_reacceptance": true,
"is_active": true,
"requires_consent": true,
"accepted_count": 0,
"pending_count": 16,
"published_at": "2026-08-05T16:18:17+00:00",
"created_at": "2026-08-05T16:18:17+00:00"
},
{
"id": "019fd2b7-ef7c-732a-b29e-ef789f899c9d",
"document_type": "aug_info",
"document_label": "Temporary Employment Contract (AÜG)",
"version": 1,
"locale": "de",
"title": "Information gemäß AÜG (Arbeitskräfteüberlassungsgesetz)",
"public_url": null,
"requires_reacceptance": false,
"is_active": true,
"requires_consent": false,
"accepted_count": 0,
"pending_count": 0,
"published_at": "2026-08-05T16:18:17+00:00",
"created_at": "2026-08-05T16:18:17+00:00"
},
{
"id": "019fd2b7-ef7f-72f2-9fb3-4a25c846761e",
"document_type": "aug_info",
"document_label": "Temporary Employment Contract (AÜG)",
"version": 1,
"locale": "en",
"title": "Information pursuant to AÜG (Temporary Work Act)",
"public_url": null,
"requires_reacceptance": false,
"is_active": true,
"requires_consent": false,
"accepted_count": 0,
"pending_count": 0,
"published_at": "2026-08-05T16:18:17+00:00",
"created_at": "2026-08-05T16:18:17+00:00"
},
{
"id": "019fd2b7-ef83-7298-a78c-af4b1e36b67b",
"document_type": "svnr_consent",
"document_label": "Social Security Number Consent",
"version": 1,
"locale": "de",
"title": "Einwilligung zur Verarbeitung der Sozialversicherungsnummer",
"public_url": null,
"requires_reacceptance": true,
"is_active": true,
"requires_consent": true,
"accepted_count": 1,
"pending_count": 15,
"published_at": "2026-08-05T16:18:17+00:00",
"created_at": "2026-08-05T16:18:17+00:00"
},
{
"id": "019fd2b7-ef86-70be-8580-5a1ac1757a9a",
"document_type": "cookie_policy",
"document_label": "Cookie Policy",
"version": 1,
"locale": "de",
"title": "Cookie-Richtlinie",
"public_url": null,
"requires_reacceptance": false,
"is_active": true,
"requires_consent": false,
"accepted_count": 0,
"pending_count": 0,
"published_at": "2026-08-05T16:18:17+00:00",
"created_at": "2026-08-05T16:18:17+00:00"
},
{
"id": "019fd2b7-ef88-722e-9c3a-fa64bb1c2833",
"document_type": "cookie_policy",
"document_label": "Cookie Policy",
"version": 1,
"locale": "en",
"title": "Cookie Policy",
"public_url": null,
"requires_reacceptance": false,
"is_active": true,
"requires_consent": false,
"accepted_count": 0,
"pending_count": 0,
"published_at": "2026-08-05T16:18:17+00:00",
"created_at": "2026-08-05T16:18:17+00:00"
},
{
"id": "019fd2b7-ef8a-7286-ada6-84f13beb905f",
"document_type": "imprint",
"document_label": "Imprint",
"version": 1,
"locale": "de",
"title": "Impressum",
"public_url": null,
"requires_reacceptance": false,
"is_active": true,
"requires_consent": false,
"accepted_count": 0,
"pending_count": 0,
"published_at": "2026-08-05T16:18:17+00:00",
"created_at": "2026-08-05T16:18:17+00:00"
},
{
"id": "019fd2b7-ef8c-70fe-970a-72fcd401d198",
"document_type": "imprint",
"document_label": "Imprint",
"version": 1,
"locale": "en",
"title": "Imprint",
"public_url": null,
"requires_reacceptance": false,
"is_active": true,
"requires_consent": false,
"accepted_count": 0,
"pending_count": 0,
"published_at": "2026-08-05T16:18:17+00:00",
"created_at": "2026-08-05T16:18:17+00:00"
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create Legal Document Version
requires authentication
Publish a new version of a legal document (terms, privacy/Datenschutz, AÜG info, …). The new version becomes active and supersedes the previous one; the activation is recorded in the immutable audit trail.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/legal/documents" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"document_type\": \"Beispieltext\",
\"content\": \"Beispieltext\",
\"locale\": \"Beispieltext\",
\"title\": \"Frage zur Abrechnung\",
\"public_url\": \"Beispieltext\",
\"requires_reacceptance\": true
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/legal/documents"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"document_type": "Beispieltext",
"content": "Beispieltext",
"locale": "Beispieltext",
"title": "Frage zur Abrechnung",
"public_url": "Beispieltext",
"requires_reacceptance": true
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/legal/documents';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'document_type' => 'Beispieltext',
'content' => 'Beispieltext',
'locale' => 'Beispieltext',
'title' => 'Frage zur Abrechnung',
'public_url' => 'Beispieltext',
'requires_reacceptance' => true,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/legal/documents');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"document_type": "Beispieltext",
"content": "Beispieltext",
"locale": "Beispieltext",
"title": "Frage zur Abrechnung",
"public_url": "Beispieltext",
"requires_reacceptance": true
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Legal Document Acceptance Status
requires authentication
For a legal document type, return its current version and which active organisations have accepted it vs. are still pending.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/legal/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2/acceptance-status" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/legal/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2/acceptance-status"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/legal/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2/acceptance-status';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/legal/documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2/acceptance-status');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "39ffedb7-32cf-41e0-aef3-b746247e7fb1",
"timestamp": "2026-08-21T05:14:36.806720Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Show Legal Document Version
requires authentication
Show a single legal document version, including its full content.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/legal/documents/019f0593-c509-716b-8a38-d51a1a7de274" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/legal/documents/019f0593-c509-716b-8a38-d51a1a7de274"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/legal/documents/019f0593-c509-716b-8a38-d51a1a7de274';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/legal/documents/019f0593-c509-716b-8a38-d51a1a7de274');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"id": "019fd2b7-ef68-7312-a1a3-6b14820cf9e2",
"document_type": "privacy_policy",
"version": 1,
"locale": "de",
"title": "Datenschutzerklärung",
"content": "# Datenschutzerklärung\n\n**Stand: 05.08.2026**\n**Version: 1.0**\n\n---\n\n## 1. Verantwortlicher\n\n**Flexxer**\nMusterstraße 1\n1010 Wien, Österreich\n\n- **Firmenbuchnummer:** FN 123456x\n- **UID-Nummer:** ATU12345678\n- **Telefon:** +43 1 234 5678\n- **E-Mail:** privacy@flexxr.at\n- **Website:** https://flexxr.at\n\n### 1.1 Datenschutzbeauftragter\n\nFür Fragen zum Datenschutz erreichen Sie unseren Datenschutzbeauftragten unter:\n- **E-Mail:** dpo@flexxr.at\n\n---\n\n## 2. Rechtsgrundlagen der Verarbeitung\n\nWir verarbeiten Ihre personenbezogenen Daten ausschließlich auf Basis der folgenden Rechtsgrundlagen gemäß **Datenschutz-Grundverordnung (DSGVO)** und dem **österreichischen Datenschutzgesetz (DSG)**:\n\n| Rechtsgrundlage | DSGVO Artikel | Anwendungsbereich |\n|-----------------|---------------|-------------------|\n| Vertragserfüllung | Art. 6 Abs. 1 lit. b | Durchführung des Arbeits-/Überlassungsvertrags |\n| Rechtliche Verpflichtung | Art. 6 Abs. 1 lit. c | ASVG-Meldungen, Lohnsteuer, AÜG-Compliance |\n| Berechtigtes Interesse | Art. 6 Abs. 1 lit. f | Betrugsprävention, IT-Sicherheit |\n| Einwilligung | Art. 6 Abs. 1 lit. a | Marketing, optionale Datenverarbeitung |\n\n---\n\n## 3. Kategorien personenbezogener Daten\n\n### 3.1 Stammdaten\n- Vor- und Nachname\n- Geburtsdatum und Geburtsort\n- Staatsangehörigkeit\n- Geschlecht\n- Familienstand\n\n### 3.2 Kontaktdaten\n- E-Mail-Adresse\n- Telefonnummer\n- Wohnadresse\n\n### 3.3 Beschäftigungsdaten\n- Sozialversicherungsnummer (SVNR) gemäß ASVG\n- Steuernummer\n- Bankverbindung (IBAN)\n- Qualifikationen und Zertifikate\n- Arbeitszeitaufzeichnungen\n\n### 3.4 Besondere Kategorien (Art. 9 DSGVO)\n- Gesundheitsdaten (nur bei medizinischen Bescheinigungen)\n- Gewerkschaftszugehörigkeit (nur bei KV-Anwendung)\n\nDiese Daten werden nur mit ausdrücklicher Einwilligung oder aufgrund gesetzlicher Verpflichtung verarbeitet.\n\n---\n\n## 4. Zwecke der Verarbeitung\n\n### 4.1 Vertragserfüllung\n- Durchführung des Arbeitsvertrags gemäß **AÜG § 11**\n- Vermittlung von Arbeitseinsätzen\n- Arbeitszeiterfassung und Abrechnung\n- Lohn- und Gehaltsabrechnung\n\n### 4.2 Gesetzliche Verpflichtungen\n- ELDA-Meldungen an die ÖGK (gemäß **ASVG §§ 33-34**)\n- Lohnsteuerabzug und Meldung an das Finanzamt (**EStG**)\n- Aufbewahrungspflichten (**BAO § 132**: 7 Jahre für Geschäftsunterlagen)\n- AÜG-Meldepflichten an die Gewerbebehörde\n\n### 4.3 Berechtigte Interessen\n- Betrugsprävention und Identitätsprüfung\n- IT-Sicherheit und Systemstabilität\n- Qualitätssicherung und Prozessoptimierung\n\n---\n\n## 5. Empfänger der Daten\n\nIhre Daten werden an folgende Kategorien von Empfängern übermittelt:\n\n| Empfänger | Zweck | Rechtsgrundlage |\n|-----------|-------|-----------------|\n| ÖGK (Österreichische Gesundheitskasse) | Sozialversicherungsmeldungen | ASVG §§ 33-34 |\n| Finanzamt | Lohnsteuer, Lohnzettel | EStG § 84 |\n| Beschäftiger (Kundenunternehmen) | Arbeitseinsatz | AÜG § 12 |\n| Lohnverrechnungsdienstleister | Gehaltsabrechnung | Auftragsverarbeitung |\n| IT-Dienstleister | Hosting, Cloud-Services | Auftragsverarbeitung |\n\n---\n\n## 6. Speicherdauer\n\n| Datenkategorie | Speicherdauer | Rechtsgrundlage |\n|----------------|---------------|-----------------|\n| Lohnabrechnungsunterlagen | 7 Jahre | BAO § 132 |\n| Arbeitszeitaufzeichnungen | 3 Jahre nach Ende des Arbeitsverhältnisses | AZG § 26 |\n| SV-Meldungen | 7 Jahre | ASVG |\n| Bewerbungsunterlagen (bei Ablehnung) | 6 Monate | DSGVO Art. 17 |\n| Vertragsdokumente | 30 Jahre (Verjährungsfrist) | ABGB § 1489 |\n\n---\n\n## 7. Ihre Rechte nach DSGVO\n\nSie haben folgende Rechte bezüglich Ihrer personenbezogenen Daten:\n\n### 7.1 Auskunftsrecht (Art. 15 DSGVO)\nSie haben das Recht, eine Bestätigung darüber zu verlangen, ob personenbezogene Daten verarbeitet werden, und gegebenenfalls Auskunft über diese Daten zu erhalten.\n\n### 7.2 Recht auf Berichtigung (Art. 16 DSGVO)\nSie haben das Recht, unrichtige personenbezogene Daten unverzüglich berichtigen zu lassen.\n\n### 7.3 Recht auf Löschung (Art. 17 DSGVO)\nSie haben das Recht, die Löschung Ihrer Daten zu verlangen, sofern keine gesetzlichen Aufbewahrungspflichten entgegenstehen.\n\n### 7.4 Recht auf Einschränkung (Art. 18 DSGVO)\nSie haben das Recht, die Einschränkung der Verarbeitung zu verlangen.\n\n### 7.5 Recht auf Datenübertragbarkeit (Art. 20 DSGVO)\nSie haben das Recht, Ihre Daten in einem strukturierten, gängigen und maschinenlesbaren Format zu erhalten.\n\n### 7.6 Widerspruchsrecht (Art. 21 DSGVO)\nSie haben das Recht, gegen die Verarbeitung Ihrer Daten Widerspruch einzulegen.\n\n### 7.7 Recht auf Widerruf der Einwilligung (Art. 7 Abs. 3 DSGVO)\nSie haben das Recht, erteilte Einwilligungen jederzeit zu widerrufen.\n\n---\n\n## 8. Beschwerderecht bei der Aufsichtsbehörde\n\nSie haben das Recht, eine Beschwerde bei der zuständigen Aufsichtsbehörde einzureichen:\n\n**Österreichische Datenschutzbehörde**\nBarichgasse 40-42\n1030 Wien\n\n- **E-Mail:** dsb@dsb.gv.at\n- **Website:** https://www.dsb.gv.at\n\n---\n\n## 9. Automatisierte Entscheidungsfindung\n\nEs findet keine automatisierte Entscheidungsfindung im Sinne von **Art. 22 DSGVO** statt, die rechtliche Wirkung entfaltet oder Sie in ähnlicher Weise erheblich beeinträchtigt.\n\n---\n\n## 10. Drittlandübermittlung\n\nEine Übermittlung Ihrer Daten in Drittländer (außerhalb des EWR) erfolgt nur:\n- Auf Basis von Angemessenheitsbeschlüssen der EU-Kommission\n- Unter Verwendung von EU-Standardvertragsklauseln\n- Mit Ihrer ausdrücklichen Einwilligung\n\n---\n\n## 11. Änderungen dieser Datenschutzerklärung\n\nWir behalten uns vor, diese Datenschutzerklärung anzupassen, um sie an geänderte Rechtslagen oder bei Änderungen unserer Dienste anzupassen. Die aktuelle Version finden Sie stets unter: https://flexxr.at/legal/privacy_policy\n\n---\n\n## 12. Kontakt\n\nBei Fragen zum Datenschutz wenden Sie sich bitte an:\n\n**Flexxer**\nMusterstraße 1, 1010 Wien\nE-Mail: privacy@flexxr.at\n",
"content_hash": "7d28b9a8ddc190e477a58a1d95a0a50d2f0428e19594df2dfff7742c94e784ff",
"public_url": null,
"requires_reacceptance": true,
"is_active": true,
"published_at": "2026-08-05T16:18:17+00:00",
"created_at": "2026-08-05T16:18:17+00:00"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Support
List Support Tickets
requires authentication
The tickets visible to the caller, newest first, optionally narrowed by status.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/support/tickets" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/support/tickets"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/support/tickets';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/support/tickets');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"tickets": [
{
"id": "019fd2b8-28b2-7322-b70c-bc7d76debfc3",
"ticket_number": "TKT-717858",
"subject": "Nihil autem neque blanditiis accusantium eaque.",
"category": "general",
"category_label": "Allgemein",
"status": "open",
"status_label": "Offen",
"priority": 3,
"requester_type": "company",
"requester_name": "Caritas",
"assignee_name": null,
"message_count": 0,
"last_message_at": null,
"created_at": "2026-08-05T16:18:32+00:00"
},
{
"id": "019fd2b8-2e3b-7096-97f9-96d4a481c803",
"ticket_number": "TKT-969367",
"subject": "Totam autem repellendus quasi iste debitis fugiat.",
"category": "complaint",
"category_label": "Beschwerde",
"status": "open",
"status_label": "Offen",
"priority": 2,
"requester_type": "worker",
"requester_name": "Anna Neuling",
"assignee_name": null,
"message_count": 0,
"last_message_at": null,
"created_at": "2026-08-05T16:18:33+00:00"
}
],
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 20,
"total": 2
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Show a Support Ticket
requires authentication
One ticket with its message thread. Internal notes are never included.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"id": "019fd2b8-28b2-7322-b70c-bc7d76debfc3",
"ticket_number": "TKT-717858",
"subject": "Nihil autem neque blanditiis accusantium eaque.",
"category": "general",
"category_label": "Allgemein",
"status": "open",
"status_label": "Offen",
"priority": 3,
"requester_type": "company",
"requester_name": "Caritas",
"assignee_name": null,
"message_count": 0,
"last_message_at": null,
"created_at": "2026-08-05T16:18:32+00:00",
"description": "Quo necessitatibus et tempora esse nemo. Omnis et molestias sed expedita cupiditate.\n\nQuidem mollitia et reprehenderit enim quidem est. Temporibus et blanditiis iusto officia neque molestiae quidem. Adipisci suscipit sit temporibus voluptatum porro molestiae omnis. Rem fuga ratione ratione odio esse odio modi.",
"resolution_notes": null,
"related_entity_type": null,
"related_entity_id": null,
"assigned_to": null,
"first_response_at": null,
"resolved_at": null,
"messages": []
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Assign Ticket
requires authentication
POST /admin/support/tickets/{ticketId}/assign — assign to an agent, defaulting to the acting admin.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/assign" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"admin_id\": \"019f9939-c4c3-70fb-a54e-5ebf63db36d2\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/assign"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"admin_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/assign';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'admin_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/assign');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"admin_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"id": "019fd2b8-28b2-7322-b70c-bc7d76debfc3",
"assigned_to": "019fd2b7-edab-7280-b09f-b18f58a272ee",
"assignee_name": "Super Admin"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reply to a Support Ticket
requires authentication
Appends a message to an existing ticket.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/messages" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"message\": \"Bitte um Rueckmeldung zur naechsten Schicht.\",
\"is_internal\": true
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/messages"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"message": "Bitte um Rueckmeldung zur naechsten Schicht.",
"is_internal": true
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/messages';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'message' => 'Bitte um Rueckmeldung zur naechsten Schicht.',
'is_internal' => true,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/messages');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"message": "Bitte um Rueckmeldung zur naechsten Schicht.",
"is_internal": true
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Your message has been sent.",
"data": {
"message": {
"id": "019fd2b8-539c-7266-9498-f92f5406de4a",
"message": "Bitte um Rueckmeldung zur naechsten Schicht.",
"sender_type": "agent",
"sender_name": "Super Admin",
"is_internal": true,
"attachments": null,
"created_at": "2026-08-05T16:18:43+00:00"
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Ticket Status
requires authentication
POST /admin/support/tickets/{ticketId}/status — transition a ticket. "open" reopens a resolved/closed ticket. Moving to "resolved" notifies the requester and stamps resolved_at; "closed" stamps closed_at.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/status" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"status\": \"Beispieltext\",
\"resolution_notes\": \"Beispieltext\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/status"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"status": "Beispieltext",
"resolution_notes": "Beispieltext"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/status';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'status' => 'Beispieltext',
'resolution_notes' => 'Beispieltext',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/status');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"status": "Beispieltext",
"resolution_notes": "Beispieltext"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Ticket Priority
requires authentication
POST /admin/support/tickets/{ticketId}/priority — 1 (low) .. 4 (urgent).
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/priority" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"priority\": 1
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/priority"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"priority": 1
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/priority';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'priority' => 1,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/priority');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"priority": 1
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"id": "019fd2b8-28b2-7322-b70c-bc7d76debfc3",
"priority": 1
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Organization API
Endpoints for the mobile application (employee users). All endpoints (except authentication) require a valid Bearer token with 2FA verification.
Authentication
Register Organization
Registers a new organization account. All new organizations begin with a pending_verification status. They can authenticate and receive tokens immediately but the org.approved middleware blocks access to protected dashboard endpoints until an admin verifies them.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/auth/register" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Water Foundation\",
\"email\": \"org@example.com\",
\"password\": \"OrgPassword123\",
\"password_confirmation\": \"OrgPassword123\",
\"country_code\": \"+43\",
\"phone_number\": \"6641234567\",
\"description\": \"A charity focused on water access in developing nations.\",
\"website\": \"https:\\/\\/waterfoundation.org\",
\"address\": \"b\",
\"address_line2\": \"n\",
\"uid_number\": \"gzmiyvdljnikhway\",
\"legal_form\": \"ag\",
\"firmenbuchnummer\": \"kcmyuwpwlvqwrsit\",
\"contact_person_name\": \"c\",
\"contact_person_phone\": \"p\",
\"industry_code\": \"scqldz\",
\"company_size\": \"11-50\",
\"terms_accepted\": true,
\"avv_accepted\": true,
\"postal_code\": \"snrwtujwvlxjklqp\",
\"city\": \"p\",
\"country\": \"w\",
\"iso_country_code\": \"qb\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/auth/register"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Water Foundation",
"email": "org@example.com",
"password": "OrgPassword123",
"password_confirmation": "OrgPassword123",
"country_code": "+43",
"phone_number": "6641234567",
"description": "A charity focused on water access in developing nations.",
"website": "https:\/\/waterfoundation.org",
"address": "b",
"address_line2": "n",
"uid_number": "gzmiyvdljnikhway",
"legal_form": "ag",
"firmenbuchnummer": "kcmyuwpwlvqwrsit",
"contact_person_name": "c",
"contact_person_phone": "p",
"industry_code": "scqldz",
"company_size": "11-50",
"terms_accepted": true,
"avv_accepted": true,
"postal_code": "snrwtujwvlxjklqp",
"city": "p",
"country": "w",
"iso_country_code": "qb"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/auth/register';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'name' => 'Water Foundation',
'email' => 'org@example.com',
'password' => 'OrgPassword123',
'password_confirmation' => 'OrgPassword123',
'country_code' => '+43',
'phone_number' => '6641234567',
'description' => 'A charity focused on water access in developing nations.',
'website' => 'https://waterfoundation.org',
'address' => 'b',
'address_line2' => 'n',
'uid_number' => 'gzmiyvdljnikhway',
'legal_form' => 'ag',
'firmenbuchnummer' => 'kcmyuwpwlvqwrsit',
'contact_person_name' => 'c',
'contact_person_phone' => 'p',
'industry_code' => 'scqldz',
'company_size' => '11-50',
'terms_accepted' => true,
'avv_accepted' => true,
'postal_code' => 'snrwtujwvlxjklqp',
'city' => 'p',
'country' => 'w',
'iso_country_code' => 'qb',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/auth/register');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"name": "Water Foundation",
"email": "org@example.com",
"password": "OrgPassword123",
"password_confirmation": "OrgPassword123",
"country_code": "+43",
"phone_number": "6641234567",
"description": "A charity focused on water access in developing nations.",
"website": "https:\/\/waterfoundation.org",
"address": "b",
"address_line2": "n",
"uid_number": "gzmiyvdljnikhway",
"legal_form": "ag",
"firmenbuchnummer": "kcmyuwpwlvqwrsit",
"contact_person_name": "c",
"contact_person_phone": "p",
"industry_code": "scqldz",
"company_size": "11-50",
"terms_accepted": true,
"avv_accepted": true,
"postal_code": "snrwtujwvlxjklqp",
"city": "p",
"country": "w",
"iso_country_code": "qb"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Success):
{
"status": "CREATED",
"message": "Organization registered successfully.",
"data": {
"token": "1|abcdef123456...",
"organization": {
"id": "org-uuid",
"name": "Water Foundation",
"email": "org@example.com",
"status": "pending_verification"
}
},
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (409, Email Already Registered):
{
"status": "EMAIL_ALREADY_EXISTS",
"message": "This email is already registered.",
"data": null,
"errors": [
{
"field": "email",
"message": "This email is already registered."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "name",
"message": "The name field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Login Organization
Authenticates an organization against the organization guard and issues a Sanctum token. If the organization has 2FA enabled a limited challenge token is returned. Note: the org.approved middleware is not applied here; it is applied on the protected routes. An organization in any status may log in — they simply cannot access protected endpoints until approved.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/auth/login" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"org@example.com\",
\"country_code\": \"+43\",
\"phone_number\": \"6641234567\",
\"password\": \"OrgPassword123\",
\"code\": \"123456\",
\"recovery_code\": \"ABCD-1234-EFGH\",
\"remember_me\": false
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/auth/login"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "org@example.com",
"country_code": "+43",
"phone_number": "6641234567",
"password": "OrgPassword123",
"code": "123456",
"recovery_code": "ABCD-1234-EFGH",
"remember_me": false
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/auth/login';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'org@example.com',
'country_code' => '+43',
'phone_number' => '6641234567',
'password' => 'OrgPassword123',
'code' => '123456',
'recovery_code' => 'ABCD-1234-EFGH',
'remember_me' => false,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/auth/login');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "org@example.com",
"country_code": "+43",
"phone_number": "6641234567",
"password": "OrgPassword123",
"code": "123456",
"recovery_code": "ABCD-1234-EFGH",
"remember_me": false
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Login successful.",
"data": {
"token": "10|4Ucu33DSapxQkfLaVou7QWZebPNBb0UxdrbLmEPj11373a72",
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"slug": "caritas-4v1ues",
"email": "caritas-portal@flexxr.eu.cc",
"country_code": "+43",
"phone_number": "6641234567",
"contact_person_name": null,
"contact_person_phone": null,
"iso_country_code": "AT",
"phone_e164": "+436641234567",
"description": "Caritas test organisation used for end-to-end portal QA. Safe to delete.",
"logo_url": null,
"website": "https://www.caritas.at",
"address": "Albrechtskreithgasse 19-21",
"address_line2": null,
"postal_code": null,
"city": "Vienna",
"country": "Austria",
"status": "active",
"verified_at": "2026-08-05T16:18:17.000000Z",
"is_verified": true,
"total_raised": null,
"created_at": "2026-08-05T16:18:17.000000Z",
"platform_fee_flat_cents": {},
"firmenbuchnummer": {},
"uid_number": {},
"uid_validation_status": {},
"gisa_status": {},
"payout_method": {},
"stripe_connect_account_id": {},
"connect_charges_enabled": {},
"connect_payouts_enabled": {},
"connect_details_submitted": {},
"connect_requirements_due": {},
"connect_country_code": {},
"connect_external_account": {}
}
},
"errors": null,
"meta": {
"request_id": "8a92c2fa-6959-4cc4-b267-75087ca278f0",
"timestamp": "2026-08-05T16:18:37.432170Z"
}
}
Example response (401, 2FA Required):
{
"status": "TWO_FACTOR_REQUIRED",
"message": "Two-factor authentication is required.",
"data": {
"token": "2|challenge-token...",
"two_factor_method": "totp"
},
"errors": [
{
"field": null,
"message": "Two-factor authentication is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (401, Invalid Credentials):
{
"status": "INVALID_CREDENTIALS",
"message": "The provided credentials are incorrect.",
"data": null,
"errors": [
{
"field": "email",
"message": "The provided credentials are incorrect."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "email",
"message": "The email field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (423, Account Temporarily Locked):
{
"status": "ACCOUNT_TEMPORARILY_LOCKED",
"message": "Account temporarily locked. Try again in 15 minutes.",
"data": null,
"errors": [
{
"field": "email",
"message": "Account temporarily locked. Try again in 15 minutes."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Member Login
Authenticates an OrganizationMember using the linked User account's email and password. Issues a Sanctum token scoped to the OrganizationMember model so the member can access the organisation routes independently of the Organisation principal.
When the member has 2FA enrolled a limited challenge token is returned and the client must complete the two-factor flow via the challenge endpoint before accessing protected resources.
Only members belonging to organisations with an Active status are permitted to reach the approved route group; this action itself does not block based on org status (mirrors LoginOrganizationAction).
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/auth/member/login" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"jane@example.com\",
\"password\": \"SecureP4ssword!\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/auth/member/login"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "jane@example.com",
"password": "SecureP4ssword!"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/auth/member/login';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'jane@example.com',
'password' => 'SecureP4ssword!',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/auth/member/login');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "jane@example.com",
"password": "SecureP4ssword!"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Success):
{
"status": "SUCCESS",
"message": "Login successful.",
"data": {
"token": "1|abc...",
"member": {
"id": "uuid",
"name": "Jane Doe",
"email": "jane@example.com",
"role": "member",
"organization_id": "org-uuid"
},
"acl": {
"scope": "org-member",
"presets": [
"viewer"
],
"permissions": [
"profile.view",
"team.view"
]
}
}
}
Example response (401, 2FA Required):
{
"status": "TWO_FACTOR_REQUIRED",
"message": "Two-factor authentication is required.",
"data": {
"token": "2|challenge-token...",
"two_factor_method": "totp"
}
}
Example response (401, Invalid Credentials):
{
"status": "INVALID_CREDENTIALS",
"message": "The provided credentials are incorrect."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Two-Factor Authentication
Regenerate Recovery Codes
requires authentication
Generates a fresh set of single-use 2FA recovery codes, immediately invalidating the previous batch. Codes are returned in plain text exactly once — they cannot be retrieved again after this response. Requires 2FA to be enabled and confirmed.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/security/recovery-codes/regenerate" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/security/recovery-codes/regenerate"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/security/recovery-codes/regenerate';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/security/recovery-codes/regenerate');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Recovery codes regenerated. Store them securely — they will not be shown again.",
"data": {
"recovery_codes": [
"GDLZX-N9LP9",
"VPZAB-DJHRO",
"73VKY-CYUZU",
"NB6X9-M7H4O",
"HKRRW-SKJ2S",
"9FCNW-CBQ2E",
"SW6IZ-ZHVXH",
"DC8MJ-NXVZF"
]
},
"errors": null,
"meta": {
"request_id": "1d2ba116-7b58-49a0-a5a9-cdf820d35b7d",
"timestamp": "2026-08-05T16:18:38.620100Z"
}
}
Example response (403, 2FA Not Enabled):
{
"status": "FORBIDDEN",
"message": "Two-factor authentication is not enabled.",
"data": null,
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Profile
Show Profile
requires authentication
Returns the full profile of the organisation the caller belongs to. Invited members receive their company's profile, not their own membership record.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/profile" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/profile"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/profile';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/profile');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Profile retrieved successfully.",
"data": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"slug": "caritas-4v1ues",
"email": "caritas-portal@flexxr.eu.cc",
"country_code": "+43",
"phone_number": "6641234567",
"contact_person_name": null,
"contact_person_phone": null,
"iso_country_code": "AT",
"phone_e164": "+436641234567",
"description": "Caritas test organisation used for end-to-end portal QA. Safe to delete.",
"logo_url": null,
"website": "https://www.caritas.at",
"address": "Albrechtskreithgasse 19-21",
"address_line2": null,
"postal_code": null,
"city": "Vienna",
"country": "Austria",
"status": "active",
"verified_at": "2026-08-05T16:18:17.000000Z",
"is_verified": true,
"total_raised": null,
"created_at": "2026-08-05T16:18:17.000000Z",
"platform_fee_flat_cents": null,
"firmenbuchnummer": null,
"uid_number": null,
"uid_validation_status": null,
"payout_method": null,
"stripe_connect_account_id": null,
"connect_charges_enabled": null,
"connect_payouts_enabled": null,
"connect_details_submitted": null,
"connect_requirements_due": null,
"connect_country_code": null
},
"errors": null,
"meta": {
"request_id": "e435791d-4abf-49f0-ba30-628b75142d31",
"timestamp": "2026-08-05T16:18:37.730963Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Org Profile
requires authentication
Updates mutable profile fields on the authenticated organisation. Only provided fields are applied; absent keys leave existing values untouched. Password and bank-detail changes have dedicated endpoints.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/org/profile" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Hope Foundation\",
\"country_code\": \"+49\",
\"phone_number\": \"1234567890\",
\"contact_person_name\": \"u\",
\"contact_person_phone\": \"w\",
\"description\": \"A non-profit dedicated to helping communities.\",
\"website\": \"https:\\/\\/hopefoundation.org\",
\"address\": \"Musterstr. 1\",
\"address_line2\": \"i\",
\"postal_code\": \"tcpscqldzsnrwtuj\",
\"city\": \"Berlin\",
\"country\": \"Germany\",
\"iso_country_code\": \"lx\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/profile"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Hope Foundation",
"country_code": "+49",
"phone_number": "1234567890",
"contact_person_name": "u",
"contact_person_phone": "w",
"description": "A non-profit dedicated to helping communities.",
"website": "https:\/\/hopefoundation.org",
"address": "Musterstr. 1",
"address_line2": "i",
"postal_code": "tcpscqldzsnrwtuj",
"city": "Berlin",
"country": "Germany",
"iso_country_code": "lx"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/profile';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'name' => 'Hope Foundation',
'country_code' => '+49',
'phone_number' => '1234567890',
'contact_person_name' => 'u',
'contact_person_phone' => 'w',
'description' => 'A non-profit dedicated to helping communities.',
'website' => 'https://hopefoundation.org',
'address' => 'Musterstr. 1',
'address_line2' => 'i',
'postal_code' => 'tcpscqldzsnrwtuj',
'city' => 'Berlin',
'country' => 'Germany',
'iso_country_code' => 'lx',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/profile');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"name": "Hope Foundation",
"country_code": "+49",
"phone_number": "1234567890",
"contact_person_name": "u",
"contact_person_phone": "w",
"description": "A non-profit dedicated to helping communities.",
"website": "https:\/\/hopefoundation.org",
"address": "Musterstr. 1",
"address_line2": "i",
"postal_code": "tcpscqldzsnrwtuj",
"city": "Berlin",
"country": "Germany",
"iso_country_code": "lx"
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Profile updated successfully.",
"data": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Hope Foundation",
"slug": "caritas-4v1ues",
"email": "caritas-portal@flexxr.eu.cc",
"country_code": "+43",
"phone_number": "13456789",
"contact_person_name": "u",
"contact_person_phone": "w",
"iso_country_code": "lx",
"phone_e164": "+4313456789",
"description": "A non-profit dedicated to helping communities.",
"logo_url": null,
"website": "https://hopefoundation.org",
"address": "Musterstr. 1",
"address_line2": "i",
"postal_code": "tcpscqldzsnrwtuj",
"city": "Berlin",
"country": "Germany",
"status": "active",
"verified_at": "2026-08-05T16:18:17.000000Z",
"is_verified": true,
"total_raised": null,
"created_at": "2026-08-05T16:18:17.000000Z",
"platform_fee_flat_cents": null,
"firmenbuchnummer": null,
"uid_number": null,
"uid_validation_status": null,
"payout_method": null,
"stripe_connect_account_id": null,
"connect_charges_enabled": null,
"connect_payouts_enabled": null,
"connect_details_submitted": null,
"connect_requirements_due": null,
"connect_country_code": null
},
"errors": null,
"meta": {
"request_id": "4205ec1a-adaa-4fa2-a3e2-8cf17da36ec3",
"timestamp": "2026-08-05T16:18:37.748449Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "Validation failed.",
"data": null,
"errors": [
{
"field": "phone_number",
"message": "Phone number format is invalid."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Change Org Password
requires authentication
Changes the authenticated organisation's login password. Requires the current password to be provided and verified before the new one is persisted. Pass logout_other_devices: true to revoke every other Sanctum session on the organisation account.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/org/profile/password" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"current_password\": \"OldPassword123!\",
\"password\": \"NewPassword456!\",
\"logout_other_devices\": true,
\"password_confirmation\": \"NewPassword456!\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/profile/password"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"current_password": "OldPassword123!",
"password": "NewPassword456!",
"logout_other_devices": true,
"password_confirmation": "NewPassword456!"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/profile/password';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'current_password' => 'OldPassword123!',
'password' => 'NewPassword456!',
'logout_other_devices' => true,
'password_confirmation' => 'NewPassword456!',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/profile/password');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"current_password": "OldPassword123!",
"password": "NewPassword456!",
"logout_other_devices": true,
"password_confirmation": "NewPassword456!"
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Password changed successfully.",
"data": {
"revoked_sessions": 0
},
"errors": null,
"meta": {
"request_id": "dff4679b-ef2a-4fb9-94a7-48ac27abddfa",
"timestamp": "2026-08-05T16:18:38.445813Z"
}
}
Example response (422, Wrong Password):
{
"status": "VALIDATION_ERROR",
"message": "The current password is incorrect.",
"data": null,
"errors": [
{
"field": "current_password",
"message": "The current password is incorrect."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Password Reuse):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "password",
"message": "You cannot reuse your last 3 passwords."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Me
requires authentication
Returns the authenticated organisation's profile (name, email, avatar).
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/me" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/me"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/me';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/me');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"email": "caritas-portal@flexxr.eu.cc",
"email_verified_at": null,
"avatar_url": null,
"created_at": "2026-08-05T16:18:17+00:00"
},
"errors": null,
"meta": {
"request_id": "a45b6707-e121-40d2-a89f-c692e5d6c2bb",
"timestamp": "2026-08-05T16:18:38.460687Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Me
requires authentication
Example request:
curl --request PATCH \
"https://backend-dev.flexxr.at/api/v1/org/me" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"ACME Foundation\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/me"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "ACME Foundation"
};
fetch(url, {
method: "PATCH",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/me';
$response = $client->patch(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'name' => 'ACME Foundation',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/me');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"name": "ACME Foundation"
};
final response = await http.patch(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Profile updated successfully.",
"data": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "ACME Foundation",
"email": "caritas-portal@flexxr.eu.cc"
},
"errors": null,
"meta": {
"request_id": "83d44c1f-73cb-42d8-b29f-3ec083b2921a",
"timestamp": "2026-08-05T16:18:38.470674Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "name",
"message": "The name may not be greater than 255 characters."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Dashboard
Get Org Dashboard Stats
requires authentication
Returns aggregated dashboard statistics for the authenticated organisation.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/dashboard/stats" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/dashboard/stats"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/dashboard/stats';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/dashboard/stats');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Dashboard statistics retrieved successfully.",
"data": {
"users_count": 1,
"pending_invitations": 0,
"active_shifts": 4,
"upcoming_jobs": 4,
"pending_applicants": 227,
"monthly_spend_cents": 37747,
"attendance_rate_percent": 13,
"open_positions": 96
},
"errors": null,
"meta": {
"request_id": "52103b61-fa39-4660-988a-b44356150484",
"timestamp": "2026-08-05T16:18:38.749634Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Organisation Dashboard Trends
requires authentication
Daily activity series for the dashboard charts: shifts and applications over the last 14 days (zero-filled) plus the current vacancy fill across open jobs.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/dashboard/trends" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/dashboard/trends"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/dashboard/trends';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/dashboard/trends');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"days": [
{
"date": "2026-07-23",
"shifts": 0,
"completed": 0,
"applications": 0
},
{
"date": "2026-07-24",
"shifts": 0,
"completed": 0,
"applications": 0
},
{
"date": "2026-07-25",
"shifts": 0,
"completed": 0,
"applications": 0
},
{
"date": "2026-07-26",
"shifts": 0,
"completed": 0,
"applications": 0
},
{
"date": "2026-07-27",
"shifts": 0,
"completed": 0,
"applications": 0
},
{
"date": "2026-07-28",
"shifts": 0,
"completed": 0,
"applications": 0
},
{
"date": "2026-07-29",
"shifts": 0,
"completed": 0,
"applications": 0
},
{
"date": "2026-07-30",
"shifts": 0,
"completed": 0,
"applications": 0
},
{
"date": "2026-07-31",
"shifts": 0,
"completed": 0,
"applications": 28
},
{
"date": "2026-08-01",
"shifts": 0,
"completed": 0,
"applications": 111
},
{
"date": "2026-08-02",
"shifts": 0,
"completed": 0,
"applications": 77
},
{
"date": "2026-08-03",
"shifts": 1,
"completed": 1,
"applications": 12
},
{
"date": "2026-08-04",
"shifts": 1,
"completed": 0,
"applications": 4
},
{
"date": "2026-08-05",
"shifts": 1,
"completed": 0,
"applications": 1
}
],
"vacancies": {
"total": 96,
"filled": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Team
List Team Members
requires authentication
Returns the list of team members for the authenticated organisation:
the principal plus every accepted member. Each member row includes
the presets array of currently-assigned preset keys.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/team" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/team"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/team';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/team');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [
{
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"email": "caritas-portal@flexxr.eu.cc",
"role": "owner",
"status": "active",
"avatar_url": null,
"is_self": true,
"is_primary_admin": true,
"is_active": true,
"presets": [],
"joined_at": "2026-08-05T16:18:17+00:00",
"last_active_at": "2026-08-05T16:18:33+00:00"
},
{
"id": "019fd2b8-285e-707c-865a-ffbe4b08f730",
"name": "Nikolas Klocko",
"email": "omacejkovic@example.net",
"role": "admin",
"status": "active",
"avatar_url": null,
"is_self": false,
"is_primary_admin": false,
"is_active": true,
"presets": [],
"joined_at": "2026-08-05T16:18:32+00:00",
"last_active_at": null
}
],
"errors": null,
"meta": {
"request_id": "89fd6657-4c88-42a0-aeea-ecc0ef10dd35",
"timestamp": "2026-08-05T16:18:38.792198Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Assignable Presets
requires authentication
Returns the list of presets an org may assign to its team members. Used by the dashboard's "Manage roles" dialog.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/team/presets" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/team/presets"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/team/presets';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/team/presets');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [
{
"key": "owner",
"label": "Owner",
"description": "Primary company owner with unrestricted access to all company features.",
"permissions": [
"applicants.accept",
"applicants.reject",
"applicants.view",
"assignments.manage",
"assignments.view",
"attendance.approve-hours",
"attendance.report-noshow",
"attendance.view",
"audit.view",
"gdpr.request",
"invoices.download",
"invoices.view",
"jobs.configure-assignment",
"jobs.create",
"jobs.delete",
"jobs.edit",
"jobs.publish",
"jobs.view",
"messages.access",
"notifications.preferences.manage",
"payments.manage",
"payments.view",
"profile.edit",
"profile.view",
"ratings.create",
"ratings.view",
"reports.export",
"reports.view",
"requests.decide",
"requests.view",
"shifts.adjust",
"shifts.cancel",
"shifts.check-in",
"shifts.dispute-time",
"shifts.generate-qr",
"shifts.report-signature-refusal",
"shifts.view",
"support.create-ticket",
"support.view-tickets",
"team.invite",
"team.manage-roles",
"team.remove",
"team.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "org-admin",
"label": "Admin",
"description": "Company settings, team, jobs, applicants, attendance, and the company wallet.",
"permissions": [
"applicants.accept",
"applicants.reject",
"applicants.view",
"assignments.manage",
"assignments.view",
"attendance.approve-hours",
"attendance.report-noshow",
"attendance.view",
"audit.view",
"jobs.configure-assignment",
"jobs.create",
"jobs.delete",
"jobs.edit",
"jobs.publish",
"jobs.view",
"messages.access",
"notifications.preferences.manage",
"payments.manage",
"payments.view",
"profile.edit",
"profile.view",
"ratings.create",
"ratings.view",
"reports.export",
"reports.view",
"requests.decide",
"requests.view",
"shifts.adjust",
"shifts.cancel",
"shifts.check-in",
"shifts.dispute-time",
"shifts.generate-qr",
"shifts.report-signature-refusal",
"shifts.view",
"support.create-ticket",
"support.view-tickets",
"team.invite",
"team.manage-roles",
"team.remove",
"team.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "recruiter",
"label": "Recruiter",
"description": "Create and manage job listings, review and manage applicants.",
"permissions": [
"applicants.accept",
"applicants.reject",
"applicants.view",
"jobs.configure-assignment",
"jobs.create",
"jobs.delete",
"jobs.edit",
"jobs.publish",
"jobs.view",
"messages.access",
"ratings.view",
"reports.view",
"shifts.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "shift-manager",
"label": "Shift Manager",
"description": "Manage attendance, approve hours, and handle no-shows.",
"permissions": [
"assignments.view",
"attendance.approve-hours",
"attendance.report-noshow",
"attendance.view",
"messages.access",
"ratings.create",
"ratings.view",
"reports.view",
"requests.decide",
"requests.view",
"shifts.adjust",
"shifts.cancel",
"shifts.check-in",
"shifts.dispute-time",
"shifts.generate-qr",
"shifts.report-signature-refusal",
"shifts.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "finance",
"label": "Finance",
"description": "View and manage invoices and payments.",
"permissions": [
"invoices.download",
"invoices.view",
"payments.manage",
"payments.view",
"reports.export",
"reports.view",
"requests.decide",
"requests.view"
],
"category": null,
"highlights": [],
"risk_level": null
},
{
"key": "co-admin",
"label": "Co-admin",
"description": "Full access except team role management and member removal. Use \"admin\" instead.",
"permissions": [
"applicants.accept",
"applicants.reject",
"applicants.view",
"assignments.manage",
"assignments.view",
"attendance.approve-hours",
"attendance.report-noshow",
"attendance.view",
"audit.view",
"gdpr.request",
"invoices.download",
"invoices.view",
"jobs.configure-assignment",
"jobs.create",
"jobs.delete",
"jobs.edit",
"jobs.publish",
"jobs.view",
"messages.access",
"notifications.preferences.manage",
"payments.manage",
"payments.view",
"profile.edit",
"profile.view",
"ratings.create",
"ratings.view",
"reports.export",
"reports.view",
"requests.decide",
"requests.view",
"shifts.adjust",
"shifts.cancel",
"shifts.check-in",
"shifts.dispute-time",
"shifts.generate-qr",
"shifts.report-signature-refusal",
"shifts.view",
"support.create-ticket",
"support.view-tickets",
"team.invite",
"team.view"
],
"category": "organization_admin",
"highlights": [
"presets.co-admin.highlights.almost_full_access",
"presets.co-admin.highlights.manage_team",
"presets.co-admin.highlights.no_ownership_transfer"
],
"risk_level": "high"
},
{
"key": "manager",
"label": "Manager",
"description": "Operational team management. Use \"admin\" preset instead.",
"permissions": [
"applicants.accept",
"applicants.reject",
"applicants.view",
"attendance.approve-hours",
"attendance.report-noshow",
"attendance.view",
"jobs.configure-assignment",
"jobs.create",
"jobs.delete",
"jobs.edit",
"jobs.publish",
"jobs.view",
"notifications.preferences.manage",
"profile.edit",
"profile.view",
"ratings.create",
"ratings.view",
"shifts.adjust",
"shifts.cancel",
"shifts.check-in",
"shifts.dispute-time",
"shifts.generate-qr",
"shifts.report-signature-refusal",
"shifts.view",
"team.invite",
"team.view"
],
"category": "operations",
"highlights": [
"presets.manager.highlights.edit_profile",
"presets.manager.highlights.invite_members",
"presets.manager.highlights.manage_notifications"
],
"risk_level": "medium"
},
{
"key": "viewer",
"label": "Viewer",
"description": "Read-only access. Cannot make any changes.",
"permissions": [
"applicants.view",
"attendance.view",
"invoices.view",
"jobs.view",
"profile.view",
"ratings.view",
"reports.view",
"shifts.view",
"team.view"
],
"category": "read_only",
"highlights": [
"presets.viewer.highlights.read_only",
"presets.viewer.highlights.no_changes"
],
"risk_level": "low"
}
],
"errors": null,
"meta": {
"request_id": "c429e72e-0dee-402b-939b-bc1bce7762b4",
"timestamp": "2026-08-05T16:18:38.809465Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Assignable Roles and Presets
requires authentication
The roles a member may hold and the presets that may be granted to them — everything the portal's team screens need to render a role picker and the permission matrix without hardcoding either list.
Owner is excluded: ownership is the organisation account itself and is never assigned to a member.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/team/roles" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/team/roles"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/team/roles';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/team/roles');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"roles": [
{
"id": "admin",
"label": "Admin",
"description": "Company settings, team, jobs, applicants, attendance, and the company wallet.",
"permissions": [
"applicants.accept",
"applicants.reject",
"applicants.view",
"assignments.manage",
"assignments.view",
"attendance.approve-hours",
"attendance.report-noshow",
"attendance.view",
"audit.view",
"jobs.configure-assignment",
"jobs.create",
"jobs.delete",
"jobs.edit",
"jobs.publish",
"jobs.view",
"messages.access",
"notifications.preferences.manage",
"payments.manage",
"payments.view",
"profile.edit",
"profile.view",
"ratings.create",
"ratings.view",
"reports.export",
"reports.view",
"requests.decide",
"requests.view",
"shifts.adjust",
"shifts.cancel",
"shifts.check-in",
"shifts.dispute-time",
"shifts.generate-qr",
"shifts.report-signature-refusal",
"shifts.view",
"support.create-ticket",
"support.view-tickets",
"team.invite",
"team.manage-roles",
"team.remove",
"team.view"
]
},
{
"id": "recruiter",
"label": "Recruiter",
"description": "Create and manage job listings, review and manage applicants.",
"permissions": [
"applicants.accept",
"applicants.reject",
"applicants.view",
"jobs.configure-assignment",
"jobs.create",
"jobs.delete",
"jobs.edit",
"jobs.publish",
"jobs.view",
"messages.access",
"ratings.view",
"reports.view",
"shifts.view"
]
},
{
"id": "shift_manager",
"label": "Shift Manager",
"description": "Manage attendance, approve hours, and handle no-shows.",
"permissions": [
"assignments.view",
"attendance.approve-hours",
"attendance.report-noshow",
"attendance.view",
"messages.access",
"ratings.create",
"ratings.view",
"reports.view",
"requests.decide",
"requests.view",
"shifts.adjust",
"shifts.cancel",
"shifts.check-in",
"shifts.dispute-time",
"shifts.generate-qr",
"shifts.report-signature-refusal",
"shifts.view"
]
},
{
"id": "finance",
"label": "Finance",
"description": "View and manage invoices and payments.",
"permissions": [
"invoices.download",
"invoices.view",
"payments.manage",
"payments.view",
"reports.export",
"reports.view",
"requests.decide",
"requests.view"
]
}
],
"presets": [
{
"id": "owner",
"label": "Owner",
"description": "Primary company owner with unrestricted access to all company features.",
"permissions": [
"applicants.accept",
"applicants.reject",
"applicants.view",
"assignments.manage",
"assignments.view",
"attendance.approve-hours",
"attendance.report-noshow",
"attendance.view",
"audit.view",
"gdpr.request",
"invoices.download",
"invoices.view",
"jobs.configure-assignment",
"jobs.create",
"jobs.delete",
"jobs.edit",
"jobs.publish",
"jobs.view",
"messages.access",
"notifications.preferences.manage",
"payments.manage",
"payments.view",
"profile.edit",
"profile.view",
"ratings.create",
"ratings.view",
"reports.export",
"reports.view",
"requests.decide",
"requests.view",
"shifts.adjust",
"shifts.cancel",
"shifts.check-in",
"shifts.dispute-time",
"shifts.generate-qr",
"shifts.report-signature-refusal",
"shifts.view",
"support.create-ticket",
"support.view-tickets",
"team.invite",
"team.manage-roles",
"team.remove",
"team.view"
],
"category": null,
"risk_level": null
},
{
"id": "org-admin",
"label": "Admin",
"description": "Company settings, team, jobs, applicants, attendance, and the company wallet.",
"permissions": [
"applicants.accept",
"applicants.reject",
"applicants.view",
"assignments.manage",
"assignments.view",
"attendance.approve-hours",
"attendance.report-noshow",
"attendance.view",
"audit.view",
"jobs.configure-assignment",
"jobs.create",
"jobs.delete",
"jobs.edit",
"jobs.publish",
"jobs.view",
"messages.access",
"notifications.preferences.manage",
"payments.manage",
"payments.view",
"profile.edit",
"profile.view",
"ratings.create",
"ratings.view",
"reports.export",
"reports.view",
"requests.decide",
"requests.view",
"shifts.adjust",
"shifts.cancel",
"shifts.check-in",
"shifts.dispute-time",
"shifts.generate-qr",
"shifts.report-signature-refusal",
"shifts.view",
"support.create-ticket",
"support.view-tickets",
"team.invite",
"team.manage-roles",
"team.remove",
"team.view"
],
"category": null,
"risk_level": null
},
{
"id": "recruiter",
"label": "Recruiter",
"description": "Create and manage job listings, review and manage applicants.",
"permissions": [
"applicants.accept",
"applicants.reject",
"applicants.view",
"jobs.configure-assignment",
"jobs.create",
"jobs.delete",
"jobs.edit",
"jobs.publish",
"jobs.view",
"messages.access",
"ratings.view",
"reports.view",
"shifts.view"
],
"category": null,
"risk_level": null
},
{
"id": "shift-manager",
"label": "Shift Manager",
"description": "Manage attendance, approve hours, and handle no-shows.",
"permissions": [
"assignments.view",
"attendance.approve-hours",
"attendance.report-noshow",
"attendance.view",
"messages.access",
"ratings.create",
"ratings.view",
"reports.view",
"requests.decide",
"requests.view",
"shifts.adjust",
"shifts.cancel",
"shifts.check-in",
"shifts.dispute-time",
"shifts.generate-qr",
"shifts.report-signature-refusal",
"shifts.view"
],
"category": null,
"risk_level": null
},
{
"id": "finance",
"label": "Finance",
"description": "View and manage invoices and payments.",
"permissions": [
"invoices.download",
"invoices.view",
"payments.manage",
"payments.view",
"reports.export",
"reports.view",
"requests.decide",
"requests.view"
],
"category": null,
"risk_level": null
},
{
"id": "co-admin",
"label": "Co-admin",
"description": "Full access except team role management and member removal. Use \"admin\" instead.",
"permissions": [
"applicants.accept",
"applicants.reject",
"applicants.view",
"assignments.manage",
"assignments.view",
"attendance.approve-hours",
"attendance.report-noshow",
"attendance.view",
"audit.view",
"gdpr.request",
"invoices.download",
"invoices.view",
"jobs.configure-assignment",
"jobs.create",
"jobs.delete",
"jobs.edit",
"jobs.publish",
"jobs.view",
"messages.access",
"notifications.preferences.manage",
"payments.manage",
"payments.view",
"profile.edit",
"profile.view",
"ratings.create",
"ratings.view",
"reports.export",
"reports.view",
"requests.decide",
"requests.view",
"shifts.adjust",
"shifts.cancel",
"shifts.check-in",
"shifts.dispute-time",
"shifts.generate-qr",
"shifts.report-signature-refusal",
"shifts.view",
"support.create-ticket",
"support.view-tickets",
"team.invite",
"team.view"
],
"category": "organization_admin",
"risk_level": "high"
},
{
"id": "manager",
"label": "Manager",
"description": "Operational team management. Use \"admin\" preset instead.",
"permissions": [
"applicants.accept",
"applicants.reject",
"applicants.view",
"attendance.approve-hours",
"attendance.report-noshow",
"attendance.view",
"jobs.configure-assignment",
"jobs.create",
"jobs.delete",
"jobs.edit",
"jobs.publish",
"jobs.view",
"notifications.preferences.manage",
"profile.edit",
"profile.view",
"ratings.create",
"ratings.view",
"shifts.adjust",
"shifts.cancel",
"shifts.check-in",
"shifts.dispute-time",
"shifts.generate-qr",
"shifts.report-signature-refusal",
"shifts.view",
"team.invite",
"team.view"
],
"category": "operations",
"risk_level": "medium"
},
{
"id": "viewer",
"label": "Viewer",
"description": "Read-only access. Cannot make any changes.",
"permissions": [
"applicants.view",
"attendance.view",
"invoices.view",
"jobs.view",
"profile.view",
"ratings.view",
"reports.view",
"shifts.view",
"team.view"
],
"category": "read_only",
"risk_level": "low"
}
]
},
"errors": null,
"meta": {
"request_id": "936accb8-3905-4985-9c5c-f3310da1c479",
"timestamp": "2026-08-05T16:18:38.827828Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Team Invitations
requires authentication
Returns all pending invitations for the authenticated organisation, newest first.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/team/invitations" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/team/invitations"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/team/invitations';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/team/invitations');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [],
"errors": null,
"meta": {
"request_id": "37de59fd-ab57-4351-b751-f42c1912b877",
"timestamp": "2026-08-05T16:18:38.848580Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Invite Team Member
requires authentication
Creates a pending team invitation and sends an accept-link email to the invitee.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/team/invitations" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"member@example.com\",
\"name\": \"Jane Smith\",
\"preset_key\": \"viewer\",
\"role\": \"member\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/team/invitations"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "member@example.com",
"name": "Jane Smith",
"preset_key": "viewer",
"role": "member"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/team/invitations';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'member@example.com',
'name' => 'Jane Smith',
'preset_key' => 'viewer',
'role' => 'member',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/team/invitations');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "member@example.com",
"name": "Jane Smith",
"preset_key": "viewer",
"role": "member"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "CREATED",
"message": "Invitation sent.",
"data": {
"id": "019fd2b8-b25f-72cd-80f6-76a3fa80752a",
"email": "kole.murray@example.com",
"name": null,
"role": "member",
"preset_key": "viewer",
"preset_label": "Viewer",
"status": "pending",
"invited_by_name": "Schuppe-D'Amore",
"invited_at": "2026-08-05T16:19:07+00:00",
"expires_at": "2026-08-12T16:19:07+00:00",
"accepted_at": null,
"accepted_by_email": null,
"revoked_at": null,
"last_sent_at": "2026-08-05T16:19:07+00:00",
"send_count": 1,
"created_at": "2026-08-05T16:19:07+00:00"
},
"errors": null,
"meta": {
"request_id": "07ca8112-6166-4ac4-b613-5485efe2470a",
"timestamp": "2026-08-05T16:19:07.496377Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "email",
"message": "The email field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Resend Team Invitation
requires authentication
Re-sends the accept-link email for a pending invitation, rotating the token and resetting the expiry window.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/team/invitations/661f9511-f3ac-52e5-b827-557766551111/resend" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/team/invitations/661f9511-f3ac-52e5-b827-557766551111/resend"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/team/invitations/661f9511-f3ac-52e5-b827-557766551111/resend';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/team/invitations/661f9511-f3ac-52e5-b827-557766551111/resend');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Invitation re-sent.",
"data": {
"id": "019fd2b8-affd-71e3-b323-f2b2d9a8c01b",
"email": "zweite.kollegin@example.at",
"name": null,
"role": "member",
"preset_key": "viewer",
"preset_label": "Viewer",
"status": "pending",
"invited_by_name": "Franecki-Christiansen",
"invited_at": "2026-08-05T16:19:06+00:00",
"expires_at": "2026-08-12T16:19:06+00:00",
"accepted_at": null,
"accepted_by_email": null,
"revoked_at": null,
"last_sent_at": "2026-08-05T16:19:06+00:00",
"send_count": 2,
"created_at": "2026-08-05T16:19:06+00:00"
},
"errors": null,
"meta": {
"request_id": "619fc1d5-dc41-43a9-9212-7cc961686f00",
"timestamp": "2026-08-05T16:19:06.913816Z"
}
}
Example response (404, Invitation Not Found):
{
"status": "NOT_FOUND",
"message": "No query results for model.",
"data": null,
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Revoke Team Invitation
requires authentication
Revokes a pending team invitation. Accepted invitations cannot be revoked.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/org/team/invitations/661f9511-f3ac-52e5-b827-557766551111" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/team/invitations/661f9511-f3ac-52e5-b827-557766551111"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/team/invitations/661f9511-f3ac-52e5-b827-557766551111';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/team/invitations/661f9511-f3ac-52e5-b827-557766551111');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Invitation revoked.",
"data": {
"id": "019fd2b8-affd-71e3-b323-f2b2d9a8c01b",
"email": "zweite.kollegin@example.at",
"name": null,
"role": "member",
"preset_key": "viewer",
"preset_label": "Viewer",
"status": "revoked",
"invited_by_name": "Franecki-Christiansen",
"invited_at": "2026-08-05T16:19:06+00:00",
"expires_at": "2026-08-12T16:19:06+00:00",
"accepted_at": null,
"accepted_by_email": null,
"revoked_at": "2026-08-05T16:19:06+00:00",
"last_sent_at": "2026-08-05T16:19:06+00:00",
"send_count": 2,
"created_at": "2026-08-05T16:19:06+00:00"
},
"errors": null,
"meta": {
"request_id": "af8be4ed-34a6-4610-a07f-38b7cc5318b3",
"timestamp": "2026-08-05T16:19:06.936143Z"
}
}
Example response (404, Invitation Not Found):
{
"status": "NOT_FOUND",
"message": "No query results for model.",
"data": null,
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Member Role
requires authentication
Updates a team member's role. Only the owning organisation may perform this action. The Owner role cannot be assigned via this endpoint — it belongs exclusively to the Organisation principal itself.
Example request:
curl --request PATCH \
"https://backend-dev.flexxr.at/api/v1/org/team/members/architecto" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"role\": \"shift_manager\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/team/members/architecto"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"role": "shift_manager"
};
fetch(url, {
method: "PATCH",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/team/members/architecto';
$response = $client->patch(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'role' => 'shift_manager',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/team/members/architecto');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"role": "shift_manager"
};
final response = await http.patch(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Member role updated.",
"data": {
"id": "019fd2b8-285e-707c-865a-ffbe4b08f730",
"user_id": "019fd2b8-285d-733a-9a39-9eff7782cebc",
"role": "shift_manager",
"joined_at": "2026-08-05T16:18:32.000000Z"
},
"errors": null,
"meta": {
"request_id": "112413aa-862d-4d0d-b901-32f1e694825b",
"timestamp": "2026-08-05T16:18:38.884959Z"
}
}
Example response (403):
{
"status": "FORBIDDEN",
"message": "This action is unauthorized.",
"data": null,
"errors": [
{
"field": null,
"message": "This action is unauthorized."
}
]
}
Example response (422):
{
"status": "VALIDATION_ERROR",
"message": "Cannot assign the owner role via this endpoint.",
"data": null,
"errors": [
{
"field": "role",
"message": "Cannot assign the owner role via this endpoint."
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Member Presets
requires authentication
Bulk-replaces the presets assigned to a team member. The request body carries an array of preset keys; presets currently held but absent from the array are revoked, presets present but not yet assigned are added. Diff and writes run inside a single transaction.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/org/team/members/architecto/presets" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"presets\": [
\"manager\",
\"finance\"
]
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/team/members/architecto/presets"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"presets": [
"manager",
"finance"
]
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/team/members/architecto/presets';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'presets' => ['manager', 'finance'],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/team/members/architecto/presets');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"presets": [
"manager",
"finance"
]
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Success):
{
"status": "SUCCESS",
"message": "Member presets updated.",
"data": {
"member_id": "uuid",
"presets": [
"manager"
]
},
"errors": null
}
Example response (403, Forbidden):
{
"status": "FORBIDDEN",
"message": "This action is unauthorized."
}
Example response (422, Unknown preset):
{
"status": "VALIDATION_ERROR",
"message": "Validation failed.",
"errors": [
{
"field": "presets.0",
"message": "Unknown preset 'foo'."
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Deactivate Team Member
requires authentication
Soft-deactivates a team member: sets is_active = false and revokes all Sanctum tokens so any in-flight sessions are immediately invalidated. The member row is retained for audit and compliance purposes.
Guards:
- The target member must belong to the requesting actor's organisation.
- A member cannot deactivate themselves.
- The organisation owner cannot be deactivated via this endpoint.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/org/team/members/architecto/deactivate" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/team/members/architecto/deactivate"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "PUT",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/team/members/architecto/deactivate';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/team/members/architecto/deactivate');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.put(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Member deactivated.",
"data": null,
"errors": null,
"meta": {
"request_id": "e0a4f5b9-485f-468f-a82e-e0e71a736f71",
"timestamp": "2026-08-05T16:18:38.928851Z"
}
}
Example response (403):
{
"status": "FORBIDDEN",
"message": "This action is unauthorized."
}
Example response (422):
{
"status": "VALIDATION_ERROR",
"message": "You cannot deactivate yourself."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reactivate Team Member
requires authentication
Re-enables a previously deactivated team member. The member regains access to the organisation dashboard on their next login; existing tokens were revoked at deactivation time so a fresh login is required.
Guards:
- The target member must belong to the requesting actor's organisation.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/org/team/members/architecto/reactivate" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/team/members/architecto/reactivate"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "PUT",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/team/members/architecto/reactivate';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/team/members/architecto/reactivate');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.put(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Member reactivated.",
"data": null,
"errors": null,
"meta": {
"request_id": "6022ea0d-33c3-46cd-a043-6dbbbc198b31",
"timestamp": "2026-08-05T16:18:38.951107Z"
}
}
Example response (403):
{
"status": "FORBIDDEN",
"message": "This action is unauthorized."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Remove Team Member
requires authentication
Removes a member from the organisation's team. The primary admin (Owner role) cannot be removed via this endpoint — ownership transfer is a separate, deliberate operation.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/org/team/members/architecto" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/team/members/architecto"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/team/members/architecto';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/team/members/architecto');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (204):
Empty response
Example response (403):
{
"status": "FORBIDDEN",
"message": "This action is unauthorized.",
"data": null,
"errors": [
{
"field": null,
"message": "This action is unauthorized."
}
]
}
Example response (422):
{
"status": "VALIDATION_ERROR",
"message": "The organisation owner cannot be removed.",
"data": null,
"errors": [
{
"field": null,
"message": "The organisation owner cannot be removed."
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Jobs
List Organization Jobs
requires authentication
List all jobs for the organization.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/jobs" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"jobs": [
{
"id": "019fd2b8-28ee-71e0-b50d-2c303c17f728",
"title": "Kindergarten Teacher",
"category": "warehouse",
"category_label": "Warehouse",
"status": "pending_review",
"status_label": "In Prüfung",
"status_color": "yellow",
"location_city": "Eldahaven",
"start_date": "2026-08-21",
"end_date": "2026-09-15",
"shift_start_time": "06:44:00",
"shift_end_time": "06:04:00",
"next_shift_date": null,
"total_vacancies": 1,
"filled_vacancies": 0,
"hourly_rate_gross": 18.4,
"applications_count": 0,
"shifts_count": 0,
"application_deadline": "2026-09-05 16:18",
"published_at": null,
"created_at": "2026-08-05 16:18"
},
{
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant",
"category": "office",
"category_label": "Office",
"status": "active",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "East Eliseo",
"start_date": "2026-08-12",
"end_date": "2026-08-19",
"shift_start_time": "01:49:00",
"shift_end_time": "18:57:00",
"next_shift_date": "2026-08-05",
"total_vacancies": 5,
"filled_vacancies": 0,
"hourly_rate_gross": 32.08,
"applications_count": 1,
"shifts_count": 1,
"application_deadline": "2026-09-05 16:18",
"published_at": null,
"created_at": "2026-08-05 16:18"
},
{
"id": "019fd2b8-28e8-73a4-94d6-5a423c21f064",
"title": "Foundry Mold and Coremaker",
"category": "software",
"category_label": "Software",
"status": "draft",
"status_label": "Entwurf",
"status_color": "gray",
"location_city": "South Zachery",
"start_date": "2026-08-29",
"end_date": "2026-09-25",
"shift_start_time": "16:30:00",
"shift_end_time": "14:33:00",
"next_shift_date": null,
"total_vacancies": 10,
"filled_vacancies": 0,
"hourly_rate_gross": 29.86,
"applications_count": 0,
"shifts_count": 0,
"application_deadline": "2026-09-05 16:18",
"published_at": null,
"created_at": "2026-08-05 16:18"
},
{
"id": "019fd2b8-2705-73fd-a401-002956f1f401",
"title": "Fahrer*in Zustelldienst Wien Nord",
"category": "logistics",
"category_label": "Logistics",
"status": "published",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-14",
"end_date": "2026-08-15",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"next_shift_date": null,
"total_vacancies": 4,
"filled_vacancies": 0,
"hourly_rate_gross": 15,
"applications_count": 0,
"shifts_count": 0,
"application_deadline": "2026-08-12 00:00",
"published_at": "2026-08-05 04:18",
"created_at": "2026-08-05 16:18"
},
{
"id": "019fd2b8-2700-724b-adc5-2be8957e0590",
"title": "Kassierer*in Supermarkt Floridsdorf",
"category": "supermarket",
"category_label": "Grocery",
"status": "published",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-11",
"end_date": "2026-08-12",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"next_shift_date": null,
"total_vacancies": 5,
"filled_vacancies": 0,
"hourly_rate_gross": 13.5,
"applications_count": 0,
"shifts_count": 0,
"application_deadline": "2026-08-09 00:00",
"published_at": "2026-08-05 08:18",
"created_at": "2026-08-05 16:18"
},
{
"id": "019fd2b8-26fb-7142-b3a3-df10c3591584",
"title": "Küchenhilfe Streetfood Festival Naschmarkt",
"category": "catering",
"category_label": "Catering",
"status": "published",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-13",
"end_date": "2026-08-14",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"next_shift_date": null,
"total_vacancies": 6,
"filled_vacancies": 0,
"hourly_rate_gross": 13,
"applications_count": 0,
"shifts_count": 0,
"application_deadline": "2026-08-11 00:00",
"published_at": "2026-08-05 13:18",
"created_at": "2026-08-05 16:18"
},
{
"id": "019fd2b8-270f-715d-a3a0-76c4c314e3ff",
"title": "Verkäufer*in Elektronik Mediamarkt Vösendorf",
"category": "retail",
"category_label": "Retail",
"status": "published",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Vösendorf",
"start_date": "2026-08-20",
"end_date": "2026-08-21",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"next_shift_date": null,
"total_vacancies": 7,
"filled_vacancies": 0,
"hourly_rate_gross": 14,
"applications_count": 0,
"shifts_count": 0,
"application_deadline": "2026-08-18 00:00",
"published_at": "2026-08-04 16:18",
"created_at": "2026-08-05 16:18"
},
{
"id": "019fd2b8-2599-7355-a7f1-dcb185b05faa",
"title": "Rezeptionist*in Hotel Sacher",
"category": "hotel",
"category_label": "Hospitality",
"status": "published",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-17",
"end_date": "2026-08-19",
"shift_start_time": "09:00:00",
"shift_end_time": "17:00:00",
"next_shift_date": null,
"total_vacancies": 4,
"filled_vacancies": 0,
"hourly_rate_gross": 17.5,
"applications_count": 51,
"shifts_count": 0,
"application_deadline": "2026-08-14 00:00",
"published_at": "2026-07-31 16:18",
"created_at": "2026-08-05 16:18"
},
{
"id": "019fd2b8-24b0-700a-ae2a-142f5e48aead",
"title": "Lagerhelfer*in Logistikzentrum Inzersdorf",
"category": "warehouse",
"category_label": "Warehouse",
"status": "published",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-12",
"end_date": "2026-08-14",
"shift_start_time": "22:00:00",
"shift_end_time": "06:00:00",
"next_shift_date": null,
"total_vacancies": 15,
"filled_vacancies": 0,
"hourly_rate_gross": 14.8,
"applications_count": 29,
"shifts_count": 0,
"application_deadline": "2026-08-09 00:00",
"published_at": "2026-08-01 16:18",
"created_at": "2026-08-05 16:18"
},
{
"id": "019fd2b8-270a-71f9-a13c-ef188105041c",
"title": "Reinigungskraft Hotel Ibis Mariahilf",
"category": "cleaning",
"category_label": "Cleaning",
"status": "published",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-16",
"end_date": "2026-08-17",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"next_shift_date": null,
"total_vacancies": 3,
"filled_vacancies": 0,
"hourly_rate_gross": 13.2,
"applications_count": 0,
"shifts_count": 0,
"application_deadline": "2026-08-14 00:00",
"published_at": "2026-08-04 22:18",
"created_at": "2026-08-05 16:18"
},
{
"id": "019fd2b8-21c8-72cc-80b1-47fd13450522",
"title": "Barkeeper*in Sommernacht Open Air",
"category": "gastro",
"category_label": "Gastronomy",
"status": "published",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-15",
"end_date": "2026-08-17",
"shift_start_time": "22:00:00",
"shift_end_time": "06:00:00",
"next_shift_date": null,
"total_vacancies": 8,
"filled_vacancies": 0,
"hourly_rate_gross": 16,
"applications_count": 38,
"shifts_count": 0,
"application_deadline": "2026-08-12 00:00",
"published_at": "2026-07-31 16:18",
"created_at": "2026-08-05 16:18"
},
{
"id": "019fd2b8-22cf-71c5-8edd-5e3ce9d29e8b",
"title": "Promoter*in Vienna Marathon",
"category": "event",
"category_label": "Events",
"status": "published",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-26",
"end_date": "2026-08-28",
"shift_start_time": "09:00:00",
"shift_end_time": "17:00:00",
"next_shift_date": null,
"total_vacancies": 20,
"filled_vacancies": 0,
"hourly_rate_gross": 13.5,
"applications_count": 62,
"shifts_count": 0,
"application_deadline": "2026-08-23 00:00",
"published_at": "2026-07-31 16:18",
"created_at": "2026-08-05 16:18"
},
{
"id": "019fd2b8-1f86-7376-9a3a-c072ab5675cb",
"title": "Service-Mitarbeiter*in Wiener Prater Festival",
"category": "gastro",
"category_label": "Gastronomy",
"status": "published",
"status_label": "Aktiv",
"status_color": "green",
"location_city": "Wien",
"start_date": "2026-08-19",
"end_date": "2026-08-21",
"shift_start_time": "09:00:00",
"shift_end_time": "17:00:00",
"next_shift_date": null,
"total_vacancies": 12,
"filled_vacancies": 0,
"hourly_rate_gross": 15.5,
"applications_count": 45,
"shifts_count": 0,
"application_deadline": "2026-08-16 00:00",
"published_at": "2026-07-31 16:18",
"created_at": "2026-08-05 16:18"
},
{
"id": "019fd2b8-1dcd-734a-a041-f809f58e95fb",
"title": "IT Supportkraft Vertretung",
"category": "it_services",
"category_label": "IT Services",
"status": "pending_review",
"status_label": "In Prüfung",
"status_color": "yellow",
"location_city": "Wien",
"start_date": "2026-08-20",
"end_date": "2026-09-04",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"next_shift_date": null,
"total_vacancies": 2,
"filled_vacancies": 0,
"hourly_rate_gross": 22,
"applications_count": 0,
"shifts_count": 0,
"application_deadline": "2026-08-15 16:18",
"published_at": null,
"created_at": "2026-08-05 16:18"
},
{
"id": "019fd2b8-1dcb-73f4-9257-e7fa42fe8514",
"title": "Sommerfest Catering",
"category": "catering",
"category_label": "Catering",
"status": "pending_review",
"status_label": "In Prüfung",
"status_color": "yellow",
"location_city": "Wien",
"start_date": "2026-09-24",
"end_date": "2026-09-25",
"shift_start_time": "08:00:00",
"shift_end_time": "16:00:00",
"next_shift_date": null,
"total_vacancies": 12,
"filled_vacancies": 0,
"hourly_rate_gross": 15,
"applications_count": 0,
"shifts_count": 0,
"application_deadline": "2026-09-22 16:18",
"published_at": null,
"created_at": "2026-08-05 16:18"
}
],
"pagination": {
"current_page": 1,
"last_page": 2,
"per_page": 15,
"total": 18
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Organization Job Categories
requires authentication
List the active job categories available to an organization when creating a job or filtering the jobs list. Returns a flat, ordered list keyed by slug, each carrying its authoritative KV minimum hourly wage (LSD-BG equal treatment) so the portal validates pay against the same floor the backend enforces at submit.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/jobs/categories" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs/categories"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs/categories';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs/categories');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"categories": [
{
"code": "gastro",
"label": "Gastronomy",
"icon": "utensils",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "hotel",
"label": "Hospitality",
"icon": "hotel",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "food_service",
"label": "Food Service",
"icon": "utensils",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "catering",
"label": "Catering",
"icon": "utensils",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "retail",
"label": "Retail",
"icon": "shopping-cart",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "supermarket",
"label": "Grocery",
"icon": "shopping-cart",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "pharmacy",
"label": "Pharmacy",
"icon": "heart-pulse",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "production",
"label": "Production",
"icon": "industry",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "warehouse",
"label": "Warehouse",
"icon": "industry",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "logistics",
"label": "Logistics",
"icon": "truck",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "manufacturing",
"label": "Manufacturing",
"icon": "industry",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "transportation",
"label": "Transportation",
"icon": "truck",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "event",
"label": "Events",
"icon": "calendar-star",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "security",
"label": "Security",
"icon": "shield",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "office",
"label": "Office",
"icon": "briefcase",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "reception",
"label": "Reception",
"icon": "briefcase",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "call_center",
"label": "Call Center",
"icon": "briefcase",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "customer_service",
"label": "Customer Service",
"icon": "briefcase",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "software",
"label": "Software",
"icon": "code",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "it_services",
"label": "IT Services",
"icon": "code",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "cleaning",
"label": "Cleaning",
"icon": "broom",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "facility",
"label": "Facility Management",
"icon": "broom",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "care",
"label": "Care",
"icon": "heart-pulse",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "healthcare",
"label": "Healthcare",
"icon": "heart-pulse",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "construction",
"label": "Construction",
"icon": "building",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "real_estate",
"label": "Real Estate",
"icon": "building",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "graphic_design",
"label": "Graphic Design",
"icon": "palette",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "media",
"label": "Media",
"icon": "palette",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "education",
"label": "Education",
"icon": "graduation-cap",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "finance",
"label": "Finance",
"icon": "chart-line",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "agriculture",
"label": "Agriculture",
"icon": "leaf",
"min_hourly_cents": null,
"rate_source": null
},
{
"code": "other",
"label": "Other",
"icon": "ellipsis",
"min_hourly_cents": null,
"rate_source": null
}
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Job Document Types
requires authentication
The catalog of worker document types a company can require as an application prerequisite (e.g. work permit, driver licence). Only types an admin has left company-selectable are offered. Backs the required-documents multiselect on the create/edit job form.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/jobs/document-types" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs/document-types"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs/document-types';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs/document-types');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"document_types": [
{
"code": "passport",
"label": "Passport"
},
{
"code": "id_card",
"label": "ID card"
},
{
"code": "driver_license",
"label": "Driver's licence"
},
{
"code": "work_permit",
"label": "Work permit"
},
{
"code": "residence_permit",
"label": "Residence permit"
},
{
"code": "rot_weiss_rot_karte",
"label": "Rot-Weiß-Rot card"
},
{
"code": "blue_card",
"label": "EU Blue Card"
},
{
"code": "bank_statement",
"label": "Bank statement"
},
{
"code": "proof_of_address",
"label": "Proof of address"
},
{
"code": "social_insurance_card",
"label": "Social insurance record"
},
{
"code": "tax_document",
"label": "Tax document"
},
{
"code": "certification",
"label": "Certification"
},
{
"code": "health_certificate",
"label": "Health certificate"
},
{
"code": "criminal_record_check",
"label": "Criminal record check"
},
{
"code": "other",
"label": "Other"
}
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create Job
requires authentication
Create a new job listing for the organization.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/jobs" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The job has been created successfully.",
"data": {
"job": {
"id": "019fd2b8-6bb5-7113-b62c-7434d5f44733",
"title": "Lagermitarbeiter (m/w/d)",
"status": "draft",
"status_label": "Entwurf",
"created_at": "2026-08-05 16:18:49"
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Organization Job
requires authentication
Get job details for the organization.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"job": {
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant",
"description": "Ut nostrum rerum ut alias quia libero excepturi. Voluptatum et aut non quia quisquam molestias. Perferendis qui hic unde.",
"category": "office",
"category_label": "Office",
"status": "active",
"status_label": "Aktiv",
"status_color": "green",
"shift_type": "night",
"shift_type_label": "Nachtschicht",
"location": {
"name": "Barrows, Christiansen and Jones",
"address": "586 Tremaine Row",
"city": "East Eliseo",
"postal_code": "10547-3697",
"lat": 46.931383,
"lng": 11.998284
},
"schedule": {
"start_date": "2026-08-12",
"end_date": "2026-08-19",
"shift_start_time": "01:49:00",
"shift_end_time": "18:57:00"
},
"vacancies": {
"total": 5,
"filled": 0,
"available": 5
},
"compensation": {
"hourly_rate_gross": 32.08,
"supplements": {
"night": 0.7,
"weekend": 3.86
},
"estimated_total_gross": 0
},
"requirements": {
"qualifications": [],
"dress_code": "Tempore necessitatibus quia illo suscipit.",
"equipment_provided": "Adipisci fugiat doloremque atque consectetur necessitatibus sunt cumque."
},
"contact": {
"parking_info": null,
"special_instructions": null
},
"deadlines": {
"application_deadline": "2026-09-05 16:18",
"confirmation_deadline": "2026-08-16 10:20",
"sign_window_hours": 24
},
"statistics": {
"applications_count": 1,
"shifts_count": 1
},
"assignment": {
"method": "manual",
"auto_reject_after_hours": null
},
"required_documents": [
{
"code": "passport",
"name": "Reisepass"
},
{
"code": "driver_license",
"name": "Führerschein"
}
],
"custom_document_requests": [],
"planned_shifts": [
{
"id": "019fd2b8-28d5-7103-b951-9f6ff1d94556",
"shift_date": "2026-08-05",
"start_time": "08:00",
"end_time": "16:00",
"break_minutes": 30,
"workers_needed": 2,
"shift_manager_member_id": null,
"shift_manager_name": null,
"notes": null,
"dress_code": null,
"contact_person_name": null,
"contact_person_phone": null,
"meeting_point": null,
"geofence": null,
"application_deadline": null
}
],
"review": {
"submitted_at": null,
"reviewed_at": null,
"rejection_note": null
},
"timestamps": {
"published_at": null,
"filled_at": null,
"cancelled_at": null,
"cancellation_reason": null,
"created_at": "2026-08-05 16:18",
"updated_at": "2026-08-05 16:18"
}
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Submit Job For Review
requires authentication
Submit a draft (or previously rejected) job for admin review. Funds for
every shift + promotion are blocked from the wallet at submit time, so an
admin only ever reviews a job the company can afford. The job then waits in
pending_review until an admin approves (→ active) or rejects it.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/submit" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/submit"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/submit';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/submit');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The job has been submitted for admin review.",
"data": {
"job": {
"id": "019fd2b8-6bb5-7113-b62c-7434d5f44733",
"status": "pending_review",
"status_label": "In Prüfung",
"submitted_at": "2026-08-05 16:18"
},
"compliance_flags": []
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Close Job
requires authentication
Close a job (cancel or mark as filled).
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/close" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"filled\",
\"cancellation_reason\": \"Krankheitsbedingt kurzfristig abgesagt.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/close"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "filled",
"cancellation_reason": "Krankheitsbedingt kurzfristig abgesagt."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/close';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'filled',
'cancellation_reason' => 'Krankheitsbedingt kurzfristig abgesagt.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/close');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "filled",
"cancellation_reason": "Krankheitsbedingt kurzfristig abgesagt."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The job has been marked as filled.",
"data": {
"job": {
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"status": "filled",
"status_label": "Besetzt"
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Applicants
requires authentication
List all applicants for a specific job.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"applicants": [
{
"id": "019fd2b8-76c6-72bb-a2d9-98ed4934fb02",
"status": "pending",
"status_label": "Eingereicht",
"applied_at": "2026-08-05 16:18",
"has_scheduling_conflict": false,
"acknowledged_conflict": false,
"shortlisted_at": null,
"selected_at": null,
"rejected_at": null,
"notes": null,
"match_score": 78,
"employee": {
"id": "019fd2b8-7352-72bc-9514-ac7713e5c225",
"name": "Fae G.",
"identity_revealed": false,
"email": null,
"phone": null
},
"profile": {
"nationality": "AT",
"city": "North Asa",
"profile_completion_percentage": 86,
"avg_rating": null,
"total_shifts_completed": 0
}
}
],
"summary": {
"total": 1,
"by_status": {
"pending": 1,
"shortlisted": 0,
"selected": 0,
"rejected": 0
}
},
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 20,
"total": 1
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Job Shifts
requires authentication
List a job's shift SLOTS (the shifts table — one row per planned slot),
each with how many of its workers are filled. Per-worker rows live under the
assignments endpoints, not here. A job has few slots, so the collection is
loaded once and filtered/paginated in memory.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/shifts" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/shifts"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/shifts';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/shifts');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"job": {
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant",
"status": "active",
"status_label": "Aktiv"
},
"shifts": [
{
"id": "019fd2b8-28d5-7103-b951-9f6ff1d94556",
"shift_date": "2026-08-05",
"start_time": "08:00",
"end_time": "16:00",
"break_minutes": 30,
"workers_needed": 2,
"filled_count": 0,
"open_count": 2,
"status": "scheduled",
"status_label": "Geplant",
"shift_manager": null,
"notes": null
}
],
"summary": {
"total_slots": 1,
"total_workers_needed": 2,
"total_filled": 0,
"by_status": {
"scheduled": 1,
"in_progress": 0,
"completed": 0,
"cancelled": 0
}
},
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 50,
"total": 1
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Job Contracts
requires authentication
List the leasing (Überlassung) contracts tied to a job's shifts, with the worker, signing status and a download URL for the signed PDF. Powers the Contracts tab on the redesigned job detail page.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/contracts" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/contracts"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/contracts';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/contracts');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"job": {
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant"
},
"contracts": [],
"summary": {
"total": 0,
"signed": 0,
"pending": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Job Contract Template
requires authentication
A job's contract template for the job editor: the job-level override when one exists ("customized"), otherwise the effective template inherited from the organisation default (or the built-in body) — plus the merge fields.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/contract-template" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/contract-template"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/contract-template';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/contract-template');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"template": {
"name": "Überlassungsvertrag",
"body_html": "<h2>Arbeitskraft</h2>\n<p>{worker_name}, geboren am {worker_birth_date}, {worker_address}</p>\n<h2>Beschäftiger</h2>\n<p>{organization_name}, {organization_address}</p>\n<h2>Überlassung</h2>\n<p>Tätigkeit: {job_title}<br>Einsatzort: {location}<br>Zeitraum: {start_date} – {end_date}<br>Entgelt (brutto/Std.): {hourly_rate}<br>Kollektivvertrag: {collective_agreement}</p>\n<p>Für die Dauer der Überlassung gelten gemäß § 10 AÜG die im Beschäftigerbetrieb für vergleichbare Arbeitnehmer geltenden wesentlichen Arbeits- und Beschäftigungsbedingungen. Rechtsgrundlage: {legal_basis}.</p>",
"version": 0,
"is_active": false,
"is_customized": false
},
"merge_fields": [
"contract_number",
"worker_name",
"worker_birth_date",
"worker_nationality",
"worker_address",
"organization_name",
"organization_address",
"job_title",
"job_description",
"location",
"start_date",
"end_date",
"hourly_rate",
"collective_agreement",
"legal_basis"
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Job Contract Template
requires authentication
Save (or reset) a job's contract template override. inherit: true deletes
the job-level row so the job falls back to the organisation default;
otherwise the body is upserted, seeded from the resolved parent (the
organisation default, or the built-in body) the first time a job is
customised.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/contract-template" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Beispieltext\",
\"body_html\": \"Bitte um Rueckmeldung zur naechsten Schicht.\",
\"is_active\": true,
\"inherit\": true
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/contract-template"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Beispieltext",
"body_html": "Bitte um Rueckmeldung zur naechsten Schicht.",
"is_active": true,
"inherit": true
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/contract-template';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'name' => 'Beispieltext',
'body_html' => 'Bitte um Rueckmeldung zur naechsten Schicht.',
'is_active' => true,
'inherit' => true,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/contract-template');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"name": "Beispieltext",
"body_html": "Bitte um Rueckmeldung zur naechsten Schicht.",
"is_active": true,
"inherit": true
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The contract template has been saved.",
"data": {
"template": {
"name": "Überlassungsvertrag",
"body_html": "<h2>Arbeitskraft</h2>\n<p>{worker_name}, geboren am {worker_birth_date}, {worker_address}</p>\n<h2>Beschäftiger</h2>\n<p>{organization_name}, {organization_address}</p>\n<h2>Überlassung</h2>\n<p>Tätigkeit: {job_title}<br>Einsatzort: {location}<br>Zeitraum: {start_date} – {end_date}<br>Entgelt (brutto/Std.): {hourly_rate}<br>Kollektivvertrag: {collective_agreement}</p>\n<p>Für die Dauer der Überlassung gelten gemäß § 10 AÜG die im Beschäftigerbetrieb für vergleichbare Arbeitnehmer geltenden wesentlichen Arbeits- und Beschäftigungsbedingungen. Rechtsgrundlage: {legal_basis}.</p>",
"version": 0,
"is_active": false,
"is_customized": false
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Shortlist Applicant
requires authentication
Shortlist an applicant for consideration.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants/019f9939-c4c3-70fb-a54e-5ebf63db36d2/shortlist" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants/019f9939-c4c3-70fb-a54e-5ebf63db36d2/shortlist"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants/019f9939-c4c3-70fb-a54e-5ebf63db36d2/shortlist';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants/019f9939-c4c3-70fb-a54e-5ebf63db36d2/shortlist');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "messages.applicant_shortlisted",
"data": {
"application": {
"id": "019fd2b8-76c6-72bb-a2d9-98ed4934fb02",
"status": "shortlisted",
"shortlisted_at": "2026-08-05 16:18"
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Select Applicant
requires authentication
Select an applicant for the job and create their shifts.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants/019f9939-c4c3-70fb-a54e-5ebf63db36d2/select" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants/019f9939-c4c3-70fb-a54e-5ebf63db36d2/select"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants/019f9939-c4c3-70fb-a54e-5ebf63db36d2/select';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants/019f9939-c4c3-70fb-a54e-5ebf63db36d2/select');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The applicant has been selected and assigned to shifts.",
"data": {
"application": {
"id": "019fd2b8-76c6-72bb-a2d9-98ed4934fb02",
"status": "selected",
"selected_at": "2026-08-05 16:18"
},
"shifts_created": 1,
"job_vacancies": {
"total": 3,
"filled": 0,
"available": 3
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Add To Waitlist
requires authentication
Add an applicant to the waitlist (standby).
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants/019f9939-c4c3-70fb-a54e-5ebf63db36d2/waitlist" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"position\": 1
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants/019f9939-c4c3-70fb-a54e-5ebf63db36d2/waitlist"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"position": 1
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants/019f9939-c4c3-70fb-a54e-5ebf63db36d2/waitlist';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'position' => 1,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants/019f9939-c4c3-70fb-a54e-5ebf63db36d2/waitlist');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"position": 1
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "messages.applicant_added_to_waitlist",
"data": {
"application": {
"id": "019fd2b8-7cd7-7331-a92c-cf1a3939282f",
"status": "standby",
"waitlist_position": 1,
"added_to_waitlist_at": "2026-08-05 16:18"
},
"waitlist_summary": {
"total": 1,
"max_size": 5,
"positions": [
{
"position": 1,
"application_id": "019fd2b8-7cd7-7331-a92c-cf1a3939282f",
"added_at": "2026-08-05 16:18"
}
]
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reject Applicant
requires authentication
Reject an applicant for the job.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants/019f9939-c4c3-70fb-a54e-5ebf63db36d2/reject" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason_code\": \"position_filled\",
\"internal_note\": \"Beispieltext\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants/019f9939-c4c3-70fb-a54e-5ebf63db36d2/reject"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason_code": "position_filled",
"internal_note": "Beispieltext"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants/019f9939-c4c3-70fb-a54e-5ebf63db36d2/reject';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason_code' => 'position_filled',
'internal_note' => 'Beispieltext',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants/019f9939-c4c3-70fb-a54e-5ebf63db36d2/reject');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason_code": "position_filled",
"internal_note": "Beispieltext"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The applicant has been rejected.",
"data": {
"application": {
"id": "019fd2b8-7cd7-7331-a92c-cf1a3939282f",
"status": "rejected",
"rejected_at": "2026-08-05 16:18"
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Deassign Shift
requires authentication
De-assign a worker from one of their chosen shifts.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants/019f9939-c4c3-70fb-a54e-5ebf63db36d2/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/deassign" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Krankheitsbedingt kurzfristig abgesagt.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants/019f9939-c4c3-70fb-a54e-5ebf63db36d2/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/deassign"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants/019f9939-c4c3-70fb-a54e-5ebf63db36d2/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/deassign';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'Krankheitsbedingt kurzfristig abgesagt.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs/019f9939-c4c3-70fb-a54e-5ebf63db36d2/applicants/019f9939-c4c3-70fb-a54e-5ebf63db36d2/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/deassign');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Applicants
Get a single applicant's profile.
requires authentication
Per Austrian AÜG (Arbeitskräfteüberlassungsgesetz), client organizations must be able to verify worker qualifications before assignment — but not their identity, which stays masked until the company selects them.
Passing reveal=true unmasks it early. That requires the audit.view
permission and writes an OrgPiiReveal audit entry before the data is
returned, so the record is made where the disclosure actually happens rather
than wherever a client chooses to report it.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/jobs/architecto/applicants/architecto?reveal=1" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs/architecto/applicants/architecto"
);
const params = {
"reveal": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs/architecto/applicants/architecto';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'reveal' => '1',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs/architecto/applicants/architecto')
.replace(queryParameters: {
'reveal': '1',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"id": "019fd2b8-76c6-72bb-a2d9-98ed4934fb02",
"status": "selected",
"status_label": "Ausgewählt",
"applied_at": "2026-08-05 16:18",
"has_scheduling_conflict": false,
"acknowledged_conflict": false,
"shortlisted_at": "2026-08-05 16:18",
"selected_at": "2026-08-05 16:18",
"rejected_at": null,
"notes": null,
"chosen_shifts": [
{
"id": "019fd2b8-756e-70aa-a7ad-01157af79df0",
"shift_date": "2026-08-12",
"start_time": "08:00:00",
"end_time": "16:00:00"
}
],
"cover_letter": null,
"availability": null,
"expected_hourly_rate": null,
"application_documents": [],
"user": {
"id": "019fd2b8-7352-72bc-9514-ac7713e5c225",
"display_name": "Fae Green",
"first_name": "Fae",
"last_name": "Green",
"email": "ruthie17@example.com",
"phone": null,
"avatar_url": null
},
"profile": {
"nationality": "AT",
"city": "North Asa",
"gender": "not_specified",
"date_of_birth": "2007-02-21",
"profile_completion_percentage": 86,
"avg_rating": 0,
"reliability_score": 100,
"punctuality_percentage": null,
"hours_worked": 0,
"total_shifts_completed": 0,
"no_shows_count": 0,
"bio": null,
"education": null,
"skills": [],
"languages": [],
"certifications": [],
"reviews": [],
"documents": []
}
}
}
Example response (403, Not permitted to reveal):
{
"status": "FORBIDDEN",
"message": "You are not permitted to reveal applicant identities."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Shifts
Get Shift Detail
requires authentication
Returns a single shift slot with its worker assignments and each assignment's live check-in / clock state — backs the portal's live shift view page.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"shift": {
"id": "019fd2b8-28d5-7103-b951-9f6ff1d94556",
"job": {
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant"
},
"shift_date": "2026-08-05",
"start_time": "08:00:00",
"end_time": "16:00:00",
"break_minutes": 30,
"workers_needed": 2,
"notes": null,
"status": "scheduled",
"status_label": "Geplant",
"shift_manager": null,
"counts": {
"needed": 2,
"awaiting_signature": 0,
"signed": 0,
"checked_in": 0,
"completed": 0,
"no_show": 0
},
"assignments": []
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Shift Contract Template
requires authentication
A shift's contract template for the shift editor: the shift-level override when one exists ("customized"), otherwise the effective template inherited from the job override (or the organisation default, or the built-in body) — plus the merge fields.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/contract-template" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/contract-template"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/contract-template';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/contract-template');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"template": {
"name": "Überlassungsvertrag",
"body_html": "<h2>Arbeitskraft</h2>\n<p>{worker_name}, geboren am {worker_birth_date}, {worker_address}</p>\n<h2>Beschäftiger</h2>\n<p>{organization_name}, {organization_address}</p>\n<h2>Überlassung</h2>\n<p>Tätigkeit: {job_title}<br>Einsatzort: {location}<br>Zeitraum: {start_date} – {end_date}<br>Entgelt (brutto/Std.): {hourly_rate}<br>Kollektivvertrag: {collective_agreement}</p>\n<p>Für die Dauer der Überlassung gelten gemäß § 10 AÜG die im Beschäftigerbetrieb für vergleichbare Arbeitnehmer geltenden wesentlichen Arbeits- und Beschäftigungsbedingungen. Rechtsgrundlage: {legal_basis}.</p>",
"version": 0,
"is_active": false,
"is_customized": false
},
"merge_fields": [
"contract_number",
"worker_name",
"worker_birth_date",
"worker_nationality",
"worker_address",
"organization_name",
"organization_address",
"job_title",
"job_description",
"location",
"start_date",
"end_date",
"hourly_rate",
"collective_agreement",
"legal_basis"
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Shift Contract Template
requires authentication
Save (or reset) a shift's contract template override. inherit: true
deletes the shift-level row so the shift falls back to its job's template
(or the organisation default); otherwise the body is upserted, seeded from
the resolved job-level body the first time a shift is customised.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/org/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/contract-template" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Beispieltext\",
\"body_html\": \"Bitte um Rueckmeldung zur naechsten Schicht.\",
\"is_active\": true,
\"inherit\": true
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/contract-template"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Beispieltext",
"body_html": "Bitte um Rueckmeldung zur naechsten Schicht.",
"is_active": true,
"inherit": true
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/contract-template';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'name' => 'Beispieltext',
'body_html' => 'Bitte um Rueckmeldung zur naechsten Schicht.',
'is_active' => true,
'inherit' => true,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/contract-template');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"name": "Beispieltext",
"body_html": "Bitte um Rueckmeldung zur naechsten Schicht.",
"is_active": true,
"inherit": true
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The contract template has been saved.",
"data": {
"template": {
"name": "Überlassungsvertrag",
"body_html": "<h2>Arbeitskraft</h2>\n<p>{worker_name}, geboren am {worker_birth_date}, {worker_address}</p>\n<h2>Beschäftiger</h2>\n<p>{organization_name}, {organization_address}</p>\n<h2>Überlassung</h2>\n<p>Tätigkeit: {job_title}<br>Einsatzort: {location}<br>Zeitraum: {start_date} – {end_date}<br>Entgelt (brutto/Std.): {hourly_rate}<br>Kollektivvertrag: {collective_agreement}</p>\n<p>Für die Dauer der Überlassung gelten gemäß § 10 AÜG die im Beschäftigerbetrieb für vergleichbare Arbeitnehmer geltenden wesentlichen Arbeits- und Beschäftigungsbedingungen. Rechtsgrundlage: {legal_basis}.</p>",
"version": 0,
"is_active": false,
"is_customized": false
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Scan Check In Qr
requires authentication
Scan an employee's QR code to record check-in/check-out.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/shifts/scan-qr" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"qr_payload\": \"Beispieltext\",
\"lat\": 1,
\"lng\": 1,
\"signature\": \"Beispieltext\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/scan-qr"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"qr_payload": "Beispieltext",
"lat": 1,
"lng": 1,
"signature": "Beispieltext"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/scan-qr';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'qr_payload' => 'Beispieltext',
'lat' => 1,
'lng' => 1,
'signature' => 'Beispieltext',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/scan-qr');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"qr_payload": "Beispieltext",
"lat": 1,
"lng": 1,
"signature": "Beispieltext"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Cancel Shift By Organisation
requires authentication
Organization cancels a shift.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/cancel" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Krankheitsbedingt kurzfristig abgesagt.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/cancel"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/cancel';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'Krankheitsbedingt kurzfristig abgesagt.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/cancel');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Notify Shift Extension
requires authentication
Allows an organisation to extend an active shift — updating the end time and notifying the assigned employee via push notification.
The extension is only allowed when the shift is currently in_progress.
The organisation must provide a reason and the new end time must be later
than the current scheduled end time.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/shifts/9c3f5f3d-0123-4abc-b456-426614174000/extend" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"extended_end_time\": \"20:00\",
\"reason\": \"Production running late, need 2 more hours.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/9c3f5f3d-0123-4abc-b456-426614174000/extend"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"extended_end_time": "20:00",
"reason": "Production running late, need 2 more hours."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/9c3f5f3d-0123-4abc-b456-426614174000/extend';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'extended_end_time' => '20:00',
'reason' => 'Production running late, need 2 more hours.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/9c3f5f3d-0123-4abc-b456-426614174000/extend');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"extended_end_time": "20:00",
"reason": "Production running late, need 2 more hours."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"message": "Schichtverlängerung wurde gemeldet.",
"extended_end_time": "20:00"
}
}
Example response (400):
{
"status": "ERROR",
"message": "Die Schicht ist nicht aktiv."
}
Example response (403):
{
"status": "ERROR",
"message": "Diese Schicht gehört nicht zu Ihrem Unternehmen."
}
Example response (404):
{
"status": "ERROR",
"message": "Schicht nicht gefunden."
}
Example response (422):
{
"status": "ERROR",
"message": "The extended end time field is required."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Rate Employee
requires authentication
Organization submits a rating for an employee after shift completion.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/rate" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"overall_score\": 1,
\"punctuality_score\": 1,
\"professionalism_score\": 1,
\"communication_score\": 1,
\"work_quality_score\": 1,
\"comment\": \"Beispieltext\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/rate"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"overall_score": 1,
"punctuality_score": 1,
"professionalism_score": 1,
"communication_score": 1,
"work_quality_score": 1,
"comment": "Beispieltext"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/rate';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'overall_score' => 1,
'punctuality_score' => 1,
'professionalism_score' => 1,
'communication_score' => 1,
'work_quality_score' => 1,
'comment' => 'Beispieltext',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/019f9939-c4c3-70fb-a54e-5ebf63db36d2/rate');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"overall_score": 1,
"punctuality_score": 1,
"professionalism_score": 1,
"communication_score": 1,
"work_quality_score": 1,
"comment": "Beispieltext"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Your rating has been submitted successfully.",
"data": {
"rating": {
"id": "019fd2b8-45d9-707b-89cf-d4a026834fe3",
"overall_score": 1,
"created_at": "2026-08-05 16:18"
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Shift Requests
requires authentication
The company's inbox of worker requests. Pending ones come first regardless of sort, because they are the only ones that need an action — and until they are decided the shift is not settled and the worker is not paid.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/requests?status=pending&type=overtime&shift_id=019f9939-c4c3-70fb-a54e-5ebf63db36d2&per_page=25" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"status\": \"declined\",
\"type\": \"manual_check_in\",
\"shift_id\": \"6ff8f7f6-1eb3-3525-be4a-3932c805afed\",
\"per_page\": 7
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/requests"
);
const params = {
"status": "pending",
"type": "overtime",
"shift_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"per_page": "25",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"status": "declined",
"type": "manual_check_in",
"shift_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed",
"per_page": 7
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/requests';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'status' => 'pending',
'type' => 'overtime',
'shift_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'per_page' => '25',
],
'json' => [
'status' => 'declined',
'type' => 'manual_check_in',
'shift_id' => '6ff8f7f6-1eb3-3525-be4a-3932c805afed',
'per_page' => 7,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/requests')
.replace(queryParameters: {
'status': 'pending',
'type': 'overtime',
'shift_id': '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'per_page': '25',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"status": "declined",
"type": "manual_check_in",
"shift_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed",
"per_page": 7
};
final response = await http.get(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"requests": [],
"pending_count": 0,
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 7,
"total": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Approve or Decline a Shift Request
requires authentication
The company's answer to a worker. Approving overtime raises what the shift pays; declining leaves it at the capped amount. Either way the decision is stamped with whoever made it — the organisation account or the member — and written to the audit trail, because it changes what someone is paid.
A decline must carry a reason. The worker sees it.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/requests/019f9939-c4c3-70fb-a54e-5ebf63db36d2/decide" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"approve\": true,
\"note\": \"Overtime was not authorised on site.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/requests/019f9939-c4c3-70fb-a54e-5ebf63db36d2/decide"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"approve": true,
"note": "Overtime was not authorised on site."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/requests/019f9939-c4c3-70fb-a54e-5ebf63db36d2/decide';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'approve' => true,
'note' => 'Overtime was not authorised on site.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/requests/019f9939-c4c3-70fb-a54e-5ebf63db36d2/decide');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"approve": true,
"note": "Overtime was not authorised on site."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (409, Already decided):
{
"status": "INVALID_OPERATION",
"message": "This request has already been decided."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Open a Conversation About a Shift Request
requires authentication
Starts (or returns) the thread between the company and the worker about one specific request — for when a manager needs to ask something before deciding, rather than approving or declining blind.
Scoped to the request, not the shift, so the exchange stays attached to the decision it belongs to. Calling this twice returns the same thread.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/requests/019f9939-c4c3-70fb-a54e-5ebf63db36d2/conversation" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/requests/019f9939-c4c3-70fb-a54e-5ebf63db36d2/conversation"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/requests/019f9939-c4c3-70fb-a54e-5ebf63db36d2/conversation';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/requests/019f9939-c4c3-70fb-a54e-5ebf63db36d2/conversation');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Thread ready):
{
"status": "SUCCESS",
"data": {
"conversation_id": "019f...",
"shift_request_id": "019f...",
"subject": "Überstunden"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Notifications
List Notifications
requires authentication
Paginated list of notifications for the authenticated organisation.
Includes an unread_count in meta for the inbox badge.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/notifications?page=16&per_page=16&unread_only=" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/notifications"
);
const params = {
"page": "16",
"per_page": "16",
"unread_only": "0",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/notifications';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'page' => '16',
'per_page' => '16',
'unread_only' => '0',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/notifications')
.replace(queryParameters: {
'page': '16',
'per_page': '16',
'unread_only': '',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Notifications retrieved successfully.",
"data": [],
"errors": null,
"meta": {
"request_id": "09377940-8cb9-4640-a522-b88869dfb7fe",
"timestamp": "2026-08-05T16:18:38.542194Z",
"current_page": 16,
"per_page": 16,
"total": 0,
"last_page": 1,
"unread_count": 0
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Unread Notifications Count
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/notifications/unread-count" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/notifications/unread-count"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/notifications/unread-count';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/notifications/unread-count');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"count": 0
},
"errors": null,
"meta": {
"request_id": "a0972d73-64ed-4c2d-a149-88962625ec88",
"timestamp": "2026-08-05T16:18:38.548222Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Mark Notification As Read
requires authentication
Marks a single notification as read for the authenticated organisation.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/notifications/architecto/read" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/notifications/architecto/read"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/notifications/architecto/read';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/notifications/architecto/read');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Success):
{
"status": "SUCCESS",
"message": "Notification marked as read.",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"read_at": "2026-04-02T12:00:00+00:00"
},
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (404, Not Found):
{
"status": "NOT_FOUND",
"message": "Notification not found.",
"data": null,
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Mark All Notifications As Read
requires authentication
Marks every unread notification of the authenticated organisation as read in a single call.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/notifications/read-all" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/notifications/read-all"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/notifications/read-all';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/notifications/read-all');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "All notifications marked as read.",
"data": {
"marked": true
},
"errors": null,
"meta": {
"request_id": "d6f09336-8a5c-476c-880f-8abb84800194",
"timestamp": "2026-08-05T16:18:38.554649Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Notification Preferences
requires authentication
Returns per-category notification preferences for the authenticated organisation. Defaults to email enabled / push disabled for every category.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/notification-preferences" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/notification-preferences"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/notification-preferences';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/notification-preferences');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [
{
"category": "jobs",
"email": true,
"push": false
},
{
"category": "finance",
"email": true,
"push": false
},
{
"category": "communication",
"email": true,
"push": false
},
{
"category": "security",
"email": true,
"push": false
},
{
"category": "system",
"email": true,
"push": false
},
{
"category": "marketing",
"email": true,
"push": false
}
],
"errors": null,
"meta": {
"request_id": "062e170a-40d4-47f4-a976-a64ae4b9bad4",
"timestamp": "2026-08-05T16:18:38.560328Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Notification Preferences
requires authentication
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/org/notification-preferences" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"category\": \"finance\",
\"channel\": \"email\",
\"enabled\": true
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/notification-preferences"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"category": "finance",
"channel": "email",
"enabled": true
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/notification-preferences';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'category' => 'finance',
'channel' => 'email',
'enabled' => true,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/notification-preferences');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"category": "finance",
"channel": "email",
"enabled": true
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Notification preference updated.",
"data": {
"category": "finance",
"email": true,
"push": false
},
"errors": null,
"meta": {
"request_id": "7f992b80-e97b-48f0-a60d-8d3da4d4684e",
"timestamp": "2026-08-05T16:18:38.567378Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "category",
"message": "The selected category is invalid."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Auth
Forgot Password
Sends a 4-digit password reset code to the given email address.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/forgot-password" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"boris@example.com\",
\"guard\": \"user\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/forgot-password"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "boris@example.com",
"guard": "user"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/forgot-password';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'boris@example.com',
'guard' => 'user',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/forgot-password');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "boris@example.com",
"guard": "user"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "If that email address is registered, a password reset code has been sent.",
"data": {
"email": "opal56@example.net",
"code": "448891"
},
"errors": null,
"meta": {
"request_id": "04e13c3e-6945-4f40-bb63-a330434430e3",
"timestamp": "2026-08-05T16:18:54.164086Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "guard",
"message": "The guard field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Verify Reset Code
Validates the 4-digit password reset code for the given email and guard.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/forgot-password/verify" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"boris@example.com\",
\"code\": \"123456\",
\"guard\": \"user\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/forgot-password/verify"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "boris@example.com",
"code": "123456",
"guard": "user"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/forgot-password/verify';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'boris@example.com',
'code' => '123456',
'guard' => 'user',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/forgot-password/verify');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "boris@example.com",
"code": "123456",
"guard": "user"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Reset code verified successfully.",
"data": {
"reset_token": "c97701d0-c4de-4755-b3c4-f7d1a803efc5"
},
"errors": null,
"meta": {
"request_id": "67df2724-9771-46b5-8d4d-71f98573d3e5",
"timestamp": "2026-08-05T16:18:54.166696Z"
}
}
Example response (401, Invalid Code):
{
"status": "RESET_CODE_INVALID",
"message": "Invalid reset code.",
"data": null,
"errors": [
{
"field": "code",
"message": "Invalid reset code."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (410, Code Expired):
{
"status": "RESET_CODE_EXPIRED",
"message": "Reset code has expired.",
"data": null,
"errors": [
{
"field": "code",
"message": "Reset code has expired."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "code",
"message": "The code field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Too Many Attempts):
{
"status": "RESET_ATTEMPTS_EXHAUSTED",
"message": "Too many failed attempts. Please request a new code.",
"data": null,
"errors": [
{
"field": "code",
"message": "Too many failed attempts. Please request a new code."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Resend Reset Code
Re-sends a 4-digit password reset code for the given email and guard.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/forgot-password/resend" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"boris@example.com\",
\"guard\": \"user\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/forgot-password/resend"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "boris@example.com",
"guard": "user"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/forgot-password/resend';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'boris@example.com',
'guard' => 'user',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/forgot-password/resend');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "boris@example.com",
"guard": "user"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "If that email address is registered, a new password reset code has been sent.",
"data": {
"code": "443677"
},
"errors": null,
"meta": {
"request_id": "a265e26e-388c-4782-b9ce-bc4722cc5958",
"timestamp": "2026-08-05T16:18:58.095803Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "guard",
"message": "The guard field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reset Password
Resets the password for any actor type and revokes all existing tokens.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/reset-password" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"boris@example.com\",
\"reset_token\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",
\"password\": \"NewPassword123\",
\"password_confirmation\": \"NewPassword123\",
\"guard\": \"user\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/reset-password"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "boris@example.com",
"reset_token": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"password": "NewPassword123",
"password_confirmation": "NewPassword123",
"guard": "user"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/reset-password';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'boris@example.com',
'reset_token' => 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
'password' => 'NewPassword123',
'password_confirmation' => 'NewPassword123',
'guard' => 'user',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/reset-password');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "boris@example.com",
"reset_token": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"password": "NewPassword123",
"password_confirmation": "NewPassword123",
"guard": "user"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Password has been reset successfully.",
"data": null,
"errors": null,
"meta": {
"request_id": "85c34424-2c5f-4d2e-aa97-5edf63d5d429",
"timestamp": "2026-08-05T16:18:54.626775Z"
}
}
Example response (403, Email Not Verified):
{
"status": "RESET_NOT_VERIFIED",
"message": "Email not verified. Complete the verification step first.",
"data": null,
"errors": [
{
"field": null,
"message": "Email not verified. Complete the verification step first."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (404, Account Not Found):
{
"status": "ACCOUNT_NOT_FOUND",
"message": "Account not found.",
"data": null,
"errors": [
{
"field": null,
"message": "Account not found."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "password",
"message": "The password must be at least 8 characters."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Password Reuse):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "password",
"message": "You cannot reuse your last 3 passwords."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Two Factor Challenge
requires authentication
Completes the two-factor authentication challenge for any guard.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/two-factor/challenge" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"code\": \"123456\",
\"recovery_code\": \"ABCD-1234-EFGH\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/two-factor/challenge"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"code": "123456",
"recovery_code": "ABCD-1234-EFGH"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/two-factor/challenge';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'code' => '123456',
'recovery_code' => 'ABCD-1234-EFGH',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/two-factor/challenge');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"code": "123456",
"recovery_code": "ABCD-1234-EFGH"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Two-factor authentication verified successfully.",
"data": {
"token": "42|wMrUbv7gI4CRWxcRbQIldttPzbyXBl2z181bI8Yt86612731",
"refresh_token": "43|VPtqTDVPb3gY2MF4mIkms7vJcLWgUA47iwIxRI8e34e4f629",
"expires_in": 900,
"user": {
"id": "019fd2b8-b86e-738d-8bfa-a29262a83558",
"email": "hansen.mohammad@example.org"
}
},
"errors": null,
"meta": {
"request_id": "0ff1a162-0832-4ffa-9700-d0f30d00a580",
"timestamp": "2026-08-05T16:19:09.319799Z"
}
}
Example response (401, Invalid Code):
{
"status": "TWO_FACTOR_CODE_INVALID",
"message": "The provided code is invalid or has expired.",
"data": null,
"errors": [
{
"field": "code",
"message": "The provided code is invalid or has expired."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (401, Unauthenticated):
{
"status": "UNAUTHORIZED",
"message": "Unauthenticated.",
"data": null,
"errors": [
{
"field": null,
"message": "Unauthenticated."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (409, 2FA Not Configured):
{
"status": "TWO_FACTOR_NOT_CONFIGURED",
"message": "Two-factor authentication is not configured for this account.",
"data": null,
"errors": [
{
"field": null,
"message": "Two-factor authentication is not configured for this account."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "code",
"message": "Either code or recovery_code is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Logout
requires authentication
Revokes the currently active Sanctum token for any guard.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/logout" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/logout"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/logout';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/logout');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (204, Success):
Empty response
Example response (401, Unauthenticated):
{
"status": "UNAUTHORIZED",
"message": "Unauthenticated.",
"data": null,
"errors": [
{
"field": null,
"message": "Unauthenticated."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Enable Two Factor
requires authentication
Initiates the 2FA setup flow for the authenticated user.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/two-factor/enable" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"method\": \"totp\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/two-factor/enable"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"method": "totp"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/two-factor/enable';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'method' => 'totp',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/two-factor/enable');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"method": "totp"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Email):
{
"status": "SUCCESS",
"message": "Two-factor authentication initiated.",
"data": {
"method": "email"
},
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Scan the QR code with your authenticator app, then confirm with the generated code.",
"data": {
"method": "totp",
"secret": "6RL4HDCP2F4CDU27SRQOWOS454GFGIL6",
"qr_uri": "otpauth://totp/Flexxer%20Backend:019fd2b8-b36f-7307-92fb-5d28e58ef9f2?secret=6RL4HDCP2F4CDU27SRQOWOS454GFGIL6&issuer=Flexxer%20Backend&algorithm=SHA1&digits=6&period=30"
},
"errors": null,
"meta": {
"request_id": "e9e9b449-d901-409b-a9b4-fd071002aa0e",
"timestamp": "2026-08-05T16:19:07.791377Z"
}
}
Example response (401, Unauthenticated):
{
"status": "UNAUTHORIZED",
"message": "Unauthenticated.",
"data": null,
"errors": [
{
"field": null,
"message": "Unauthenticated."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "method",
"message": "The selected method is invalid."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Confirm Two Factor
requires authentication
Confirms and activates 2FA after the user has verified their code.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/two-factor/confirm" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"code\": \"123456\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/two-factor/confirm"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"code": "123456"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/two-factor/confirm';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'code' => '123456',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/two-factor/confirm');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"code": "123456"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Two-factor authentication has been enabled. Save your recovery codes in a safe place.",
"data": {
"recovery_codes": [
"DTPLO-U2SCF",
"MRWS1-IKBUY",
"MVM4F-Z42ES",
"AUSXU-FTDPK",
"U7WHX-TIU99",
"12AWU-NZVH6",
"ZY5XK-4WOKJ",
"47MAL-ZSDLU"
]
},
"errors": null,
"meta": {
"request_id": "315aafcb-764e-4f38-9faa-b9c4f45e3461",
"timestamp": "2026-08-05T16:19:07.807225Z"
}
}
Example response (401, Invalid Code):
{
"status": "TWO_FACTOR_CODE_INVALID",
"message": "The provided code is invalid or has expired.",
"data": null,
"errors": [
{
"field": "code",
"message": "The provided code is invalid or has expired."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (401, Unauthenticated):
{
"status": "UNAUTHORIZED",
"message": "Unauthenticated.",
"data": null,
"errors": [
{
"field": null,
"message": "Unauthenticated."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (409, No Pending Setup):
{
"status": "TWO_FACTOR_NO_PENDING_SETUP",
"message": "No pending two-factor setup found. Please restart the setup process.",
"data": null,
"errors": [
{
"field": null,
"message": "No pending two-factor setup found. Please restart the setup process."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "code",
"message": "The code field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Request Disable Two Factor Code
requires authentication
Dispatches a 6-digit OTP to the user's account email so they can confirm a 2FA-disable request. No-op for TOTP accounts (the code comes from the authenticator app directly) and for accounts without an enabled 2FA setting — both return 200 so the client's happy path is uniform.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/two-factor/disable/request-code" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/two-factor/disable/request-code"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/two-factor/disable/request-code';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/two-factor/disable/request-code');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, TOTP — use authenticator):
{
"status": "SUCCESS",
"message": "Enter the current code from your authenticator app.",
"data": {
"method": "totp"
},
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-22T12:00:00.000000Z"
}
}
Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Enter the current code from your authenticator app.",
"data": {
"method": "totp"
},
"errors": null,
"meta": {
"request_id": "0542b19f-0c0a-4bf3-93a4-d90bbac46f63",
"timestamp": "2026-08-05T16:18:37.138042Z"
}
}
Example response (409, Not Enabled):
{
"status": "TWO_FACTOR_NOT_ENABLED",
"message": "Two-factor authentication is not currently enabled.",
"data": null,
"errors": [
{
"field": null,
"message": "Two-factor authentication is not currently enabled."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-22T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Disable Two Factor
requires authentication
Disables 2FA for the authenticated user after verifying a current challenge code — the same proof the user provides at login time.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/mobile/auth/two-factor/disable" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"code\": \"123456\",
\"recovery_code\": \"ABCD-1234-EFGH\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/auth/two-factor/disable"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"code": "123456",
"recovery_code": "ABCD-1234-EFGH"
};
fetch(url, {
method: "DELETE",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/auth/two-factor/disable';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'code' => '123456',
'recovery_code' => 'ABCD-1234-EFGH',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/auth/two-factor/disable');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"code": "123456",
"recovery_code": "ABCD-1234-EFGH"
};
final response = await http.delete(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Two-factor authentication has been disabled.",
"data": null,
"errors": null,
"meta": {
"request_id": "255f0d6e-8c58-4e47-84a4-c47dd821febf",
"timestamp": "2026-08-05T16:19:07.817111Z"
}
}
Example response (401, Invalid Code):
{
"status": "TWO_FACTOR_CODE_INVALID",
"message": "The provided code is invalid or has expired.",
"data": null,
"errors": [
{
"field": "code",
"message": "The provided code is invalid or has expired."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-22T12:00:00.000000Z"
}
}
Example response (409, Not Enabled):
{
"status": "TWO_FACTOR_NOT_ENABLED",
"message": "Two-factor authentication is not currently enabled.",
"data": null,
"errors": [
{
"field": null,
"message": "Two-factor authentication is not currently enabled."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-22T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "code",
"message": "Either code or recovery_code is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-22T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Forgot Password
Sends a 4-digit password reset code to the given email address.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/auth/forgot-password" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"boris@example.com\",
\"guard\": \"user\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/auth/forgot-password"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "boris@example.com",
"guard": "user"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/auth/forgot-password';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'boris@example.com',
'guard' => 'user',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/auth/forgot-password');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "boris@example.com",
"guard": "user"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "If that email address is registered, a password reset code has been sent.",
"data": {
"email": "opal56@example.net",
"code": "448891"
},
"errors": null,
"meta": {
"request_id": "04e13c3e-6945-4f40-bb63-a330434430e3",
"timestamp": "2026-08-05T16:18:54.164086Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "guard",
"message": "The guard field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Verify Reset Code
Validates the 4-digit password reset code for the given email and guard.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/auth/forgot-password/verify" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"boris@example.com\",
\"code\": \"123456\",
\"guard\": \"user\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/auth/forgot-password/verify"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "boris@example.com",
"code": "123456",
"guard": "user"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/auth/forgot-password/verify';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'boris@example.com',
'code' => '123456',
'guard' => 'user',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/auth/forgot-password/verify');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "boris@example.com",
"code": "123456",
"guard": "user"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Reset code verified successfully.",
"data": {
"reset_token": "c97701d0-c4de-4755-b3c4-f7d1a803efc5"
},
"errors": null,
"meta": {
"request_id": "67df2724-9771-46b5-8d4d-71f98573d3e5",
"timestamp": "2026-08-05T16:18:54.166696Z"
}
}
Example response (401, Invalid Code):
{
"status": "RESET_CODE_INVALID",
"message": "Invalid reset code.",
"data": null,
"errors": [
{
"field": "code",
"message": "Invalid reset code."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (410, Code Expired):
{
"status": "RESET_CODE_EXPIRED",
"message": "Reset code has expired.",
"data": null,
"errors": [
{
"field": "code",
"message": "Reset code has expired."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "code",
"message": "The code field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Too Many Attempts):
{
"status": "RESET_ATTEMPTS_EXHAUSTED",
"message": "Too many failed attempts. Please request a new code.",
"data": null,
"errors": [
{
"field": "code",
"message": "Too many failed attempts. Please request a new code."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Resend Reset Code
Re-sends a 4-digit password reset code for the given email and guard.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/auth/forgot-password/resend" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"boris@example.com\",
\"guard\": \"user\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/auth/forgot-password/resend"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "boris@example.com",
"guard": "user"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/auth/forgot-password/resend';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'boris@example.com',
'guard' => 'user',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/auth/forgot-password/resend');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "boris@example.com",
"guard": "user"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "If that email address is registered, a new password reset code has been sent.",
"data": {
"code": "443677"
},
"errors": null,
"meta": {
"request_id": "a265e26e-388c-4782-b9ce-bc4722cc5958",
"timestamp": "2026-08-05T16:18:58.095803Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "guard",
"message": "The guard field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reset Password
Resets the password for any actor type and revokes all existing tokens.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/auth/reset-password" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"boris@example.com\",
\"reset_token\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",
\"password\": \"NewPassword123\",
\"password_confirmation\": \"NewPassword123\",
\"guard\": \"user\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/auth/reset-password"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "boris@example.com",
"reset_token": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"password": "NewPassword123",
"password_confirmation": "NewPassword123",
"guard": "user"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/auth/reset-password';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'boris@example.com',
'reset_token' => 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
'password' => 'NewPassword123',
'password_confirmation' => 'NewPassword123',
'guard' => 'user',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/auth/reset-password');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "boris@example.com",
"reset_token": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"password": "NewPassword123",
"password_confirmation": "NewPassword123",
"guard": "user"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Password has been reset successfully.",
"data": null,
"errors": null,
"meta": {
"request_id": "85c34424-2c5f-4d2e-aa97-5edf63d5d429",
"timestamp": "2026-08-05T16:18:54.626775Z"
}
}
Example response (403, Email Not Verified):
{
"status": "RESET_NOT_VERIFIED",
"message": "Email not verified. Complete the verification step first.",
"data": null,
"errors": [
{
"field": null,
"message": "Email not verified. Complete the verification step first."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (404, Account Not Found):
{
"status": "ACCOUNT_NOT_FOUND",
"message": "Account not found.",
"data": null,
"errors": [
{
"field": null,
"message": "Account not found."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "password",
"message": "The password must be at least 8 characters."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Password Reuse):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "password",
"message": "You cannot reuse your last 3 passwords."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Two Factor Challenge
requires authentication
Completes the two-factor authentication challenge for any guard.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/auth/two-factor/challenge" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"code\": \"123456\",
\"recovery_code\": \"ABCD-1234-EFGH\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/auth/two-factor/challenge"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"code": "123456",
"recovery_code": "ABCD-1234-EFGH"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/auth/two-factor/challenge';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'code' => '123456',
'recovery_code' => 'ABCD-1234-EFGH',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/auth/two-factor/challenge');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"code": "123456",
"recovery_code": "ABCD-1234-EFGH"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Two-factor authentication verified successfully.",
"data": {
"token": "42|wMrUbv7gI4CRWxcRbQIldttPzbyXBl2z181bI8Yt86612731",
"refresh_token": "43|VPtqTDVPb3gY2MF4mIkms7vJcLWgUA47iwIxRI8e34e4f629",
"expires_in": 900,
"user": {
"id": "019fd2b8-b86e-738d-8bfa-a29262a83558",
"email": "hansen.mohammad@example.org"
}
},
"errors": null,
"meta": {
"request_id": "0ff1a162-0832-4ffa-9700-d0f30d00a580",
"timestamp": "2026-08-05T16:19:09.319799Z"
}
}
Example response (401, Invalid Code):
{
"status": "TWO_FACTOR_CODE_INVALID",
"message": "The provided code is invalid or has expired.",
"data": null,
"errors": [
{
"field": "code",
"message": "The provided code is invalid or has expired."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (401, Unauthenticated):
{
"status": "UNAUTHORIZED",
"message": "Unauthenticated.",
"data": null,
"errors": [
{
"field": null,
"message": "Unauthenticated."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (409, 2FA Not Configured):
{
"status": "TWO_FACTOR_NOT_CONFIGURED",
"message": "Two-factor authentication is not configured for this account.",
"data": null,
"errors": [
{
"field": null,
"message": "Two-factor authentication is not configured for this account."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "code",
"message": "Either code or recovery_code is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Two Factor Challenge
requires authentication
Completes the two-factor authentication challenge for any guard.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/auth/member/two-factor/challenge" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"code\": \"123456\",
\"recovery_code\": \"ABCD-1234-EFGH\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/auth/member/two-factor/challenge"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"code": "123456",
"recovery_code": "ABCD-1234-EFGH"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/auth/member/two-factor/challenge';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'code' => '123456',
'recovery_code' => 'ABCD-1234-EFGH',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/auth/member/two-factor/challenge');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"code": "123456",
"recovery_code": "ABCD-1234-EFGH"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Two-factor authentication verified successfully.",
"data": {
"token": "42|wMrUbv7gI4CRWxcRbQIldttPzbyXBl2z181bI8Yt86612731",
"refresh_token": "43|VPtqTDVPb3gY2MF4mIkms7vJcLWgUA47iwIxRI8e34e4f629",
"expires_in": 900,
"user": {
"id": "019fd2b8-b86e-738d-8bfa-a29262a83558",
"email": "hansen.mohammad@example.org"
}
},
"errors": null,
"meta": {
"request_id": "0ff1a162-0832-4ffa-9700-d0f30d00a580",
"timestamp": "2026-08-05T16:19:09.319799Z"
}
}
Example response (401, Invalid Code):
{
"status": "TWO_FACTOR_CODE_INVALID",
"message": "The provided code is invalid or has expired.",
"data": null,
"errors": [
{
"field": "code",
"message": "The provided code is invalid or has expired."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (401, Unauthenticated):
{
"status": "UNAUTHORIZED",
"message": "Unauthenticated.",
"data": null,
"errors": [
{
"field": null,
"message": "Unauthenticated."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (409, 2FA Not Configured):
{
"status": "TWO_FACTOR_NOT_CONFIGURED",
"message": "Two-factor authentication is not configured for this account.",
"data": null,
"errors": [
{
"field": null,
"message": "Two-factor authentication is not configured for this account."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "code",
"message": "Either code or recovery_code is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Current Organization / Member
requires authentication
Returns the authenticated actor's profile alongside an ACL manifest.
Two actor types share this route (both pass the guard:organization
middleware):
- Organization (principal): synthetic manifest built from the
principalpreset; no rows in acl_actor_presets are consulted. - OrganizationMember: real manifest resolved from the member's stored
presets via
Acl::manifest($member).
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/auth/me" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/auth/me"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/auth/me';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/auth/me');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, OrganizationMember):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"profile": {
"id": "uuid",
"name": "Jane Doe",
"email": "jane@example.com",
"role": "member",
"organization_id": "org-uuid",
"organization_name": "Acme e.V.",
"is_primary_admin": false
},
"acl": {
"scope": "org-member",
"presets": [
"viewer"
],
"permissions": [
"profile.view",
"team.view"
],
"conditional": {},
"computed_at": "2026-05-12T10:00:00+00:00"
}
}
}
Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"profile": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"email": "caritas-portal@flexxr.eu.cc",
"status": "active",
"is_primary_admin": true
},
"acl": {
"scope": "org-member",
"presets": [
"principal"
],
"permissions": [
"applicants.accept",
"applicants.reject",
"applicants.view",
"assignments.manage",
"assignments.view",
"attendance.approve-hours",
"attendance.report-noshow",
"attendance.view",
"audit.view",
"gdpr.request",
"invoices.download",
"invoices.view",
"jobs.configure-assignment",
"jobs.create",
"jobs.delete",
"jobs.edit",
"jobs.publish",
"jobs.view",
"messages.access",
"notifications.preferences.manage",
"payments.manage",
"payments.view",
"profile.edit",
"profile.view",
"ratings.create",
"ratings.view",
"reports.export",
"reports.view",
"requests.decide",
"requests.view",
"shifts.adjust",
"shifts.cancel",
"shifts.check-in",
"shifts.dispute-time",
"shifts.generate-qr",
"shifts.report-signature-refusal",
"shifts.view",
"support.create-ticket",
"support.view-tickets",
"team.invite",
"team.manage-roles",
"team.remove",
"team.view"
],
"conditional": {},
"computed_at": "2026-08-05T16:18:37+00:00"
}
},
"errors": null,
"meta": {
"request_id": "e4ea4c8e-c454-4449-891f-5f615816a929",
"timestamp": "2026-08-05T16:18:37.721087Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Logout
requires authentication
Revokes the currently active Sanctum token for any guard.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/auth/logout" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/auth/logout"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/auth/logout';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/auth/logout');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (204, Success):
Empty response
Example response (401, Unauthenticated):
{
"status": "UNAUTHORIZED",
"message": "Unauthenticated.",
"data": null,
"errors": [
{
"field": null,
"message": "Unauthenticated."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Enable Two Factor
requires authentication
Initiates the 2FA setup flow for the authenticated user.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/auth/two-factor/enable" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"method\": \"totp\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/auth/two-factor/enable"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"method": "totp"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/auth/two-factor/enable';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'method' => 'totp',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/auth/two-factor/enable');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"method": "totp"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Email):
{
"status": "SUCCESS",
"message": "Two-factor authentication initiated.",
"data": {
"method": "email"
},
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Scan the QR code with your authenticator app, then confirm with the generated code.",
"data": {
"method": "totp",
"secret": "6RL4HDCP2F4CDU27SRQOWOS454GFGIL6",
"qr_uri": "otpauth://totp/Flexxer%20Backend:019fd2b8-b36f-7307-92fb-5d28e58ef9f2?secret=6RL4HDCP2F4CDU27SRQOWOS454GFGIL6&issuer=Flexxer%20Backend&algorithm=SHA1&digits=6&period=30"
},
"errors": null,
"meta": {
"request_id": "e9e9b449-d901-409b-a9b4-fd071002aa0e",
"timestamp": "2026-08-05T16:19:07.791377Z"
}
}
Example response (401, Unauthenticated):
{
"status": "UNAUTHORIZED",
"message": "Unauthenticated.",
"data": null,
"errors": [
{
"field": null,
"message": "Unauthenticated."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "method",
"message": "The selected method is invalid."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Confirm Two Factor
requires authentication
Confirms and activates 2FA after the user has verified their code.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/auth/two-factor/confirm" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"code\": \"123456\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/auth/two-factor/confirm"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"code": "123456"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/auth/two-factor/confirm';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'code' => '123456',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/auth/two-factor/confirm');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"code": "123456"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Two-factor authentication has been enabled. Save your recovery codes in a safe place.",
"data": {
"recovery_codes": [
"DTPLO-U2SCF",
"MRWS1-IKBUY",
"MVM4F-Z42ES",
"AUSXU-FTDPK",
"U7WHX-TIU99",
"12AWU-NZVH6",
"ZY5XK-4WOKJ",
"47MAL-ZSDLU"
]
},
"errors": null,
"meta": {
"request_id": "315aafcb-764e-4f38-9faa-b9c4f45e3461",
"timestamp": "2026-08-05T16:19:07.807225Z"
}
}
Example response (401, Invalid Code):
{
"status": "TWO_FACTOR_CODE_INVALID",
"message": "The provided code is invalid or has expired.",
"data": null,
"errors": [
{
"field": "code",
"message": "The provided code is invalid or has expired."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (401, Unauthenticated):
{
"status": "UNAUTHORIZED",
"message": "Unauthenticated.",
"data": null,
"errors": [
{
"field": null,
"message": "Unauthenticated."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (409, No Pending Setup):
{
"status": "TWO_FACTOR_NO_PENDING_SETUP",
"message": "No pending two-factor setup found. Please restart the setup process.",
"data": null,
"errors": [
{
"field": null,
"message": "No pending two-factor setup found. Please restart the setup process."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "code",
"message": "The code field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Request Disable Two Factor Code
requires authentication
Dispatches a 6-digit OTP to the user's account email so they can confirm a 2FA-disable request. No-op for TOTP accounts (the code comes from the authenticator app directly) and for accounts without an enabled 2FA setting — both return 200 so the client's happy path is uniform.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/auth/two-factor/disable-code" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/auth/two-factor/disable-code"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/auth/two-factor/disable-code';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/auth/two-factor/disable-code');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, TOTP — use authenticator):
{
"status": "SUCCESS",
"message": "Enter the current code from your authenticator app.",
"data": {
"method": "totp"
},
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-22T12:00:00.000000Z"
}
}
Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Enter the current code from your authenticator app.",
"data": {
"method": "totp"
},
"errors": null,
"meta": {
"request_id": "0542b19f-0c0a-4bf3-93a4-d90bbac46f63",
"timestamp": "2026-08-05T16:18:37.138042Z"
}
}
Example response (409, Not Enabled):
{
"status": "TWO_FACTOR_NOT_ENABLED",
"message": "Two-factor authentication is not currently enabled.",
"data": null,
"errors": [
{
"field": null,
"message": "Two-factor authentication is not currently enabled."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-22T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Disable Two Factor
requires authentication
Disables 2FA for the authenticated user after verifying a current challenge code — the same proof the user provides at login time.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/org/auth/two-factor/disable" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"code\": \"123456\",
\"recovery_code\": \"ABCD-1234-EFGH\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/auth/two-factor/disable"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"code": "123456",
"recovery_code": "ABCD-1234-EFGH"
};
fetch(url, {
method: "DELETE",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/auth/two-factor/disable';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'code' => '123456',
'recovery_code' => 'ABCD-1234-EFGH',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/auth/two-factor/disable');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"code": "123456",
"recovery_code": "ABCD-1234-EFGH"
};
final response = await http.delete(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Two-factor authentication has been disabled.",
"data": null,
"errors": null,
"meta": {
"request_id": "255f0d6e-8c58-4e47-84a4-c47dd821febf",
"timestamp": "2026-08-05T16:19:07.817111Z"
}
}
Example response (401, Invalid Code):
{
"status": "TWO_FACTOR_CODE_INVALID",
"message": "The provided code is invalid or has expired.",
"data": null,
"errors": [
{
"field": "code",
"message": "The provided code is invalid or has expired."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-22T12:00:00.000000Z"
}
}
Example response (409, Not Enabled):
{
"status": "TWO_FACTOR_NOT_ENABLED",
"message": "Two-factor authentication is not currently enabled.",
"data": null,
"errors": [
{
"field": null,
"message": "Two-factor authentication is not currently enabled."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-22T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "code",
"message": "Either code or recovery_code is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-22T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Forgot Password
Sends a 4-digit password reset code to the given email address.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/auth/forgot-password" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"boris@example.com\",
\"guard\": \"user\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/auth/forgot-password"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "boris@example.com",
"guard": "user"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/auth/forgot-password';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'boris@example.com',
'guard' => 'user',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/auth/forgot-password');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "boris@example.com",
"guard": "user"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "If that email address is registered, a password reset code has been sent.",
"data": {
"email": "opal56@example.net",
"code": "448891"
},
"errors": null,
"meta": {
"request_id": "04e13c3e-6945-4f40-bb63-a330434430e3",
"timestamp": "2026-08-05T16:18:54.164086Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "guard",
"message": "The guard field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Verify Reset Code
Validates the 4-digit password reset code for the given email and guard.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/auth/forgot-password/verify" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"boris@example.com\",
\"code\": \"123456\",
\"guard\": \"user\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/auth/forgot-password/verify"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "boris@example.com",
"code": "123456",
"guard": "user"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/auth/forgot-password/verify';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'boris@example.com',
'code' => '123456',
'guard' => 'user',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/auth/forgot-password/verify');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "boris@example.com",
"code": "123456",
"guard": "user"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Reset code verified successfully.",
"data": {
"reset_token": "c97701d0-c4de-4755-b3c4-f7d1a803efc5"
},
"errors": null,
"meta": {
"request_id": "67df2724-9771-46b5-8d4d-71f98573d3e5",
"timestamp": "2026-08-05T16:18:54.166696Z"
}
}
Example response (401, Invalid Code):
{
"status": "RESET_CODE_INVALID",
"message": "Invalid reset code.",
"data": null,
"errors": [
{
"field": "code",
"message": "Invalid reset code."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (410, Code Expired):
{
"status": "RESET_CODE_EXPIRED",
"message": "Reset code has expired.",
"data": null,
"errors": [
{
"field": "code",
"message": "Reset code has expired."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "code",
"message": "The code field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Too Many Attempts):
{
"status": "RESET_ATTEMPTS_EXHAUSTED",
"message": "Too many failed attempts. Please request a new code.",
"data": null,
"errors": [
{
"field": "code",
"message": "Too many failed attempts. Please request a new code."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Resend Reset Code
Re-sends a 4-digit password reset code for the given email and guard.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/auth/forgot-password/resend" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"boris@example.com\",
\"guard\": \"user\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/auth/forgot-password/resend"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "boris@example.com",
"guard": "user"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/auth/forgot-password/resend';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'boris@example.com',
'guard' => 'user',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/auth/forgot-password/resend');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "boris@example.com",
"guard": "user"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "If that email address is registered, a new password reset code has been sent.",
"data": {
"code": "443677"
},
"errors": null,
"meta": {
"request_id": "a265e26e-388c-4782-b9ce-bc4722cc5958",
"timestamp": "2026-08-05T16:18:58.095803Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "guard",
"message": "The guard field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reset Password
Resets the password for any actor type and revokes all existing tokens.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/auth/reset-password" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"boris@example.com\",
\"reset_token\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",
\"password\": \"NewPassword123\",
\"password_confirmation\": \"NewPassword123\",
\"guard\": \"user\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/auth/reset-password"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "boris@example.com",
"reset_token": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"password": "NewPassword123",
"password_confirmation": "NewPassword123",
"guard": "user"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/auth/reset-password';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'boris@example.com',
'reset_token' => 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
'password' => 'NewPassword123',
'password_confirmation' => 'NewPassword123',
'guard' => 'user',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/auth/reset-password');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "boris@example.com",
"reset_token": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"password": "NewPassword123",
"password_confirmation": "NewPassword123",
"guard": "user"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Password has been reset successfully.",
"data": null,
"errors": null,
"meta": {
"request_id": "85c34424-2c5f-4d2e-aa97-5edf63d5d429",
"timestamp": "2026-08-05T16:18:54.626775Z"
}
}
Example response (403, Email Not Verified):
{
"status": "RESET_NOT_VERIFIED",
"message": "Email not verified. Complete the verification step first.",
"data": null,
"errors": [
{
"field": null,
"message": "Email not verified. Complete the verification step first."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (404, Account Not Found):
{
"status": "ACCOUNT_NOT_FOUND",
"message": "Account not found.",
"data": null,
"errors": [
{
"field": null,
"message": "Account not found."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "password",
"message": "The password must be at least 8 characters."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Password Reuse):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "password",
"message": "You cannot reuse your last 3 passwords."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Two Factor Challenge
requires authentication
Completes the two-factor authentication challenge for any guard.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor/challenge" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"code\": \"123456\",
\"recovery_code\": \"ABCD-1234-EFGH\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor/challenge"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"code": "123456",
"recovery_code": "ABCD-1234-EFGH"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor/challenge';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'code' => '123456',
'recovery_code' => 'ABCD-1234-EFGH',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor/challenge');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"code": "123456",
"recovery_code": "ABCD-1234-EFGH"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Two-factor authentication verified successfully.",
"data": {
"token": "42|wMrUbv7gI4CRWxcRbQIldttPzbyXBl2z181bI8Yt86612731",
"refresh_token": "43|VPtqTDVPb3gY2MF4mIkms7vJcLWgUA47iwIxRI8e34e4f629",
"expires_in": 900,
"user": {
"id": "019fd2b8-b86e-738d-8bfa-a29262a83558",
"email": "hansen.mohammad@example.org"
}
},
"errors": null,
"meta": {
"request_id": "0ff1a162-0832-4ffa-9700-d0f30d00a580",
"timestamp": "2026-08-05T16:19:09.319799Z"
}
}
Example response (401, Invalid Code):
{
"status": "TWO_FACTOR_CODE_INVALID",
"message": "The provided code is invalid or has expired.",
"data": null,
"errors": [
{
"field": "code",
"message": "The provided code is invalid or has expired."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (401, Unauthenticated):
{
"status": "UNAUTHORIZED",
"message": "Unauthenticated.",
"data": null,
"errors": [
{
"field": null,
"message": "Unauthenticated."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (409, 2FA Not Configured):
{
"status": "TWO_FACTOR_NOT_CONFIGURED",
"message": "Two-factor authentication is not configured for this account.",
"data": null,
"errors": [
{
"field": null,
"message": "Two-factor authentication is not configured for this account."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "code",
"message": "Either code or recovery_code is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Logout
requires authentication
Revokes the currently active Sanctum token for any guard.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/auth/logout" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/auth/logout"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/auth/logout';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/auth/logout');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (204, Success):
Empty response
Example response (401, Unauthenticated):
{
"status": "UNAUTHORIZED",
"message": "Unauthenticated.",
"data": null,
"errors": [
{
"field": null,
"message": "Unauthenticated."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Enable Two Factor
requires authentication
Initiates the 2FA setup flow for the authenticated user.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor/enable" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"method\": \"totp\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor/enable"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"method": "totp"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor/enable';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'method' => 'totp',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor/enable');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"method": "totp"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Email):
{
"status": "SUCCESS",
"message": "Two-factor authentication initiated.",
"data": {
"method": "email"
},
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Scan the QR code with your authenticator app, then confirm with the generated code.",
"data": {
"method": "totp",
"secret": "6RL4HDCP2F4CDU27SRQOWOS454GFGIL6",
"qr_uri": "otpauth://totp/Flexxer%20Backend:019fd2b8-b36f-7307-92fb-5d28e58ef9f2?secret=6RL4HDCP2F4CDU27SRQOWOS454GFGIL6&issuer=Flexxer%20Backend&algorithm=SHA1&digits=6&period=30"
},
"errors": null,
"meta": {
"request_id": "e9e9b449-d901-409b-a9b4-fd071002aa0e",
"timestamp": "2026-08-05T16:19:07.791377Z"
}
}
Example response (401, Unauthenticated):
{
"status": "UNAUTHORIZED",
"message": "Unauthenticated.",
"data": null,
"errors": [
{
"field": null,
"message": "Unauthenticated."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "method",
"message": "The selected method is invalid."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Confirm Two Factor
requires authentication
Confirms and activates 2FA after the user has verified their code.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor/confirm" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"code\": \"123456\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor/confirm"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"code": "123456"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor/confirm';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'code' => '123456',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor/confirm');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"code": "123456"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Two-factor authentication has been enabled. Save your recovery codes in a safe place.",
"data": {
"recovery_codes": [
"DTPLO-U2SCF",
"MRWS1-IKBUY",
"MVM4F-Z42ES",
"AUSXU-FTDPK",
"U7WHX-TIU99",
"12AWU-NZVH6",
"ZY5XK-4WOKJ",
"47MAL-ZSDLU"
]
},
"errors": null,
"meta": {
"request_id": "315aafcb-764e-4f38-9faa-b9c4f45e3461",
"timestamp": "2026-08-05T16:19:07.807225Z"
}
}
Example response (401, Invalid Code):
{
"status": "TWO_FACTOR_CODE_INVALID",
"message": "The provided code is invalid or has expired.",
"data": null,
"errors": [
{
"field": "code",
"message": "The provided code is invalid or has expired."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (401, Unauthenticated):
{
"status": "UNAUTHORIZED",
"message": "Unauthenticated.",
"data": null,
"errors": [
{
"field": null,
"message": "Unauthenticated."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (409, No Pending Setup):
{
"status": "TWO_FACTOR_NO_PENDING_SETUP",
"message": "No pending two-factor setup found. Please restart the setup process.",
"data": null,
"errors": [
{
"field": null,
"message": "No pending two-factor setup found. Please restart the setup process."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "code",
"message": "The code field is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Disable Two Factor
requires authentication
Disables 2FA for the authenticated user after verifying a current challenge code — the same proof the user provides at login time.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor/disable" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"code\": \"123456\",
\"recovery_code\": \"ABCD-1234-EFGH\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor/disable"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"code": "123456",
"recovery_code": "ABCD-1234-EFGH"
};
fetch(url, {
method: "DELETE",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor/disable';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'code' => '123456',
'recovery_code' => 'ABCD-1234-EFGH',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor/disable');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"code": "123456",
"recovery_code": "ABCD-1234-EFGH"
};
final response = await http.delete(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Two-factor authentication has been disabled.",
"data": null,
"errors": null,
"meta": {
"request_id": "255f0d6e-8c58-4e47-84a4-c47dd821febf",
"timestamp": "2026-08-05T16:19:07.817111Z"
}
}
Example response (401, Invalid Code):
{
"status": "TWO_FACTOR_CODE_INVALID",
"message": "The provided code is invalid or has expired.",
"data": null,
"errors": [
{
"field": "code",
"message": "The provided code is invalid or has expired."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-22T12:00:00.000000Z"
}
}
Example response (409, Not Enabled):
{
"status": "TWO_FACTOR_NOT_ENABLED",
"message": "Two-factor authentication is not currently enabled.",
"data": null,
"errors": [
{
"field": null,
"message": "Two-factor authentication is not currently enabled."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-22T12:00:00.000000Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "code",
"message": "Either code or recovery_code is required."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-22T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Request Disable Two Factor Code
requires authentication
Dispatches a 6-digit OTP to the user's account email so they can confirm a 2FA-disable request. No-op for TOTP accounts (the code comes from the authenticator app directly) and for accounts without an enabled 2FA setting — both return 200 so the client's happy path is uniform.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor/disable/request-code" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor/disable/request-code"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor/disable/request-code';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/auth/two-factor/disable/request-code');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, TOTP — use authenticator):
{
"status": "SUCCESS",
"message": "Enter the current code from your authenticator app.",
"data": {
"method": "totp"
},
"errors": null,
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-22T12:00:00.000000Z"
}
}
Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Enter the current code from your authenticator app.",
"data": {
"method": "totp"
},
"errors": null,
"meta": {
"request_id": "0542b19f-0c0a-4bf3-93a4-d90bbac46f63",
"timestamp": "2026-08-05T16:18:37.138042Z"
}
}
Example response (409, Not Enabled):
{
"status": "TWO_FACTOR_NOT_ENABLED",
"message": "Two-factor authentication is not currently enabled.",
"data": null,
"errors": [
{
"field": null,
"message": "Two-factor authentication is not currently enabled."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-22T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Sessions
List Sessions
requires authentication
Lists the authenticated user's (or org's, or admin's) active Sanctum sessions with their device metadata, sorted by last_used_at descending so the most recently active device is first.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/sessions" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/sessions"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/sessions';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/sessions');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [
{
"id": 4,
"name": "docs",
"device": null,
"ip_address": null,
"last_used_at": "2026-08-05T16:18:37+00:00",
"expires_at": null,
"created_at": "2026-08-05T16:18:33+00:00",
"is_current": true
}
],
"errors": null,
"meta": {
"request_id": "b9c7f080-de76-4ae2-92d4-98f5f9c63e35",
"timestamp": "2026-08-05T16:18:37.159008Z"
}
}
Example response (401, Unauthenticated):
{
"status": "UNAUTHENTICATED",
"message": "Unauthenticated.",
"data": null,
"errors": [
{
"field": null,
"message": "Unauthenticated."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Revoke Other Sessions
requires authentication
Logs out every OTHER active session of the authenticated caller, keeping the current one alive ("Alle anderen Geräte abmelden").
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/mobile/sessions" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/sessions"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/sessions';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/sessions');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"revoked": 0
},
"errors": null,
"meta": {
"request_id": "99342b48-bea9-49b3-a788-41e38c4c0892",
"timestamp": "2026-08-05T16:18:37.170260Z"
}
}
Example response (401, Unauthenticated):
{
"status": "UNAUTHENTICATED",
"message": "Unauthenticated.",
"data": null,
"errors": [
{
"field": null,
"message": "Unauthenticated."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-06-18T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Revoke Session
requires authentication
Revokes a single active session by id.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/mobile/sessions/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/sessions/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/sessions/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/sessions/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (204, Revoked):
Empty response
Example response (401, Unauthenticated):
{
"status": "UNAUTHENTICATED",
"message": "Unauthenticated.",
"data": null,
"errors": [
{
"field": null,
"message": "Unauthenticated."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Example response (404, Not Found):
{
"status": "NOT_FOUND",
"message": "Session not found.",
"data": null,
"errors": [
{
"field": null,
"message": "Session not found."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Sessions
requires authentication
Lists the authenticated user's (or org's, or admin's) active Sanctum sessions with their device metadata, sorted by last_used_at descending so the most recently active device is first.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/sessions" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/sessions"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/sessions';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/sessions');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [
{
"id": 4,
"name": "docs",
"device": null,
"ip_address": null,
"last_used_at": "2026-08-05T16:18:37+00:00",
"expires_at": null,
"created_at": "2026-08-05T16:18:33+00:00",
"is_current": true
}
],
"errors": null,
"meta": {
"request_id": "b9c7f080-de76-4ae2-92d4-98f5f9c63e35",
"timestamp": "2026-08-05T16:18:37.159008Z"
}
}
Example response (401, Unauthenticated):
{
"status": "UNAUTHENTICATED",
"message": "Unauthenticated.",
"data": null,
"errors": [
{
"field": null,
"message": "Unauthenticated."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Revoke Other Sessions
requires authentication
Logs out every OTHER active session of the authenticated caller, keeping the current one alive ("Alle anderen Geräte abmelden").
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/org/sessions" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/sessions"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/sessions';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/sessions');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"revoked": 0
},
"errors": null,
"meta": {
"request_id": "99342b48-bea9-49b3-a788-41e38c4c0892",
"timestamp": "2026-08-05T16:18:37.170260Z"
}
}
Example response (401, Unauthenticated):
{
"status": "UNAUTHENTICATED",
"message": "Unauthenticated.",
"data": null,
"errors": [
{
"field": null,
"message": "Unauthenticated."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-06-18T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Revoke Session
requires authentication
Revokes a single active session by id.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/org/sessions/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/sessions/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/sessions/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/sessions/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (204, Revoked):
Empty response
Example response (401, Unauthenticated):
{
"status": "UNAUTHENTICATED",
"message": "Unauthenticated.",
"data": null,
"errors": [
{
"field": null,
"message": "Unauthenticated."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Example response (404, Not Found):
{
"status": "NOT_FOUND",
"message": "Session not found.",
"data": null,
"errors": [
{
"field": null,
"message": "Session not found."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Example response (429, Rate Limited):
{
"status": "RATE_LIMITED",
"message": "Too many requests.",
"data": null,
"errors": [
{
"field": null,
"message": "Too many requests."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T19:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Logo
Upload Org Logo
requires authentication
Stores a new logo file for the authenticated organisation, replacing any existing one and returning the updated profile.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/profile/logo" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "logo=@/tmp/php0e6c0178c3f28u30ii6" const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/profile/logo"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('logo', document.querySelector('input[name="logo"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/profile/logo';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'multipart/form-data',
'Accept' => 'application/json',
],
'multipart' => [
[
'name' => 'logo',
'contents' => fopen('/tmp/php0e6c0178c3f28u30ii6', 'r')
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/profile/logo');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'multipart/form-data',
'Accept': 'application/json',
};
final request = http.MultipartRequest('POST', uri);
request.headers.addAll(headers);
request.files.add(await http.MultipartFile.fromPath('logo', '/tmp/php0e6c0178c3f28u30ii6'));
final streamed = await request.send();
final response = await http.Response.fromStream(streamed);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Logo uploaded successfully.",
"data": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"slug": "caritas-4v1ues",
"email": "caritas-portal@flexxr.eu.cc",
"country_code": "+43",
"phone_number": "6641234567",
"contact_person_name": null,
"contact_person_phone": null,
"iso_country_code": "AT",
"phone_e164": "+436641234567",
"description": "Caritas test organisation used for end-to-end portal QA. Safe to delete.",
"logo_url": "/storage/logos/organizations/LREuwBDCi9PVWwBEWq51HyvWGY2EpxnhjPCtkxMn.jpg",
"website": "https://www.caritas.at",
"address": "Albrechtskreithgasse 19-21",
"address_line2": null,
"postal_code": null,
"city": "Vienna",
"country": "Austria",
"status": "active",
"verified_at": "2026-08-05T16:18:17.000000Z",
"is_verified": true,
"total_raised": null,
"created_at": "2026-08-05T16:18:17.000000Z",
"platform_fee_flat_cents": null,
"firmenbuchnummer": null,
"uid_number": null,
"uid_validation_status": null,
"payout_method": null,
"stripe_connect_account_id": null,
"connect_charges_enabled": null,
"connect_payouts_enabled": null,
"connect_details_submitted": null,
"connect_requirements_due": null,
"connect_country_code": null
},
"errors": null,
"meta": {
"request_id": "f13486bc-77c2-4f13-8a66-6f45b8c5609f",
"timestamp": "2026-08-05T16:18:37.762427Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "Validation failed.",
"data": null,
"errors": [
{
"field": "logo",
"message": "Logo file is required and must be an image."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-02T12:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete Org Logo
requires authentication
Removes the authenticated organisation's logo from storage and clears the logo_url field.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/org/profile/logo" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/profile/logo"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/profile/logo';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/profile/logo');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Logo deleted successfully.",
"data": null,
"errors": null,
"meta": {
"request_id": "6be9ac36-baba-4a55-aff3-f87b0f8d5c17",
"timestamp": "2026-08-05T16:18:37.773548Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Privacy & GDPR
Lists GDPR Art. 12(3) requests submitted by the authenticated organisation.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/me/gdpr-requests" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/me/gdpr-requests"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/me/gdpr-requests';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/me/gdpr-requests');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [],
"errors": null,
"meta": {
"request_id": "c161e586-954d-48ca-928d-41bad21a8adf",
"timestamp": "2026-08-05T16:18:38.479808Z",
"current_page": 1,
"last_page": 1,
"per_page": 15,
"total": 0
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Records a new GDPR Art. 12(3) request forwarded by an organisation on behalf of a data subject. Persists the request, emits an audit event, and notifies all super-admins via in-app and email.
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/me/gdpr-requests" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"subject_email\": \"name@example.at\",
\"request_type\": \"access\",
\"message\": \"Bitte um Rueckmeldung zur naechsten Schicht.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/me/gdpr-requests"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"subject_email": "name@example.at",
"request_type": "access",
"message": "Bitte um Rueckmeldung zur naechsten Schicht."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/me/gdpr-requests';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'subject_email' => 'name@example.at',
'request_type' => 'access',
'message' => 'Bitte um Rueckmeldung zur naechsten Schicht.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/me/gdpr-requests');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"subject_email": "name@example.at",
"request_type": "access",
"message": "Bitte um Rueckmeldung zur naechsten Schicht."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "CREATED",
"message": "GDPR request submitted successfully.",
"data": {
"id": "019fd2b8-4116-7347-914a-230153f403ce",
"request_type": "access",
"request_type_label": "Access (Art. 15)",
"subject_email": "name@example.at",
"message": "Bitte um Rueckmeldung zur naechsten Schicht.",
"status": "pending",
"status_label": "Pending",
"submitted_at": "2026-08-05T16:18:38.000000Z",
"resolved_at": null,
"platform_note": null,
"created_at": "2026-08-05T16:18:38.000000Z"
},
"errors": null,
"meta": {
"request_id": "8f34c05d-27c1-4a19-b728-9442355514a1",
"timestamp": "2026-08-05T16:18:38.490505Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
GDPR Art. 15 (Right of Access) / Art. 20 (Right to Data Portability).
requires authentication
Returns a structured JSON export of the organisation's platform data: campaigns (with images), donations received, recurring donations, and team members. Donor PII is masked — only display names and masked email addresses are included.
Austrian DSG §1(1) + GDPR Art. 12(3): response within one month, delivered immediately here as structured JSON.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/me/data-export" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/me/data-export"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/me/data-export';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/me/data-export');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Data export generated.",
"data": {
"organisation": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"name": "Caritas",
"legal_name": null,
"legal_form": null,
"tax_id": null,
"email": "caritas-portal@flexxr.eu.cc",
"phone": "+436641234567",
"website": "https://www.caritas.at",
"country": "Austria",
"city": "Vienna",
"address": "Albrechtskreithgasse 19-21",
"postal_code": null,
"created_at": "2026-08-05T16:18:17+00:00"
},
"team_members": [
{
"id": "019fd2b8-285e-707c-865a-ffbe4b08f730",
"role": "admin",
"is_active": true,
"joined_at": "2026-08-05T16:18:32+00:00"
}
],
"exported_at": "2026-08-05T16:18:38+00:00"
},
"errors": null,
"meta": {
"request_id": "c29cdf34-d349-42b5-9f9b-af7de00d12c4",
"timestamp": "2026-08-05T16:18:38.498181Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Lists GDPR Art. 12(3) requests submitted by the authenticated organisation.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/gdpr/requests" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/gdpr/requests"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/gdpr/requests';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/gdpr/requests');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [],
"errors": null,
"meta": {
"request_id": "c161e586-954d-48ca-928d-41bad21a8adf",
"timestamp": "2026-08-05T16:18:38.479808Z",
"current_page": 1,
"last_page": 1,
"per_page": 15,
"total": 0
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Records a new GDPR Art. 12(3) request forwarded by an organisation on behalf of a data subject. Persists the request, emits an audit event, and notifies all super-admins via in-app and email.
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/gdpr/requests" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"subject_email\": \"name@example.at\",
\"request_type\": \"access\",
\"message\": \"Bitte um Rueckmeldung zur naechsten Schicht.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/gdpr/requests"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"subject_email": "name@example.at",
"request_type": "access",
"message": "Bitte um Rueckmeldung zur naechsten Schicht."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/gdpr/requests';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'subject_email' => 'name@example.at',
'request_type' => 'access',
'message' => 'Bitte um Rueckmeldung zur naechsten Schicht.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/gdpr/requests');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"subject_email": "name@example.at",
"request_type": "access",
"message": "Bitte um Rueckmeldung zur naechsten Schicht."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "CREATED",
"message": "GDPR request submitted successfully.",
"data": {
"id": "019fd2b8-4116-7347-914a-230153f403ce",
"request_type": "access",
"request_type_label": "Access (Art. 15)",
"subject_email": "name@example.at",
"message": "Bitte um Rueckmeldung zur naechsten Schicht.",
"status": "pending",
"status_label": "Pending",
"submitted_at": "2026-08-05T16:18:38.000000Z",
"resolved_at": null,
"platform_note": null,
"created_at": "2026-08-05T16:18:38.000000Z"
},
"errors": null,
"meta": {
"request_id": "8f34c05d-27c1-4a19-b728-9442355514a1",
"timestamp": "2026-08-05T16:18:38.490505Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Privacy
Consent History
requires authentication
Returns a paginated list of cookie-consent decisions recorded for the authenticated organisation. Backed by the immutable audit log (GDPR Art. 15 right of access).
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/me/consent-history?per_page=25" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/me/consent-history"
);
const params = {
"per_page": "25",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/me/consent-history';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'per_page' => '25',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/me/consent-history')
.replace(queryParameters: {
'per_page': '25',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [],
"errors": null,
"meta": {
"request_id": "a726ed83-b8fd-4332-9cfe-5ef5302a22f0",
"timestamp": "2026-08-05T16:18:38.519100Z",
"total": 0,
"current_page": 1,
"last_page": 1,
"per_page": 25
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Record Cookie Consent
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/me/consent" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"version\": \"2026-04-01\",
\"choices\": {
\"necessary\": true,
\"analytics\": false,
\"marketing\": false
},
\"timestamp\": \"2026-04-21T10:00:00.000Z\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/me/consent"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"version": "2026-04-01",
"choices": {
"necessary": true,
"analytics": false,
"marketing": false
},
"timestamp": "2026-04-21T10:00:00.000Z"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/me/consent';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'version' => '2026-04-01',
'choices' => ['necessary' => true, 'analytics' => false, 'marketing' => false],
'timestamp' => '2026-04-21T10:00:00.000Z',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/me/consent');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"version": "2026-04-01",
"choices": {
"necessary": true,
"analytics": false,
"marketing": false
},
"timestamp": "2026-04-21T10:00:00.000Z"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Consent recorded.",
"data": {
"recorded_at": "2026-08-05T16:18:38+00:00"
},
"errors": null,
"meta": {
"request_id": "5a2c4cdb-a5b7-4ed0-adc0-6d872d01255a",
"timestamp": "2026-08-05T16:18:38.527726Z"
}
}
Example response (422, Validation Error):
{
"status": "VALIDATION_ERROR",
"message": "The given data was invalid.",
"data": null,
"errors": [
{
"field": "choices.necessary",
"message": "The choices.necessary field must be accepted."
}
],
"meta": {
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-21T10:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Audit
List Org Audit Log
requires authentication
A paginated view of everything the authenticated organisation did, had done to it, or had done on its behalf. A row is in scope when any of the following holds:
a) the organisation is the actor; b) the organisation is the subject; c) the subject is one of its members; or d) one of its members is the actor — most of a company's work is done by the people it invited, so without this the log showed almost none of the company's real activity.
The event filter accepts a value from the allowed list, which excludes admin-internal and user-PII events so they are never exposed here.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/audit-log?event=model.updated&from=2026-01-01&to=2026-12-31&page=1&per_page=25" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"event\": \"architecto\",
\"from\": \"2026-08-21T05:14:34\",
\"to\": \"2052-09-13\",
\"page\": 22,
\"per_page\": 67
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/audit-log"
);
const params = {
"event": "model.updated",
"from": "2026-01-01",
"to": "2026-12-31",
"page": "1",
"per_page": "25",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"event": "architecto",
"from": "2026-08-21T05:14:34",
"to": "2052-09-13",
"page": 22,
"per_page": 67
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/audit-log';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'event' => 'model.updated',
'from' => '2026-01-01',
'to' => '2026-12-31',
'page' => '1',
'per_page' => '25',
],
'json' => [
'event' => 'architecto',
'from' => '2026-08-21T05:14:34',
'to' => '2052-09-13',
'page' => 22,
'per_page' => 67,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/audit-log')
.replace(queryParameters: {
'event': 'model.updated',
'from': '2026-01-01',
'to': '2026-12-31',
'page': '1',
'per_page': '25',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"event": "architecto",
"from": "2026-08-21T05:14:34",
"to": "2052-09-13",
"page": 22,
"per_page": 67
};
final response = await http.get(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Audit log retrieved.",
"data": [],
"errors": null,
"meta": {
"request_id": "24a91099-8b31-42b2-ae2c-6bcd6450f1fd",
"timestamp": "2026-08-05T16:18:38.535487Z",
"current_page": 22,
"last_page": 1,
"per_page": 67,
"total": 0
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Security
Get Two-Factor State
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/security/two-factor" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/security/two-factor"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/security/two-factor';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/security/two-factor');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": {
"enabled": true,
"method": "totp",
"confirmed_at": "2026-08-05T16:18:32+00:00",
"recovery_codes_remaining": 2
},
"errors": null,
"meta": {
"request_id": "3f0ace2f-07fd-4e6e-9bd0-24b9619f2e8e",
"timestamp": "2026-08-05T16:18:38.604346Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List Login History
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/security/login-history?limit=50" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/security/login-history"
);
const params = {
"limit": "50",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/security/login-history';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'limit' => '50',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/security/login-history')
.replace(queryParameters: {
'limit': '50',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Success",
"data": [],
"errors": null,
"meta": {
"request_id": "a1ef4b94-6775-44ca-996f-3a02b14c2a73",
"timestamp": "2026-08-05T16:18:38.610416Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Kyc Status
Get Organisation KYC Status
requires authentication
Returns the KYC checklist status for the authenticated organisation.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/kyc-status" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/kyc-status"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/kyc-status';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/kyc-status');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "KYC-Status erfolgreich abgerufen.",
"data": {
"organization": {
"id": "019fd2b7-f072-7154-8961-5b324cc6c46c",
"status": "active",
"statusLabel": "Active",
"rejectionReason": null,
"verifiedAt": "2026-08-05T16:18:17+00:00"
},
"summary": {
"requiredCount": 5,
"uploadedCount": 0,
"approvedCount": 0,
"rejectedCount": 0,
"missingCount": 5,
"completionPercent": 0,
"isReadyForReview": false,
"nextAction": "upload_missing"
},
"checklist": [
{
"type": "gewerbeschein",
"label": "Gewerbeschein",
"description": null,
"required": true,
"source": "baseline",
"status": "missing",
"latestDocument": null,
"historyCount": 0,
"openRequestId": null
},
{
"type": "firmenbuch_auszug",
"label": "Firmenbuchauszug",
"description": null,
"required": true,
"source": "baseline",
"status": "missing",
"latestDocument": null,
"historyCount": 0,
"openRequestId": null
},
{
"type": "aueg_bewilligung",
"label": "AÜG-Bewilligung",
"description": null,
"required": true,
"source": "baseline",
"status": "missing",
"latestDocument": null,
"historyCount": 0,
"openRequestId": null
},
{
"type": "ausweis_gf",
"label": "Ausweis Geschäftsführer",
"description": null,
"required": true,
"source": "baseline",
"status": "missing",
"latestDocument": null,
"historyCount": 0,
"openRequestId": null
},
{
"type": "unterschriftenprobe",
"label": "Unterschriftenprobe",
"description": null,
"required": true,
"source": "baseline",
"status": "missing",
"latestDocument": null,
"historyCount": 0,
"openRequestId": null
},
{
"type": "uid_bestaetigung",
"label": "UID-Bestätigung",
"description": null,
"required": false,
"source": "baseline",
"status": "missing",
"latestDocument": null,
"historyCount": 0,
"openRequestId": null
}
],
"openRequests": []
},
"errors": null,
"meta": {
"request_id": "673ba49d-0208-4a7a-8bd6-ccba99d10ede",
"timestamp": "2026-08-05T16:18:38.651604Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Documents
List Organization Documents
requires authentication
Lists all non-deleted KYC documents belonging to the authenticated organisation.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/documents" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/documents"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/documents';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/documents');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Dokumente erfolgreich abgerufen.",
"data": [],
"errors": null,
"meta": {
"request_id": "f421c038-b8cf-43c0-ab3b-142d37da1232",
"timestamp": "2026-08-05T16:18:38.658086Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Upload Organization Document
requires authentication
Accepts a KYC document upload from the authenticated organisation.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/documents" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "type=Beispieltext"\
--form "document_request_id=019f9939-c4c3-70fb-a54e-5ebf63db36d2"\
--form "file=@/tmp/php9itgkdkhc241c2Z59vG" const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/documents"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('type', 'Beispieltext');
body.append('document_request_id', '019f9939-c4c3-70fb-a54e-5ebf63db36d2');
body.append('file', document.querySelector('input[name="file"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/documents';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'multipart/form-data',
'Accept' => 'application/json',
],
'multipart' => [
[
'name' => 'type',
'contents' => 'Beispieltext'
],
[
'name' => 'document_request_id',
'contents' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2'
],
[
'name' => 'file',
'contents' => fopen('/tmp/php9itgkdkhc241c2Z59vG', 'r')
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/documents');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'multipart/form-data',
'Accept': 'application/json',
};
final request = http.MultipartRequest('POST', uri);
request.headers.addAll(headers);
request.fields['type'] = 'Beispieltext';
request.fields['document_request_id'] = '019f9939-c4c3-70fb-a54e-5ebf63db36d2';
request.files.add(await http.MultipartFile.fromPath('file', '/tmp/php9itgkdkhc241c2Z59vG'));
final streamed = await request.send();
final response = await http.Response.fromStream(streamed);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Download Organization Document
requires authentication
Streams a KYC document back to the owning organisation.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/documents/019f34d3-5029-7158-a549-910ae39abad5/download" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/documents/019f34d3-5029-7158-a549-910ae39abad5/download"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/documents/019f34d3-5029-7158-a549-910ae39abad5/download';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/documents/019f34d3-5029-7158-a549-910ae39abad5/download');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "b21dce97-33bd-4cbb-a28c-67af75128d72",
"timestamp": "2026-08-21T05:14:34.591593Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete Organization Document
requires authentication
Soft-deletes a Pending KYC document belonging to the authenticated organisation.
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/org/documents/019f34d3-5029-7158-a549-910ae39abad5" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/documents/019f34d3-5029-7158-a549-910ae39abad5"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/documents/019f34d3-5029-7158-a549-910ae39abad5';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/documents/019f34d3-5029-7158-a549-910ae39abad5');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Legal Documents
List Organisation Legal Documents
requires authentication
Lists the legal documents the organisation must accept, the current acceptance state per type, and the full acceptance history (for the "Legal documents" page).
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/legal-documents" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/legal-documents"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/legal-documents';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/legal-documents');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Rechtsdokumente erfolgreich abgerufen.",
"data": {
"documents": [
{
"type": "privacy_policy",
"label": "Datenschutzerklärung",
"locale": "de",
"currentVersion": 1,
"currentVersionId": "019fd2b7-ef68-7312-a1a3-6b14820cf9e2",
"acceptedVersion": 1,
"acceptedAt": "2026-08-05T16:18:32+00:00",
"status": "accepted",
"viewUrl": "http://localhost:8001/legal/privacy_policy/de/v/1"
},
{
"type": "terms_of_service",
"label": "Allgemeine Geschäftsbedingungen",
"locale": "de",
"currentVersion": 1,
"currentVersionId": "019fd2b7-ef6f-72ae-8c86-d9977da26ec0",
"acceptedVersion": 1,
"acceptedAt": "2026-08-05T16:18:32+00:00",
"status": "accepted",
"viewUrl": "http://localhost:8001/legal/terms_of_service/de/v/1"
},
{
"type": "data_processing",
"label": "Auftragsverarbeitung",
"locale": "de",
"currentVersion": 1,
"currentVersionId": "019fd2b7-ef76-73b5-a9c5-d7cca778324b",
"acceptedVersion": 1,
"acceptedAt": "2026-08-05T16:18:32+00:00",
"status": "accepted",
"viewUrl": "http://localhost:8001/legal/data_processing/de/v/1"
},
{
"type": "svnr_consent",
"label": "Einwilligung zur SV-Nummer",
"locale": "de",
"currentVersion": 1,
"currentVersionId": "019fd2b7-ef83-7298-a78c-af4b1e36b67b",
"acceptedVersion": 1,
"acceptedAt": "2026-08-05T16:18:32+00:00",
"status": "accepted",
"viewUrl": "http://localhost:8001/legal/svnr_consent/de/v/1"
}
],
"history": [
{
"type": "svnr_consent",
"label": "Einwilligung zur SV-Nummer",
"version": 1,
"acceptedAt": "2026-08-05T16:18:32+00:00",
"withdrawnAt": null
},
{
"type": "data_processing",
"label": "Auftragsverarbeitung",
"version": 1,
"acceptedAt": "2026-08-05T16:18:32+00:00",
"withdrawnAt": null
},
{
"type": "terms_of_service",
"label": "Allgemeine Geschäftsbedingungen",
"version": 1,
"acceptedAt": "2026-08-05T16:18:32+00:00",
"withdrawnAt": null
},
{
"type": "privacy_policy",
"label": "Datenschutzerklärung",
"version": 1,
"acceptedAt": "2026-08-05T16:18:32+00:00",
"withdrawnAt": null
}
]
},
"errors": null,
"meta": {
"request_id": "5088afd2-6632-4150-9a93-7a8d53e7d090",
"timestamp": "2026-08-05T16:18:38.691599Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Organisation Pending Legal Acceptances
requires authentication
Returns the legal document versions the organisation must still accept.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/legal-documents/pending" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/legal-documents/pending"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/legal-documents/pending';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/legal-documents/pending');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Ausstehende Rechtsdokumente erfolgreich abgerufen.",
"data": {
"pending": []
},
"errors": null,
"meta": {
"request_id": "8b96ae8c-9c5d-435e-a7ab-974f30899fbb",
"timestamp": "2026-08-05T16:18:38.707936Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Accept Organisation Legal Document
requires authentication
Records the organisation's acceptance of the current version of a legal document type, pinning the exact version for audit.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/legal-documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2/accept" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/legal-documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2/accept"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/legal-documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2/accept';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/legal-documents/019f9939-c4c3-70fb-a54e-5ebf63db36d2/accept');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Contract Template
Get Contract Template
requires authentication
The organisation's default contract template for the settings editor: the saved organisation-level row when one exists, otherwise the built-in default body — plus the merge fields the editor can insert. Per-job and per-shift overrides have their own endpoints ({@see GetJobContractTemplateAction}, {@see GetShiftContractTemplateAction}); this is always the organisation default level (job_id and shift_id both null).
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/contract-template" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/contract-template"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/contract-template';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/contract-template');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"template": {
"name": "Überlassungsvertrag",
"body_html": "<h2>Arbeitskraft</h2>\n<p>{worker_name}, geboren am {worker_birth_date}, {worker_address}</p>\n<h2>Beschäftiger</h2>\n<p>{organization_name}, {organization_address}</p>\n<h2>Überlassung</h2>\n<p>Tätigkeit: {job_title}<br>Einsatzort: {location}<br>Zeitraum: {start_date} – {end_date}<br>Entgelt (brutto/Std.): {hourly_rate}<br>Kollektivvertrag: {collective_agreement}</p>\n<p>Für die Dauer der Überlassung gelten gemäß § 10 AÜG die im Beschäftigerbetrieb für vergleichbare Arbeitnehmer geltenden wesentlichen Arbeits- und Beschäftigungsbedingungen. Rechtsgrundlage: {legal_basis}.</p>",
"version": 0,
"is_active": false,
"is_customized": false
},
"merge_fields": [
"contract_number",
"worker_name",
"worker_birth_date",
"worker_nationality",
"worker_address",
"organization_name",
"organization_address",
"job_title",
"job_description",
"location",
"start_date",
"end_date",
"hourly_rate",
"collective_agreement",
"legal_basis"
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Contract Template
requires authentication
Save the organisation's default contract template (job_id and shift_id both null). Upserts the single per-org row, bumps its version, and strips active content (script/style) from the HTML — the body is rendered into the worker's signed PDF unless a job or shift override applies.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/org/contract-template" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"name\": \"Beispieltext\",
\"body_html\": \"Bitte um Rueckmeldung zur naechsten Schicht.\",
\"is_active\": true
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/contract-template"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Beispieltext",
"body_html": "Bitte um Rueckmeldung zur naechsten Schicht.",
"is_active": true
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/contract-template';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'name' => 'Beispieltext',
'body_html' => 'Bitte um Rueckmeldung zur naechsten Schicht.',
'is_active' => true,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/contract-template');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"name": "Beispieltext",
"body_html": "Bitte um Rueckmeldung zur naechsten Schicht.",
"is_active": true
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The contract template has been saved.",
"data": {
"template": {
"name": "Beispieltext",
"body_html": "Bitte um Rueckmeldung zur naechsten Schicht.",
"version": 1,
"is_active": true,
"is_customized": true
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Messages
List Conversations
requires authentication
List conversations for organization staff.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/messages/conversations" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/messages/conversations"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/messages/conversations';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/messages/conversations');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"conversations": [
{
"id": "64c3f8d8-55d2-4457-b394-c3277a378bac",
"participant": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"name": "Anna Neuling",
"avatar_url": null
},
"job": null,
"last_message": null,
"last_message_is_from_user": null,
"last_message_at": "2026-08-05T16:18:32+00:00",
"unread_count": 0
}
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Messages
requires authentication
Get messages for a conversation.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/messages/conversations/019fd51d-53c7-73d0-880d-8edee1800329" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/messages/conversations/019fd51d-53c7-73d0-880d-8edee1800329"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/messages/conversations/019fd51d-53c7-73d0-880d-8edee1800329';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/messages/conversations/019fd51d-53c7-73d0-880d-8edee1800329');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"conversation": {
"id": "64c3f8d8-55d2-4457-b394-c3277a378bac",
"participant": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"name": "Anna Neuling",
"avatar_url": null
},
"job": null
},
"messages": [],
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 50,
"total": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Mark Conversation Read
requires authentication
Mark a conversation as read by the organization.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/messages/conversations/019f9939-c4c3-70fb-a54e-5ebf63db36d2/read" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/messages/conversations/019f9939-c4c3-70fb-a54e-5ebf63db36d2/read"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/messages/conversations/019f9939-c4c3-70fb-a54e-5ebf63db36d2/read';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/messages/conversations/019f9939-c4c3-70fb-a54e-5ebf63db36d2/read');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Marked read):
{
"status": "SUCCESS"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Upload a Message Attachment
requires authentication
Upload a file attachment ahead of sending it with a message. The returned attachment id is bound to a message when that message is sent.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/messages/conversations/019f9939-c4c3-70fb-a54e-5ebf63db36d2/attachments" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "file=@/tmp/phpqtm74uqeke1f9ag7iaC" const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/messages/conversations/019f9939-c4c3-70fb-a54e-5ebf63db36d2/attachments"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('file', document.querySelector('input[name="file"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/messages/conversations/019f9939-c4c3-70fb-a54e-5ebf63db36d2/attachments';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'multipart/form-data',
'Accept' => 'application/json',
],
'multipart' => [
[
'name' => 'file',
'contents' => fopen('/tmp/phpqtm74uqeke1f9ag7iaC', 'r')
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/messages/conversations/019f9939-c4c3-70fb-a54e-5ebf63db36d2/attachments');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'multipart/form-data',
'Accept': 'application/json',
};
final request = http.MultipartRequest('POST', uri);
request.headers.addAll(headers);
request.files.add(await http.MultipartFile.fromPath('file', '/tmp/phpqtm74uqeke1f9ag7iaC'));
final streamed = await request.send();
final response = await http.Response.fromStream(streamed);
print(jsonDecode(response.body));
}Example response (201, Uploaded):
{
"status": "SUCCESS",
"data": {
"attachment": {
"id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"name": "beleg.pdf",
"mime_type": "application/pdf",
"file_size": 48213
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Send Message
requires authentication
Send a message to an employee.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/messages" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"user_id\": \"019f9939-c4c3-70fb-a54e-5ebf63db36d2\",
\"content\": \"Beispieltext\",
\"job_id\": \"019f9939-c4c3-70fb-a54e-5ebf63db36d2\",
\"shift_id\": \"019f9939-c4c3-70fb-a54e-5ebf63db36d2\",
\"attachments\": null
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/messages"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"user_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"content": "Beispieltext",
"job_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"shift_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"attachments": null
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/messages';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'user_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'content' => 'Beispieltext',
'job_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'shift_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'attachments' => null,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/messages');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"user_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"content": "Beispieltext",
"job_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"shift_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"attachments": null
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"message": {
"id": "019fd2b8-4623-72c9-81f4-41013427b344",
"conversation_id": "019fd2b8-4620-7315-bdd5-20f236d38c04",
"content": "Beispieltext",
"created_at": "2026-08-05T16:18:39+00:00"
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Audit Log
Record Organisation Pii Reveal
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/audit-log/pii-reveal" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"module\": \"Beispieltext\",
\"context\": \"Beispieltext\",
\"subject_type\": \"Frage zur Abrechnung\",
\"subject_id\": \"019f9939-c4c3-70fb-a54e-5ebf63db36d2\",
\"fields\": null
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/audit-log/pii-reveal"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"module": "Beispieltext",
"context": "Beispieltext",
"subject_type": "Frage zur Abrechnung",
"subject_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"fields": null
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/audit-log/pii-reveal';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'module' => 'Beispieltext',
'context' => 'Beispieltext',
'subject_type' => 'Frage zur Abrechnung',
'subject_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
'fields' => null,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/audit-log/pii-reveal');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"module": "Beispieltext",
"context": "Beispieltext",
"subject_type": "Frage zur Abrechnung",
"subject_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"fields": null
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "PII reveal has been audit logged."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Support
List Support Tickets
requires authentication
The tickets visible to the caller, newest first, optionally narrowed by status.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/support/tickets" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/support/tickets"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/support/tickets';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/support/tickets');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"tickets": [
{
"id": "019fd2b8-28b2-7322-b70c-bc7d76debfc3",
"ticket_number": "TKT-717858",
"subject": "Nihil autem neque blanditiis accusantium eaque.",
"category": "general",
"category_label": "Allgemein",
"status": "open",
"status_label": "Offen",
"priority": 3,
"requester_type": "company",
"requester_name": "Caritas",
"assignee_name": null,
"message_count": 0,
"last_message_at": null,
"created_at": "2026-08-05T16:18:32+00:00"
}
],
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 20,
"total": 1
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Open a Support Ticket
requires authentication
Raises a new support ticket with a subject and an opening message.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/support/tickets" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"category\": \"general\",
\"subject\": \"Frage zur Abrechnung\",
\"description\": \"Beispieltext\",
\"related_entity_type\": \"shift\",
\"related_entity_id\": \"019f9939-c4c3-70fb-a54e-5ebf63db36d2\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/support/tickets"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"category": "general",
"subject": "Frage zur Abrechnung",
"description": "Beispieltext",
"related_entity_type": "shift",
"related_entity_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/support/tickets';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'category' => 'general',
'subject' => 'Frage zur Abrechnung',
'description' => 'Beispieltext',
'related_entity_type' => 'shift',
'related_entity_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/support/tickets');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"category": "general",
"subject": "Frage zur Abrechnung",
"description": "Beispieltext",
"related_entity_type": "shift",
"related_entity_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Show a Support Ticket
requires authentication
One ticket with its message thread. Internal notes are never included.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"id": "019fd2b8-28b2-7322-b70c-bc7d76debfc3",
"ticket_number": "TKT-717858",
"subject": "Nihil autem neque blanditiis accusantium eaque.",
"category": "general",
"category_label": "Allgemein",
"status": "open",
"status_label": "Offen",
"priority": 3,
"requester_type": "company",
"requester_name": "Caritas",
"assignee_name": null,
"message_count": 0,
"last_message_at": null,
"created_at": "2026-08-05T16:18:32+00:00",
"description": "Quo necessitatibus et tempora esse nemo. Omnis et molestias sed expedita cupiditate.\n\nQuidem mollitia et reprehenderit enim quidem est. Temporibus et blanditiis iusto officia neque molestiae quidem. Adipisci suscipit sit temporibus voluptatum porro molestiae omnis. Rem fuga ratione ratione odio esse odio modi.",
"resolution_notes": null,
"related_entity_type": null,
"related_entity_id": null,
"assigned_to": null,
"first_response_at": null,
"resolved_at": null,
"messages": []
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reply to a Support Ticket
requires authentication
Appends a message to an existing ticket.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/messages" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"message\": \"Bitte um Rueckmeldung zur naechsten Schicht.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/messages"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"message": "Bitte um Rueckmeldung zur naechsten Schicht."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/messages';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'message' => 'Bitte um Rueckmeldung zur naechsten Schicht.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/support/tickets/019f9939-c4c3-70fb-a54e-5ebf63db36d2/messages');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"message": "Bitte um Rueckmeldung zur naechsten Schicht."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Your message has been sent.",
"data": {
"message": {
"id": "019fd2b8-46aa-7182-9c38-e64d58e94097",
"message": "Bitte um Rueckmeldung zur naechsten Schicht.",
"sender_type": "company",
"sender_name": "Caritas",
"is_internal": false,
"attachments": null,
"created_at": "2026-08-05T16:18:39+00:00"
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Admin - Employees
Admin dashboard endpoints for platform management. Requires admin-level Bearer token authentication.
Employees
Apply a sanction to a worker who was sent home or breached the rules. The admin chooses the consequence: suspension days, a payment treatment (full / partial / none / goodwill) and/or a warning (Ermahnung).
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/employees/architecto/sanction" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Wiederholtes Zuspätkommen\",
\"suspension_days\": 7,
\"payment_treatment\": \"partial\",
\"issue_warning\": true,
\"shift_id\": \"architecto\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/employees/architecto/sanction"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Wiederholtes Zuspätkommen",
"suspension_days": 7,
"payment_treatment": "partial",
"issue_warning": true,
"shift_id": "architecto"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/employees/architecto/sanction';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'Wiederholtes Zuspätkommen',
'suspension_days' => 7,
'payment_treatment' => 'partial',
'issue_warning' => true,
'shift_id' => 'architecto',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/employees/architecto/sanction');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "Wiederholtes Zuspätkommen",
"suspension_days": 7,
"payment_treatment": "partial",
"issue_warning": true,
"shift_id": "architecto"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Admin - LHR Payroll
Admin dashboard endpoints for platform management. Requires admin-level Bearer token authentication.
Lhr
Request Payroll Approval
requires authentication
Opens a four-eyes approval request for a payroll period.
A different admin with admin.payroll.trigger must then approve it
before the payroll trigger endpoint will accept the approval_id.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/approval-requests" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"period\": \"2026-06\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/approval-requests"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"period": "2026-06"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/approval-requests';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'period' => '2026-06',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/approval-requests');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"period": "2026-06"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (201, Recorded from a live call):
{
"status": "CREATED",
"message": "Approval request opened.",
"data": {
"id": "019fd2b8-53e2-72c9-afe8-17239fd1a8e1",
"period": "2026-06",
"status": "pending",
"requested_by_id": "019fd2b7-edab-7280-b09f-b18f58a272ee",
"created_at": "2026-08-05T16:18:43.000000Z"
},
"errors": null,
"meta": {
"request_id": "b7e77921-3f4d-4d85-83af-84afa8e7b97e",
"timestamp": "2026-08-05T16:18:43.305161Z"
}
}
Example response (409):
{
"status": "CONFLICT",
"message": "An open approval request already exists for this period."
}
Example response (422):
{
"status": "VALIDATION_ERROR",
"message": "This period has already been executed."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Approve Payroll Approval Request
requires authentication
Approves a pending four-eyes payroll approval request. The approver must be a different admin from the requester.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/approval-requests/architecto" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/approval-requests/architecto"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "PUT",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/approval-requests/architecto';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/approval-requests/architecto');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.put(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200):
{
"status": "SUCCESS",
"message": "Approval granted.",
"data": {
"id": "uuid",
"period": "2026-06",
"status": "approved",
"approved_by_id": "uuid",
"approved_at": "2026-06-14T10:05:00.000000Z"
}
}
Example response (403):
{
"status": "FORBIDDEN",
"message": "The requester cannot approve their own request."
}
Example response (422):
{
"status": "VALIDATION_ERROR",
"message": "This approval request is not in a pending state."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reject Payroll Approval Request
requires authentication
Declines a pending four-eyes payroll approval request, closing the period to payroll until a new request is raised. The reviewer must be a different admin from the requester, and must say why — the requester needs to know what to change before asking again.
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/approval-requests/architecto/reject" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Overtime for the Graz site is still unconfirmed.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/approval-requests/architecto/reject"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Overtime for the Graz site is still unconfirmed."
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/approval-requests/architecto/reject';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'Overtime for the Graz site is still unconfirmed.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/approval-requests/architecto/reject');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "Overtime for the Graz site is still unconfirmed."
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200):
{
"status": "SUCCESS",
"message": "Approval rejected.",
"data": {
"id": "uuid",
"period": "2026-06",
"status": "rejected",
"approved_by_id": "uuid",
"approved_at": "2026-06-14T10:05:00.000000Z",
"rejection_reason": "Overtime for the Graz site is still unconfirmed."
}
}
Example response (403):
{
"status": "FORBIDDEN",
"message": "The requester cannot approve their own request."
}
Example response (422):
{
"status": "VALIDATION_ERROR",
"message": "This approval request is not in a pending state."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Trigger LHR payroll.
requires authentication
Trigger monthly payroll calculation in LHR.
Requires a pre-approved four-eyes approval record. The approval_id
must reference a PayrollApproval in approved state for the same
period, approved by a different admin than the caller who requested it.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/trigger" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"period\": \"2026-01\",
\"approval_id\": \"architecto\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/trigger"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"period": "2026-01",
"approval_id": "architecto"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/trigger';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'period' => '2026-01',
'approval_id' => 'architecto',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/trigger');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"period": "2026-01",
"approval_id": "architecto"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (202):
{
"status": "success",
"message": "Payroll calculation triggered",
"data": {
"abrechnung_id": "abc-123",
"period": "2026-01",
"status": "queued"
}
}
Example response (422):
{
"status": "VALIDATION_ERROR",
"message": "Approval is not in an approved state."
}
Example response (503):
{
"status": "error",
"message": "LHR service unavailable"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get payroll calculation status from LHR.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/architecto/status" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/architecto/status"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/architecto/status';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/architecto/status');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "83b111e4-96dc-4495-ba19-ba40d5076dc9",
"timestamp": "2026-08-21T05:14:36.862690Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get payroll results from LHR.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/architecto/results" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/architecto/results"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/architecto/results';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/lhr/payroll/architecto/results');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "524f03f5-0c13-41af-82bd-26b21bef8af1",
"timestamp": "2026-08-21T05:14:36.871506Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Sync employee data with LHR.
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/lhr/dienstnehmer/sync" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"user_id\": \"019f9939-c4c3-70fb-a54e-5ebf63db36d2\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/lhr/dienstnehmer/sync"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"user_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/lhr/dienstnehmer/sync';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'user_id' => '019f9939-c4c3-70fb-a54e-5ebf63db36d2',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/lhr/dienstnehmer/sync');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"user_id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List employee documents from LHR.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/lhr/users/architecto/documents" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/lhr/users/architecto/documents"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/lhr/users/architecto/documents';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/lhr/users/architecto/documents');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"documents": []
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Download payslips from LHR.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/admin/lhr/users/architecto/payslip" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/lhr/users/architecto/payslip"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/lhr/users/architecto/payslip';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/lhr/users/architecto/payslip');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "25d24af1-490a-490e-878a-158c3d0a4b2e",
"timestamp": "2026-08-21T05:14:36.907967Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Admin - Shifts
Admin dashboard endpoints for platform management. Requires admin-level Bearer token authentication.
Shifts
Resolve an attendance hours dispute (conflict) raised during check-out.
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/admin/shifts/architecto/resolve-dispute" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"resolution\": \"Stunden laut Anwesenheitsliste bestätigt.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/admin/shifts/architecto/resolve-dispute"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"resolution": "Stunden laut Anwesenheitsliste bestätigt."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/admin/shifts/architecto/resolve-dispute';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'resolution' => 'Stunden laut Anwesenheitsliste bestätigt.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/admin/shifts/architecto/resolve-dispute');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"resolution": "Stunden laut Anwesenheitsliste bestätigt."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Company - Assignments
Organization (Company Portal) endpoints for managing jobs, applicants, shifts, team, and organization profiles. Requires organization-level Bearer token. Some endpoints require approved organization status.
Shifts
List all shift assignments for the organization.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/shifts/assignments" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/assignments"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/assignments';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/assignments');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"assignments": [
{
"id": "019fd2b8-1636-72ac-b1d9-8d969732067e",
"status": "signed",
"status_label": "Unterschrieben",
"shift_date": "2026-08-25",
"scheduled_start_time": "08:00:00",
"scheduled_end_time": "16:00:00",
"location_name": "MuseumsQuartier Wien",
"location_address": "Museumsplatz 1, 1070 Wien",
"hourly_rate_gross": "14.00",
"confirmed_at": "2026-08-22 00:00",
"started_at": null,
"completed_at": null,
"job": {
"id": "019fd2b8-1628-73ae-86e5-b232f0363a96",
"title": "Event-Fotograf Assistent",
"category": "Events"
},
"employee": {
"id": "019fd2b8-0d32-71d1-98de-ce0b40a5b75d",
"name": "Andreas Weber",
"email": "andreas.weber12@demo-employee.at",
"city": "Linz"
}
},
{
"id": "019fd2b8-18c6-71d1-9d10-c4ee02fbff17",
"status": "signed",
"status_label": "Unterschrieben",
"shift_date": "2026-08-07",
"scheduled_start_time": "08:00:00",
"scheduled_end_time": "16:00:00",
"location_name": "H&M Mariahilfer",
"location_address": "Mariahilfer Straße 42, 1070 Wien",
"hourly_rate_gross": "13.50",
"confirmed_at": "2026-08-06 00:00",
"started_at": null,
"completed_at": null,
"job": {
"id": "019fd2b8-18bd-713e-8faf-09b99d95cb72",
"title": "Kassiere*r Modegeschäft",
"category": "Einzelhandel"
},
"employee": {
"id": "019fd2b8-02bf-72ff-a65c-330126050c95",
"name": "Stefan Müller",
"email": "stefan.müller0@demo-employee.at",
"city": "Wien"
}
},
{
"id": "019fd2b8-28d3-70d7-92eb-f1bb1577acaf",
"status": "signed",
"status_label": "Unterschrieben",
"shift_date": "2026-08-06",
"scheduled_start_time": "08:00:00",
"scheduled_end_time": "16:00:00",
"location_name": "Nolan-Roberts",
"location_address": "4309 O'Reilly Way Suite 012",
"hourly_rate_gross": "34.72",
"confirmed_at": null,
"started_at": null,
"completed_at": null,
"job": {
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant",
"category": "Büro"
},
"employee": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"name": "Anna Neuling",
"email": "pending@demo.flexxr.at",
"city": "Linz"
}
},
{
"id": "019fd2b8-28d8-728d-a447-8de1a42eec83",
"status": "checked_in",
"status_label": "Eingecheckt",
"shift_date": "2026-08-05",
"scheduled_start_time": "11:58:00",
"scheduled_end_time": "12:13:00",
"location_name": "Goldner and Sons",
"location_address": "30005 Prosacco Orchard",
"hourly_rate_gross": "18.57",
"confirmed_at": null,
"started_at": null,
"completed_at": null,
"job": {
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant",
"category": "Büro"
},
"employee": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"name": "Anna Neuling",
"email": "pending@demo.flexxr.at",
"city": "Linz"
}
},
{
"id": "019fd2b8-28df-7265-8b1e-cb5de026e4d7",
"status": "completed",
"status_label": "Abgeschlossen",
"shift_date": "2026-08-03",
"scheduled_start_time": "08:31:00",
"scheduled_end_time": "05:12:00",
"location_name": "Wehner Inc",
"location_address": "45222 Hansen Gardens",
"hourly_rate_gross": "18.25",
"confirmed_at": null,
"started_at": null,
"completed_at": null,
"job": {
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant",
"category": "Büro"
},
"employee": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"name": "Anna Neuling",
"email": "pending@demo.flexxr.at",
"city": "Linz"
}
}
],
"summary": {
"total": 5,
"by_status": {
"confirmed": 3,
"in_progress": 1,
"completed": 1
},
"today": 1,
"this_week": 3
}
},
"meta": {
"current_page": 1,
"last_page": 1,
"per_page": 20,
"total": 5
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get the full audit trail for a single assignment (shift).
requires authentication
Returns the assignment summary (incl. contract status + download URL) and a chronological event timeline covering the whole lifecycle: contract signed/countersigned, clock-in/out, completion, hours confirm/dispute, signature refusal, no-show incidents and invoice lines.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/shifts/assignments/550e8400-e29b-41d4-a716-446655440000/timeline" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/assignments/550e8400-e29b-41d4-a716-446655440000/timeline"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/assignments/550e8400-e29b-41d4-a716-446655440000/timeline';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/assignments/550e8400-e29b-41d4-a716-446655440000/timeline');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"assignment": {
"id": "019fd2b8-28d1-7112-b8e9-68bd79fbafb9",
"status": "awaiting_signature",
"status_label": "Unterschrift ausstehend",
"shift_date": "2026-08-04",
"scheduled_start_time": "16:57:00",
"scheduled_end_time": "09:21:00",
"location_name": "Buckridge-Collier",
"location_address": "661 Cayla Unions Suite 344",
"hourly_rate_gross": "27.68",
"started_at": null,
"completed_at": null,
"job": {
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant"
},
"employee": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"name": "Anna Neuling"
},
"contract": null,
"attendance": null,
"rating": null
},
"timeline": [
{
"event_type": "assignment.created",
"actor": "system",
"title": "Assignment created",
"description": "Assignment was created from job selection.",
"occurred_at": "2026-08-05T16:18:32+00:00",
"path": "/hours"
}
]
}
}
Example response (404, Not Found):
{
"status": "NOT_FOUND",
"message": "Assignment not found."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Company - Attendance
Organization (Company Portal) endpoints for managing jobs, applicants, shifts, team, and organization profiles. Requires organization-level Bearer token. Some endpoints require approved organization status.
Shifts
List attendance records for shifts.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/shifts/attendance" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/attendance"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/attendance';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/attendance');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"records": [
{
"id": "019fd2b8-28d8-728d-a447-8de1a42eec83",
"shift_date": "2026-08-05",
"scheduled_start_time": "11:58:00",
"scheduled_end_time": "12:13:00",
"status": "checked_in",
"attendance_status": "checked_in",
"attendance_status_label": "Eingecheckt",
"started_at": null,
"completed_at": null,
"is_no_show": false,
"no_show_reason": null,
"location_name": "Goldner and Sons",
"job": {
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant"
},
"employee": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"name": "Anna Neuling",
"email": "pending@demo.flexxr.at",
"phone": "+436769876543"
},
"contract_signed_at": null,
"contract_in_force": false,
"hourly_rate_gross": "18.57"
}
],
"summary": {
"total": 1,
"pending": 0,
"checked_in": 1,
"completed": 0,
"no_show": 0
}
},
"meta": {
"current_page": 1,
"last_page": 1,
"per_page": 50,
"total": 1
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Company - Auth
Organization (Company Portal) endpoints for managing jobs, applicants, shifts, team, and organization profiles. Requires organization-level Bearer token. Some endpoints require approved organization status.
Authentication
Confirm a company's email ownership by consuming the verification link token (Szenario Unternehmen — "E-Mail-Adresse (Verifizierung)").
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/auth/verify-email/confirm" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"kontakt@firma.at\",
\"token\": \"abc123def456...\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/auth/verify-email/confirm"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "kontakt@firma.at",
"token": "abc123def456..."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/auth/verify-email/confirm';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'kontakt@firma.at',
'token' => 'abc123def456...',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/auth/verify-email/confirm');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "kontakt@firma.at",
"token": "abc123def456..."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Resend the company email-verification link. Always returns success to avoid leaking which addresses are registered.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/auth/verify-email/resend" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"kontakt@firma.at\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/auth/verify-email/resend"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "kontakt@firma.at"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/auth/verify-email/resend';
$response = $client->post(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'kontakt@firma.at',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/auth/verify-email/resend');
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"email": "kontakt@firma.at"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "If this address has a pending verification, a new link has been sent.",
"data": {
"email": "kontakt@firma.at"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Company - Billing
Organization (Company Portal) endpoints for managing jobs, applicants, shifts, team, and organization profiles. Requires organization-level Bearer token. Some endpoints require approved organization status.
Invoices
List invoices for the authenticated organization.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/invoices?status=paid&year=2026&month=5&per_page=20&page=1" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/invoices"
);
const params = {
"status": "paid",
"year": "2026",
"month": "5",
"per_page": "20",
"page": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/invoices';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'status' => 'paid',
'year' => '2026',
'month' => '5',
'per_page' => '20',
'page' => '1',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/invoices')
.replace(queryParameters: {
'status': 'paid',
'year': '2026',
'month': '5',
'per_page': '20',
'page': '1',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"invoices": [],
"summary": {
"total": 1,
"paid": 0,
"pending": 1,
"overdue": 0,
"total_paid_cents": 0
},
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 20,
"total": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Show a single invoice with line items.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/invoices/550e8400-e29b-41d4-a716-446655440000" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/invoices/550e8400-e29b-41d4-a716-446655440000"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/invoices/550e8400-e29b-41d4-a716-446655440000';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/invoices/550e8400-e29b-41d4-a716-446655440000');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"invoice": {
"id": "3257a732-8d8a-4de5-8dee-a54e85c7e111",
"invoice_number": "RE-2026-055747",
"period": "2026-08",
"status": "draft",
"status_label": "Draft",
"reference": null,
"notes": null,
"summary": {
"subtotal_cents": 55952,
"vat_rate_percent": 20,
"vat_amount_cents": 11190,
"platform_fee_cents": 0,
"total_cents": 67142,
"paid_amount_cents": 0
},
"dates": {
"invoice_date": "2026-08-05",
"due_date": "2026-08-19",
"sent_at": null,
"paid_at": null
},
"pdf_path": null,
"line_items": []
}
}
}
Example response (404, Not Found):
{
"status": "NOT_FOUND",
"message": "Invoice not found."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Company - Jobs
Organization (Company Portal) endpoints for managing jobs, applicants, shifts, team, and organization profiles. Requires organization-level Bearer token. Some endpoints require approved organization status.
Jobs
Update a draft job listing for the organization.
requires authentication
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/org/jobs/550e8400-e29b-41d4-a716-446655440000" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"title\": \"Eventhelfer Messe Wien\",
\"description\": \"Aufbau und Betreuung eines Messestands.\",
\"hourly_rate_gross\": \"14.50\",
\"location_name\": \"Messe Wien\",
\"location_address\": \"Messeplatz 1\",
\"location_city\": \"Wien\",
\"location_postal_code\": \"1020\",
\"location_lat\": \"48.2208\",
\"location_lng\": \"16.4108\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs/550e8400-e29b-41d4-a716-446655440000"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"title": "Eventhelfer Messe Wien",
"description": "Aufbau und Betreuung eines Messestands.",
"hourly_rate_gross": "14.50",
"location_name": "Messe Wien",
"location_address": "Messeplatz 1",
"location_city": "Wien",
"location_postal_code": "1020",
"location_lat": "48.2208",
"location_lng": "16.4108"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs/550e8400-e29b-41d4-a716-446655440000';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'title' => 'Eventhelfer Messe Wien',
'description' => 'Aufbau und Betreuung eines Messestands.',
'hourly_rate_gross' => '14.50',
'location_name' => 'Messe Wien',
'location_address' => 'Messeplatz 1',
'location_city' => 'Wien',
'location_postal_code' => '1020',
'location_lat' => '48.2208',
'location_lng' => '16.4108',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs/550e8400-e29b-41d4-a716-446655440000');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"title": "Eventhelfer Messe Wien",
"description": "Aufbau und Betreuung eines Messestands.",
"hourly_rate_gross": "14.50",
"location_name": "Messe Wien",
"location_address": "Messeplatz 1",
"location_city": "Wien",
"location_postal_code": "1020",
"location_lat": "48.2208",
"location_lng": "16.4108"
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The job has been updated successfully.",
"data": {
"job": {
"id": "019fd2b8-6bb5-7113-b62c-7434d5f44733",
"title": "Lagermitarbeiter Nachtschicht (m/w/d)",
"description": "Kommissionieren und Verräumen im Zentrallager.",
"location": {
"name": "Zentrallager Wien",
"address": null,
"city": "Wien",
"postal_code": null,
"lat": null,
"lng": null
},
"compensation": {
"hourly_rate_gross": 15.5,
"estimated_total_gross": 372
},
"timestamps": {
"updated_at": "2026-08-05 16:18"
}
}
}
}
Example response (404, Job Not Found):
{
"status": "NOT_FOUND",
"message": "Job not found."
}
Example response (422, Job Not Editable):
{
"status": "INVALID_OPERATION",
"message": "Only draft jobs can be edited."
}
Example response (422, Validation Error):
{
"status": "ERROR",
"message": "The title field must not be greater than 200 characters.",
"errors": {
"title": [
"The title field must not be greater than 200 characters."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Upload the optional cover image for a job listing ("Optional kann ein Bild hochgeladen werden").
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/jobs/550e8400-e29b-41d4-a716-446655440000/cover-image" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "image=@/tmp/phprgl8kashlq3u36M00gl" const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs/550e8400-e29b-41d4-a716-446655440000/cover-image"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('image', document.querySelector('input[name="image"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs/550e8400-e29b-41d4-a716-446655440000/cover-image';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'multipart/form-data',
'Accept' => 'application/json',
],
'multipart' => [
[
'name' => 'image',
'contents' => fopen('/tmp/phprgl8kashlq3u36M00gl', 'r')
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs/550e8400-e29b-41d4-a716-446655440000/cover-image');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'multipart/form-data',
'Accept': 'application/json',
};
final request = http.MultipartRequest('POST', uri);
request.headers.addAll(headers);
request.files.add(await http.MultipartFile.fromPath('image', '/tmp/phprgl8kashlq3u36M00gl'));
final streamed = await request.send();
final response = await http.Response.fromStream(streamed);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update assignment method and auto-reject settings for a job.
requires authentication
Example request:
curl --request PATCH \
"https://backend-dev.flexxr.at/api/v1/org/jobs/architecto/assignment-settings" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"assignment_method\": \"manual\",
\"auto_reject_after_hours\": 1
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/jobs/architecto/assignment-settings"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"assignment_method": "manual",
"auto_reject_after_hours": 1
};
fetch(url, {
method: "PATCH",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/jobs/architecto/assignment-settings';
$response = $client->patch(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'assignment_method' => 'manual',
'auto_reject_after_hours' => 1,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/jobs/architecto/assignment-settings');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"assignment_method": "manual",
"auto_reject_after_hours": 1
};
final response = await http.patch(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "messages.assignment_settings_updated",
"data": {
"job_id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"assignment_method": "manual",
"auto_reject_after_hours": 1
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Company - No-Show
Organization (Company Portal) endpoints for managing jobs, applicants, shifts, team, and organization profiles. Requires organization-level Bearer token. Some endpoints require approved organization status.
Shifts
Request emergency replacement for a no-show incident.
requires authentication
Allowed when the incident status is detected, confirmed, or disputed,
and no replacement worker has been assigned yet.
Status transitions to replacement_requested.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/shifts/no-shows/550e8400-e29b-41d4-a716-446655440000/replacement-request" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Dringender Ersatz benötigt - Standup beginnt in 30 Minuten.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/no-shows/550e8400-e29b-41d4-a716-446655440000/replacement-request"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Dringender Ersatz benötigt - Standup beginnt in 30 Minuten."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/no-shows/550e8400-e29b-41d4-a716-446655440000/replacement-request';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'Dringender Ersatz benötigt - Standup beginnt in 30 Minuten.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/no-shows/550e8400-e29b-41d4-a716-446655440000/replacement-request');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "Dringender Ersatz benötigt - Standup beginnt in 30 Minuten."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Success):
{
"status": "SUCCESS",
"message": "Replacement requested.",
"data": {
"incident_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "replacement_requested",
"status_label": "Ersatz angefordert",
"replacement_requested_at": "2026-05-10 08:15"
}
}
Example response (404, Incident Not Found):
{
"status": "NOT_FOUND",
"message": "No-show incident not found."
}
Example response (422, Not Allowed):
{
"status": "INVALID_OPERATION",
"message": "Replacement cannot be requested for this incident."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Company - No-Shows
Organization (Company Portal) endpoints for managing jobs, applicants, shifts, team, and organization profiles. Requires organization-level Bearer token. Some endpoints require approved organization status.
Shifts
List no-show incidents for the organization.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/shifts/no-shows" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/no-shows"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/no-shows';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/no-shows');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"incidents": [],
"summary": {
"total": 0,
"unresolved": 0,
"excused": 0,
"with_replacement": 0
}
},
"meta": {
"current_page": 1,
"last_page": 1,
"per_page": 20,
"total": 0
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Company - Reports
Organization (Company Portal) endpoints for managing jobs, applicants, shifts, team, and organization profiles. Requires organization-level Bearer token. Some endpoints require approved organization status.
Reports
Get workforce reports summary for the organization.
requires authentication
Returns shift statistics, hours metrics, worker engagement, financial overview, no-show analysis, compliance violations, and top workers for the specified date range. Defaults to the current calendar month when no dates are provided.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/reports/summary?date_from=2026-05-01&date_to=2026-05-31" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/reports/summary"
);
const params = {
"date_from": "2026-05-01",
"date_to": "2026-05-31",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/reports/summary';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'date_from' => '2026-05-01',
'date_to' => '2026-05-31',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/reports/summary')
.replace(queryParameters: {
'date_from': '2026-05-01',
'date_to': '2026-05-31',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"period": {
"date_from": "2026-05-01",
"date_to": "2026-05-31"
},
"kpis": {
"fill_rate_percent": 0,
"total_hours": 0,
"monthly_cost_cents": 0,
"avg_hours_per_worker": 0,
"repeat_rate_percent": 0
},
"attendance": {
"pending": 0,
"checked_in": 0,
"completed": 0,
"no_show": 0,
"total": 0
},
"no_shows": {
"total": 0,
"excused": 0,
"unresolved": 0,
"with_replacement": 0
},
"compliance": {
"score": 100,
"critical_violations": 0,
"open_violations": 0,
"disputed_hours_entries": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Export compliance report data for the organization.
requires authentication
Returns a structured JSON dataset containing per-shift compliance information (hours worked, breaks, no-show flags, AZG/ARG compliance). Intended for PDF/CSV export by the frontend. Defaults to the current calendar month when no dates are provided.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/reports/compliance/export?date_from=2026-05-01&date_to=2026-05-31" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/reports/compliance/export"
);
const params = {
"date_from": "2026-05-01",
"date_to": "2026-05-31",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/reports/compliance/export';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'date_from' => '2026-05-01',
'date_to' => '2026-05-31',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/reports/compliance/export')
.replace(queryParameters: {
'date_from': '2026-05-01',
'date_to': '2026-05-31',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Report export is ready.",
"data": {
"filename": "compliance-report-2026-05-01-to-2026-05-31.csv",
"mime_type": "text/csv; charset=UTF-8",
"csv": "date,shift_id,job_title,employee_name,employee_email,scheduled_start,scheduled_end,worked_hours,break_minutes,no_show,no_show_status,attendance_dispute,azg_daily_hours_flag\n",
"rows": 0,
"period": {
"date_from": "2026-05-01",
"date_to": "2026-05-31"
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Company - Shifts
Organization (Company Portal) endpoints for managing jobs, applicants, shifts, team, and organization profiles. Requires organization-level Bearer token. Some endpoints require approved organization status.
Shifts
Resolve step of the smart QR flow: decodes the scanned code and returns the assignment's info + terms + the single currently-valid action (check_in, check_out, or blocked-with-reason). Read-only — never burns the QR's single-use nonce and never mutates state. Whoever scans (worker self-service or shift manager) sees this before confirming.
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/shifts/scan-qr/resolve" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"qr_payload\": \"architecto\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/scan-qr/resolve"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"qr_payload": "architecto"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/scan-qr/resolve';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'qr_payload' => 'architecto',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/scan-qr/resolve');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"qr_payload": "architecto"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Confirm step of the smart QR flow: burns the QR's 60-second single-use nonce and executes the freshly re-resolved smart action (check_in or check_out). The action is recomputed here, not trusted from the resolve response, so a state change between the two calls can't be bypassed.
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/shifts/scan-qr/confirm" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"qr_payload\": \"architecto\",
\"lat\": 4326.41688,
\"lng\": 4326.41688,
\"signature\": \"architecto\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/scan-qr/confirm"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"qr_payload": "architecto",
"lat": 4326.41688,
"lng": 4326.41688,
"signature": "architecto"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/scan-qr/confirm';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'qr_payload' => 'architecto',
'lat' => 4326.41688,
'lng' => 4326.41688,
'signature' => 'architecto',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/scan-qr/confirm');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"qr_payload": "architecto",
"lat": 4326.41688,
"lng": 4326.41688,
"signature": "architecto"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Organization reports that an employee refused to sign the shift time record.
requires authentication
Sets dispute_type = 'signature_refused' on the shift attendance.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/shifts/architecto/signature-refused" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Krankheitsbedingt kurzfristig abgesagt.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/architecto/signature-refused"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/architecto/signature-refused';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'Krankheitsbedingt kurzfristig abgesagt.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/architecto/signature-refused');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Manager override: the shift manager (or an org admin/owner) checks a worker in directly, no QR needed — how a worker gets checked in past the self-service window. Replaces the old "start the shift" step: check-in IS clock-in, there is no separate start.
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/shifts/architecto/assignments/architecto/check-in" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"lat\": 1,
\"lng\": 1
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/architecto/assignments/architecto/check-in"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"lat": 1,
"lng": 1
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/architecto/assignments/architecto/check-in';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'lat' => 1,
'lng' => 1,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/architecto/assignments/architecto/check-in');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"lat": 1,
"lng": 1
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Supervisor ends a worker's in-progress shift early (on-site initiated early checkout — sickness, employer-ended, sent home, …). Records the reason and category and clocks the worker out.
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/shifts/architecto/early-checkout" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Mitarbeiter erkrankt, nach Hause geschickt.\",
\"category\": \"employer_ended\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/architecto/early-checkout"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Mitarbeiter erkrankt, nach Hause geschickt.",
"category": "employer_ended"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/architecto/early-checkout';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'Mitarbeiter erkrankt, nach Hause geschickt.',
'category' => 'employer_ended',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/architecto/early-checkout');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "Mitarbeiter erkrankt, nach Hause geschickt.",
"category": "employer_ended"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Company modifies an upcoming assigned shift — its scheduled time and/or its location/meeting point — and the assigned worker is notified accordingly ("Schicht geändert" / "Einsatzort geändert").
requires authentication
Only allowed before the shift starts (pending confirmation, confirmed or scheduled).
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/shifts/9c3f5f3d-0123-4abc-b456-426614174000/modify" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"shift_date\": \"2026-07-02\",
\"scheduled_start_time\": \"09:00\",
\"scheduled_end_time\": \"17:00\",
\"location_name\": \"Messe Wien Halle B\",
\"location_address\": \"Messeplatz 1\",
\"location_lat\": \"48.2208\",
\"location_lng\": \"16.4108\",
\"reason\": \"Halle wurde verlegt.\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/9c3f5f3d-0123-4abc-b456-426614174000/modify"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"shift_date": "2026-07-02",
"scheduled_start_time": "09:00",
"scheduled_end_time": "17:00",
"location_name": "Messe Wien Halle B",
"location_address": "Messeplatz 1",
"location_lat": "48.2208",
"location_lng": "16.4108",
"reason": "Halle wurde verlegt."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/9c3f5f3d-0123-4abc-b456-426614174000/modify';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'shift_date' => '2026-07-02',
'scheduled_start_time' => '09:00',
'scheduled_end_time' => '17:00',
'location_name' => 'Messe Wien Halle B',
'location_address' => 'Messeplatz 1',
'location_lat' => '48.2208',
'location_lng' => '16.4108',
'reason' => 'Halle wurde verlegt.',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/9c3f5f3d-0123-4abc-b456-426614174000/modify');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"shift_date": "2026-07-02",
"scheduled_start_time": "09:00",
"scheduled_end_time": "17:00",
"location_name": "Messe Wien Halle B",
"location_address": "Messeplatz 1",
"location_lat": "48.2208",
"location_lng": "16.4108",
"reason": "Halle wurde verlegt."
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List shifts pending time confirmation.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/shifts/pending-confirmation" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/pending-confirmation"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/pending-confirmation';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/pending-confirmation');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"shifts": [
{
"id": "019fd2b8-28df-7265-8b1e-cb5de026e4d7",
"job": {
"id": "019fd2b8-28c4-732f-a94c-fb5a71a7d682",
"title": "Accountant"
},
"employee": {
"id": "019fd2b7-f271-73fd-8268-848be381e136",
"name": "Anna Neuling",
"lhr_synced": false
},
"date": "2026-08-03",
"planned_start": "08:31",
"planned_end": "05:12",
"actual_check_in": null,
"actual_check_out": null,
"worked_minutes": 0,
"break_minutes": 0,
"status": "completed",
"dispute_reason": null,
"hourly_rate": 18.25,
"gross_amount": 0
}
],
"summary": {
"total_shifts": 1,
"total_minutes": 0,
"total_gross": 0
},
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 20,
"total": 1
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Confirm shift worked time.
requires authentication
When a company confirms the worked time, the payout process is triggered via LHR (lohn.at). This is the critical step that initiates employee payment.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/shifts/architecto/confirm" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"actual_minutes\": 1,
\"break_minutes\": 1,
\"note\": \"Beispieltext\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/architecto/confirm"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"actual_minutes": 1,
"break_minutes": 1,
"note": "Beispieltext"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/architecto/confirm';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'actual_minutes' => 1,
'break_minutes' => 1,
'note' => 'Beispieltext',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/architecto/confirm');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"actual_minutes": 1,
"break_minutes": 1,
"note": "Beispieltext"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "Shift time confirmed, payout initiated.",
"data": {
"shift_id": "019fd2b8-a5fe-72da-bca5-e12ff2951c28",
"status": "hours_confirmed",
"actual_minutes": 480,
"gross_amount": 263.36,
"payout_queued": true
}
}
Example response (422, Open requests on the shift):
{
"status": "INVALID_OPERATION",
"message": "Diese Schicht hat noch offene Anfragen. Bitte zuerst alle Anfragen entscheiden.",
"data": {
"pending_requests": [
{
"id": "019f9939-c4c3-70fb-a54e-5ebf63db36d2",
"type": "overtime",
"type_label": "Überstunden"
}
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Dispute shift worked time.
requires authentication
When a company disputes the worked time, the payout is held pending resolution. The dispute must be resolved before the employee can be paid.
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/shifts/architecto/dispute" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"reason\": \"Krankheitsbedingt kurzfristig abgesagt.\",
\"disputed_minutes\": 1
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/shifts/architecto/dispute"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt.",
"disputed_minutes": 1
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/shifts/architecto/dispute';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'reason' => 'Krankheitsbedingt kurzfristig abgesagt.',
'disputed_minutes' => 1,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/shifts/architecto/dispute');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"reason": "Krankheitsbedingt kurzfristig abgesagt.",
"disputed_minutes": 1
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"message": "The shift time has been disputed.",
"data": {
"shift_id": "019fd2b8-a9b8-7256-a83d-365a8c7761c8",
"status": "disputed",
"reason": "Die erfasste Zeit weicht von unserer Aufzeichnung ab."
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Company - Wallet
Organization (Company Portal) endpoints for managing jobs, applicants, shifts, team, and organization profiles. Requires organization-level Bearer token. Some endpoints require approved organization status.
Wallet
Returns the authenticated organization's wallet summary, auto-creating the wallet row on first access via {@see WalletService::walletFor()}.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/wallet" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/wallet"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/wallet';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/wallet');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"balance_cents": 250000,
"blocked_cents": 0,
"available_cents": 250000,
"currency": "EUR",
"has_payment_method": false,
"withdrawable_cents": 0
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Paginated wallet ledger, newest first. Auto-creates the wallet via {@see WalletService::walletFor()} so a fresh organization sees an empty list instead of a 404.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/wallet/transactions" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/wallet/transactions"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/wallet/transactions';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/wallet/transactions');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"transactions": [
{
"id": "019fd2b8-c69e-714a-8069-e4d9c2c222ac",
"type": "topup",
"type_label": "Aufladung",
"amount_cents": 250000,
"balance_after_cents": 250000,
"blocked_after_cents": 0,
"description": "Guthaben für den Testlauf",
"reference_type": null,
"created_at": "2026-08-05T16:19:12+00:00"
}
],
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 20,
"total": 1
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Admin-configured top-up amounts with their fee preview, so the portal can render top-up buttons without duplicating the fee formula client-side.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/wallet/topup-options" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/wallet/topup-options"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/wallet/topup-options';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/wallet/topup-options');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"options": [
{
"amount_cents": 100000,
"platform_fee_cents": 0,
"stripe_fee_cents": 1525,
"vat_cents": 0,
"total_charged_cents": 101525
},
{
"amount_cents": 200000,
"platform_fee_cents": 0,
"stripe_fee_cents": 3025,
"vat_cents": 0,
"total_charged_cents": 203025
},
{
"amount_cents": 500000,
"platform_fee_cents": 0,
"stripe_fee_cents": 7525,
"vat_cents": 0,
"total_charged_cents": 507525
}
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Creates a pending WalletTopup for one of the admin-configured amounts and, when Stripe is configured, opens a hosted Checkout Session for it. The wallet is only credited later — by App\Http\Controllers\StripeWebhookController once `checkout.session.completed` confirms payment.
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/wallet/topup" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"amount_cents\": 1
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/wallet/topup"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"amount_cents": 1
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/wallet/topup';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'amount_cents' => 1,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/wallet/topup');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"amount_cents": 1
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
POST /org/wallet/topup/confirm — settle a top-up right on the checkout return instead of waiting for the async webhook. Looks the top-up up by its checkout session id (scoped to the caller's organisation), asks Stripe for the session's real state and settles it if paid. Idempotent: the shared settle path means a later webhook or the reconcile cron can never double-credit.
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/wallet/topup/confirm" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"session_id\": \"Beispieltext\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/wallet/topup/confirm"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"session_id": "Beispieltext"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/wallet/topup/confirm';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'session_id' => 'Beispieltext',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/wallet/topup/confirm');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"session_id": "Beispieltext"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
POST /org/wallet/topup/cancel — close a top-up the instant the user returns from an abandoned checkout, instead of leaving it pending until the session expires. Safety-first: if Stripe says the session was in fact paid (e.g. the user paid in another tab then hit back), it's settled rather than failed.
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/wallet/topup/cancel" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"session_id\": \"Beispieltext\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/wallet/topup/cancel"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"session_id": "Beispieltext"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/wallet/topup/cancel';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'session_id' => 'Beispieltext',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/wallet/topup/cancel');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"session_id": "Beispieltext"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Paginated top-up history, newest first, with the fee breakdown and whether a receipt PDF is available for download.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/wallet/topups" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/wallet/topups"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/wallet/topups';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/wallet/topups');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"topups": [],
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 20,
"total": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Streams the receipt PDF for a succeeded top-up. Guarded at the route by the `invoices.download` ACL ability (see App\Providers\AclServiceProvider) on top of the org-member auth/2FA/approved guard, and here by ownership + the topup actually having a stored receipt.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/wallet/topups/architecto/receipt" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/wallet/topups/architecto/receipt"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/wallet/topups/architecto/receipt';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/wallet/topups/architecto/receipt');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (503):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"status": "ERROR",
"message": "Service Unavailable",
"data": null,
"errors": [
{
"field": null,
"message": "Service Unavailable"
}
],
"meta": {
"request_id": "cecb0139-a407-44f0-afa8-04001609da18",
"timestamp": "2026-08-21T05:14:35.364603Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
POST /org/wallet/withdraw — return available wallet balance to the card that funded it (Stripe refund). Amounts up to the auto-approval threshold complete instantly; larger ones come back `pending` for an admin to approve.
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/wallet/withdraw" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"amount_cents\": 1
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/wallet/withdraw"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"amount_cents": 1
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/wallet/withdraw';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'amount_cents' => 1,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/wallet/withdraw');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"amount_cents": 1
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
GET /org/wallet/withdrawals — the company's withdrawal history, newest first.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/org/wallet/withdrawals" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/wallet/withdrawals"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/wallet/withdrawals';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/wallet/withdrawals');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"withdrawals": [],
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 20,
"total": 0
}
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
POST /org/wallet/withdrawals/{withdrawalId}/cancel — a company withdraws its own still-pending (over-threshold, awaiting-admin-review) withdrawal request before it's reviewed, releasing the reserved funds back to its available balance immediately.
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/org/wallet/withdrawals/architecto/cancel" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/org/wallet/withdrawals/architecto/cancel"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/org/wallet/withdrawals/architecto/cancel';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/org/wallet/withdrawals/architecto/cancel');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.post(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Employee - Shifts
Endpoints for the mobile application (employee users). All endpoints (except authentication) require a valid Bearer token with 2FA verification.
Shifts
Download / retrieve a shift time record summary for the authenticated employee.
requires authentication
Returns worked hours, break time, and a gross earnings estimate for the shift.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/shifts/architecto/time-record" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/shifts/architecto/time-record"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/shifts/architecto/time-record';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/shifts/architecto/time-record');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"shift_id": "019fd4e7-ff04-72e4-a010-3ff64e0d3e8f",
"shift_date": "2026-08-06",
"scheduled_start_time": "02:30:00",
"scheduled_end_time": "10:30:00",
"clock_in_at": "2026-08-06T02:30:01+00:00",
"clock_out_at": "2026-08-06T10:30:01+00:00",
"total_hours_worked": 8,
"break_minutes": 480,
"net_hours_worked": 0,
"hourly_rate": 22.64,
"gross_amount": 0,
"dispute_type": null
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Employee - Wallet
Endpoints for the mobile application (employee users). All endpoints (except authentication) require a valid Bearer token with 2FA verification.
Wallet
Get the authenticated employee's wallet summary.
requires authentication
Aggregates earnings from completed/confirmed shifts, separating pending and paid amounts.
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/wallet" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/wallet"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/wallet';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/wallet');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"total_earned_gross": 0,
"pending_payout_gross": 0,
"processing_payout_gross": 0,
"paid_gross": 0,
"shifts_completed": 2,
"shifts_pending_payment": 2,
"pending_payments": [
{
"shift_id": "019fd3d3-f998-72c7-affb-87f0986474d4",
"shift_date": "2026-08-03",
"job_title": "Communications Teacher",
"organization_name": "Caritas",
"gross_amount": 0,
"payment_status": "pending",
"expected_payout_by": "2026-08-17"
},
{
"shift_id": "019fd3d3-f98a-70d2-83d5-eba7cae30f9a",
"shift_date": "2026-08-06",
"job_title": "Communications Teacher",
"organization_name": "Caritas",
"gross_amount": 0,
"payment_status": "pending",
"expected_payout_by": "2026-08-20"
}
],
"recent_payments": []
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Paginated payment history for the authenticated worker — the full ledger of paid shifts, beyond the last-5 preview surfaced on the wallet summary.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/wallet/payments?status=paid&per_page=20&page=1" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/wallet/payments"
);
const params = {
"status": "paid",
"per_page": "20",
"page": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/wallet/payments';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'status' => 'paid',
'per_page' => '20',
'page' => '1',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/wallet/payments')
.replace(queryParameters: {
'status': 'paid',
'per_page': '20',
'page': '1',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": [],
"meta": {
"current_page": 1,
"last_page": 1,
"per_page": 20,
"total": 0
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Stream the authenticated worker's legally binding monthly Lohnzettel (Gehaltszettel) for a given period from lohn.at. Distinct from the per-shift Verdienstabrechnung — this is the official monthly payslip.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/wallet/payslip?period=2026-05" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"period\": \"6425-59\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/wallet/payslip"
);
const params = {
"period": "2026-05",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"period": "6425-59"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/wallet/payslip';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'period' => '2026-05',
],
'json' => [
'period' => '6425-59',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/wallet/payslip')
.replace(queryParameters: {
'period': '2026-05',
});
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"period": "6425-59"
};
final response = await http.get(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Example response (200):
PDF file download
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Mobile - Profile
Endpoints for the mobile application (employee users). All endpoints (except authentication) require a valid Bearer token with 2FA verification.
Education
List the authenticated employee's education (Ausbildung) records.
requires authentication
Example request:
curl --request GET \
--get "https://backend-dev.flexxr.at/api/v1/mobile/education" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/education"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/education';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/education');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.get(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Example response (200, Recorded from a live call):
{
"status": "SUCCESS",
"data": {
"education": []
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Add an education (Ausbildung) record for the authenticated employee.
requires authentication
Example request:
curl --request POST \
"https://backend-dev.flexxr.at/api/v1/mobile/education" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"institution\": \"HTL Wien\",
\"degree\": \"Matura\",
\"field_of_study\": \"Elektrotechnik\",
\"level\": \"Matura\",
\"start_year\": 2008,
\"end_year\": 2013,
\"is_completed\": true,
\"document_id\": \"architecto\"
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/education"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"institution": "HTL Wien",
"degree": "Matura",
"field_of_study": "Elektrotechnik",
"level": "Matura",
"start_year": 2008,
"end_year": 2013,
"is_completed": true,
"document_id": "architecto"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/education';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'institution' => 'HTL Wien',
'degree' => 'Matura',
'field_of_study' => 'Elektrotechnik',
'level' => 'Matura',
'start_year' => 2008,
'end_year' => 2013,
'is_completed' => true,
'document_id' => 'architecto',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/education');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"institution": "HTL Wien",
"degree": "Matura",
"field_of_study": "Elektrotechnik",
"level": "Matura",
"start_year": 2008,
"end_year": 2013,
"is_completed": true,
"document_id": "architecto"
};
final response = await http.post(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update one of the authenticated employee's education records.
requires authentication
Example request:
curl --request PUT \
"https://backend-dev.flexxr.at/api/v1/mobile/education/architecto" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"institution\": \"Beispieltext\",
\"degree\": \"Beispieltext\",
\"field_of_study\": \"Beispieltext\",
\"level\": \"Beispieltext\",
\"start_year\": 1,
\"end_year\": 1,
\"is_completed\": true
}"
const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/education/architecto"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"institution": "Beispieltext",
"degree": "Beispieltext",
"field_of_study": "Beispieltext",
"level": "Beispieltext",
"start_year": 1,
"end_year": 1,
"is_completed": true
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/education/architecto';
$response = $client->put(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'institution' => 'Beispieltext',
'degree' => 'Beispieltext',
'field_of_study' => 'Beispieltext',
'level' => 'Beispieltext',
'start_year' => 1,
'end_year' => 1,
'is_completed' => true,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/education/architecto');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
"institution": "Beispieltext",
"degree": "Beispieltext",
"field_of_study": "Beispieltext",
"level": "Beispieltext",
"start_year": 1,
"end_year": 1,
"is_completed": true
};
final response = await http.put(
uri,
headers: headers,
body: jsonEncode(body),
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete one of the authenticated employee's education records.
requires authentication
Example request:
curl --request DELETE \
"https://backend-dev.flexxr.at/api/v1/mobile/education/architecto" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://backend-dev.flexxr.at/api/v1/mobile/education/architecto"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://backend-dev.flexxr.at/api/v1/mobile/education/architecto';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
final uri = Uri.parse('https://backend-dev.flexxr.at/api/v1/mobile/education/architecto');
final headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final response = await http.delete(
uri,
headers: headers,
);
print(jsonDecode(response.body));
}Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.