API v2
Návody
Guides
Celé scénáře krok za krokem – od připojení po poslední požadavek – v curl a v oficiálních knihovnách pro JavaScript, TypeScript, PHP, Javu, Kotlin, C#, Python, Swift, Dart a Go. Každý krok je stejná ukázka jako u operace v referenci, s příkladem odpovědi.
Whole scenarios step by step – from connecting to the last request – in curl and the official libraries for JavaScript, TypeScript, PHP, Java, Kotlin, C#, Python, Swift, Dart and Go. Every step is the same example as at the operation in the reference, with an example answer.
EET 2.0 eviduje ProfirestTržby objednávek placených na místě (hotově nebo kartou kurýrovi či při odběru) i účtenky pokladen zaeviduje do EET 2.0 server Profirestu – při předání, certifikátem provozovny. Online platby se neevidují. Vaše aplikace finanční správě nic neposílá a certifikát nepotřebuje.
EET 2.0 is done by ProfirestThe Profirest server records orders paid on the spot (cash or card to the courier or at pickup) and register receipts in EET 2.0 – at the hand-over, with the restaurant's certificate. Online payments are not recorded. Your application sends nothing to the tax administration and needs no certificate.
Co ukázky předpokládajíSpárovaného klienta oficiální knihovny v proměnné
api – tokeny, obnovu, Idempotency-Key a opakování obstará knihovna (nastavení je
v části Nastavení a chyby a na stránce každé knihovny v nabídce Knihovny). curl ukazuje
čisté HTTP s proměnnými $ACCESS_TOKEN a $STAFF_TOKEN. Všechny ukázky se před vydáním překládají proti skutečným knihovnám.
What the examples assumeA paired client of the official library in the variable
api – the library takes care of tokens, refreshing, Idempotency-Key and retries (setup is
in Setup and errors and on each library's page in the Libraries menu). curl shows plain
HTTP with the variables $ACCESS_TOKEN and $STAFF_TOKEN. Every example is compiled against the real libraries before release.
Každý krok si vyzkoušejteTlačítko ▶ Vyzkoušet u kroku otevře playground s operací a příkladem kroku – v režimu Ukázka hned odpoví příkladem ze smlouvy (nic se neodesílá), naostro pošle skutečný požadavek s vaším tokenem. Ukázky v JavaScriptu spustíte tlačítkem ▶ Spustit přímo v prohlížeči s klientem profirest-api.js.
Try every stepThe ▶ Try it button at a step opens the playground with the step's operation and example – in Example mode it answers at once with the contract's example (nothing is sent), live it sends a real request with your token. Run the JavaScript examples with ▶ Run right in the browser with the profirest-api.js client.
Základy
Basics
Nastavení a chyby
Setup and errors
Kroky scénářů níže volají oficiální knihovnu vybraného jazyka (curl ukazuje čisté HTTP). Knihovna přidá token a obnoví ho, pošle a přečte JSON a chybu promění ve výjimku s code z katalogu chyb. Rozhodujte se podle code, ne podle HTTP stavu. Instalace a celá reference klienta: nabídka Knihovny nahoře.
The scenario steps below call the official library of the chosen language (curl shows plain HTTP). The library adds and refreshes the token, sends and reads JSON and turns an error into an exception with the code from the error catalog. Branch on code, not on the HTTP status. Installation and the full client reference: the Libraries menu at the top.
# adresa API: https://api.mujprofirest.cz
export ACCESS_TOKEN='pfa_…' # z /oauth/token
curl "https://api.mujprofirest.cz/v2/" -H "Authorization: Bearer $ACCESS_TOKEN"
# chyba přijde jako application/problem+json – rozhodujte se podle "code"
# {"type":"https://api.mujprofirest.cz/v2/docs/errors#not_found","status":404,"code":"not_found",…}# API address: https://api.mujprofirest.cz
export ACCESS_TOKEN='pfa_…' # from /oauth/token
curl "https://api.mujprofirest.cz/v2/" -H "Authorization: Bearer $ACCESS_TOKEN"
# an error comes as application/problem+json – branch on "code"
# {"type":"https://api.mujprofirest.cz/v2/docs/errors#not_found","status":404,"code":"not_found",…}<script src="https://api.mujprofirest.cz/v2/profirest-api.min.js"></script>
<script>
const api = new ProfirestApi({ clientId: 'profirest-pos' }); // tokeny přežijí restart; chraňte je jako heslo (localStorage)
if (!api.isPaired()) { // jen poprvé: kód potvrdí vedoucí v administraci
const pairing = await api.pair({ scope: 'restaurants:read catalog:read orders:write', deviceName: 'Pokladna 1' });
showCode(pairing.userCode);
await pairing.connected;
}
try {
const restaurants = await api.all('/restaurants');
} catch (e) {
if (e.code === 'not_paired') showPairing(); // kód z katalogu chyb
}
</script><script src="https://api.mujprofirest.cz/v2/profirest-api.min.js"></script>
<script>
const api = new ProfirestApi({ clientId: 'profirest-pos' }); // tokens survive a restart; protect them like a password (localStorage)
if (!api.isPaired()) { // only the first time: a manager confirms the code in the administration
const pairing = await api.pair({ scope: 'restaurants:read catalog:read orders:write', deviceName: 'Pokladna 1' });
showCode(pairing.userCode);
await pairing.connected;
}
try {
const restaurants = await api.all('/restaurants');
} catch (e) {
if (e.code === 'not_paired') showPairing(); // the code from the error catalog
}
</script>import ProfirestApi = require('./profirest-api'); // + profirest-api.d.ts
const api = new ProfirestApi({ clientId: 'profirest-pos' });
if (!api.isPaired()) { // jen poprvé: kód potvrdí vedoucí v administraci
const pairing = await api.pair({ scope: 'restaurants:read catalog:read orders:write', deviceName: 'Pokladna 1' });
showCode(pairing.userCode);
await pairing.connected;
}
try {
const restaurants = await api.all('/restaurants'); // Restaurant[]
} catch (e) {
if (e instanceof ProfirestApi.ApiError && e.code === 'not_paired') showPairing(); // kód z katalogu chyb
}import ProfirestApi = require('./profirest-api'); // + profirest-api.d.ts
const api = new ProfirestApi({ clientId: 'profirest-pos' });
if (!api.isPaired()) { // only the first time: a manager confirms the code in the administration
const pairing = await api.pair({ scope: 'restaurants:read catalog:read orders:write', deviceName: 'Pokladna 1' });
showCode(pairing.userCode);
await pairing.connected;
}
try {
const restaurants = await api.all('/restaurants'); // Restaurant[]
} catch (e) {
if (e instanceof ProfirestApi.ApiError && e.code === 'not_paired') showPairing(); // the code from the error catalog
}<?php
// composer require profirest/api-client
use Profirest\Api\{ApiError, Client};
use Profirest\Api\Storage\FileStorage;
$api = new Client(clientId: 'profirest-pos',
storage: new FileStorage('/var/lib/app/profirest.json')); // tokeny přežijí restart; chraňte je jako heslo
if (!$api->isPaired()) { // jen poprvé: kód potvrdí vedoucí v administraci
$pairing = $api->pair(scope: 'restaurants:read catalog:read orders:write', deviceName: 'Kiosek 1');
echo $pairing->userCode;
$pairing->wait();
}
try {
$restaurants = $api->all('/restaurants');
} catch (ApiError $e) {
if ($e->errorCode === 'not_paired') { showPairing(); } // kód z katalogu chyb
}<?php
// composer require profirest/api-client
use Profirest\Api\{ApiError, Client};
use Profirest\Api\Storage\FileStorage;
$api = new Client(clientId: 'profirest-pos',
storage: new FileStorage('/var/lib/app/profirest.json')); // tokens survive a restart; protect them like a password
if (!$api->isPaired()) { // only the first time: a manager confirms the code in the administration
$pairing = $api->pair(scope: 'restaurants:read catalog:read orders:write', deviceName: 'Kiosek 1');
echo $pairing->userCode;
$pairing->wait();
}
try {
$restaurants = $api->all('/restaurants');
} catch (ApiError $e) {
if ($e->errorCode === 'not_paired') { showPairing(); } // the code from the error catalog
}// implementation(files("libs/profirest-api-1.0.0.jar")) – volání blokuje, ne na hlavním vlákně
ProfirestApi api = ProfirestApi.builder()
.clientId("profirest-pos")
.storage(new FileStorage("profirest.json")) // tokeny přežijí restart; chraňte je jako heslo
.build();
if (!api.isPaired()) { // jen poprvé: kód potvrdí vedoucí v administraci
Pairing pairing = api.pair(PairOptions.builder().scope("restaurants:read catalog:read orders:write").deviceName("Pokladna 1").build());
showCode(pairing.getUserCode());
pairing.awaitConnected();
}
try {
List<Restaurant> restaurants = api.all("/restaurants", null, Restaurant::fromJson);
} catch (ApiException e) {
if ("not_paired".equals(e.getCode())) showPairing(); // kód z katalogu chyb
}// implementation(files("libs/profirest-api-1.0.0.jar")) – volání blokuje, ne na hlavním vlákně
ProfirestApi api = ProfirestApi.builder()
.clientId("profirest-pos")
.storage(new FileStorage("profirest.json")) // tokens survive a restart; protect them like a password
.build();
if (!api.isPaired()) { // only the first time: a manager confirms the code in the administration
Pairing pairing = api.pair(PairOptions.builder().scope("restaurants:read catalog:read orders:write").deviceName("Pokladna 1").build());
showCode(pairing.getUserCode());
pairing.awaitConnected();
}
try {
List<Restaurant> restaurants = api.all("/restaurants", null, Restaurant::fromJson);
} catch (ApiException e) {
if ("not_paired".equals(e.getCode())) showPairing(); // the code from the error catalog
}// implementation(files("libs/profirest-api-1.0.0.jar"))
val api = ProfirestApi.builder()
.clientId("profirest-pos")
.storage(SharedPreferencesStorage(context)) // tokeny přežijí restart; chraňte je jako heslo
.build()
suspend fun start() = withContext(Dispatchers.IO) {
if (!api.isPaired) { // jen poprvé: kód potvrdí vedoucí v administraci
val pairing = api.pair(PairOptions.builder().scope("restaurants:read catalog:read orders:write").deviceName("Pokladna 1").build())
showCode(pairing.userCode)
pairing.awaitConnected()
}
try {
val restaurants = api.all("/restaurants", null, Restaurant::fromJson)
} catch (e: ApiException) {
if (e.code == "not_paired") showPairing() // kód z katalogu chyb
}
}// implementation(files("libs/profirest-api-1.0.0.jar"))
val api = ProfirestApi.builder()
.clientId("profirest-pos")
.storage(SharedPreferencesStorage(context)) // tokens survive a restart; protect them like a password
.build()
suspend fun start() = withContext(Dispatchers.IO) {
if (!api.isPaired) { // only the first time: a manager confirms the code in the administration
val pairing = api.pair(PairOptions.builder().scope("restaurants:read catalog:read orders:write").deviceName("Pokladna 1").build())
showCode(pairing.userCode)
pairing.awaitConnected()
}
try {
val restaurants = api.all("/restaurants", null, Restaurant::fromJson)
} catch (e: ApiException) {
if (e.code == "not_paired") showPairing() // the code from the error catalog
}
}// dotnet add package Profirest.Api
using Profirest.Api;
using Profirest.Api.Models;
using Profirest.Api.Storage;
var api = new ProfirestApi(new ProfirestApiOptions
{
ClientId = "profirest-pos",
Storage = new FileTokenStorage("profirest.json"), // tokeny přežijí restart; chraňte je jako heslo
});
if (!api.IsPaired) // jen poprvé: kód potvrdí vedoucí v administraci
{
var pairing = await api.PairAsync(new PairOptions { Scope = "restaurants:read catalog:read orders:write", DeviceName = "Pokladna 1" });
ShowCode(pairing.UserCode);
await pairing.Connected;
}
try
{
List<Restaurant> restaurants = await api.AllAsync<Restaurant>("/restaurants");
}
catch (ProfirestApiException e) when (e.Code == ErrorCodes.NotPaired) // kód z katalogu chyb
{
ShowPairing();
}// dotnet add package Profirest.Api
using Profirest.Api;
using Profirest.Api.Models;
using Profirest.Api.Storage;
var api = new ProfirestApi(new ProfirestApiOptions
{
ClientId = "profirest-pos",
Storage = new FileTokenStorage("profirest.json"), // tokens survive a restart; protect them like a password
});
if (!api.IsPaired) // only the first time: a manager confirms the code in the administration
{
var pairing = await api.PairAsync(new PairOptions { Scope = "restaurants:read catalog:read orders:write", DeviceName = "Pokladna 1" });
ShowCode(pairing.UserCode);
await pairing.Connected;
}
try
{
List<Restaurant> restaurants = await api.AllAsync<Restaurant>("/restaurants");
}
catch (ProfirestApiException e) when (e.Code == ErrorCodes.NotPaired) // the code from the error catalog
{
ShowPairing();
}# pip install profirest-api
from profirest_api import ApiError, FileStorage, ProfirestApi
api = ProfirestApi(client_id='profirest-pos',
storage=FileStorage('/var/lib/app/profirest.json')) # tokeny přežijí restart; chraňte je jako heslo
if not api.is_paired(): # jen poprvé: kód potvrdí vedoucí v administraci
pairing = api.pair(scope='restaurants:read catalog:read orders:write', device_name='Kiosek 1')
print(pairing.user_code)
pairing.wait()
try:
restaurants = api.all('/restaurants')
except ApiError as e:
if e.code == 'not_paired': # kód z katalogu chyb
show_pairing()# pip install profirest-api
from profirest_api import ApiError, FileStorage, ProfirestApi
api = ProfirestApi(client_id='profirest-pos',
storage=FileStorage('/var/lib/app/profirest.json')) # tokens survive a restart; protect them like a password
if not api.is_paired(): # only the first time: a manager confirms the code in the administration
pairing = api.pair(scope='restaurants:read catalog:read orders:write', device_name='Kiosek 1')
print(pairing.user_code)
pairing.wait()
try:
restaurants = api.all('/restaurants')
except ApiError as e:
if e.code == 'not_paired': # the code from the error catalog
show_pairing()// Package.swift: .package(path: "profirest-api-swift-1.0.0"), knihovna ProfirestAPI
import ProfirestAPI
let api = ProfirestApi(options: .init(clientID: "profirest-pos",
storage: KeychainTokenStorage())) // tokeny přežijí restart; chraňte je jako heslo (Klíčenka)
if !api.isPaired { // jen poprvé: kód potvrdí vedoucí v administraci
let pairing = try await api.pair(scope: "restaurants:read catalog:read orders:write", deviceName: "Pokladna 1")
showCode(pairing.userCode)
_ = try await pairing.connected()
}
do {
let restaurants: [Restaurant] = try await api.all("/restaurants")
} catch let error as ProfirestAPIError where error.code == ErrorCode.notPaired { // kód z katalogu chyb
showPairing()
}// Package.swift: .package(path: "profirest-api-swift-1.0.0"), knihovna ProfirestAPI
import ProfirestAPI
let api = ProfirestApi(options: .init(clientID: "profirest-pos",
storage: KeychainTokenStorage())) // tokens survive a restart; protect them like a password (Klíčenka)
if !api.isPaired { // only the first time: a manager confirms the code in the administration
let pairing = try await api.pair(scope: "restaurants:read catalog:read orders:write", deviceName: "Pokladna 1")
showCode(pairing.userCode)
_ = try await pairing.connected()
}
do {
let restaurants: [Restaurant] = try await api.all("/restaurants")
} catch let error as ProfirestAPIError where error.code == ErrorCode.notPaired { // the code from the error catalog
showPairing()
}// pubspec.yaml: profirest_api: {path: ../profirest-api-dart-1.0.0}
import 'package:profirest_api/profirest_api.dart';
import 'package:profirest_api/io.dart'; // FileStorage (ne na webu)
import 'package:profirest_api/models.dart' as pr; // modely (volitelné)
final api = ProfirestApi(clientId: 'profirest-pos', storage: FileStorage('profirest.json')); // tokeny přežijí restart; chraňte je jako heslo
Future<void> start() async {
if (!await api.isPaired()) { // jen poprvé: kód potvrdí vedoucí v administraci
final pairing = await api.pair(scope: 'restaurants:read catalog:read orders:write', deviceName: 'Pokladna 1');
showCode(pairing.userCode);
await pairing.connected;
}
try {
final restaurants = await api.all('/restaurants');
} on ApiError catch (e) {
if (e.code == 'not_paired') showPairing(); // kód z katalogu chyb
}
}// pubspec.yaml: profirest_api: {path: ../profirest-api-dart-1.0.0}
import 'package:profirest_api/profirest_api.dart';
import 'package:profirest_api/io.dart'; // FileStorage (ne na webu)
import 'package:profirest_api/models.dart' as pr; // modely (volitelné)
final api = ProfirestApi(clientId: 'profirest-pos', storage: FileStorage('profirest.json')); // tokens survive a restart; protect them like a password
Future<void> start() async {
if (!await api.isPaired()) { // only the first time: a manager confirms the code in the administration
final pairing = await api.pair(scope: 'restaurants:read catalog:read orders:write', deviceName: 'Pokladna 1');
showCode(pairing.userCode);
await pairing.connected;
}
try {
final restaurants = await api.all('/restaurants');
} on ApiError catch (e) {
if (e.code == 'not_paired') showPairing(); // the code from the error catalog
}
}// import profirest "github.com/profirest/profirest-api-go" (+ ".../model")
api := profirest.New(profirest.Options{
ClientID: "profirest-pos",
Storage: profirest.NewFileStorage("profirest.json"), // tokeny přežijí restart; chraňte je jako heslo
})
if !api.IsPaired() { // jen poprvé: kód potvrdí vedoucí v administraci
pairing, err := api.Pair(ctx, profirest.PairOptions{Scope: "restaurants:read catalog:read orders:write", DeviceName: "Pokladna 1"})
if err != nil {
return err
}
showCode(pairing.UserCode)
if _, err := pairing.Wait(ctx); err != nil {
return err
}
}
restaurants, err := profirest.All[model.Restaurant](ctx, api, "/restaurants", nil)
var apiErr *profirest.APIError
if errors.As(err, &apiErr) && apiErr.Code == profirest.CodeNotPaired { // kód z katalogu chyb
showPairing()
}// import profirest "github.com/profirest/profirest-api-go" (+ ".../model")
api := profirest.New(profirest.Options{
ClientID: "profirest-pos",
Storage: profirest.NewFileStorage("profirest.json"), // tokens survive a restart; protect them like a password
})
if !api.IsPaired() { // only the first time: a manager confirms the code in the administration
pairing, err := api.Pair(ctx, profirest.PairOptions{Scope: "restaurants:read catalog:read orders:write", DeviceName: "Pokladna 1"})
if err != nil {
return err
}
showCode(pairing.UserCode)
if _, err := pairing.Wait(ctx); err != nil {
return err
}
}
restaurants, err := profirest.All[model.Restaurant](ctx, api, "/restaurants", nil)
var apiErr *profirest.APIError
if errors.As(err, &apiErr) && apiErr.Code == profirest.CodeNotPaired { // the code from the error catalog
showPairing()
}Základy
Basics
Opakování se stejným klíčem
Retries with the same key
Každý POST nese Idempotency-Key; při opakování stejného požadavku jde stejný klíč a server druhý záznam nezaloží. Knihovny to dělají samy: opakují výpadek sítě, 429, 409 idempotency_in_progress a stavy 500–504 a čekají podle Retry-After. Když požadavek opakujete vy (třeba po restartu aplikace), předejte vlastní klíč uložený u záznamu. Klíč, který vytvoří knihovna, žije jen v paměti procesu – po pádu aplikace ho nemáte. Vlastní klíč proto vytvořte (nebo odvoďte z ID záznamu) a uložte k záznamu dřív, než požadavek odešlete; server výsledek pod klíčem drží 24 hodin a stejný klíč s jiným tělem odmítne (422 idempotency_key_mismatch). Objednávka má navíc dvě pojistky nezávislé na klíči: kalkulaci jde použít jen jednou (409 quote_already_used) a vaše external_id je trvalé (409 external_id_conflict) – obě chyby nesou v existing_id ID už založené objednávky.
Every POST carries an Idempotency-Key; a repeat of the same request sends the same key and the server never creates a second record. The libraries do it themselves: they retry a network failure, 429, 409 idempotency_in_progress and the statuses 500–504 and wait as Retry-After says. When you repeat a request yourself (say after an application restart), pass your own key stored with the record. The key a library makes lives only in the memory of the process – after a crash you do not have it. So create your own key (or derive it from the ID of the record) and store it with the record before you send the request; the server keeps the result under the key for 24 hours and rejects the same key with another body (422 idempotency_key_mismatch). An order has two more guards that do not depend on the key: a quote can be used only once (409 quote_already_used) and your external_id is permanent (409 external_id_conflict) – both errors carry the ID of the existing order in existing_id.
# stejný klíč při každém opakování – server druhou nabídku nezaloží
KEY=$(uuidgen)
curl "https://api.mujprofirest.cz/v2/restaurants/123/quotes" \
-H "Authorization: Bearer $ACCESS_TOKEN" -H "Idempotency-Key: $KEY" -H "Content-Type: application/json" \
-d '{"fulfillment": {"type": "pickup"}, "items": [{"product_id": "4567", "quantity": 2}]}'
# 429 nebo 503: počkejte Retry-After sekund a pošlete totéž se stejným $KEY# the same key on every retry – the server creates no second quote
KEY=$(uuidgen)
curl "https://api.mujprofirest.cz/v2/restaurants/123/quotes" \
-H "Authorization: Bearer $ACCESS_TOKEN" -H "Idempotency-Key: $KEY" -H "Content-Type: application/json" \
-d '{"fulfillment": {"type": "pickup"}, "items": [{"product_id": "4567", "quantity": 2}]}'
# 429 or 503: wait Retry-After seconds and send the same with the same $KEY// knihovna opakuje sama: výpadek sítě, timeout, 429, 409 idempotency_in_progress a 5xx – se stejným Idempotency-Key
const quote = await api.post('/restaurants/123/quotes', basket);
// vlastní klíč z ID záznamu, který jste uložili před odesláním – opakování i po restartu aplikace nic nezdvojí
const order = await api.post('/restaurants/123/orders', body, { idempotencyKey: 'order-' + localId });// the library retries itself: a network failure, a timeout, 429, 409 idempotency_in_progress and 5xx – with the same Idempotency-Key
const quote = await api.post('/restaurants/123/quotes', basket);
// your own key from the ID of the record you stored before sending – a retry even after an application restart duplicates nothing
const order = await api.post('/restaurants/123/orders', body, { idempotencyKey: 'order-' + localId });// knihovna opakuje sama: výpadek sítě, timeout, 429, 409 idempotency_in_progress a 5xx – se stejným Idempotency-Key
const quote = await api.post('/restaurants/123/quotes', basket); // Quote
// vlastní klíč z ID záznamu, který jste uložili před odesláním – opakování i po restartu aplikace nic nezdvojí
const order = await api.post('/restaurants/123/orders', body, { idempotencyKey: 'order-' + localId });// the library retries itself: a network failure, a timeout, 429, 409 idempotency_in_progress and 5xx – with the same Idempotency-Key
const quote = await api.post('/restaurants/123/quotes', basket); // Quote
// your own key from the ID of the record you stored before sending – a retry even after an application restart duplicates nothing
const order = await api.post('/restaurants/123/orders', body, { idempotencyKey: 'order-' + localId });// knihovna opakuje sama: výpadek sítě, timeout, 429, 409 idempotency_in_progress a 5xx – se stejným Idempotency-Key
$quote = $api->post('/restaurants/123/quotes', $basket);
// vlastní klíč z ID záznamu, který jste uložili před odesláním – opakování i po restartu aplikace nic nezdvojí
$order = $api->post('/restaurants/123/orders', $body, ['idempotencyKey' => 'order-' . $localId]);// the library retries itself: a network failure, a timeout, 429, 409 idempotency_in_progress and 5xx – with the same Idempotency-Key
$quote = $api->post('/restaurants/123/quotes', $basket);
// your own key from the ID of the record you stored before sending – a retry even after an application restart duplicates nothing
$order = $api->post('/restaurants/123/orders', $body, ['idempotencyKey' => 'order-' . $localId]);// knihovna opakuje sama: výpadek sítě, timeout, 429, 409 idempotency_in_progress a 5xx – se stejným Idempotency-Key
Quote quote = api.post("/restaurants/123/quotes", basket, Quote::fromJson);
// vlastní klíč z ID záznamu, který jste uložili před odesláním – opakování i po restartu aplikace nic nezdvojí
Order order = api.post("/restaurants/123/orders", body,
RequestOptions.builder().idempotencyKey("order-" + localId).build(), Order::fromJson);// the library retries itself: a network failure, a timeout, 429, 409 idempotency_in_progress and 5xx – with the same Idempotency-Key
Quote quote = api.post("/restaurants/123/quotes", basket, Quote::fromJson);
// your own key from the ID of the record you stored before sending – a retry even after an application restart duplicates nothing
Order order = api.post("/restaurants/123/orders", body,
RequestOptions.builder().idempotencyKey("order-" + localId).build(), Order::fromJson);// knihovna opakuje sama: výpadek sítě, timeout, 429, 409 idempotency_in_progress a 5xx – se stejným Idempotency-Key
val quote = api.post("/restaurants/123/quotes", basket, Quote::fromJson)
// vlastní klíč z ID záznamu, který jste uložili před odesláním – opakování i po restartu aplikace nic nezdvojí
val order = api.post("/restaurants/123/orders", body,
RequestOptions.builder().idempotencyKey("order-$localId").build(), Order::fromJson)// the library retries itself: a network failure, a timeout, 429, 409 idempotency_in_progress and 5xx – with the same Idempotency-Key
val quote = api.post("/restaurants/123/quotes", basket, Quote::fromJson)
// your own key from the ID of the record you stored before sending – a retry even after an application restart duplicates nothing
val order = api.post("/restaurants/123/orders", body,
RequestOptions.builder().idempotencyKey("order-$localId").build(), Order::fromJson)// knihovna opakuje sama: výpadek sítě, timeout, 429, 409 idempotency_in_progress a 5xx – se stejným Idempotency-Key
var quote = await api.PostAsync<Quote>("/restaurants/123/quotes", basket);
// vlastní klíč z ID záznamu, který jste uložili před odesláním – opakování i po restartu aplikace nic nezdvojí
var order = await api.PostAsync<Order>("/restaurants/123/orders", body,
new RequestOptions { IdempotencyKey = "order-" + localId });// the library retries itself: a network failure, a timeout, 429, 409 idempotency_in_progress and 5xx – with the same Idempotency-Key
var quote = await api.PostAsync<Quote>("/restaurants/123/quotes", basket);
// your own key from the ID of the record you stored before sending – a retry even after an application restart duplicates nothing
var order = await api.PostAsync<Order>("/restaurants/123/orders", body,
new RequestOptions { IdempotencyKey = "order-" + localId });# knihovna opakuje sama: výpadek sítě, timeout, 429, 409 idempotency_in_progress a 5xx – se stejným Idempotency-Key
quote = api.post('/restaurants/123/quotes', basket)
# vlastní klíč z ID záznamu, který jste uložili před odesláním – opakování i po restartu aplikace nic nezdvojí
order = api.post('/restaurants/123/orders', body, idempotency_key=f'order-{local_id}')# the library retries itself: a network failure, a timeout, 429, 409 idempotency_in_progress and 5xx – with the same Idempotency-Key
quote = api.post('/restaurants/123/quotes', basket)
# your own key from the ID of the record you stored before sending – a retry even after an application restart duplicates nothing
order = api.post('/restaurants/123/orders', body, idempotency_key=f'order-{local_id}')// knihovna opakuje sama: výpadek sítě, timeout, 429, 409 idempotency_in_progress a 5xx – se stejným Idempotency-Key
let quote: Quote = try await api.post("/restaurants/123/quotes", body: basket)
// vlastní klíč z ID záznamu, který jste uložili před odesláním – opakování i po restartu aplikace nic nezdvojí
let order: Order = try await api.post("/restaurants/123/orders", body: body,
options: .init(idempotencyKey: .key("order-\(localID)")))// the library retries itself: a network failure, a timeout, 429, 409 idempotency_in_progress and 5xx – with the same Idempotency-Key
let quote: Quote = try await api.post("/restaurants/123/quotes", body: basket)
// your own key from the ID of the record you stored before sending – a retry even after an application restart duplicates nothing
let order: Order = try await api.post("/restaurants/123/orders", body: body,
options: .init(idempotencyKey: .key("order-\(localID)")))// knihovna opakuje sama: výpadek sítě, timeout, 429, 409 idempotency_in_progress a 5xx – se stejným Idempotency-Key
final quote = pr.Quote.fromJson(await api.post('/restaurants/123/quotes', basket));
// vlastní klíč z ID záznamu, který jste uložili před odesláním – opakování i po restartu aplikace nic nezdvojí
final order = pr.Order.fromJson(await api.post('/restaurants/123/orders', body, idempotencyKey: 'order-$localId'));// the library retries itself: a network failure, a timeout, 429, 409 idempotency_in_progress and 5xx – with the same Idempotency-Key
final quote = pr.Quote.fromJson(await api.post('/restaurants/123/quotes', basket));
// your own key from the ID of the record you stored before sending – a retry even after an application restart duplicates nothing
final order = pr.Order.fromJson(await api.post('/restaurants/123/orders', body, idempotencyKey: 'order-$localId'));// knihovna opakuje sama: výpadek sítě, timeout, 429, 409 idempotency_in_progress a 5xx – se stejným Idempotency-Key
res, err := api.Post(ctx, "/restaurants/123/quotes", basket, nil)
// vlastní klíč z ID záznamu, který jste uložili před odesláním – opakování i po restartu aplikace nic nezdvojí
res, err = api.Post(ctx, "/restaurants/123/orders", body, &profirest.RequestOptions{IdempotencyKey: "order-" + localID})// the library retries itself: a network failure, a timeout, 429, 409 idempotency_in_progress and 5xx – with the same Idempotency-Key
res, err := api.Post(ctx, "/restaurants/123/quotes", basket, nil)
// your own key from the ID of the record you stored before sending – a retry even after an application restart duplicates nothing
res, err = api.Post(ctx, "/restaurants/123/orders", body, &profirest.RequestOptions{IdempotencyKey: "order-" + localID})Základy
Basics
Stránkování
Paging
Seznamy vrací {"data": [...], "next_cursor": "..."}. Knihovny projdou stránky samy – všechny položky najednou, nebo stránku po stránce; konec je stránka bez next_cursor nebo prázdná stránka. Kurzor nikdy neskládejte sami.
Lists return {"data": [...], "next_cursor": "..."}. The libraries walk the pages themselves – all items at once, or page by page; the end is a page without next_cursor or an empty page. Never build a cursor yourself.
# další stránka jen s next_cursor z předchozí odpovědi; kurzor nikdy neskládejte sami
curl "https://api.mujprofirest.cz/v2/restaurants/123/staff?limit=50" -H "Authorization: Bearer $ACCESS_TOKEN"
curl "https://api.mujprofirest.cz/v2/restaurants/123/staff?limit=50&cursor=$NEXT_CURSOR" -H "Authorization: Bearer $ACCESS_TOKEN"# the next page only with next_cursor from the previous answer; never build a cursor yourself
curl "https://api.mujprofirest.cz/v2/restaurants/123/staff?limit=50" -H "Authorization: Bearer $ACCESS_TOKEN"
curl "https://api.mujprofirest.cz/v2/restaurants/123/staff?limit=50&cursor=$NEXT_CURSOR" -H "Authorization: Bearer $ACCESS_TOKEN"const staff = await api.all('/restaurants/123/staff'); // všechny položky všech stránek
for await (const page of api.pages('/restaurants/123/staff', { query: { limit: 50 } })) { // nebo stránku po stránce
render(page.data);
}const staff = await api.all('/restaurants/123/staff'); // all items of all pages
for await (const page of api.pages('/restaurants/123/staff', { query: { limit: 50 } })) { // or page by page
render(page.data);
}const staff = await api.all(`/restaurants/${rid}/staff`); // StaffMember[] – všechny položky všech stránek
for await (const page of api.pages(`/restaurants/${rid}/staff`, { query: { limit: 50 } })) { // nebo stránku po stránce
render(page.data); // StaffMemberPage
}const staff = await api.all(`/restaurants/${rid}/staff`); // StaffMember[] – all items of all pages
for await (const page of api.pages(`/restaurants/${rid}/staff`, { query: { limit: 50 } })) { // or page by page
render(page.data); // StaffMemberPage
}$staff = $api->all('/restaurants/123/staff'); // všechny položky všech stránek
foreach ($api->pages('/restaurants/123/staff', ['query' => ['limit' => 50]]) as $page) { // nebo stránku po stránce
render($page['data']);
}$staff = $api->all('/restaurants/123/staff'); // all items of all pages
foreach ($api->pages('/restaurants/123/staff', ['query' => ['limit' => 50]]) as $page) { // or page by page
render($page['data']);
}List<StaffMember> staff = api.all("/restaurants/123/staff", null, StaffMember::fromJson); // všechny položky všech stránek
for (StaffMemberPage page : api.pages("/restaurants/123/staff",
RequestOptions.builder().query("limit", 50).build(), StaffMemberPage::fromJson)) { // nebo stránku po stránce
render(page.data);
}List<StaffMember> staff = api.all("/restaurants/123/staff", null, StaffMember::fromJson); // all items of all pages
for (StaffMemberPage page : api.pages("/restaurants/123/staff",
RequestOptions.builder().query("limit", 50).build(), StaffMemberPage::fromJson)) { // or page by page
render(page.data);
}val staff = api.all("/restaurants/123/staff", null, StaffMember::fromJson) // všechny položky všech stránek
for (page in api.pages("/restaurants/123/staff", RequestOptions.builder().query("limit", 50).build(),
StaffMemberPage::fromJson)) { // nebo stránku po stránce
render(page.data)
}val staff = api.all("/restaurants/123/staff", null, StaffMember::fromJson) // all items of all pages
for (page in api.pages("/restaurants/123/staff", RequestOptions.builder().query("limit", 50).build(),
StaffMemberPage::fromJson)) { // or page by page
render(page.data)
}List<StaffMember> staff = await api.AllAsync<StaffMember>("/restaurants/123/staff"); // všechny položky všech stránek
await foreach (StaffMemberPage page in api.PagesAsync<StaffMemberPage>("/restaurants/123/staff")) // nebo stránku po stránce
{
Render(page.Data);
}List<StaffMember> staff = await api.AllAsync<StaffMember>("/restaurants/123/staff"); // all items of all pages
await foreach (StaffMemberPage page in api.PagesAsync<StaffMemberPage>("/restaurants/123/staff")) // or page by page
{
Render(page.Data);
}staff = api.all('/restaurants/123/staff') # všechny položky všech stránek
for page in api.pages('/restaurants/123/staff', {'limit': 50}): # nebo stránku po stránce
render(page['data'])staff = api.all('/restaurants/123/staff') # all items of all pages
for page in api.pages('/restaurants/123/staff', {'limit': 50}): # or page by page
render(page['data'])let staff: [StaffMember] = try await api.all("/restaurants/123/staff") // všechny položky všech stránek
for try await page in api.pages("/restaurants/123/staff", as: StaffMemberPage.self) { // nebo stránku po stránce
render(page.data)
}let staff: [StaffMember] = try await api.all("/restaurants/123/staff") // all items of all pages
for try await page in api.pages("/restaurants/123/staff", as: StaffMemberPage.self) { // or page by page
render(page.data)
}final staff = await api.all('/restaurants/123/staff'); // všechny položky všech stránek
await for (final page in api.pages('/restaurants/123/staff', query: {'limit': '50'})) { // nebo stránku po stránce
render(page['data']);
}final staff = await api.all('/restaurants/123/staff'); // all items of all pages
await for (final page in api.pages('/restaurants/123/staff', query: {'limit': '50'})) { // or page by page
render(page['data']);
}staff, err := profirest.All[model.StaffMember](ctx, api, "/restaurants/123/staff", nil) // všechny položky všech stránek
for page, err := range api.Pages(ctx, "/restaurants/123/staff", &profirest.RequestOptions{Query: map[string]any{"limit": 50}}) { // nebo stránku po stránce
if err != nil {
return err
}
render(page.Data)
}staff, err := profirest.All[model.StaffMember](ctx, api, "/restaurants/123/staff", nil) // all items of all pages
for page, err := range api.Pages(ctx, "/restaurants/123/staff", &profirest.RequestOptions{Query: map[string]any{"limit": 50}}) { // or page by page
if err != nil {
return err
}
render(page.Data)
}Základy
Basics
Proud událostí
The event feed
GET /events vrací změny v pořadí, v jakém nastaly; next_cursor tu nikdy není null. Tytéž události posílá živě GET /events/stream (Server-Sent Events) – bez dotazování, se stejným kurzorem v id každé zprávy; když proud neběží (503, stream_url je null), čte se GET /events. Knihovny (watchEvents) mezi nimi přepínají samy: čtou proud, a když neběží, ptají se GET /events a o proud se pokusí znovu za Retry-After. Čtou dokola a kurzor uloží až po zpracování událostí – nic se tak neztratí, jen může přijít podruhé.
GET /events returns the changes in the order they happened; next_cursor is never null here. GET /events/stream (Server-Sent Events) sends the same events live – without polling, with the same cursor in the id of every message; when the stream is not running (503, stream_url is null), read GET /events. The libraries (watchEvents) switch between them by themselves: they read the stream, and when it does not run they ask GET /events and try the stream again after Retry-After. They read in a loop and store the cursor only after processing the events – nothing gets lost, an event may only come twice.
# bez kurzoru vrátí next_cursor na aktuálním konci; pak se ptejte s ním a ukládejte nový
curl "https://api.mujprofirest.cz/v2/events?restaurant_id=123" -H "Authorization: Bearer $ACCESS_TOKEN"
curl "https://api.mujprofirest.cz/v2/events?restaurant_id=123&cursor=$CURSOR" -H "Authorization: Bearer $ACCESS_TOKEN"
# živě (SSE): id každé zprávy je kurzor; po výpadku pokračujte s posledním v Last-Event-ID
curl -N "https://api.mujprofirest.cz/v2/events/stream?restaurant_id=123" -H "Authorization: Bearer $ACCESS_TOKEN" -H "Last-Event-ID: $CURSOR"# without a cursor it returns next_cursor at the current end; then ask with it and store the new one
curl "https://api.mujprofirest.cz/v2/events?restaurant_id=123" -H "Authorization: Bearer $ACCESS_TOKEN"
curl "https://api.mujprofirest.cz/v2/events?restaurant_id=123&cursor=$CURSOR" -H "Authorization: Bearer $ACCESS_TOKEN"
# live (SSE): the id of every message is the cursor; after a disconnection continue with the last one in Last-Event-ID
curl -N "https://api.mujprofirest.cz/v2/events/stream?restaurant_id=123" -H "Authorization: Bearer $ACCESS_TOKEN" -H "Last-Event-ID: $CURSOR"const feed = api.watchEvents({
restaurantId: '123',
onEvents: async (events) => {
for (const event of events) handle(event); // kurzor se uloží až po zpracování; neznámé typy přeskočte
},
onReset: () => reloadEverything(), // 410 cursor_expired: načtěte stav znovu
});
feed.stop(); // čtení ukončíconst feed = api.watchEvents({
restaurantId: '123',
onEvents: async (events) => {
for (const event of events) handle(event); // the cursor is stored only after processing; skip unknown types
},
onReset: () => reloadEverything(), // 410 cursor_expired: reload the state
});
feed.stop(); // ends the readingconst feed = api.watchEvents({
restaurantId: '123',
onEvents: async (events) => { // ProfirestApi.Models.Event[]
for (const event of events) handle(event); // kurzor se uloží až po zpracování; neznámé typy přeskočte
},
onReset: () => reloadEverything(), // 410 cursor_expired: načtěte stav znovu
});
feed.stop(); // čtení ukončíconst feed = api.watchEvents({
restaurantId: '123',
onEvents: async (events) => { // ProfirestApi.Models.Event[]
for (const event of events) handle(event); // the cursor is stored only after processing; skip unknown types
},
onReset: () => reloadEverything(), // 410 cursor_expired: reload the state
});
feed.stop(); // ends the reading$watcher = $api->watchEvents([
'restaurantId' => '123',
'onEvents' => function (array $events): void {
foreach ($events as $event) { handle($event); } // kurzor se uloží až po zpracování; neznámé typy přeskočte
},
'onReset' => fn() => reloadEverything(), // 410 cursor_expired: načtěte stav znovu
]);
$watcher->run(); // $watcher->stop() čtení ukončí; cron: $watcher->once()$watcher = $api->watchEvents([
'restaurantId' => '123',
'onEvents' => function (array $events): void {
foreach ($events as $event) { handle($event); } // the cursor is stored only after processing; skip unknown types
},
'onReset' => fn() => reloadEverything(), // 410 cursor_expired: reload the state
]);
$watcher->run(); // $watcher->stop() ends the reading; cron: $watcher->once()EventWatcher feed = api.watchEvents(WatchOptions.builder()
.restaurantId("123")
.onEvents(events -> events.forEach(this::handle)) // kurzor se uloží až po zpracování; neznámé typy přeskočte
.onReset(error -> reloadEverything()) // 410 cursor_expired: načtěte stav znovu
.build());
feed.start();
feed.stop(); // čtení ukončíEventWatcher feed = api.watchEvents(WatchOptions.builder()
.restaurantId("123")
.onEvents(events -> events.forEach(this::handle)) // the cursor is stored only after processing; skip unknown types
.onReset(error -> reloadEverything()) // 410 cursor_expired: reload the state
.build());
feed.start();
feed.stop(); // ends the readingval feed = api.watchEvents(WatchOptions.builder()
.restaurantId("123")
.onEvents { events -> events.forEach { handle(it) } } // kurzor se uloží až po zpracování; neznámé typy přeskočte
.onReset { reloadEverything() } // 410 cursor_expired: načtěte stav znovu
.build())
feed.start()
feed.stop() // čtení ukončíval feed = api.watchEvents(WatchOptions.builder()
.restaurantId("123")
.onEvents { events -> events.forEach { handle(it) } } // the cursor is stored only after processing; skip unknown types
.onReset { reloadEverything() } // 410 cursor_expired: reload the state
.build())
feed.start()
feed.stop() // ends the readingawait api.WatchEventsAsync(new WatchOptions
{
RestaurantId = "123",
OnEvents = async (events, ct) => { foreach (var e in events) await HandleAsync(e, ct); }, // kurzor se uloží až po zpracování; neznámé typy přeskočte
OnReset = _ => ReloadEverythingAsync(), // 410 cursor_expired: načtěte stav znovu
}, stoppingToken); // čtení ukončí: stoppingTokenawait api.WatchEventsAsync(new WatchOptions
{
RestaurantId = "123",
OnEvents = async (events, ct) => { foreach (var e in events) await HandleAsync(e, ct); }, // the cursor is stored only after processing; skip unknown types
OnReset = _ => ReloadEverythingAsync(), // 410 cursor_expired: reload the state
}, stoppingToken); // ends the reading: stoppingTokenfeed = api.watch_events(
lambda events: [handle(e) for e in events], # kurzor se uloží až po zpracování; neznámé typy přeskočte
restaurant_id='123',
on_reset=lambda error: reload_everything(), # 410 cursor_expired: načtěte stav znovu
)
feed.start()
feed.stop() # čtení ukončífeed = api.watch_events(
lambda events: [handle(e) for e in events], # the cursor is stored only after processing; skip unknown types
restaurant_id='123',
on_reset=lambda error: reload_everything(), # 410 cursor_expired: reload the state
)
feed.start()
feed.stop() # ends the readinglet feed = api.watchEvents(.init(
restaurantID: "123",
onEvents: { events in for event in events { handle(event) } }, // kurzor se uloží až po zpracování; neznámé typy přeskočte
onReset: { _ in reloadEverything() } // 410 cursor_expired: načtěte stav znovu
))
feed.cancel() // čtení ukončílet feed = api.watchEvents(.init(
restaurantID: "123",
onEvents: { events in for event in events { handle(event) } }, // the cursor is stored only after processing; skip unknown types
onReset: { _ in reloadEverything() } // 410 cursor_expired: reload the state
))
feed.cancel() // ends the readingfinal feed = api.watchEvents(
restaurantId: '123',
onEvents: (events) async { for (final e in events) handle(e); }, // kurzor se uloží až po zpracování; neznámé typy přeskočte
onReset: (error) => reloadEverything(), // 410 cursor_expired: načtěte stav znovu
)..start();
feed.stop(); // čtení ukončífinal feed = api.watchEvents(
restaurantId: '123',
onEvents: (events) async { for (final e in events) handle(e); }, // the cursor is stored only after processing; skip unknown types
onReset: (error) => reloadEverything(), // 410 cursor_expired: reload the state
)..start();
feed.stop(); // ends the readingctx, stop := context.WithCancel(ctx)
err := api.WatchEvents(ctx, profirest.WatchOptions{
RestaurantID: "123",
OnEvents: func(ctx context.Context, events []model.Event) error {
for _, e := range events {
handle(e) // kurzor se uloží až po zpracování; neznámé typy přeskočte
}
return nil
},
OnReset: func(*profirest.APIError) { reloadEverything() }, // 410 cursor_expired: načtěte stav znovu
})
stop() // čtení ukončíctx, stop := context.WithCancel(ctx)
err := api.WatchEvents(ctx, profirest.WatchOptions{
RestaurantID: "123",
OnEvents: func(ctx context.Context, events []model.Event) error {
for _, e := range events {
handle(e) // the cursor is stored only after processing; skip unknown types
}
return nil
},
OnReset: func(*profirest.APIError) { reloadEverything() }, // 410 cursor_expired: reload the state
})
stop() // ends the readingScénář
Scenario
Objednávka z e-shopu
An order from an e-shop
Partner s vlastním serveremA partner with its own serverAplikace partnera připojí restauraci, ukáže sortiment, spočítá košík a založí objednávku zaplacenou online. Ceny, dopravu i DPH počítá vždy server – aplikace je jen ukazuje. Tržbu do EET 2.0 eviduje Profirest sám (online platba se neeviduje, hotovost a karta kurýrovi při předání) – aplikace finanční správě nic neposílá.
A partner application connects a restaurant, shows the catalog, prices the basket and creates an order paid online. The server always computes prices, delivery and VAT – the application only shows them. Profirest records the sale in EET 2.0 itself (an online payment is not recorded, cash and card to the courier at the hand-over) – the application sends nothing to the tax administration.
-
Pošlete majitele na souhlas
Send the owner to the consent page
GET /oauth/authorize · oauthAuthorize
Přesměrujte prohlížeč na
/oauth/authorizes PKCE (code_challenge= BASE64URL(SHA-256(code_verifier))) a náhodnýmstate. Majitel vybere provozovny a potvrdí oprávnění; vrátí se naredirect_uriscode,stateaiss. Ověřtestateiiss.Redirect the browser to
/oauth/authorizewith PKCE (code_challenge= BASE64URL(SHA-256(code_verifier))) and a randomstate. The owner picks the restaurants and grants the scopes; the browser returns toredirect_uriwithcode,stateandiss. Check bothstateandiss.
Souhlas „Připojit přes Profirest“: majitel vybere provozovny a povolí, co aplikace smí.The “Connect via Profirest” consent: the owner picks the restaurants and grants the scopes. # souhlas běží v prohlížeči majitele: adresu otevřete, nevolejte ji z kódu CODE_VERIFIER=$(openssl rand -base64 48 | tr '+/' '-_' | tr -d '=\n') CODE_CHALLENGE=$(printf '%s' "$CODE_VERIFIER" | openssl dgst -sha256 -binary | openssl base64 | tr '+/' '-_' | tr -d '=') echo "https://api.mujprofirest.cz/oauth/authorize?response_type=code&client_id=eshop-u-lipy&redirect_uri=https%3A%2F%2Fshop.example%2Fcallback&scope=restaurants%3Aread%20catalog%3Aread%20orders%3Awrite%20orders%3Aread&state=$(openssl rand -hex 16)&code_challenge=$CODE_CHALLENGE&code_challenge_method=S256"# consent runs in the owner's browser: open the address, do not call it from code CODE_VERIFIER=$(openssl rand -base64 48 | tr '+/' '-_' | tr -d '=\n') CODE_CHALLENGE=$(printf '%s' "$CODE_VERIFIER" | openssl dgst -sha256 -binary | openssl base64 | tr '+/' '-_' | tr -d '=') echo "https://api.mujprofirest.cz/oauth/authorize?response_type=code&client_id=eshop-u-lipy&redirect_uri=https%3A%2F%2Fshop.example%2Fcallback&scope=restaurants%3Aread%20catalog%3Aread%20orders%3Awrite%20orders%3Aread&state=$(openssl rand -hex 16)&code_challenge=$CODE_CHALLENGE&code_challenge_method=S256"// klient: viz /v2/docs/js // PKCE a state hlídá knihovna location.href = await api.authorizationUrl({ redirectUri: 'https://shop.example/callback', scope: 'restaurants:read catalog:read orders:write orders:read', }); // na redirect_uri: const connection = await api.completeAuthorization();// the client: see /v2/docs/js // the library handles PKCE and state location.href = await api.authorizationUrl({ redirectUri: 'https://shop.example/callback', scope: 'restaurants:read catalog:read orders:write orders:read', }); // on the redirect_uri: const connection = await api.completeAuthorization();// klient: viz /v2/docs/typescript // PKCE a state hlídá knihovna location.href = await api.authorizationUrl({ redirectUri: 'https://shop.example/callback', scope: 'restaurants:read catalog:read orders:write orders:read', }); // na redirect_uri: const connection = await api.completeAuthorization();// the client: see /v2/docs/typescript // the library handles PKCE and state location.href = await api.authorizationUrl({ redirectUri: 'https://shop.example/callback', scope: 'restaurants:read catalog:read orders:write orders:read', }); // on the redirect_uri: const connection = await api.completeAuthorization();// klient: viz /v2/docs/php // PKCE a state hlídá knihovna header('Location: ' . $api->authorizationUrl('https://shop.example/callback', 'restaurants:read catalog:read orders:write orders:read')); // na redirect_uri: $connection = $api->completeAuthorization($_GET);// the client: see /v2/docs/php // the library handles PKCE and state header('Location: ' . $api->authorizationUrl('https://shop.example/callback', 'restaurants:read catalog:read orders:write orders:read')); // on the redirect_uri: $connection = $api->completeAuthorization($_GET);// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // PKCE a state hlídá knihovna response.sendRedirect(api.authorizationUrl("https://shop.example/callback", "restaurants:read catalog:read orders:write orders:read")); // na redirect_uri: Map<String, Object> connection = api.completeAuthorization(request.getRequestURL() + "?" + request.getQueryString());// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library handles PKCE and state response.sendRedirect(api.authorizationUrl("https://shop.example/callback", "restaurants:read catalog:read orders:write orders:read")); // on the redirect_uri: Map<String, Object> connection = api.completeAuthorization(request.getRequestURL() + "?" + request.getQueryString());// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // PKCE a state hlídá knihovna val url = api.authorizationUrl("https://shop.example/callback", "restaurants:read catalog:read orders:write orders:read") // na redirect_uri: val connection = api.completeAuthorization(callbackUrl)// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library handles PKCE and state val url = api.authorizationUrl("https://shop.example/callback", "restaurants:read catalog:read orders:write orders:read") // on the redirect_uri: val connection = api.completeAuthorization(callbackUrl)// klient: viz /v2/docs/csharp // PKCE a state hlídá knihovna var url = api.AuthorizationUrl(new AuthorizationOptions { RedirectUri = "https://shop.example/callback", Scope = "restaurants:read catalog:read orders:write orders:read", }); // na redirect_uri: Connection? connection = await api.CompleteAuthorizationAsync(callbackUrl);// the client: see /v2/docs/csharp // the library handles PKCE and state var url = api.AuthorizationUrl(new AuthorizationOptions { RedirectUri = "https://shop.example/callback", Scope = "restaurants:read catalog:read orders:write orders:read", }); // on the redirect_uri: Connection? connection = await api.CompleteAuthorizationAsync(callbackUrl);# klient: viz /v2/docs/python # PKCE a state hlídá knihovna url = api.authorization_url(redirect_uri='https://shop.example/callback', scope='restaurants:read catalog:read orders:write orders:read') # na redirect_uri: connection = api.complete_authorization(request.url)# the client: see /v2/docs/python # the library handles PKCE and state url = api.authorization_url(redirect_uri='https://shop.example/callback', scope='restaurants:read catalog:read orders:write orders:read') # on the redirect_uri: connection = api.complete_authorization(request.url)// klient: viz /v2/docs/swift // PKCE a state hlídá knihovna let url = try api.authorizationURL(redirectURI: "profirest-shop://callback", scope: "restaurants:read catalog:read orders:write orders:read") // na redirect_uri: (ASWebAuthenticationSession) let connection = try await api.completeAuthorization(callbackURL)// the client: see /v2/docs/swift // the library handles PKCE and state let url = try api.authorizationURL(redirectURI: "profirest-shop://callback", scope: "restaurants:read catalog:read orders:write orders:read") // on the redirect_uri: (ASWebAuthenticationSession) let connection = try await api.completeAuthorization(callbackURL)// klient: viz /v2/docs/dart // PKCE a state hlídá knihovna final url = await api.authorizationUrl(redirectUri: 'https://shop.example/callback', scope: 'restaurants:read catalog:read orders:write orders:read'); // na redirect_uri: final connection = await api.completeAuthorization(callbackUrl);// the client: see /v2/docs/dart // the library handles PKCE and state final url = await api.authorizationUrl(redirectUri: 'https://shop.example/callback', scope: 'restaurants:read catalog:read orders:write orders:read'); // on the redirect_uri: final connection = await api.completeAuthorization(callbackUrl);// klient: viz /v2/docs/go // PKCE a state hlídá knihovna url, err := api.AuthorizationURL(profirest.AuthorizationOptions{ RedirectURI: "https://shop.example/callback", Scope: "restaurants:read catalog:read orders:write orders:read", }) // na redirect_uri: connection, err := api.CompleteAuthorization(ctx, r.URL.String())// the client: see /v2/docs/go // the library handles PKCE and state url, err := api.AuthorizationURL(profirest.AuthorizationOptions{ RedirectURI: "https://shop.example/callback", Scope: "restaurants:read catalog:read orders:write orders:read", }) // on the redirect_uri: connection, err := api.CompleteAuthorization(ctx, r.URL.String()) -
Vyměňte kód za tokeny
Exchange the code for tokens
POST /oauth/token · oauthToken
Na serveru, s tajemstvím klienta. Access token platí 30 minut, refresh token 90 dní od posledního použití; každá obnova (
grant_type=refresh_token) vrátí nový refresh token. Tokeny ukládejte ke každému připojenému účtu zvlášť – v knihovnách vlastní instance s vlastním klíčem úložiště odvozeným z ID účtu ve vašem systému; výchozí klíč je jeden pro celou aplikaci a další připojení by přepsalo předchozí.On your server, with the client secret. The access token lives 30 minutes, the refresh token 90 days since its last use; every refresh (
grant_type=refresh_token) returns a new refresh token. Store the tokens separately for every connected account – in the libraries a separate instance with its own storage key derived from the account ID in your system; the default key is one for the whole application and the next connection would overwrite the previous one.curl "https://api.mujprofirest.cz/oauth/token" \ -u "$CLIENT_ID:$CLIENT_SECRET" \ -d grant_type=authorization_code \ -d code=pfc_VpTQii5T_8rgwxA-Wtb2B2q9lg6x-KVldwQLwQKPcCs \ -d redirect_uri=https://shop.example/callback \ -d code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXkcurl "https://api.mujprofirest.cz/oauth/token" \ -u "$CLIENT_ID:$CLIENT_SECRET" \ -d grant_type=authorization_code \ -d code=pfc_VpTQii5T_8rgwxA-Wtb2B2q9lg6x-KVldwQLwQKPcCs \ -d redirect_uri=https://shop.example/callback \ -d code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk// klient: viz /v2/docs/js // tokeny vyzvedne a obnovuje knihovna sama (párování nebo dokončení souhlasu); obnova minutu před koncem, jen jednou const connection = await api.connection();// the client: see /v2/docs/js // the library picks up and refreshes the tokens itself (pairing or completing the consent); refreshed a minute early, once const connection = await api.connection();// klient: viz /v2/docs/typescript // tokeny vyzvedne a obnovuje knihovna sama (párování nebo dokončení souhlasu); obnova minutu před koncem, jen jednou const connection = await api.connection();// the client: see /v2/docs/typescript // the library picks up and refreshes the tokens itself (pairing or completing the consent); refreshed a minute early, once const connection = await api.connection();// klient: viz /v2/docs/php // tokeny vyzvedne a obnovuje knihovna sama (párování nebo dokončení souhlasu); obnova minutu před koncem, jen jednou $connection = $api->connection();// the client: see /v2/docs/php // the library picks up and refreshes the tokens itself (pairing or completing the consent); refreshed a minute early, once $connection = $api->connection();// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // tokeny vyzvedne a obnovuje knihovna sama (párování nebo dokončení souhlasu); obnova minutu před koncem, jen jednou Map<String, Object> connection = api.connection();// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library picks up and refreshes the tokens itself (pairing or completing the consent); refreshed a minute early, once Map<String, Object> connection = api.connection();// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // tokeny vyzvedne a obnovuje knihovna sama (párování nebo dokončení souhlasu); obnova minutu před koncem, jen jednou val connection = api.connection()// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library picks up and refreshes the tokens itself (pairing or completing the consent); refreshed a minute early, once val connection = api.connection()// klient: viz /v2/docs/csharp // tokeny vyzvedne a obnovuje knihovna sama (párování nebo dokončení souhlasu); obnova minutu před koncem, jen jednou Connection? connection = await api.ConnectionAsync();// the client: see /v2/docs/csharp // the library picks up and refreshes the tokens itself (pairing or completing the consent); refreshed a minute early, once Connection? connection = await api.ConnectionAsync();# klient: viz /v2/docs/python # tokeny vyzvedne a obnovuje knihovna sama (párování nebo dokončení souhlasu); obnova minutu před koncem, jen jednou connection = api.connection()# the client: see /v2/docs/python # the library picks up and refreshes the tokens itself (pairing or completing the consent); refreshed a minute early, once connection = api.connection()// klient: viz /v2/docs/swift // tokeny vyzvedne a obnovuje knihovna sama (párování nebo dokončení souhlasu); obnova minutu před koncem, jen jednou let connection = try await api.connection()// the client: see /v2/docs/swift // the library picks up and refreshes the tokens itself (pairing or completing the consent); refreshed a minute early, once let connection = try await api.connection()// klient: viz /v2/docs/dart // tokeny vyzvedne a obnovuje knihovna sama (párování nebo dokončení souhlasu); obnova minutu před koncem, jen jednou final connection = await api.connection();// the client: see /v2/docs/dart // the library picks up and refreshes the tokens itself (pairing or completing the consent); refreshed a minute early, once final connection = await api.connection();// klient: viz /v2/docs/go // tokeny vyzvedne a obnovuje knihovna sama (párování nebo dokončení souhlasu); obnova minutu před koncem, jen jednou connection, err := api.Connection(ctx)// the client: see /v2/docs/go // the library picks up and refreshes the tokens itself (pairing or completing the consent); refreshed a minute early, once connection, err := api.Connection(ctx)Příklad odpovědi 200Example answer 200
{ "access_token": "pfa_oFYf1knNtrqnhAVfBRuteW6gr-8X_KOCGVSd7rpOjBo", "token_type": "Bearer", "expires_in": 1800, "refresh_token": "pfr_1swKCIwHaDxlzSZoYMq42Us6GTexdCDZ2jDKKZwJ-3c", "refresh_token_expires_in": 7776000, "scope": "restaurants:read catalog:read orders:write orders:read" } -
Zjistěte provozovny
Find the restaurants
GET /restaurants · listRestaurants
Jen ty, které majitel připojení svěřil.
orderingříká, jestli provozovna právě přijímá objednávky.Only those the owner granted to the connection.
orderingtells whether the restaurant takes orders right now.
Integrace › Připojené aplikace: provozovny, oprávnění a kdo píše zákazníkům – majitel je může kdykoli změnit nebo připojení zrušit.Integrations › Connected applications: restaurants, scopes and who messages the customers – the owner can change them or revoke the connection at any time. curl "https://api.mujprofirest.cz/v2/restaurants?limit=20" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants?limit=20" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const { data, next_cursor } = await api.get('/restaurants', { query: { limit: 20 } }); // 200// the client: see /v2/docs/js const { data, next_cursor } = await api.get('/restaurants', { query: { limit: 20 } }); // 200// klient: viz /v2/docs/typescript const { data, next_cursor } = await api.get('/restaurants', { query: { limit: 20 } }); // 200 RestaurantPage// the client: see /v2/docs/typescript const { data, next_cursor } = await api.get('/restaurants', { query: { limit: 20 } }); // 200 RestaurantPage// klient: viz /v2/docs/php $page = $api->get('/restaurants', ['query' => ['limit' => 20]]); // $page['data'], $page['next_cursor']// the client: see /v2/docs/php $page = $api->get('/restaurants', ['query' => ['limit' => 20]]); // $page['data'], $page['next_cursor']// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) RestaurantPage listRestaurants = api.get( "/restaurants", RequestOptions.builder().query("limit", "20").build(), RestaurantPage::fromJson ); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) RestaurantPage listRestaurants = api.get( "/restaurants", RequestOptions.builder().query("limit", "20").build(), RestaurantPage::fromJson ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val listRestaurants = api.get( "/restaurants", RequestOptions.builder().query("limit", "20").build(), RestaurantPage::fromJson, ) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val listRestaurants = api.get( "/restaurants", RequestOptions.builder().query("limit", "20").build(), RestaurantPage::fromJson, ) // 200// klient: viz /v2/docs/csharp var listRestaurants = await api.GetAsync<RestaurantPage>( "/restaurants", new RequestOptions { Query = new() { ["limit"] = "20" } } ); // 200// the client: see /v2/docs/csharp var listRestaurants = await api.GetAsync<RestaurantPage>( "/restaurants", new RequestOptions { Query = new() { ["limit"] = "20" } } ); // 200# klient: viz /v2/docs/python page = api.get('/restaurants', query={'limit': 20}) # page['data'], page['next_cursor']# the client: see /v2/docs/python page = api.get('/restaurants', query={'limit': 20}) # page['data'], page['next_cursor']// klient: viz /v2/docs/swift let listRestaurants: RestaurantPage = try await api.get("/restaurants", options: .init(query: ["limit": "20"])) // 200// the client: see /v2/docs/swift let listRestaurants: RestaurantPage = try await api.get("/restaurants", options: .init(query: ["limit": "20"])) // 200// klient: viz /v2/docs/dart final listRestaurants = pr.RestaurantPage.fromJson(await api.get('/restaurants', query: {'limit': '20'})); // 200// the client: see /v2/docs/dart final listRestaurants = pr.RestaurantPage.fromJson(await api.get('/restaurants', query: {'limit': '20'})); // 200// klient: viz /v2/docs/go res, err := api.Get(ctx, "/restaurants", &profirest.RequestOptions{Query: map[string]any{"limit": "20"}}) var listRestaurants model.RestaurantPage // 200 if err == nil { err = res.Decode(&listRestaurants) }// the client: see /v2/docs/go res, err := api.Get(ctx, "/restaurants", &profirest.RequestOptions{Query: map[string]any{"limit": "20"}}) var listRestaurants model.RestaurantPage // 200 if err == nil { err = res.Decode(&listRestaurants) }Příklad odpovědi 200Example answer 200
{ "data": [ { "id": "123", "name": "Bistro U Lípy", "is_test": false, "address": { "street": "Vinohradská", "house_number": "1200/48", "city": "Praha 2", "postal_code": "120 00", "country": "CZ", "note": null, "formatted": "Vinohradská 1200/48, 120 00 Praha 2" }, "location": { "lat": 50.0769, "lon": 14.4459 }, "phone": "+420222333444", "website": "https://www.bistroulipy.cz", "timezone": "Europe/Prague", "currency": "CZK", "ordering": { "accepting_orders": true, "open_now": true, "venue_open_now": true, "next_change_at": "2027-01-15T22:00:00+01:00", "delivery": { "enabled": true, "available_now": true }, "pickup": { "enabled": true, "available_now": true }, "scheduled_orders": { "enabled": true, "max_days_ahead": 7, "slot_minutes": 15, "lead_minutes": 90 } }, "portion_tracking": true, "external_id": "vinohrady", "metadata": { "branch": "praha-2" } }, { "id": "124", "name": "Bistro U Lípy Karlín", "is_test": false, "address": { "street": "Sokolovská", "house_number": "316/101", "city": "Praha 8", "postal_code": "186 00", "country": "CZ", "note": null, "formatted": "Sokolovská 316/101, 186 00 Praha 8" }, "location": { "lat": 50.0927, "lon": 14.4521 }, "phone": "+420222333555", "website": "https://www.bistroulipy.cz", "timezone": "Europe/Prague", "currency": "CZK", "ordering": { "accepting_orders": false, "open_now": false, "venue_open_now": false, "next_change_at": "2027-01-15T16:00:00+01:00", "delivery": { "enabled": true, "available_now": false }, "pickup": { "enabled": true, "available_now": false }, "scheduled_orders": { "enabled": true, "max_days_ahead": 7, "slot_minutes": 15, "lead_minutes": 90 } }, "portion_tracking": false, "external_id": "karlin", "metadata": { "branch": "praha-8" } } ], "next_cursor": null } -
Načtěte sortiment
Load the catalog
GET /restaurants/{restaurant_id}/catalog · getCatalog
Jeden snímek s kategoriemi, produkty, přílohami, denním menu a alergeny – nestránkuje se. Pošlete
If-None-Matchs ETagem; když se nic nezměnilo, přijde304. Jídla ve více velikostech (pizza Ø28cm / Ø32cm / Ø42cm) jsou samostatné produkty se stejnýmsize.group_id– ukažte je jako jednu položku s přepínačem a objednejteidzvolené velikosti. Produkt ssplitjde složit do pizzy z půlek nebo čtvrtek (položkatypesplitsparts, každý díl se svými přílohami); produkt soption_groupssi zákazník skládá z voleb (vlastní pizza, povinný výběr těsta) – pošleteoptionssoption_ida počtem porcí, meze i ingredience v ceně spočítá server. Víc porcí jedné přílohy (dvojitý sýr) jeadd_ons[].quantity. Suroviny zremovable_ingredientssi host smí odebrat (bez bazalky) – ukažte je zaškrtnuté a odškrtnuté pošlete vremoved_ingredient_idspoložky nebo dílu; cena se nemění.One snapshot with categories, products, add-ons, the daily menu and allergens – not paged. Send
If-None-Matchwith the ETag; when nothing changed you get304. Dishes sold in several sizes (pizza Ø28cm / Ø32cm / Ø42cm) are separate products with the samesize.group_id– show them as one item with a size switcher and order theidof the chosen size. A product withsplitcan be a part of a pizza from halves or quarters (an item oftypesplitwithparts, each part with its own add-ons); a product withoption_groupsis composed by the customer from options (a custom pizza, a required choice of dough) – sendoptionswithoption_idand portions, the server checks the limits and the included toppings. More portions of one add-on (double cheese) areadd_ons[].quantity. The guest may remove ingredients fromremovable_ingredients(without basil) – show them ticked and send the unticked ones inremoved_ingredient_idsof the item or the part; the price does not change.curl "https://api.mujprofirest.cz/v2/restaurants/123/catalog?channel=web" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/catalog?channel=web" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const catalog = await api.get('/restaurants/123/catalog', { query: { channel: 'web' } }); // 200// the client: see /v2/docs/js const catalog = await api.get('/restaurants/123/catalog', { query: { channel: 'web' } }); // 200// klient: viz /v2/docs/typescript const catalog = await api.get('/restaurants/123/catalog', { query: { channel: 'web' } }); // 200 Catalog// the client: see /v2/docs/typescript const catalog = await api.get('/restaurants/123/catalog', { query: { channel: 'web' } }); // 200 Catalog// klient: viz /v2/docs/php $catalog = $api->get('/restaurants/123/catalog', ['query' => ['channel' => 'web']]); // 200// the client: see /v2/docs/php $catalog = $api->get('/restaurants/123/catalog', ['query' => ['channel' => 'web']]); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) Catalog catalog = api.get( "/restaurants/123/catalog", RequestOptions.builder().query("channel", "web").build(), Catalog::fromJson ); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) Catalog catalog = api.get( "/restaurants/123/catalog", RequestOptions.builder().query("channel", "web").build(), Catalog::fromJson ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val catalog = api.get( "/restaurants/123/catalog", RequestOptions.builder().query("channel", "web").build(), Catalog::fromJson, ) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val catalog = api.get( "/restaurants/123/catalog", RequestOptions.builder().query("channel", "web").build(), Catalog::fromJson, ) // 200// klient: viz /v2/docs/csharp var catalog = await api.GetAsync<Catalog>( "/restaurants/123/catalog", new RequestOptions { Query = new() { ["channel"] = "web" } } ); // 200// the client: see /v2/docs/csharp var catalog = await api.GetAsync<Catalog>( "/restaurants/123/catalog", new RequestOptions { Query = new() { ["channel"] = "web" } } ); // 200# klient: viz /v2/docs/python catalog = api.get('/restaurants/123/catalog', query={'channel': 'web'}) # 200# the client: see /v2/docs/python catalog = api.get('/restaurants/123/catalog', query={'channel': 'web'}) # 200// klient: viz /v2/docs/swift let catalog: Catalog = try await api.get("/restaurants/123/catalog", options: .init(query: ["channel": "web"])) // 200// the client: see /v2/docs/swift let catalog: Catalog = try await api.get("/restaurants/123/catalog", options: .init(query: ["channel": "web"])) // 200// klient: viz /v2/docs/dart final catalog = pr.Catalog.fromJson(await api.get('/restaurants/123/catalog', query: {'channel': 'web'})); // 200// the client: see /v2/docs/dart final catalog = pr.Catalog.fromJson(await api.get('/restaurants/123/catalog', query: {'channel': 'web'})); // 200// klient: viz /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/catalog", &profirest.RequestOptions{Query: map[string]any{"channel": "web"}}, ) var catalog model.Catalog // 200 if err == nil { err = res.Decode(&catalog) }// the client: see /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/catalog", &profirest.RequestOptions{Query: map[string]any{"channel": "web"}}, ) var catalog model.Catalog // 200 if err == nil { err = res.Decode(&catalog) }Příklad odpovědi 200Example answer 200
{ "restaurant_id": "123", "currency": "CZK", "at": "2027-01-15T11:42:00+01:00", "generated_at": "2027-01-15T11:40:00+01:00", "next_change_at": "2027-01-15T15:00:00+01:00", "categories": [ { "id": "312", "name": "Hlavní jídla", "description": null, "image_url": null, "color": "#e53935", "icon": "fa-utensils", "position": 1, "external_id": null, "metadata": {} }, { "id": "315", "name": "Pizza", "description": "Pečeme v peci na dřevo.", "image_url": null, "color": "#fb8c00", "icon": "fa-pizza-slice", "position": 2, "external_id": null, "metadata": {} }, { "id": "320", "name": "Nápoje", "description": null, "image_url": null, "color": "#1e88e5", "icon": null, "position": 3, "external_id": null, "metadata": {} } ], "products": [ { "id": "4567", "category_id": "312", "name": "Svíčková na smetaně, houskový knedlík", "description": "Hovězí svíčková, smetanová omáčka, brusinky, šlehačka.", "image_url": "https://www.mujprofirest.cz/data/products/4567.jpg", "price": { "amount": 19900, "currency": "CZK" }, "vat_rate": "12", "packaging_fee": null, "weight": 150, "allergens": [ "1", "3", "7", "9" ], "labels": [ "home_made" ], "age_restricted": false, "add_ons": [], "option_groups": [], "removable_ingredients": [], "split": null, "half_price": null, "position": 1, "ean": null, "kitchen_name": null, "size": null, "pos": null, "external_id": null, "metadata": {} }, { "id": "4568", "category_id": "312", "name": "Smažený sýr, hranolky, tatarská omáčka", "description": "Eidam 120 g, hranolky, domácí tatarská omáčka.", "image_url": null, "price": { "amount": 17900, "currency": "CZK" }, "vat_rate": "12", "packaging_fee": null, "weight": 120, "allergens": [ "1", "3", "7" ], "labels": [], "age_restricted": false, "add_ons": [], "option_groups": [], "removable_ingredients": [], "split": null, "half_price": null, "position": 2, "ean": null, "kitchen_name": null, "size": null, "pos": null, "external_id": null, "metadata": {} }, { "id": "4571", "category_id": "315", "name": "Pizza Margherita", "description": "Rajčata San Marzano, mozzarella, bazalka.", "image_url": null, "price": { "amount": 18900, "currency": "CZK" }, "vat_rate": "12", "packaging_fee": null, "weight": 450, "allergens": [ "1", "7" ], "labels": [ "bestseller" ], "age_restricted": false, "add_ons": [ { "product_id": "4602", "name": "Extra sýr", "price": { "amount": 3000, "currency": "CZK" }, "vat_rate": "12", "allergens": [ "7" ] } ], "option_groups": [], "removable_ingredients": [ { "id": "9001", "name": "bazalka" }, { "id": "9002", "name": "oregano" } ], "split": { "half_price": { "amount": 13300, "currency": "CZK" }, "quarter_price": null }, "half_price": null, "position": 1, "ean": null, "kitchen_name": null, "size": null, "pos": null, "external_id": null, "metadata": {} }, { "id": "4590", "category_id": "315", "name": "Vlastní pizza Ø32cm", "description": "Složte si pizzu: těsto a až 8 ingrediencí, 4 jsou v ceně.", "image_url": null, "price": { "amount": 18900, "currency": "CZK" }, "vat_rate": "12", "packaging_fee": null, "weight": 450, "allergens": [ "1", "7" ], "labels": [], "age_restricted": false, "add_ons": [], "option_groups": [ { "id": "71", "name": "Těsto", "min_quantity": 1, "max_quantity": 1, "max_per_option": 1, "included_quantity": 0, "options": [ { "id": "1001", "product_id": "4591", "name": "Klasické těsto", "price": { "amount": 0, "currency": "CZK" }, "base_price": null, "vat_rate": "12", "allergens": [ "1" ] }, { "id": "1002", "product_id": "4592", "name": "Celozrnné těsto", "price": { "amount": 2000, "currency": "CZK" }, "base_price": null, "vat_rate": "12", "allergens": [ "1" ] } ] }, { "id": "72", "name": "Ingredience", "min_quantity": 0, "max_quantity": 8, "max_per_option": 2, "included_quantity": 4, "options": [ { "id": "1101", "product_id": "4605", "name": "Šunka", "price": { "amount": 2400, "currency": "CZK" }, "base_price": null, "vat_rate": "12", "allergens": [] }, { "id": "1102", "product_id": "4603", "name": "Žampiony", "price": { "amount": 1900, "currency": "CZK" }, "base_price": null, "vat_rate": "12", "allergens": [] }, { "id": "1103", "product_id": "4604", "name": "Krevety", "price": { "amount": 0, "currency": "CZK" }, "base_price": { "amount": 20900, "currency": "CZK" }, "vat_rate": "12", "allergens": [ "2" ] }, { "id": "1104", "product_id": "4606", "name": "Olivy", "price": { "amount": 1500, "currency": "CZK" }, "base_price": null, "vat_rate": "12", "allergens": [] } ] } ], "removable_ingredients": [], "split": null, "half_price": null, "position": 4, "ean": null, "kitchen_name": null, "size": null, "pos": null, "external_id": null, "metadata": {} }, { "id": "4580", "category_id": "315", "name": "Ø32cm Prosciutto", "description": "Šunka, mozzarella, rajčata.", "image_url": null, "price": { "amount": 21900, "currency": "CZK" }, "vat_rate": "12", "packaging_fee": null, "weight": 450, "allergens": [ "1", "7" ], "labels": [], "age_restricted": false, "add_ons": [], "option_groups": [], "removable_ingredients": [], "split": null, "half_price": null, "position": 2, "ean": null, "kitchen_name": null, "size": { "group_id": "4580", "name": "Ø32cm", "dish_name": "Prosciutto", "position": 1, "base": true }, "pos": null, "external_id": null, "metadata": {} }, { "id": "4583", "category_id": "315", "name": "Ø42cm Prosciutto", "description": "Šunka, mozzarella, rajčata.", "image_url": null, "price": { "amount": 30900, "currency": "CZK" }, "vat_rate": "12", "packaging_fee": null, "weight": 700, "allergens": [ "1", "7" ], "labels": [], "age_restricted": false, "add_ons": [], "option_groups": [], "removable_ingredients": [], "split": null, "half_price": null, "position": 3, "ean": null, "kitchen_name": null, "size": { "group_id": "4580", "name": "Ø42cm", "dish_name": "Prosciutto", "position": 2, "base": false }, "pos": null, "external_id": null, "metadata": {} }, { "id": "4590", "category_id": "320", "name": "Pivo 12° 0,5 l", "description": null, "image_url": null, "price": { "amount": 6900, "currency": "CZK" }, "vat_rate": "21", "packaging_fee": null, "weight": null, "allergens": [], "labels": [], "age_restricted": true, "add_ons": [], "option_groups": [], "removable_ingredients": [], "split": null, "half_price": null, "position": 1, "ean": null, "kitchen_name": null, "size": null, "pos": null, "external_id": null, "metadata": {} }, { "id": "4593", "category_id": "320", "name": "Domácí limonáda 0,4 l", "description": "Citron, máta, třtinový cukr.", "image_url": null, "price": { "amount": 5900, "currency": "CZK" }, "vat_rate": "12", "packaging_fee": null, "weight": null, "allergens": [], "labels": [], "age_restricted": false, "add_ons": [], "option_groups": [], "removable_ingredients": [], "split": null, "half_price": null, "position": 2, "ean": null, "kitchen_name": null, "size": null, "pos": null, "external_id": null, "metadata": {} } ], "daily_menu": { "date": "2027-01-15", "available_from": "11:00", "available_to": "15:00", "items": [ { "product_id": "4567", "position": 1 }, { "product_id": "4568", "position": 2 } ] }, "allergens": [ { "code": "1", "name": "Obiloviny obsahující lepek" }, { "code": "3", "name": "Vejce" }, { "code": "7", "name": "Mléko" }, { "code": "9", "name": "Celer" } ] } -
Nabídněte čas
Offer a time
GET /restaurants/{restaurant_id}/time-slots · listTimeSlots
Časy, kdy provozovna stihne rozvoz nebo vyzvednutí;
asapříká, jestli jde „co nejdřív“.The times the restaurant can deliver or have the order ready;
asaptells whether “as soon as possible” works.
Nastavení › Objednávky z aplikací: příjem objednávek, rozvoz a odběr a objednávky na pozdější čas – pro každou provozovnu zvlášť.Settings › Orders from applications: accepting orders, delivery and pickup and orders for later – for every restaurant separately. curl "https://api.mujprofirest.cz/v2/restaurants/123/time-slots?type=delivery&date=2027-01-15&zone_id=21" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/time-slots?type=delivery&date=2027-01-15&zone_id=21" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const listTimeSlots = await api.get( '/restaurants/123/time-slots', { query: { type: 'delivery', date: '2027-01-15', zone_id: '21' } }, ); // 200// the client: see /v2/docs/js const listTimeSlots = await api.get( '/restaurants/123/time-slots', { query: { type: 'delivery', date: '2027-01-15', zone_id: '21' } }, ); // 200// klient: viz /v2/docs/typescript const listTimeSlots = await api.get( '/restaurants/123/time-slots', { query: { type: 'delivery', date: '2027-01-15', zone_id: '21' } }, ); // 200 TimeSlots// the client: see /v2/docs/typescript const listTimeSlots = await api.get( '/restaurants/123/time-slots', { query: { type: 'delivery', date: '2027-01-15', zone_id: '21' } }, ); // 200 TimeSlots// klient: viz /v2/docs/php $listTimeSlots = $api->get( '/restaurants/123/time-slots', ['query' => ['type' => 'delivery', 'date' => '2027-01-15', 'zone_id' => '21']], ); // 200// the client: see /v2/docs/php $listTimeSlots = $api->get( '/restaurants/123/time-slots', ['query' => ['type' => 'delivery', 'date' => '2027-01-15', 'zone_id' => '21']], ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) TimeSlots listTimeSlots = api.get( "/restaurants/123/time-slots", RequestOptions.builder().query("type", "delivery").query("date", "2027-01-15").query("zone_id", "21").build(), TimeSlots::fromJson ); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) TimeSlots listTimeSlots = api.get( "/restaurants/123/time-slots", RequestOptions.builder().query("type", "delivery").query("date", "2027-01-15").query("zone_id", "21").build(), TimeSlots::fromJson ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val listTimeSlots = api.get( "/restaurants/123/time-slots", RequestOptions.builder().query("type", "delivery").query("date", "2027-01-15").query("zone_id", "21").build(), TimeSlots::fromJson, ) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val listTimeSlots = api.get( "/restaurants/123/time-slots", RequestOptions.builder().query("type", "delivery").query("date", "2027-01-15").query("zone_id", "21").build(), TimeSlots::fromJson, ) // 200// klient: viz /v2/docs/csharp var listTimeSlots = await api.GetAsync<TimeSlots>( "/restaurants/123/time-slots", new RequestOptions { Query = new() { ["type"] = "delivery", ["date"] = "2027-01-15", ["zone_id"] = "21" } } ); // 200// the client: see /v2/docs/csharp var listTimeSlots = await api.GetAsync<TimeSlots>( "/restaurants/123/time-slots", new RequestOptions { Query = new() { ["type"] = "delivery", ["date"] = "2027-01-15", ["zone_id"] = "21" } } ); // 200# klient: viz /v2/docs/python list_time_slots = api.get( '/restaurants/123/time-slots', query={'type': 'delivery', 'date': '2027-01-15', 'zone_id': '21'}, ) # 200# the client: see /v2/docs/python list_time_slots = api.get( '/restaurants/123/time-slots', query={'type': 'delivery', 'date': '2027-01-15', 'zone_id': '21'}, ) # 200// klient: viz /v2/docs/swift let listTimeSlots: TimeSlots = try await api.get( "/restaurants/123/time-slots", options: .init(query: ["type": "delivery", "date": "2027-01-15", "zone_id": "21"]) ) // 200// the client: see /v2/docs/swift let listTimeSlots: TimeSlots = try await api.get( "/restaurants/123/time-slots", options: .init(query: ["type": "delivery", "date": "2027-01-15", "zone_id": "21"]) ) // 200// klient: viz /v2/docs/dart final listTimeSlots = pr.TimeSlots.fromJson(await api.get( '/restaurants/123/time-slots', query: {'type': 'delivery', 'date': '2027-01-15', 'zone_id': '21'}, )); // 200// the client: see /v2/docs/dart final listTimeSlots = pr.TimeSlots.fromJson(await api.get( '/restaurants/123/time-slots', query: {'type': 'delivery', 'date': '2027-01-15', 'zone_id': '21'}, )); // 200// klient: viz /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/time-slots", &profirest.RequestOptions{Query: map[string]any{"type": "delivery", "date": "2027-01-15", "zone_id": "21"}}, ) var listTimeSlots model.TimeSlots // 200 if err == nil { err = res.Decode(&listTimeSlots) }// the client: see /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/time-slots", &profirest.RequestOptions{Query: map[string]any{"type": "delivery", "date": "2027-01-15", "zone_id": "21"}}, ) var listTimeSlots model.TimeSlots // 200 if err == nil { err = res.Decode(&listTimeSlots) }Příklad odpovědi 200Example answer 200
{ "restaurant_id": "123", "type": "delivery", "date": "2027-01-15", "asap": { "available": true, "reason": null }, "slots": [ { "time": "2027-01-15T12:30:00+01:00" }, { "time": "2027-01-15T12:45:00+01:00" }, { "time": "2027-01-15T13:00:00+01:00" }, { "time": "2027-01-15T13:15:00+01:00" } ] } -
Spočítejte košík
Price the basket
POST /restaurants/{restaurant_id}/quotes · createQuote
Server spočítá ceny, dopravu, DPH, akce a slevové kódy i vouchery a ceny drží do
expires_at. Nedostupný produkt nebo adresa mimo rozvoz přijdou jako422s kódem z katalogu chyb. Když má rozvozová zóna adresydelivery.express_fee, nabídněte „Expresní doručení +X Kč“ a při volbě spočítejte košík znovu sfulfillment.speedexpress– přibude poplatekexpress_delivery(jen rozvoz co nejdřív; kuchyň objednávku uvidí se štítkem EXPRES).The server computes prices, delivery, VAT, promotions and promo codes and vouchers and keeps the prices until
expires_at. An unavailable product or an address outside delivery comes as422with a code from the error catalog. When the delivery zone of the address hasdelivery.express_fee, offer “Express delivery +X CZK” and on that choice price the basket again withfulfillment.speedexpress– the chargeexpress_deliveryis added (delivery as soon as possible only; the kitchen sees the order marked EXPRES).
Produkty a sklady › Akce a slevové kódy: akce, které kalkulace uplatní sama, a slevové kódy, které zákazník zadá.Products and stock › Promotions and promo codes: promotions the quote applies by itself and codes the customer enters. curl "https://api.mujprofirest.cz/v2/restaurants/123/quotes" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-73e4-8e81-92356cdda12a" \ -H "Content-Type: application/json" \ -d '{"fulfillment": {"type": "pickup"}, "items": [{"product_id": "4567", "quantity": 2}]}'curl "https://api.mujprofirest.cz/v2/restaurants/123/quotes" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-73e4-8e81-92356cdda12a" \ -H "Content-Type: application/json" \ -d '{"fulfillment": {"type": "pickup"}, "items": [{"product_id": "4567", "quantity": 2}]}'// klient: viz /v2/docs/js const quote = await api.post( '/restaurants/123/quotes', { fulfillment: { type: 'pickup' }, items: [{ product_id: '4567', quantity: 2 }] }, ); // 201// the client: see /v2/docs/js const quote = await api.post( '/restaurants/123/quotes', { fulfillment: { type: 'pickup' }, items: [{ product_id: '4567', quantity: 2 }] }, ); // 201// klient: viz /v2/docs/typescript const quote = await api.post( '/restaurants/123/quotes', { fulfillment: { type: 'pickup' }, items: [{ product_id: '4567', quantity: 2 }] }, ); // 201 Quote// the client: see /v2/docs/typescript const quote = await api.post( '/restaurants/123/quotes', { fulfillment: { type: 'pickup' }, items: [{ product_id: '4567', quantity: 2 }] }, ); // 201 Quote// klient: viz /v2/docs/php $quote = $api->post('/restaurants/123/quotes', [ 'fulfillment' => ['type' => 'pickup'], 'items' => [['product_id' => '4567', 'quantity' => 2]], ]); // 201// the client: see /v2/docs/php $quote = $api->post('/restaurants/123/quotes', [ 'fulfillment' => ['type' => 'pickup'], 'items' => [['product_id' => '4567', 'quantity' => 2]], ]); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) Quote quote = api.post("/restaurants/123/quotes", Json.parse(""" {"fulfillment": {"type": "pickup"}, "items": [{"product_id": "4567", "quantity": 2}]} """), Quote::fromJson); // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) Quote quote = api.post("/restaurants/123/quotes", Json.parse(""" {"fulfillment": {"type": "pickup"}, "items": [{"product_id": "4567", "quantity": 2}]} """), Quote::fromJson); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val quote = api.post("/restaurants/123/quotes", mapOf( "fulfillment" to mapOf("type" to "pickup"), "items" to listOf(mapOf("product_id" to "4567", "quantity" to 2)), ), Quote::fromJson) // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val quote = api.post("/restaurants/123/quotes", mapOf( "fulfillment" to mapOf("type" to "pickup"), "items" to listOf(mapOf("product_id" to "4567", "quantity" to 2)), ), Quote::fromJson) // 201// klient: viz /v2/docs/csharp var quote = await api.PostAsync<Quote>("/restaurants/123/quotes", new { fulfillment = new { type = "pickup" }, items = new object[] { new { product_id = "4567", quantity = 2 } }, }); // 201// the client: see /v2/docs/csharp var quote = await api.PostAsync<Quote>("/restaurants/123/quotes", new { fulfillment = new { type = "pickup" }, items = new object[] { new { product_id = "4567", quantity = 2 } }, }); // 201# klient: viz /v2/docs/python quote = api.post( '/restaurants/123/quotes', {'fulfillment': {'type': 'pickup'}, 'items': [{'product_id': '4567', 'quantity': 2}]}, ) # 201# the client: see /v2/docs/python quote = api.post( '/restaurants/123/quotes', {'fulfillment': {'type': 'pickup'}, 'items': [{'product_id': '4567', 'quantity': 2}]}, ) # 201// klient: viz /v2/docs/swift let quote: Quote = try await api.post( "/restaurants/123/quotes", body: ["fulfillment": ["type": "pickup"], "items": [["product_id": "4567", "quantity": 2]]] ) // 201// the client: see /v2/docs/swift let quote: Quote = try await api.post( "/restaurants/123/quotes", body: ["fulfillment": ["type": "pickup"], "items": [["product_id": "4567", "quantity": 2]]] ) // 201// klient: viz /v2/docs/dart final quote = pr.Quote.fromJson(await api.post( '/restaurants/123/quotes', {'fulfillment': {'type': 'pickup'}, 'items': [{'product_id': '4567', 'quantity': 2}]}, )); // 201// the client: see /v2/docs/dart final quote = pr.Quote.fromJson(await api.post( '/restaurants/123/quotes', {'fulfillment': {'type': 'pickup'}, 'items': [{'product_id': '4567', 'quantity': 2}]}, )); // 201// klient: viz /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/quotes", map[string]any{ "fulfillment": map[string]any{"type": "pickup"}, "items": []any{map[string]any{"product_id": "4567", "quantity": 2}}, }, nil) var quote model.Quote // 201 if err == nil { err = res.Decode("e) }// the client: see /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/quotes", map[string]any{ "fulfillment": map[string]any{"type": "pickup"}, "items": []any{map[string]any{"product_id": "4567", "quantity": 2}}, }, nil) var quote model.Quote // 201 if err == nil { err = res.Decode("e) }Příklad odpovědi 201Example answer 201
{ "id": "58213", "restaurant_id": "123", "created_at": "2027-01-15T11:42:10+01:00", "expires_at": "2027-01-15T11:57:10+01:00", "customer_id": null, "fulfillment": { "type": "pickup", "speed": "standard", "asap": true, "time": null, "estimated_at": "2027-01-15T12:05:00+01:00" }, "delivery": null, "lines": [ { "id": "1", "type": "product", "variant": "full", "product_id": "4567", "name": "Svíčková na smetaně, houskový knedlík", "quantity": 2, "base_unit_price": { "amount": 19900, "currency": "CZK" }, "unit_price": { "amount": 19900, "currency": "CZK" }, "packaging_unit_price": null, "vat_rate": "12", "add_ons": [], "options": [], "parts": null, "removed_ingredients": [], "note": null, "total": { "amount": 39800, "currency": "CZK" }, "gift_of": null } ], "charges": [], "discounts": [], "totals": { "items": { "amount": 39800, "currency": "CZK" }, "charges": { "amount": 0, "currency": "CZK" }, "discounts": { "amount": 0, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" }, "vat": [ { "rate": "12", "base": { "amount": 35536, "currency": "CZK" }, "vat": { "amount": 4264, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" } } ] }, "payments": [], "amount_due": { "amount": 39800, "currency": "CZK" } } -
Založte objednávku
Create the order
POST /restaurants/{restaurant_id}/orders · createOrder
S platbou online jako
pending: objednávka čeká ve stavuawaiting_payment, porce i vouchery jsou rezervované a kuchyň ji ještě nevidí. Platby musí dát dohromadyamount_duenabídky.With an online payment as
pending: the order waits inawaiting_payment, portions and vouchers are reserved and the kitchen does not see it yet. The payments must add up to the quote'samount_due.curl "https://api.mujprofirest.cz/v2/restaurants/123/orders" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7ef0-9ac6-6e2d9864c7d1" \ -H "Content-Type: application/json" \ -d '{ "quote_id": "58213", "customer": { "name": "Jana Nováková", "phone": "+420777123456", "email": "jana.novakova@example.cz" }, "payments": [ { "method": "online", "status": "pending", "amount": {"amount": 39800, "currency": "CZK"}, "provider": "gopay" } ], "external_id": "A-2027-000124" }'curl "https://api.mujprofirest.cz/v2/restaurants/123/orders" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7ef0-9ac6-6e2d9864c7d1" \ -H "Content-Type: application/json" \ -d '{ "quote_id": "58213", "customer": { "name": "Jana Nováková", "phone": "+420777123456", "email": "jana.novakova@example.cz" }, "payments": [ { "method": "online", "status": "pending", "amount": {"amount": 39800, "currency": "CZK"}, "provider": "gopay" } ], "external_id": "A-2027-000124" }'// klient: viz /v2/docs/js const order = await api.post('/restaurants/123/orders', { quote_id: '58213', customer: { name: 'Jana Nováková', phone: '+420777123456', email: 'jana.novakova@example.cz' }, payments: [ { method: 'online', status: 'pending', amount: { amount: 39800, currency: 'CZK' }, provider: 'gopay', }, ], external_id: 'A-2027-000124', }); // 201// the client: see /v2/docs/js const order = await api.post('/restaurants/123/orders', { quote_id: '58213', customer: { name: 'Jana Nováková', phone: '+420777123456', email: 'jana.novakova@example.cz' }, payments: [ { method: 'online', status: 'pending', amount: { amount: 39800, currency: 'CZK' }, provider: 'gopay', }, ], external_id: 'A-2027-000124', }); // 201// klient: viz /v2/docs/typescript const order = await api.post('/restaurants/123/orders', { quote_id: '58213', customer: { name: 'Jana Nováková', phone: '+420777123456', email: 'jana.novakova@example.cz' }, payments: [ { method: 'online', status: 'pending', amount: { amount: 39800, currency: 'CZK' }, provider: 'gopay', }, ], external_id: 'A-2027-000124', }); // 201 Order// the client: see /v2/docs/typescript const order = await api.post('/restaurants/123/orders', { quote_id: '58213', customer: { name: 'Jana Nováková', phone: '+420777123456', email: 'jana.novakova@example.cz' }, payments: [ { method: 'online', status: 'pending', amount: { amount: 39800, currency: 'CZK' }, provider: 'gopay', }, ], external_id: 'A-2027-000124', }); // 201 Order// klient: viz /v2/docs/php $order = $api->post('/restaurants/123/orders', [ 'quote_id' => '58213', 'customer' => [ 'name' => 'Jana Nováková', 'phone' => '+420777123456', 'email' => 'jana.novakova@example.cz', ], 'payments' => [ [ 'method' => 'online', 'status' => 'pending', 'amount' => ['amount' => 39800, 'currency' => 'CZK'], 'provider' => 'gopay', ], ], 'external_id' => 'A-2027-000124', ]); // 201// the client: see /v2/docs/php $order = $api->post('/restaurants/123/orders', [ 'quote_id' => '58213', 'customer' => [ 'name' => 'Jana Nováková', 'phone' => '+420777123456', 'email' => 'jana.novakova@example.cz', ], 'payments' => [ [ 'method' => 'online', 'status' => 'pending', 'amount' => ['amount' => 39800, 'currency' => 'CZK'], 'provider' => 'gopay', ], ], 'external_id' => 'A-2027-000124', ]); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) Order order = api.post("/restaurants/123/orders", Json.parse(""" { "quote_id": "58213", "customer": { "name": "Jana Nováková", "phone": "+420777123456", "email": "jana.novakova@example.cz" }, "payments": [ { "method": "online", "status": "pending", "amount": {"amount": 39800, "currency": "CZK"}, "provider": "gopay" } ], "external_id": "A-2027-000124" } """), Order::fromJson); // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) Order order = api.post("/restaurants/123/orders", Json.parse(""" { "quote_id": "58213", "customer": { "name": "Jana Nováková", "phone": "+420777123456", "email": "jana.novakova@example.cz" }, "payments": [ { "method": "online", "status": "pending", "amount": {"amount": 39800, "currency": "CZK"}, "provider": "gopay" } ], "external_id": "A-2027-000124" } """), Order::fromJson); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val order = api.post("/restaurants/123/orders", mapOf( "quote_id" to "58213", "customer" to mapOf( "name" to "Jana Nováková", "phone" to "+420777123456", "email" to "jana.novakova@example.cz", ), "payments" to listOf( mapOf( "method" to "online", "status" to "pending", "amount" to mapOf("amount" to 39800, "currency" to "CZK"), "provider" to "gopay", ), ), "external_id" to "A-2027-000124", ), Order::fromJson) // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val order = api.post("/restaurants/123/orders", mapOf( "quote_id" to "58213", "customer" to mapOf( "name" to "Jana Nováková", "phone" to "+420777123456", "email" to "jana.novakova@example.cz", ), "payments" to listOf( mapOf( "method" to "online", "status" to "pending", "amount" to mapOf("amount" to 39800, "currency" to "CZK"), "provider" to "gopay", ), ), "external_id" to "A-2027-000124", ), Order::fromJson) // 201// klient: viz /v2/docs/csharp var order = await api.PostAsync<Order>("/restaurants/123/orders", new { quote_id = "58213", customer = new { name = "Jana Nováková", phone = "+420777123456", email = "jana.novakova@example.cz", }, payments = new object[] { new { method = "online", status = "pending", amount = new { amount = 39800, currency = "CZK" }, provider = "gopay", }, }, external_id = "A-2027-000124", }); // 201// the client: see /v2/docs/csharp var order = await api.PostAsync<Order>("/restaurants/123/orders", new { quote_id = "58213", customer = new { name = "Jana Nováková", phone = "+420777123456", email = "jana.novakova@example.cz", }, payments = new object[] { new { method = "online", status = "pending", amount = new { amount = 39800, currency = "CZK" }, provider = "gopay", }, }, external_id = "A-2027-000124", }); // 201# klient: viz /v2/docs/python order = api.post('/restaurants/123/orders', { 'quote_id': '58213', 'customer': { 'name': 'Jana Nováková', 'phone': '+420777123456', 'email': 'jana.novakova@example.cz', }, 'payments': [ { 'method': 'online', 'status': 'pending', 'amount': {'amount': 39800, 'currency': 'CZK'}, 'provider': 'gopay', }, ], 'external_id': 'A-2027-000124', }) # 201# the client: see /v2/docs/python order = api.post('/restaurants/123/orders', { 'quote_id': '58213', 'customer': { 'name': 'Jana Nováková', 'phone': '+420777123456', 'email': 'jana.novakova@example.cz', }, 'payments': [ { 'method': 'online', 'status': 'pending', 'amount': {'amount': 39800, 'currency': 'CZK'}, 'provider': 'gopay', }, ], 'external_id': 'A-2027-000124', }) # 201// klient: viz /v2/docs/swift let order: Order = try await api.post("/restaurants/123/orders", body: [ "quote_id": "58213", "customer": [ "name": "Jana Nováková", "phone": "+420777123456", "email": "jana.novakova@example.cz", ], "payments": [ [ "method": "online", "status": "pending", "amount": ["amount": 39800, "currency": "CZK"], "provider": "gopay", ], ], "external_id": "A-2027-000124", ]) // 201// the client: see /v2/docs/swift let order: Order = try await api.post("/restaurants/123/orders", body: [ "quote_id": "58213", "customer": [ "name": "Jana Nováková", "phone": "+420777123456", "email": "jana.novakova@example.cz", ], "payments": [ [ "method": "online", "status": "pending", "amount": ["amount": 39800, "currency": "CZK"], "provider": "gopay", ], ], "external_id": "A-2027-000124", ]) // 201// klient: viz /v2/docs/dart final order = pr.Order.fromJson(await api.post('/restaurants/123/orders', { 'quote_id': '58213', 'customer': { 'name': 'Jana Nováková', 'phone': '+420777123456', 'email': 'jana.novakova@example.cz', }, 'payments': [ { 'method': 'online', 'status': 'pending', 'amount': {'amount': 39800, 'currency': 'CZK'}, 'provider': 'gopay', }, ], 'external_id': 'A-2027-000124', })); // 201// the client: see /v2/docs/dart final order = pr.Order.fromJson(await api.post('/restaurants/123/orders', { 'quote_id': '58213', 'customer': { 'name': 'Jana Nováková', 'phone': '+420777123456', 'email': 'jana.novakova@example.cz', }, 'payments': [ { 'method': 'online', 'status': 'pending', 'amount': {'amount': 39800, 'currency': 'CZK'}, 'provider': 'gopay', }, ], 'external_id': 'A-2027-000124', })); // 201// klient: viz /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/orders", map[string]any{ "quote_id": "58213", "customer": map[string]any{ "name": "Jana Nováková", "phone": "+420777123456", "email": "jana.novakova@example.cz", }, "payments": []any{ map[string]any{ "method": "online", "status": "pending", "amount": map[string]any{"amount": 39800, "currency": "CZK"}, "provider": "gopay", }, }, "external_id": "A-2027-000124", }, nil) var order model.Order // 201 if err == nil { err = res.Decode(&order) }// the client: see /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/orders", map[string]any{ "quote_id": "58213", "customer": map[string]any{ "name": "Jana Nováková", "phone": "+420777123456", "email": "jana.novakova@example.cz", }, "payments": []any{ map[string]any{ "method": "online", "status": "pending", "amount": map[string]any{"amount": 39800, "currency": "CZK"}, "provider": "gopay", }, }, "external_id": "A-2027-000124", }, nil) var order model.Order // 201 if err == nil { err = res.Decode(&order) }Příklad odpovědi 201Example answer 201
{ "id": "184224", "restaurant_id": "123", "kitchen_number": null, "status": "awaiting_payment", "status_changed_at": "2027-01-15T11:42:31+01:00", "created_at": "2027-01-15T11:42:31+01:00", "payment_deadline": "2027-01-15T12:12:31+01:00", "fulfillment": { "type": "pickup", "speed": "standard", "asap": true, "time": null, "estimated_at": "2027-01-15T12:05:00+01:00" }, "customer": { "customer_id": null, "name": "Jana Nováková", "phone": "+420777123456", "email": "jana.novakova@example.cz" }, "delivery": null, "lines": [ { "id": "1", "type": "product", "variant": "full", "product_id": "4567", "name": "Svíčková na smetaně, houskový knedlík", "quantity": 2, "base_unit_price": { "amount": 19900, "currency": "CZK" }, "unit_price": { "amount": 19900, "currency": "CZK" }, "packaging_unit_price": null, "vat_rate": "12", "add_ons": [], "options": [], "parts": null, "removed_ingredients": [], "note": null, "total": { "amount": 39800, "currency": "CZK" }, "gift_of": null } ], "charges": [], "discounts": [], "totals": { "items": { "amount": 39800, "currency": "CZK" }, "charges": { "amount": 0, "currency": "CZK" }, "discounts": { "amount": 0, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" }, "vat": [ { "rate": "12", "base": { "amount": 35536, "currency": "CZK" }, "vat": { "amount": 4264, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" } } ] }, "payments": [ { "id": "301878", "method": "online", "status": "pending", "amount": { "amount": 39800, "currency": "CZK" }, "provider": "gopay", "reference": null, "voucher_code": null, "forfeited": null } ], "amount_to_collect": { "amount": 0, "currency": "CZK" }, "loyalty_points_earned": null, "note": null, "cancellation": null, "eet": null, "external_id": "A-2027-000124", "metadata": { "branch": "praha-3" } } -
Potvrďte zaplacení
Confirm the payment
POST /restaurants/{restaurant_id}/orders/{order_id}/confirm-payment · confirmOrderPayment
Až teď jde objednávka do kuchyně. Bez potvrzení se po
payment_deadlinesama zruší – zákazník tak nikdy nezaplatí za objednávku, která nevznikla.Only now the order goes to the kitchen. Without the confirmation it is cancelled after
payment_deadline– a customer is never charged for an order that was not created.curl "https://api.mujprofirest.cz/v2/restaurants/123/orders/184224/confirm-payment" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-711d-893c-093072f9b49d" \ -H "Content-Type: application/json" \ -d '{"provider": "gopay", "reference": "3260145812"}'curl "https://api.mujprofirest.cz/v2/restaurants/123/orders/184224/confirm-payment" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-711d-893c-093072f9b49d" \ -H "Content-Type: application/json" \ -d '{"provider": "gopay", "reference": "3260145812"}'// klient: viz /v2/docs/js const orderPayment = await api.post( '/restaurants/123/orders/184224/confirm-payment', { provider: 'gopay', reference: '3260145812' }, ); // 200// the client: see /v2/docs/js const orderPayment = await api.post( '/restaurants/123/orders/184224/confirm-payment', { provider: 'gopay', reference: '3260145812' }, ); // 200// klient: viz /v2/docs/typescript const orderPayment = await api.post( '/restaurants/123/orders/184224/confirm-payment', { provider: 'gopay', reference: '3260145812' }, ); // 200 Order// the client: see /v2/docs/typescript const orderPayment = await api.post( '/restaurants/123/orders/184224/confirm-payment', { provider: 'gopay', reference: '3260145812' }, ); // 200 Order// klient: viz /v2/docs/php $orderPayment = $api->post( '/restaurants/123/orders/184224/confirm-payment', ['provider' => 'gopay', 'reference' => '3260145812'], ); // 200// the client: see /v2/docs/php $orderPayment = $api->post( '/restaurants/123/orders/184224/confirm-payment', ['provider' => 'gopay', 'reference' => '3260145812'], ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) Order orderPayment = api.post("/restaurants/123/orders/184224/confirm-payment", Json.parse(""" {"provider": "gopay", "reference": "3260145812"} """), Order::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) Order orderPayment = api.post("/restaurants/123/orders/184224/confirm-payment", Json.parse(""" {"provider": "gopay", "reference": "3260145812"} """), Order::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val orderPayment = api.post( "/restaurants/123/orders/184224/confirm-payment", mapOf("provider" to "gopay", "reference" to "3260145812"), Order::fromJson, ) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val orderPayment = api.post( "/restaurants/123/orders/184224/confirm-payment", mapOf("provider" to "gopay", "reference" to "3260145812"), Order::fromJson, ) // 200// klient: viz /v2/docs/csharp var orderPayment = await api.PostAsync<Order>( "/restaurants/123/orders/184224/confirm-payment", new { provider = "gopay", reference = "3260145812" } ); // 200// the client: see /v2/docs/csharp var orderPayment = await api.PostAsync<Order>( "/restaurants/123/orders/184224/confirm-payment", new { provider = "gopay", reference = "3260145812" } ); // 200# klient: viz /v2/docs/python order_payment = api.post( '/restaurants/123/orders/184224/confirm-payment', {'provider': 'gopay', 'reference': '3260145812'}, ) # 200# the client: see /v2/docs/python order_payment = api.post( '/restaurants/123/orders/184224/confirm-payment', {'provider': 'gopay', 'reference': '3260145812'}, ) # 200// klient: viz /v2/docs/swift let orderPayment: Order = try await api.post( "/restaurants/123/orders/184224/confirm-payment", body: ["provider": "gopay", "reference": "3260145812"] ) // 200// the client: see /v2/docs/swift let orderPayment: Order = try await api.post( "/restaurants/123/orders/184224/confirm-payment", body: ["provider": "gopay", "reference": "3260145812"] ) // 200// klient: viz /v2/docs/dart final orderPayment = pr.Order.fromJson(await api.post( '/restaurants/123/orders/184224/confirm-payment', {'provider': 'gopay', 'reference': '3260145812'}, )); // 200// the client: see /v2/docs/dart final orderPayment = pr.Order.fromJson(await api.post( '/restaurants/123/orders/184224/confirm-payment', {'provider': 'gopay', 'reference': '3260145812'}, )); // 200// klient: viz /v2/docs/go res, err := api.Post( ctx, "/restaurants/123/orders/184224/confirm-payment", map[string]any{"provider": "gopay", "reference": "3260145812"}, nil, ) var orderPayment model.Order // 200 if err == nil { err = res.Decode(&orderPayment) }// the client: see /v2/docs/go res, err := api.Post( ctx, "/restaurants/123/orders/184224/confirm-payment", map[string]any{"provider": "gopay", "reference": "3260145812"}, nil, ) var orderPayment model.Order // 200 if err == nil { err = res.Decode(&orderPayment) }Příklad odpovědi 200Example answer 200
{ "id": "184224", "restaurant_id": "123", "kitchen_number": "028", "status": "received", "status_changed_at": "2027-01-15T11:43:40+01:00", "created_at": "2027-01-15T11:42:31+01:00", "payment_deadline": null, "fulfillment": { "type": "pickup", "speed": "standard", "asap": true, "time": null, "estimated_at": "2027-01-15T12:05:00+01:00" }, "customer": { "customer_id": null, "name": "Jana Nováková", "phone": "+420777123456", "email": "jana.novakova@example.cz" }, "delivery": null, "lines": [ { "id": "1", "type": "product", "variant": "full", "product_id": "4567", "name": "Svíčková na smetaně, houskový knedlík", "quantity": 2, "base_unit_price": { "amount": 19900, "currency": "CZK" }, "unit_price": { "amount": 19900, "currency": "CZK" }, "packaging_unit_price": null, "vat_rate": "12", "add_ons": [], "options": [], "parts": null, "removed_ingredients": [], "note": null, "total": { "amount": 39800, "currency": "CZK" }, "gift_of": null } ], "charges": [], "discounts": [], "totals": { "items": { "amount": 39800, "currency": "CZK" }, "charges": { "amount": 0, "currency": "CZK" }, "discounts": { "amount": 0, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" }, "vat": [ { "rate": "12", "base": { "amount": 35536, "currency": "CZK" }, "vat": { "amount": 4264, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" } } ] }, "payments": [ { "id": "301878", "method": "online", "status": "paid", "amount": { "amount": 39800, "currency": "CZK" }, "provider": "gopay", "reference": "3260145812", "voucher_code": null, "forfeited": null } ], "amount_to_collect": { "amount": 0, "currency": "CZK" }, "loyalty_points_earned": null, "note": null, "cancellation": null, "eet": null, "external_id": "A-2027-000124", "metadata": { "branch": "praha-3" } } -
Sledujte, co se děje
Follow what happens
GET /events · listEvents
Ptejte se s posledním
next_cursor(třeba každých pár sekund nebo po webhooku) a kurzor si uložte až po zpracování. Neznámé typy událostí přeskočte.Ask with the latest
next_cursor(every few seconds or after a webhook) and store the cursor only after processing. Skip event types you do not know.curl "https://api.mujprofirest.cz/v2/events?cursor=eyJzZXEiOjkxMDU1MH0&restaurant_id=123&limit=100" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/events?cursor=eyJzZXEiOjkxMDU1MH0&restaurant_id=123&limit=100" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const feed = api.watchEvents({ restaurantId: '123', onEvents: async (events) => { for (const event of events) handle(event); // kurzor se posune až potom }, onReset: () => reloadEverything(), // 410 cursor_expired: načtěte stav znovu });// the client: see /v2/docs/js const feed = api.watchEvents({ restaurantId: '123', onEvents: async (events) => { for (const event of events) handle(event); // the cursor moves only afterwards }, onReset: () => reloadEverything(), // 410 cursor_expired: reload the state });// klient: viz /v2/docs/typescript const feed = api.watchEvents({ restaurantId: '123', onEvents: async (events) => { for (const event of events) handle(event); // kurzor se posune až potom }, onReset: () => reloadEverything(), // 410 cursor_expired: načtěte stav znovu });// the client: see /v2/docs/typescript const feed = api.watchEvents({ restaurantId: '123', onEvents: async (events) => { for (const event of events) handle(event); // the cursor moves only afterwards }, onReset: () => reloadEverything(), // 410 cursor_expired: reload the state });// klient: viz /v2/docs/php $api->watchEvents([ 'restaurantId' => '123', 'onEvents' => function (array $events): void { foreach ($events as $event) { handle($event); } // kurzor se posune až potom }, 'onReset' => fn() => reloadEverything(), // 410 cursor_expired: načtěte stav znovu ])->run();// the client: see /v2/docs/php $api->watchEvents([ 'restaurantId' => '123', 'onEvents' => function (array $events): void { foreach ($events as $event) { handle($event); } // the cursor moves only afterwards }, 'onReset' => fn() => reloadEverything(), // 410 cursor_expired: reload the state ])->run();// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) EventWatcher feed = api.watchEvents(WatchOptions.builder() .restaurantId("123") .onEvents(events -> events.forEach(this::handle)) // kurzor se posune až potom .onReset(error -> reloadEverything()) // 410 cursor_expired: načtěte stav znovu .build()); feed.start();// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) EventWatcher feed = api.watchEvents(WatchOptions.builder() .restaurantId("123") .onEvents(events -> events.forEach(this::handle)) // the cursor moves only afterwards .onReset(error -> reloadEverything()) // 410 cursor_expired: reload the state .build()); feed.start();// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val feed = api.watchEvents(WatchOptions.builder() .restaurantId("123") .onEvents { events -> events.forEach { handle(it) } } // kurzor se posune až potom .onReset { reloadEverything() } // 410 cursor_expired: načtěte stav znovu .build()) feed.start()// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val feed = api.watchEvents(WatchOptions.builder() .restaurantId("123") .onEvents { events -> events.forEach { handle(it) } } // the cursor moves only afterwards .onReset { reloadEverything() } // 410 cursor_expired: reload the state .build()) feed.start()// klient: viz /v2/docs/csharp await api.WatchEventsAsync(new WatchOptions { RestaurantId = "123", OnEvents = async (events, ct) => { foreach (var e in events) await HandleAsync(e, ct); }, // kurzor se posune až potom OnReset = _ => ReloadEverythingAsync(), // 410 cursor_expired: načtěte stav znovu }, stoppingToken);// the client: see /v2/docs/csharp await api.WatchEventsAsync(new WatchOptions { RestaurantId = "123", OnEvents = async (events, ct) => { foreach (var e in events) await HandleAsync(e, ct); }, // the cursor moves only afterwards OnReset = _ => ReloadEverythingAsync(), // 410 cursor_expired: reload the state }, stoppingToken);# klient: viz /v2/docs/python feed = api.watch_events( lambda events: [handle(event) for event in events], # kurzor se posune až potom restaurant_id='123', on_reset=lambda error: reload_everything(), # 410 cursor_expired: načtěte stav znovu ) feed.start()# the client: see /v2/docs/python feed = api.watch_events( lambda events: [handle(event) for event in events], # the cursor moves only afterwards restaurant_id='123', on_reset=lambda error: reload_everything(), # 410 cursor_expired: reload the state ) feed.start()// klient: viz /v2/docs/swift let feed = api.watchEvents(.init( restaurantID: "123", onEvents: { events in for event in events { handle(event) } }, // kurzor se posune až potom onReset: { _ in reloadEverything() } // 410 cursor_expired: načtěte stav znovu )) // feed.cancel() čtení ukončí// the client: see /v2/docs/swift let feed = api.watchEvents(.init( restaurantID: "123", onEvents: { events in for event in events { handle(event) } }, // the cursor moves only afterwards onReset: { _ in reloadEverything() } // 410 cursor_expired: reload the state )) // feed.cancel() čtení ukončí// klient: viz /v2/docs/dart final feed = api.watchEvents( restaurantId: '123', onEvents: (events) async { for (final event in events) handle(event); }, // kurzor se posune až potom onReset: (error) => reloadEverything(), // 410 cursor_expired: načtěte stav znovu )..start();// the client: see /v2/docs/dart final feed = api.watchEvents( restaurantId: '123', onEvents: (events) async { for (final event in events) handle(event); }, // the cursor moves only afterwards onReset: (error) => reloadEverything(), // 410 cursor_expired: reload the state )..start();// klient: viz /v2/docs/go err := api.WatchEvents(ctx, profirest.WatchOptions{ RestaurantID: "123", OnEvents: func(ctx context.Context, events []model.Event) error { for _, event := range events { handle(event) // kurzor se posune až potom } return nil }, OnReset: func(*profirest.APIError) { reloadEverything() }, // 410 cursor_expired: načtěte stav znovu })// the client: see /v2/docs/go err := api.WatchEvents(ctx, profirest.WatchOptions{ RestaurantID: "123", OnEvents: func(ctx context.Context, events []model.Event) error { for _, event := range events { handle(event) // the cursor moves only afterwards } return nil }, OnReset: func(*profirest.APIError) { reloadEverything() }, // 410 cursor_expired: reload the state })Příklad odpovědi 200Example answer 200
{ "data": [ { "id": "910551", "api_version": "2", "sequence": 910551, "type": "order.created", "occurred_at": "2027-01-15T11:42:31+01:00", "connection_id": "2208", "account_id": "7", "restaurant_id": "123", "data": { "id": "184223", "restaurant_id": "123", "kitchen_number": "027", "status": "received", "status_changed_at": "2027-01-15T11:42:31+01:00", "created_at": "2027-01-15T11:42:31+01:00", "payment_deadline": null, "fulfillment": { "type": "pickup", "speed": "standard", "asap": true, "time": null, "estimated_at": "2027-01-15T12:05:00+01:00" }, "customer": { "customer_id": null, "name": "Jana Nováková", "phone": "+420777123456", "email": "jana.novakova@example.cz" }, "delivery": null, "lines": [ { "id": "1", "type": "product", "product_id": "4567", "name": "Svíčková na smetaně, houskový knedlík", "quantity": 2, "base_unit_price": { "amount": 19900, "currency": "CZK" }, "unit_price": { "amount": 19900, "currency": "CZK" }, "packaging_unit_price": null, "vat_rate": "12", "add_ons": [], "options": [], "parts": null, "removed_ingredients": [], "note": null, "total": { "amount": 39800, "currency": "CZK" }, "gift_of": null } ], "charges": [], "discounts": [], "totals": { "items": { "amount": 39800, "currency": "CZK" }, "charges": { "amount": 0, "currency": "CZK" }, "discounts": { "amount": 0, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" }, "vat": [ { "rate": "12", "base": { "amount": 35536, "currency": "CZK" }, "vat": { "amount": 4264, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" } } ] }, "payments": [ { "id": "301877", "method": "cash", "status": "unpaid", "amount": { "amount": 39800, "currency": "CZK" }, "provider": null, "reference": null, "voucher_code": null, "forfeited": null } ], "amount_to_collect": { "amount": 39800, "currency": "CZK" }, "loyalty_points_earned": null, "note": null, "cancellation": null, "external_id": "A-2027-000123", "metadata": { "branch": "praha-3" } } }, { "id": "910563", "api_version": "2", "sequence": 910563, "type": "order.status_changed", "occurred_at": "2027-01-15T11:44:02+01:00", "connection_id": "2208", "account_id": "7", "restaurant_id": "123", "data": { "id": "184223", "restaurant_id": "123", "kitchen_number": "027", "status": "preparing", "status_changed_at": "2027-01-15T11:44:02+01:00", "created_at": "2027-01-15T11:42:31+01:00", "payment_deadline": null, "fulfillment": { "type": "pickup", "speed": "standard", "asap": true, "time": null, "estimated_at": "2027-01-15T12:05:00+01:00" }, "customer": { "customer_id": null, "name": "Jana Nováková", "phone": "+420777123456", "email": "jana.novakova@example.cz" }, "delivery": null, "lines": [ { "id": "1", "type": "product", "product_id": "4567", "name": "Svíčková na smetaně, houskový knedlík", "quantity": 2, "base_unit_price": { "amount": 19900, "currency": "CZK" }, "unit_price": { "amount": 19900, "currency": "CZK" }, "packaging_unit_price": null, "vat_rate": "12", "add_ons": [], "options": [], "parts": null, "removed_ingredients": [], "note": null, "total": { "amount": 39800, "currency": "CZK" }, "gift_of": null } ], "charges": [], "discounts": [], "totals": { "items": { "amount": 39800, "currency": "CZK" }, "charges": { "amount": 0, "currency": "CZK" }, "discounts": { "amount": 0, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" }, "vat": [ { "rate": "12", "base": { "amount": 35536, "currency": "CZK" }, "vat": { "amount": 4264, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" } } ] }, "payments": [ { "id": "301877", "method": "cash", "status": "unpaid", "amount": { "amount": 39800, "currency": "CZK" }, "provider": null, "reference": null, "voucher_code": null, "forfeited": null } ], "amount_to_collect": { "amount": 39800, "currency": "CZK" }, "loyalty_points_earned": null, "note": null, "cancellation": null, "external_id": "A-2027-000123", "metadata": { "branch": "praha-3" } } }, { "id": "910570", "api_version": "2", "sequence": 910570, "type": "availability.changed", "occurred_at": "2027-01-15T11:45:10+01:00", "connection_id": "2208", "account_id": "7", "restaurant_id": "123", "data": { "restaurant_id": "123" } } ], "next_cursor": "eyJzZXEiOjkxMDU3MH0" }
Scénář
Scenario
Pokladna
A cash register
Vlastní zařízení ProfirestuProfirest's own devicePokladna se spáruje kódem, přihlásí obsluhu PINem, drží účty stolů, vystavuje účtenky a na konci dne uzavře směnu. Účtenky počítá i eviduje v EET 2.0 server – zařízení nepotřebuje certifikát.
A register pairs by code, signs the staff in with a PIN, keeps table tabs, issues receipts and closes the shift at the end of the day. The server computes the receipts and records them in EET 2.0 – the device needs no certificate.
-
Spárujte pokladnu kódem
Pair the register by code
POST /oauth/device_authorization · oauthDeviceAuthorization
Zařízení je veřejný klient bez tajemství. Ukažte
user_codenebo QR kódverification_uri_complete; vedoucí ho potvrdí v administraci (Správa PC / zařízení → Připojit kódem) a vybere provozovnu. Kód platí 10 minut.A device is a public client without a secret. Show
user_codeor a QR code ofverification_uri_complete; a manager confirms it in the administration and picks the restaurant. The code is valid for 10 minutes.
Nastavení › Správa PC / zařízení › Připojit kódem: vedoucí potvrdí kód ze zařízení a vybere provozovnu.Settings › PCs / devices › Connect by code: a manager confirms the code from the device and picks the restaurant. curl "https://api.mujprofirest.cz/oauth/device_authorization" \ -d client_id=profirest-pos \ --data-urlencode 'scope=restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write' \ --data-urlencode 'device_name=Pokladna u baru' \ -d device_platform=android \ -d app_version=3.4.1curl "https://api.mujprofirest.cz/oauth/device_authorization" \ -d client_id=profirest-pos \ --data-urlencode 'scope=restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write' \ --data-urlencode 'device_name=Pokladna u baru' \ -d device_platform=android \ -d app_version=3.4.1// klient: viz /v2/docs/js const pairing = await api.pair({ scope: 'restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write', deviceName: 'Pokladna u baru', appVersion: '3.4.1', }); showCode(pairing.userCode, pairing.verificationUriComplete); // kód a QR na displej const connection = await pairing.connected; // po potvrzení v administraci// the client: see /v2/docs/js const pairing = await api.pair({ scope: 'restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write', deviceName: 'Pokladna u baru', appVersion: '3.4.1', }); showCode(pairing.userCode, pairing.verificationUriComplete); // the code and a QR code on the screen const connection = await pairing.connected; // after the confirmation in the administration// klient: viz /v2/docs/typescript const pairing = await api.pair({ scope: 'restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write', deviceName: 'Pokladna u baru', appVersion: '3.4.1', }); showCode(pairing.userCode, pairing.verificationUriComplete); // kód a QR na displej const connection = await pairing.connected; // po potvrzení v administraci// the client: see /v2/docs/typescript const pairing = await api.pair({ scope: 'restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write', deviceName: 'Pokladna u baru', appVersion: '3.4.1', }); showCode(pairing.userCode, pairing.verificationUriComplete); // the code and a QR code on the screen const connection = await pairing.connected; // after the confirmation in the administration// klient: viz /v2/docs/php $pairing = $api->pair(scope: 'restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write', deviceName: 'Pokladna u baru', appVersion: '3.4.1'); showCode($pairing->userCode, $pairing->verificationUriComplete); // kód a QR na displej $connection = $pairing->wait(); // po potvrzení v administraci// the client: see /v2/docs/php $pairing = $api->pair(scope: 'restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write', deviceName: 'Pokladna u baru', appVersion: '3.4.1'); showCode($pairing->userCode, $pairing->verificationUriComplete); // the code and a QR code on the screen $connection = $pairing->wait(); // after the confirmation in the administration// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) Pairing pairing = api.pair(PairOptions.builder() .scope("restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write") .deviceName("Pokladna u baru") .appVersion("3.4.1") .build()); showCode(pairing.getUserCode(), pairing.getVerificationUriComplete()); // kód a QR na displej Map<String, Object> connection = pairing.awaitConnected(); // po potvrzení v administraci// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) Pairing pairing = api.pair(PairOptions.builder() .scope("restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write") .deviceName("Pokladna u baru") .appVersion("3.4.1") .build()); showCode(pairing.getUserCode(), pairing.getVerificationUriComplete()); // the code and a QR code on the screen Map<String, Object> connection = pairing.awaitConnected(); // after the confirmation in the administration// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val pairing = api.pair(PairOptions.builder() .scope("restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write") .deviceName("Pokladna u baru") .appVersion("3.4.1") .build()) showCode(pairing.userCode, pairing.verificationUriComplete) // kód a QR na displej val connection = pairing.awaitConnected() // po potvrzení v administraci// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val pairing = api.pair(PairOptions.builder() .scope("restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write") .deviceName("Pokladna u baru") .appVersion("3.4.1") .build()) showCode(pairing.userCode, pairing.verificationUriComplete) // the code and a QR code on the screen val connection = pairing.awaitConnected() // after the confirmation in the administration// klient: viz /v2/docs/csharp Pairing pairing = await api.PairAsync(new PairOptions { Scope = "restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write", DeviceName = "Pokladna u baru", AppVersion = "3.4.1", }); ShowCode(pairing.UserCode, pairing.VerificationUriComplete); // kód a QR na displej Connection? connection = await pairing.Connected; // po potvrzení v administraci// the client: see /v2/docs/csharp Pairing pairing = await api.PairAsync(new PairOptions { Scope = "restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write", DeviceName = "Pokladna u baru", AppVersion = "3.4.1", }); ShowCode(pairing.UserCode, pairing.VerificationUriComplete); // the code and a QR code on the screen Connection? connection = await pairing.Connected; // after the confirmation in the administration# klient: viz /v2/docs/python pairing = api.pair(scope='restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write', device_name='Pokladna u baru', app_version='3.4.1') show_code(pairing.user_code, pairing.verification_uri_complete) # kód a QR na displej connection = pairing.wait() # po potvrzení v administraci# the client: see /v2/docs/python pairing = api.pair(scope='restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write', device_name='Pokladna u baru', app_version='3.4.1') show_code(pairing.user_code, pairing.verification_uri_complete) # the code and a QR code on the screen connection = pairing.wait() # after the confirmation in the administration// klient: viz /v2/docs/swift let pairing = try await api.pair(scope: "restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write", deviceName: "Pokladna u baru", appVersion: "3.4.1") showCode(pairing.userCode, pairing.verificationURIComplete) // kód a QR na displej let connection = try await pairing.connected() // po potvrzení v administraci// the client: see /v2/docs/swift let pairing = try await api.pair(scope: "restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write", deviceName: "Pokladna u baru", appVersion: "3.4.1") showCode(pairing.userCode, pairing.verificationURIComplete) // the code and a QR code on the screen let connection = try await pairing.connected() // after the confirmation in the administration// klient: viz /v2/docs/dart final pairing = await api.pair(scope: 'restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write', deviceName: 'Pokladna u baru', appVersion: '3.4.1'); showCode(pairing.userCode, pairing.verificationUriComplete); // kód a QR na displej final connection = await pairing.connected; // po potvrzení v administraci// the client: see /v2/docs/dart final pairing = await api.pair(scope: 'restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write', deviceName: 'Pokladna u baru', appVersion: '3.4.1'); showCode(pairing.userCode, pairing.verificationUriComplete); // the code and a QR code on the screen final connection = await pairing.connected; // after the confirmation in the administration// klient: viz /v2/docs/go pairing, err := api.Pair(ctx, profirest.PairOptions{ Scope: "restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write", DeviceName: "Pokladna u baru", AppVersion: "3.4.1", }) showCode(pairing.UserCode, pairing.VerificationURIComplete) // kód a QR na displej connection, err := pairing.Wait(ctx) // po potvrzení v administraci// the client: see /v2/docs/go pairing, err := api.Pair(ctx, profirest.PairOptions{ Scope: "restaurants:read catalog:read staff:read staff:authenticate receipts:read receipts:write", DeviceName: "Pokladna u baru", AppVersion: "3.4.1", }) showCode(pairing.UserCode, pairing.VerificationURIComplete) // the code and a QR code on the screen connection, err := pairing.Wait(ctx) // after the confirmation in the administrationPříklad odpovědi 200Example answer 200
{ "device_code": "pfd_CkWGM50A5JhqtDG1-YhmK69pAlM0TblR7bOxnjTGxAQ", "user_code": "BCDF-GHJK", "verification_uri": "https://www.mujprofirest.cz/zarizeni", "verification_uri_complete": "https://www.mujprofirest.cz/zarizeni?code=BCDFGHJK", "expires_in": 600, "interval": 5 } -
Vyzvedněte tokeny
Pick up the tokens
POST /oauth/token · oauthToken
Ptejte se každých
intervalsekund. Do potvrzení přijdeauthorization_pending, přislow_downpřidejte 5 sekund,access_deniedznamená odmítnutí aexpired_tokenpropadlý kód.Ask every
intervalseconds. Until the confirmation you getauthorization_pending; onslow_downadd 5 seconds,access_deniedmeans a refusal andexpired_tokenan expired code.curl "https://api.mujprofirest.cz/oauth/token" \ -d grant_type=urn:ietf:params:oauth:grant-type:device_code \ -d device_code=pfd_CkWGM50A5JhqtDG1-YhmK69pAlM0TblR7bOxnjTGxAQ \ -d client_id=profirest-poscurl "https://api.mujprofirest.cz/oauth/token" \ -d grant_type=urn:ietf:params:oauth:grant-type:device_code \ -d device_code=pfd_CkWGM50A5JhqtDG1-YhmK69pAlM0TblR7bOxnjTGxAQ \ -d client_id=profirest-pos// klient: viz /v2/docs/js // tokeny vyzvedne a obnovuje knihovna sama (párování nebo dokončení souhlasu); obnova minutu před koncem, jen jednou const connection = await api.connection();// the client: see /v2/docs/js // the library picks up and refreshes the tokens itself (pairing or completing the consent); refreshed a minute early, once const connection = await api.connection();// klient: viz /v2/docs/typescript // tokeny vyzvedne a obnovuje knihovna sama (párování nebo dokončení souhlasu); obnova minutu před koncem, jen jednou const connection = await api.connection();// the client: see /v2/docs/typescript // the library picks up and refreshes the tokens itself (pairing or completing the consent); refreshed a minute early, once const connection = await api.connection();// klient: viz /v2/docs/php // tokeny vyzvedne a obnovuje knihovna sama (párování nebo dokončení souhlasu); obnova minutu před koncem, jen jednou $connection = $api->connection();// the client: see /v2/docs/php // the library picks up and refreshes the tokens itself (pairing or completing the consent); refreshed a minute early, once $connection = $api->connection();// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // tokeny vyzvedne a obnovuje knihovna sama (párování nebo dokončení souhlasu); obnova minutu před koncem, jen jednou Map<String, Object> connection = api.connection();// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library picks up and refreshes the tokens itself (pairing or completing the consent); refreshed a minute early, once Map<String, Object> connection = api.connection();// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // tokeny vyzvedne a obnovuje knihovna sama (párování nebo dokončení souhlasu); obnova minutu před koncem, jen jednou val connection = api.connection()// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library picks up and refreshes the tokens itself (pairing or completing the consent); refreshed a minute early, once val connection = api.connection()// klient: viz /v2/docs/csharp // tokeny vyzvedne a obnovuje knihovna sama (párování nebo dokončení souhlasu); obnova minutu před koncem, jen jednou Connection? connection = await api.ConnectionAsync();// the client: see /v2/docs/csharp // the library picks up and refreshes the tokens itself (pairing or completing the consent); refreshed a minute early, once Connection? connection = await api.ConnectionAsync();# klient: viz /v2/docs/python # tokeny vyzvedne a obnovuje knihovna sama (párování nebo dokončení souhlasu); obnova minutu před koncem, jen jednou connection = api.connection()# the client: see /v2/docs/python # the library picks up and refreshes the tokens itself (pairing or completing the consent); refreshed a minute early, once connection = api.connection()// klient: viz /v2/docs/swift // tokeny vyzvedne a obnovuje knihovna sama (párování nebo dokončení souhlasu); obnova minutu před koncem, jen jednou let connection = try await api.connection()// the client: see /v2/docs/swift // the library picks up and refreshes the tokens itself (pairing or completing the consent); refreshed a minute early, once let connection = try await api.connection()// klient: viz /v2/docs/dart // tokeny vyzvedne a obnovuje knihovna sama (párování nebo dokončení souhlasu); obnova minutu před koncem, jen jednou final connection = await api.connection();// the client: see /v2/docs/dart // the library picks up and refreshes the tokens itself (pairing or completing the consent); refreshed a minute early, once final connection = await api.connection();// klient: viz /v2/docs/go // tokeny vyzvedne a obnovuje knihovna sama (párování nebo dokončení souhlasu); obnova minutu před koncem, jen jednou connection, err := api.Connection(ctx)// the client: see /v2/docs/go // the library picks up and refreshes the tokens itself (pairing or completing the consent); refreshed a minute early, once connection, err := api.Connection(ctx)Příklad odpovědi 200Example answer 200
{ "access_token": "pfa_oFYf1knNtrqnhAVfBRuteW6gr-8X_KOCGVSd7rpOjBo", "token_type": "Bearer", "expires_in": 1800, "refresh_token": "pfr_1swKCIwHaDxlzSZoYMq42Us6GTexdCDZ2jDKKZwJ-3c", "refresh_token_expires_in": 7776000, "scope": "restaurants:read catalog:read orders:write orders:read" } -
Načtěte nastavení
Load the settings
GET /restaurants/{restaurant_id}/device-settings · getDeviceSettings
Firma na účtenku, tiskárny, stanoviště, místnosti se stoly, EET 2.0 a funkce licence.
The company for the receipt, printers, stations, rooms with tables, EET 2.0 and licence features.
curl "https://api.mujprofirest.cz/v2/restaurants/123/device-settings" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/device-settings" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const deviceSettings = await api.get('/restaurants/123/device-settings'); // 200// the client: see /v2/docs/js const deviceSettings = await api.get('/restaurants/123/device-settings'); // 200// klient: viz /v2/docs/typescript const deviceSettings = await api.get('/restaurants/123/device-settings'); // 200 DeviceSettings// the client: see /v2/docs/typescript const deviceSettings = await api.get('/restaurants/123/device-settings'); // 200 DeviceSettings// klient: viz /v2/docs/php $deviceSettings = $api->get('/restaurants/123/device-settings'); // 200// the client: see /v2/docs/php $deviceSettings = $api->get('/restaurants/123/device-settings'); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) DeviceSettings deviceSettings = api.get("/restaurants/123/device-settings", DeviceSettings::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) DeviceSettings deviceSettings = api.get("/restaurants/123/device-settings", DeviceSettings::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val deviceSettings = api.get("/restaurants/123/device-settings", DeviceSettings::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val deviceSettings = api.get("/restaurants/123/device-settings", DeviceSettings::fromJson) // 200// klient: viz /v2/docs/csharp var deviceSettings = await api.GetAsync<DeviceSettings>("/restaurants/123/device-settings"); // 200// the client: see /v2/docs/csharp var deviceSettings = await api.GetAsync<DeviceSettings>("/restaurants/123/device-settings"); // 200# klient: viz /v2/docs/python device_settings = api.get('/restaurants/123/device-settings') # 200# the client: see /v2/docs/python device_settings = api.get('/restaurants/123/device-settings') # 200// klient: viz /v2/docs/swift let deviceSettings: DeviceSettings = try await api.get("/restaurants/123/device-settings") // 200// the client: see /v2/docs/swift let deviceSettings: DeviceSettings = try await api.get("/restaurants/123/device-settings") // 200// klient: viz /v2/docs/dart final deviceSettings = pr.DeviceSettings.fromJson(await api.get('/restaurants/123/device-settings')); // 200// the client: see /v2/docs/dart final deviceSettings = pr.DeviceSettings.fromJson(await api.get('/restaurants/123/device-settings')); // 200// klient: viz /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/device-settings", nil) var deviceSettings model.DeviceSettings // 200 if err == nil { err = res.Decode(&deviceSettings) }// the client: see /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/device-settings", nil) var deviceSettings model.DeviceSettings // 200 if err == nil { err = res.Decode(&deviceSettings) }Příklad odpovědi 200Example answer 200
{ "restaurant": { "name": "Bistro U Lípy", "phone": "+420222333444", "website": "https://www.bistroulipy.cz", "address": { "street": "Vinohradská 1200/48", "city": "Praha 2", "postal_code": "120 00" }, "location": { "lat": 50.0769, "lon": 14.4459 }, "currency": "CZK", "timezone": "Europe/Prague" }, "company": { "name": "U Lípy gastro s.r.o.", "registration_number": "12345678", "vat_number": "CZ12345678", "vat_payer": true, "address": { "street": "Vinohradská 1200/48", "city": "Praha 2", "postal_code": "120 00" }, "email": "ucetni@bistroulipy.cz" }, "receipt_layouts": { "receipt": null, "takeaway": null }, "predefined_notes": [ { "id": "11", "text": "Bez cibule" }, { "id": "12", "text": "Pálivé" }, { "id": "13", "text": "S sebou" } ], "printers": [ { "id": "5", "name": "Účtenky – bar", "sections": "all", "auto_print": false }, { "id": "6", "name": "Bony – kuchyň", "sections": "kitchen", "auto_print": true } ], "kitchen_stations": [ { "id": "2", "name": "Teplá kuchyně", "sections": "kitchen", "auto_print": false }, { "id": "3", "name": "Pizza", "sections": "kitchen", "auto_print": false } ], "rooms": [ { "id": "1", "name": "Restaurace", "width": 100, "height": 100, "tables": [ { "id": "4", "name": "Stůl 4", "kind": "table", "code": "K7M2Q9XB", "left": 12, "top": 20, "width": 14, "height": 10 }, { "id": "7", "name": "Stůl 7", "kind": "table", "code": "3HFD8R2W", "left": 52, "top": 20, "width": 14, "height": 10 }, { "id": "30", "name": "Bar", "kind": "item", "code": null, "left": 80, "top": 70, "width": 18, "height": 25 } ] } ], "kitchen": { "portion_mode": "local", "extra_ticket": false, "redirect_restaurant_id": null, "ready_sms": true }, "eet": { "enabled": true, "premises_id": "273", "certificate_valid_to": "2029-12-31T23:59:59+01:00" }, "features": { "kitchen": true, "multiple_cash_registers": true, "multiple_kitchen_devices": true, "other_devices": true, "attendance": true, "reservations": false, "lodging": false, "daily_menu": true, "table_map": true, "customer_database": true }, "paid_until": "2027-12-31T23:59:59+01:00", "table_ordering": { "enabled": true, "confirm_mode": "first", "empty_table": "staff", "join_code_enabled": true, "max_quantity": 10, "expire_minutes": 10, "respect_opening_hours": true, "category_ids": [ "320" ], "note_max_length": 32, "wifi_ssid": "U Lípy – hosté" }, "pos": { "receipt_cancel_by": "staff", "takeaway_only": false, "calculator": { "enabled": true, "keys": [ { "id": "17", "name": "Pečivo", "vat_rate": "12", "color": "#119b2d", "position": 1 }, { "id": "18", "name": "Zboží", "vat_rate": "21", "color": "#5b4ac0", "position": 2 } ] } } } -
Sortiment pokladny
The register's catalog
GET /restaurants/{restaurant_id}/catalog · getCatalog
S
channel=pospřijde sortiment pokladny včetně ceny půlky, ceny pro zaměstnance a PLU (Product.pos).With
channel=posyou get the register's catalog including the half price, the employee price and the PLU (Product.pos).curl "https://api.mujprofirest.cz/v2/restaurants/123/catalog?channel=pos" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/catalog?channel=pos" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const catalog = await api.get('/restaurants/123/catalog', { query: { channel: 'pos' } }); // 200// the client: see /v2/docs/js const catalog = await api.get('/restaurants/123/catalog', { query: { channel: 'pos' } }); // 200// klient: viz /v2/docs/typescript const catalog = await api.get('/restaurants/123/catalog', { query: { channel: 'pos' } }); // 200 Catalog// the client: see /v2/docs/typescript const catalog = await api.get('/restaurants/123/catalog', { query: { channel: 'pos' } }); // 200 Catalog// klient: viz /v2/docs/php $catalog = $api->get('/restaurants/123/catalog', ['query' => ['channel' => 'pos']]); // 200// the client: see /v2/docs/php $catalog = $api->get('/restaurants/123/catalog', ['query' => ['channel' => 'pos']]); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) Catalog catalog = api.get( "/restaurants/123/catalog", RequestOptions.builder().query("channel", "pos").build(), Catalog::fromJson ); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) Catalog catalog = api.get( "/restaurants/123/catalog", RequestOptions.builder().query("channel", "pos").build(), Catalog::fromJson ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val catalog = api.get( "/restaurants/123/catalog", RequestOptions.builder().query("channel", "pos").build(), Catalog::fromJson, ) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val catalog = api.get( "/restaurants/123/catalog", RequestOptions.builder().query("channel", "pos").build(), Catalog::fromJson, ) // 200// klient: viz /v2/docs/csharp var catalog = await api.GetAsync<Catalog>( "/restaurants/123/catalog", new RequestOptions { Query = new() { ["channel"] = "pos" } } ); // 200// the client: see /v2/docs/csharp var catalog = await api.GetAsync<Catalog>( "/restaurants/123/catalog", new RequestOptions { Query = new() { ["channel"] = "pos" } } ); // 200# klient: viz /v2/docs/python catalog = api.get('/restaurants/123/catalog', query={'channel': 'pos'}) # 200# the client: see /v2/docs/python catalog = api.get('/restaurants/123/catalog', query={'channel': 'pos'}) # 200// klient: viz /v2/docs/swift let catalog: Catalog = try await api.get("/restaurants/123/catalog", options: .init(query: ["channel": "pos"])) // 200// the client: see /v2/docs/swift let catalog: Catalog = try await api.get("/restaurants/123/catalog", options: .init(query: ["channel": "pos"])) // 200// klient: viz /v2/docs/dart final catalog = pr.Catalog.fromJson(await api.get('/restaurants/123/catalog', query: {'channel': 'pos'})); // 200// the client: see /v2/docs/dart final catalog = pr.Catalog.fromJson(await api.get('/restaurants/123/catalog', query: {'channel': 'pos'})); // 200// klient: viz /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/catalog", &profirest.RequestOptions{Query: map[string]any{"channel": "pos"}}, ) var catalog model.Catalog // 200 if err == nil { err = res.Decode(&catalog) }// the client: see /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/catalog", &profirest.RequestOptions{Query: map[string]any{"channel": "pos"}}, ) var catalog model.Catalog // 200 if err == nil { err = res.Decode(&catalog) }Příklad odpovědi 200Example answer 200
{ "restaurant_id": "123", "currency": "CZK", "at": "2027-01-15T11:42:00+01:00", "generated_at": "2027-01-15T11:40:00+01:00", "next_change_at": "2027-01-15T15:00:00+01:00", "categories": [ { "id": "312", "name": "Hlavní jídla", "description": null, "image_url": null, "color": "#e53935", "icon": "fa-utensils", "position": 1, "external_id": null, "metadata": {} }, { "id": "315", "name": "Pizza", "description": "Pečeme v peci na dřevo.", "image_url": null, "color": "#fb8c00", "icon": "fa-pizza-slice", "position": 2, "external_id": null, "metadata": {} }, { "id": "320", "name": "Nápoje", "description": null, "image_url": null, "color": "#1e88e5", "icon": null, "position": 3, "external_id": null, "metadata": {} } ], "products": [ { "id": "4567", "category_id": "312", "name": "Svíčková na smetaně, houskový knedlík", "description": "Hovězí svíčková, smetanová omáčka, brusinky, šlehačka.", "image_url": "https://www.mujprofirest.cz/data/products/4567.jpg", "price": { "amount": 19900, "currency": "CZK" }, "vat_rate": "12", "packaging_fee": null, "weight": 150, "allergens": [ "1", "3", "7", "9" ], "labels": [ "home_made" ], "age_restricted": false, "add_ons": [], "option_groups": [], "removable_ingredients": [], "split": null, "half_price": null, "position": 1, "ean": null, "kitchen_name": null, "size": null, "pos": null, "external_id": null, "metadata": {} }, { "id": "4568", "category_id": "312", "name": "Smažený sýr, hranolky, tatarská omáčka", "description": "Eidam 120 g, hranolky, domácí tatarská omáčka.", "image_url": null, "price": { "amount": 17900, "currency": "CZK" }, "vat_rate": "12", "packaging_fee": null, "weight": 120, "allergens": [ "1", "3", "7" ], "labels": [], "age_restricted": false, "add_ons": [], "option_groups": [], "removable_ingredients": [], "split": null, "half_price": null, "position": 2, "ean": null, "kitchen_name": null, "size": null, "pos": null, "external_id": null, "metadata": {} }, { "id": "4571", "category_id": "315", "name": "Pizza Margherita", "description": "Rajčata San Marzano, mozzarella, bazalka.", "image_url": null, "price": { "amount": 18900, "currency": "CZK" }, "vat_rate": "12", "packaging_fee": null, "weight": 450, "allergens": [ "1", "7" ], "labels": [ "bestseller" ], "age_restricted": false, "add_ons": [ { "product_id": "4602", "name": "Extra sýr", "price": { "amount": 3000, "currency": "CZK" }, "vat_rate": "12", "allergens": [ "7" ] } ], "option_groups": [], "removable_ingredients": [ { "id": "9001", "name": "bazalka" }, { "id": "9002", "name": "oregano" } ], "split": { "half_price": { "amount": 13300, "currency": "CZK" }, "quarter_price": null }, "half_price": null, "position": 1, "ean": null, "kitchen_name": null, "size": null, "pos": null, "external_id": null, "metadata": {} }, { "id": "4590", "category_id": "315", "name": "Vlastní pizza Ø32cm", "description": "Složte si pizzu: těsto a až 8 ingrediencí, 4 jsou v ceně.", "image_url": null, "price": { "amount": 18900, "currency": "CZK" }, "vat_rate": "12", "packaging_fee": null, "weight": 450, "allergens": [ "1", "7" ], "labels": [], "age_restricted": false, "add_ons": [], "option_groups": [ { "id": "71", "name": "Těsto", "min_quantity": 1, "max_quantity": 1, "max_per_option": 1, "included_quantity": 0, "options": [ { "id": "1001", "product_id": "4591", "name": "Klasické těsto", "price": { "amount": 0, "currency": "CZK" }, "base_price": null, "vat_rate": "12", "allergens": [ "1" ] }, { "id": "1002", "product_id": "4592", "name": "Celozrnné těsto", "price": { "amount": 2000, "currency": "CZK" }, "base_price": null, "vat_rate": "12", "allergens": [ "1" ] } ] }, { "id": "72", "name": "Ingredience", "min_quantity": 0, "max_quantity": 8, "max_per_option": 2, "included_quantity": 4, "options": [ { "id": "1101", "product_id": "4605", "name": "Šunka", "price": { "amount": 2400, "currency": "CZK" }, "base_price": null, "vat_rate": "12", "allergens": [] }, { "id": "1102", "product_id": "4603", "name": "Žampiony", "price": { "amount": 1900, "currency": "CZK" }, "base_price": null, "vat_rate": "12", "allergens": [] }, { "id": "1103", "product_id": "4604", "name": "Krevety", "price": { "amount": 0, "currency": "CZK" }, "base_price": { "amount": 20900, "currency": "CZK" }, "vat_rate": "12", "allergens": [ "2" ] }, { "id": "1104", "product_id": "4606", "name": "Olivy", "price": { "amount": 1500, "currency": "CZK" }, "base_price": null, "vat_rate": "12", "allergens": [] } ] } ], "removable_ingredients": [], "split": null, "half_price": null, "position": 4, "ean": null, "kitchen_name": null, "size": null, "pos": null, "external_id": null, "metadata": {} }, { "id": "4580", "category_id": "315", "name": "Ø32cm Prosciutto", "description": "Šunka, mozzarella, rajčata.", "image_url": null, "price": { "amount": 21900, "currency": "CZK" }, "vat_rate": "12", "packaging_fee": null, "weight": 450, "allergens": [ "1", "7" ], "labels": [], "age_restricted": false, "add_ons": [], "option_groups": [], "removable_ingredients": [], "split": null, "half_price": null, "position": 2, "ean": null, "kitchen_name": null, "size": { "group_id": "4580", "name": "Ø32cm", "dish_name": "Prosciutto", "position": 1, "base": true }, "pos": null, "external_id": null, "metadata": {} }, { "id": "4583", "category_id": "315", "name": "Ø42cm Prosciutto", "description": "Šunka, mozzarella, rajčata.", "image_url": null, "price": { "amount": 30900, "currency": "CZK" }, "vat_rate": "12", "packaging_fee": null, "weight": 700, "allergens": [ "1", "7" ], "labels": [], "age_restricted": false, "add_ons": [], "option_groups": [], "removable_ingredients": [], "split": null, "half_price": null, "position": 3, "ean": null, "kitchen_name": null, "size": { "group_id": "4580", "name": "Ø42cm", "dish_name": "Prosciutto", "position": 2, "base": false }, "pos": null, "external_id": null, "metadata": {} }, { "id": "4590", "category_id": "320", "name": "Pivo 12° 0,5 l", "description": null, "image_url": null, "price": { "amount": 6900, "currency": "CZK" }, "vat_rate": "21", "packaging_fee": null, "weight": null, "allergens": [], "labels": [], "age_restricted": true, "add_ons": [], "option_groups": [], "removable_ingredients": [], "split": null, "half_price": null, "position": 1, "ean": null, "kitchen_name": null, "size": null, "pos": null, "external_id": null, "metadata": {} }, { "id": "4593", "category_id": "320", "name": "Domácí limonáda 0,4 l", "description": "Citron, máta, třtinový cukr.", "image_url": null, "price": { "amount": 5900, "currency": "CZK" }, "vat_rate": "12", "packaging_fee": null, "weight": null, "allergens": [], "labels": [], "age_restricted": false, "add_ons": [], "option_groups": [], "removable_ingredients": [], "split": null, "half_price": null, "position": 2, "ean": null, "kitchen_name": null, "size": null, "pos": null, "external_id": null, "metadata": {} } ], "daily_menu": { "date": "2027-01-15", "available_from": "11:00", "available_to": "15:00", "items": [ { "product_id": "4567", "position": 1 }, { "product_id": "4568", "position": 2 } ] }, "allergens": [ { "code": "1", "name": "Obiloviny obsahující lepek" }, { "code": "3", "name": "Vejce" }, { "code": "7", "name": "Mléko" }, { "code": "9", "name": "Celer" } ] } -
Přihlaste obsluhu
Sign the staff in
POST /restaurants/{restaurant_id}/staff-sessions · createStaffSession
PINem nebo čipem. Odpověď nese token zaměstnance – posílejte ho v hlavičce
Profirest-Staff-Token. Když stejný PIN má víc lidí, přijde409 staff_ambiguousscandidates.With a PIN or a card. The answer carries the employee's token – send it in the
Profirest-Staff-Tokenheader. When several people share the PIN you get409 staff_ambiguouswithcandidates.curl "https://api.mujprofirest.cz/v2/restaurants/123/staff-sessions" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{"method": "pin", "secret": "4321"}'curl "https://api.mujprofirest.cz/v2/restaurants/123/staff-sessions" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{"method": "pin", "secret": "4321"}'// klient: viz /v2/docs/js try { const session = await api.signInStaff('123', { method: 'pin', secret: '4321' }); } catch (e) { if (e instanceof ProfirestApi.ApiError && e.code === 'staff_ambiguous') { // stejný PIN má víc lidí: nechte vybrat z kandidátů a pošlete znovu s employee_id } }// the client: see /v2/docs/js try { const session = await api.signInStaff('123', { method: 'pin', secret: '4321' }); } catch (e) { if (e instanceof ProfirestApi.ApiError && e.code === 'staff_ambiguous') { // several people share the PIN: let them pick from the candidates and send it again with employee_id } }// klient: viz /v2/docs/typescript try { const session = await api.signInStaff('123', { method: 'pin', secret: '4321' }); } catch (e) { if (e instanceof ProfirestApi.ApiError && e.code === 'staff_ambiguous') { // stejný PIN má víc lidí: nechte vybrat z kandidátů a pošlete znovu s employee_id } }// the client: see /v2/docs/typescript try { const session = await api.signInStaff('123', { method: 'pin', secret: '4321' }); } catch (e) { if (e instanceof ProfirestApi.ApiError && e.code === 'staff_ambiguous') { // several people share the PIN: let them pick from the candidates and send it again with employee_id } }// klient: viz /v2/docs/php try { $session = $api->signInStaff('123', ['method' => 'pin', 'secret' => '4321']); } catch (\Profirest\Api\ApiError $e) { if ($e->errorCode === 'staff_ambiguous') { // stejný PIN má víc lidí: nechte vybrat z kandidátů a pošlete znovu s employee_id – $e->candidates } }// the client: see /v2/docs/php try { $session = $api->signInStaff('123', ['method' => 'pin', 'secret' => '4321']); } catch (\Profirest\Api\ApiError $e) { if ($e->errorCode === 'staff_ambiguous') { // several people share the PIN: let them pick from the candidates and send it again with employee_id – $e->candidates } }// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) try { Map<String, Object> session = api.signInStaff("123", Json.parse("{\"method\": \"pin\", \"secret\": \"4321\"}")); } catch (ApiException e) { if ("staff_ambiguous".equals(e.getCode())) { // stejný PIN má víc lidí: nechte vybrat z kandidátů a pošlete znovu s employee_id – e.getCandidates() } }// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) try { Map<String, Object> session = api.signInStaff("123", Json.parse("{\"method\": \"pin\", \"secret\": \"4321\"}")); } catch (ApiException e) { if ("staff_ambiguous".equals(e.getCode())) { // several people share the PIN: let them pick from the candidates and send it again with employee_id – e.getCandidates() } }// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) try { val session = api.signInStaff("123", mapOf("method" to "pin", "secret" to "4321")) } catch (e: ApiException) { if (e.code == "staff_ambiguous") { // stejný PIN má víc lidí: nechte vybrat z kandidátů a pošlete znovu s employee_id – e.candidates } }// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) try { val session = api.signInStaff("123", mapOf("method" to "pin", "secret" to "4321")) } catch (e: ApiException) { if (e.code == "staff_ambiguous") { // several people share the PIN: let them pick from the candidates and send it again with employee_id – e.candidates } }// klient: viz /v2/docs/csharp try { StaffSession session = await api.SignInStaffAsync("123", new StaffCredential { Method = "pin", Secret = "4321" }); } catch (ProfirestApiException e) when (e.Code == ErrorCodes.StaffAmbiguous) { // stejný PIN má víc lidí: nechte vybrat z kandidátů a pošlete znovu s employee_id – e.Candidates }// the client: see /v2/docs/csharp try { StaffSession session = await api.SignInStaffAsync("123", new StaffCredential { Method = "pin", Secret = "4321" }); } catch (ProfirestApiException e) when (e.Code == ErrorCodes.StaffAmbiguous) { // several people share the PIN: let them pick from the candidates and send it again with employee_id – e.Candidates }# klient: viz /v2/docs/python try: session = api.sign_in_staff('123', {'method': 'pin', 'secret': '4321'}) except ApiError as e: if e.code == 'staff_ambiguous': pass # stejný PIN má víc lidí: nechte vybrat z kandidátů a pošlete znovu s employee_id – e.candidates# the client: see /v2/docs/python try: session = api.sign_in_staff('123', {'method': 'pin', 'secret': '4321'}) except ApiError as e: if e.code == 'staff_ambiguous': pass # several people share the PIN: let them pick from the candidates and send it again with employee_id – e.candidates// klient: viz /v2/docs/swift do { let session = try await api.signInStaff(restaurantID: "123", credential: StaffCredential(method: "pin", secret: "4321")) } catch let error as ProfirestAPIError where error.code == ErrorCode.staffAmbiguous { // stejný PIN má víc lidí: nechte vybrat z kandidátů a pošlete znovu s employee_id – error.candidates }// the client: see /v2/docs/swift do { let session = try await api.signInStaff(restaurantID: "123", credential: StaffCredential(method: "pin", secret: "4321")) } catch let error as ProfirestAPIError where error.code == ErrorCode.staffAmbiguous { // several people share the PIN: let them pick from the candidates and send it again with employee_id – error.candidates }// klient: viz /v2/docs/dart try { final session = await api.signInStaff('123', {'method': 'pin', 'secret': '4321'}); } on ApiError catch (e) { if (e.code == 'staff_ambiguous') { // stejný PIN má víc lidí: nechte vybrat z kandidátů a pošlete znovu s employee_id – e.candidates } }// the client: see /v2/docs/dart try { final session = await api.signInStaff('123', {'method': 'pin', 'secret': '4321'}); } on ApiError catch (e) { if (e.code == 'staff_ambiguous') { // several people share the PIN: let them pick from the candidates and send it again with employee_id – e.candidates } }// klient: viz /v2/docs/go session, err := api.SignInStaff(ctx, "123", model.StaffCredential{Method: "pin", Secret: "4321"}) var apiErr *profirest.APIError if errors.As(err, &apiErr) && apiErr.Code == profirest.CodeStaffAmbiguous { // stejný PIN má víc lidí: nechte vybrat z kandidátů a pošlete znovu s employee_id – apiErr.Candidates }// the client: see /v2/docs/go session, err := api.SignInStaff(ctx, "123", model.StaffCredential{Method: "pin", Secret: "4321"}) var apiErr *profirest.APIError if errors.As(err, &apiErr) && apiErr.Code == profirest.CodeStaffAmbiguous { // several people share the PIN: let them pick from the candidates and send it again with employee_id – apiErr.Candidates }Příklad odpovědi 201Example answer 201
{ "token": "pfe_xfJc1S39DYennALz7S7F_mZZyQTbS0VzjnJDKTXKoQc", "expires_at": "2027-01-15T12:08:18+01:00", "max_expires_at": "2027-01-15T23:59:59+01:00", "idle_timeout_seconds": 300, "employee": { "id": "58", "name": "Jana Dvořáková", "roles": [ "pos" ], "attendance": { "enabled": true }, "sign_in": { "pin": true, "card": true }, "offline_approval": { "salt": "pHk3r9QnW1xY0aBcDeFgHw", "iterations": 100000, "check": 141 }, "offline_sign_in": { "salt": "pHk3r9QnW1xY0aBcDeFgHw", "iterations": 100000, "check": 141 } } } -
Účet stolu
A table tab
PUT /restaurants/{restaurant_id}/tabs/{tab_id} · putTab
Celý účet stolu se ukládá najednou s
If-Match; když ho mezitím změnilo jiné zařízení, přijde412– načtěte ho znovu a rozhodněte.The whole tab is stored at once with
If-Match; when another device changed it meanwhile you get412– read it again and decide.curl -X PUT "https://api.mujprofirest.cz/v2/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H 'If-Match: "tab-2"' \ -H "Content-Type: application/json" \ -d '{ "table_name": "Stůl 4", "items": [ { "id": "l-1", "product_id": "4567", "quantity": 1, "course": 1, "sent_to_kitchen": true }, {"id": "l-2", "product_id": "4590", "quantity": 2} ] }'curl -X PUT "https://api.mujprofirest.cz/v2/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H 'If-Match: "tab-2"' \ -H "Content-Type: application/json" \ -d '{ "table_name": "Stůl 4", "items": [ { "id": "l-1", "product_id": "4567", "quantity": 1, "course": 1, "sent_to_kitchen": true }, {"id": "l-2", "product_id": "4590", "quantity": 2} ] }'// klient: viz /v2/docs/js // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const tab = await api.put('/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418', { table_name: 'Stůl 4', items: [ { id: 'l-1', product_id: '4567', quantity: 1, course: 1, sent_to_kitchen: true }, { id: 'l-2', product_id: '4590', quantity: 2 }, ], }, { ifMatch: '"tab-2"' }); // 201// the client: see /v2/docs/js // the library adds the employee's token itself (after the employee signs in) const tab = await api.put('/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418', { table_name: 'Stůl 4', items: [ { id: 'l-1', product_id: '4567', quantity: 1, course: 1, sent_to_kitchen: true }, { id: 'l-2', product_id: '4590', quantity: 2 }, ], }, { ifMatch: '"tab-2"' }); // 201// klient: viz /v2/docs/typescript // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const tab = await api.put('/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418', { table_name: 'Stůl 4', items: [ { id: 'l-1', product_id: '4567', quantity: 1, course: 1, sent_to_kitchen: true }, { id: 'l-2', product_id: '4590', quantity: 2 }, ], }, { ifMatch: '"tab-2"' }); // 201 Tab// the client: see /v2/docs/typescript // the library adds the employee's token itself (after the employee signs in) const tab = await api.put('/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418', { table_name: 'Stůl 4', items: [ { id: 'l-1', product_id: '4567', quantity: 1, course: 1, sent_to_kitchen: true }, { id: 'l-2', product_id: '4590', quantity: 2 }, ], }, { ifMatch: '"tab-2"' }); // 201 Tab// klient: viz /v2/docs/php // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) $tab = $api->put('/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418', [ 'table_name' => 'Stůl 4', 'items' => [ [ 'id' => 'l-1', 'product_id' => '4567', 'quantity' => 1, 'course' => 1, 'sent_to_kitchen' => true, ], ['id' => 'l-2', 'product_id' => '4590', 'quantity' => 2], ], ], ['ifMatch' => '"tab-2"']); // 201// the client: see /v2/docs/php // the library adds the employee's token itself (after the employee signs in) $tab = $api->put('/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418', [ 'table_name' => 'Stůl 4', 'items' => [ [ 'id' => 'l-1', 'product_id' => '4567', 'quantity' => 1, 'course' => 1, 'sent_to_kitchen' => true, ], ['id' => 'l-2', 'product_id' => '4590', 'quantity' => 2], ], ], ['ifMatch' => '"tab-2"']); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) Tab tab = api.put("/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418", Json.parse(""" { "table_name": "Stůl 4", "items": [ { "id": "l-1", "product_id": "4567", "quantity": 1, "course": 1, "sent_to_kitchen": true }, {"id": "l-2", "product_id": "4590", "quantity": 2} ] } """), RequestOptions.builder().ifMatch("\"tab-2\"").build(), Tab::fromJson); // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) Tab tab = api.put("/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418", Json.parse(""" { "table_name": "Stůl 4", "items": [ { "id": "l-1", "product_id": "4567", "quantity": 1, "course": 1, "sent_to_kitchen": true }, {"id": "l-2", "product_id": "4590", "quantity": 2} ] } """), RequestOptions.builder().ifMatch("\"tab-2\"").build(), Tab::fromJson); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) val tab = api.put("/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418", mapOf( "table_name" to "Stůl 4", "items" to listOf( mapOf( "id" to "l-1", "product_id" to "4567", "quantity" to 1, "course" to 1, "sent_to_kitchen" to true, ), mapOf("id" to "l-2", "product_id" to "4590", "quantity" to 2), ), ), RequestOptions.builder().ifMatch("\"tab-2\"").build(), Tab::fromJson) // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) val tab = api.put("/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418", mapOf( "table_name" to "Stůl 4", "items" to listOf( mapOf( "id" to "l-1", "product_id" to "4567", "quantity" to 1, "course" to 1, "sent_to_kitchen" to true, ), mapOf("id" to "l-2", "product_id" to "4590", "quantity" to 2), ), ), RequestOptions.builder().ifMatch("\"tab-2\"").build(), Tab::fromJson) // 201// klient: viz /v2/docs/csharp // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) var tab = await api.PutAsync<Tab>("/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418", new { table_name = "Stůl 4", items = new object[] { new { id = "l-1", product_id = "4567", quantity = 1, course = 1, sent_to_kitchen = true, }, new { id = "l-2", product_id = "4590", quantity = 2 }, }, }, new RequestOptions { IfMatch = "\"tab-2\"" }); // 201// the client: see /v2/docs/csharp // the library adds the employee's token itself (after the employee signs in) var tab = await api.PutAsync<Tab>("/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418", new { table_name = "Stůl 4", items = new object[] { new { id = "l-1", product_id = "4567", quantity = 1, course = 1, sent_to_kitchen = true, }, new { id = "l-2", product_id = "4590", quantity = 2 }, }, }, new RequestOptions { IfMatch = "\"tab-2\"" }); // 201# klient: viz /v2/docs/python # token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) tab = api.put('/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418', { 'table_name': 'Stůl 4', 'items': [ { 'id': 'l-1', 'product_id': '4567', 'quantity': 1, 'course': 1, 'sent_to_kitchen': True, }, {'id': 'l-2', 'product_id': '4590', 'quantity': 2}, ], }, if_match='"tab-2"') # 201# the client: see /v2/docs/python # the library adds the employee's token itself (after the employee signs in) tab = api.put('/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418', { 'table_name': 'Stůl 4', 'items': [ { 'id': 'l-1', 'product_id': '4567', 'quantity': 1, 'course': 1, 'sent_to_kitchen': True, }, {'id': 'l-2', 'product_id': '4590', 'quantity': 2}, ], }, if_match='"tab-2"') # 201// klient: viz /v2/docs/swift // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) let tab: Tab = try await api.put("/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418", body: [ "table_name": "Stůl 4", "items": [ [ "id": "l-1", "product_id": "4567", "quantity": 1, "course": 1, "sent_to_kitchen": true, ], ["id": "l-2", "product_id": "4590", "quantity": 2], ], ], options: .init(ifMatch: "\"tab-2\"")) // 201// the client: see /v2/docs/swift // the library adds the employee's token itself (after the employee signs in) let tab: Tab = try await api.put("/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418", body: [ "table_name": "Stůl 4", "items": [ [ "id": "l-1", "product_id": "4567", "quantity": 1, "course": 1, "sent_to_kitchen": true, ], ["id": "l-2", "product_id": "4590", "quantity": 2], ], ], options: .init(ifMatch: "\"tab-2\"")) // 201// klient: viz /v2/docs/dart // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) final tab = pr.Tab.fromJson(await api.put('/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418', { 'table_name': 'Stůl 4', 'items': [ { 'id': 'l-1', 'product_id': '4567', 'quantity': 1, 'course': 1, 'sent_to_kitchen': true, }, {'id': 'l-2', 'product_id': '4590', 'quantity': 2}, ], }, ifMatch: '"tab-2"')); // 201// the client: see /v2/docs/dart // the library adds the employee's token itself (after the employee signs in) final tab = pr.Tab.fromJson(await api.put('/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418', { 'table_name': 'Stůl 4', 'items': [ { 'id': 'l-1', 'product_id': '4567', 'quantity': 1, 'course': 1, 'sent_to_kitchen': true, }, {'id': 'l-2', 'product_id': '4590', 'quantity': 2}, ], }, ifMatch: '"tab-2"')); // 201// klient: viz /v2/docs/go // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) res, err := api.Put(ctx, "/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418", map[string]any{ "table_name": "Stůl 4", "items": []any{ map[string]any{ "id": "l-1", "product_id": "4567", "quantity": 1, "course": 1, "sent_to_kitchen": true, }, map[string]any{"id": "l-2", "product_id": "4590", "quantity": 2}, }, }, &profirest.RequestOptions{IfMatch: "\"tab-2\""}) var tab model.Tab // 201 if err == nil { err = res.Decode(&tab) }// the client: see /v2/docs/go // the library adds the employee's token itself (after the employee signs in) res, err := api.Put(ctx, "/restaurants/123/tabs/01a318f0-a0c0-7834-8f31-7973aa8bb418", map[string]any{ "table_name": "Stůl 4", "items": []any{ map[string]any{ "id": "l-1", "product_id": "4567", "quantity": 1, "course": 1, "sent_to_kitchen": true, }, map[string]any{"id": "l-2", "product_id": "4590", "quantity": 2}, }, }, &profirest.RequestOptions{IfMatch: "\"tab-2\""}) var tab model.Tab // 201 if err == nil { err = res.Decode(&tab) }Příklad odpovědi 200Example answer 200
{ "id": "01a318f0-a0c0-7834-8f31-7973aa8bb418", "restaurant_id": "123", "table_name": "Stůl 4", "note": null, "opened_at": "2027-01-15T11:48:02+01:00", "opened_by": { "id": "58", "name": "Jana Dvořáková" }, "updated_by": { "id": "58", "name": "Jana Dvořáková" }, "lines": [ { "id": "l-1", "product_id": "4567", "name": "Svíčková na smetaně, houskový knedlík", "variant": "full", "quantity": 1, "ordered_at": "2027-01-15T11:51:40+01:00", "unit_price": { "amount": 19900, "currency": "CZK" }, "add_ons": [], "removed_ingredients": [], "note": null, "course": 1, "sent_to_kitchen": true, "total": { "amount": 19900, "currency": "CZK" } }, { "id": "l-2", "product_id": "4590", "name": "Pivo 12° 0,5 l", "variant": "full", "quantity": 2, "ordered_at": "2027-01-15T11:49:15+01:00", "unit_price": { "amount": 6900, "currency": "CZK" }, "add_ons": [], "removed_ingredients": [], "note": null, "course": 0, "sent_to_kitchen": false, "total": { "amount": 13800, "currency": "CZK" } } ], "totals": { "items": { "amount": 33700, "currency": "CZK" }, "total": { "amount": 33700, "currency": "CZK" } }, "version": 3, "status": "open", "updated_at": "2027-01-15T11:51:40+01:00", "device_id": "512", "closed_at": null, "receipt_id": null } -
Spočítejte účtenku
Price the receipt
POST /restaurants/{restaurant_id}/receipts/preview · previewReceipt
Stejné položky a slevy jako u vystavení; vrátí součty, DPH a
cash_amount_duepo zaokrouhlení hotovosti.The same items and discounts as for issuing; returns the totals, VAT and
cash_amount_dueafter cash rounding.curl "https://api.mujprofirest.cz/v2/restaurants/123/receipts/preview" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "order_type": "dine_in", "items": [ {"product_id": "4567", "quantity": 1, "course": 1}, {"product_id": "4590", "quantity": 2} ] }'curl "https://api.mujprofirest.cz/v2/restaurants/123/receipts/preview" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "order_type": "dine_in", "items": [ {"product_id": "4567", "quantity": 1, "course": 1}, {"product_id": "4590", "quantity": 2} ] }'// klient: viz /v2/docs/js // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const receipt = await api.post('/restaurants/123/receipts/preview', { order_type: 'dine_in', items: [{ product_id: '4567', quantity: 1, course: 1 }, { product_id: '4590', quantity: 2 }], }); // 200// the client: see /v2/docs/js // the library adds the employee's token itself (after the employee signs in) const receipt = await api.post('/restaurants/123/receipts/preview', { order_type: 'dine_in', items: [{ product_id: '4567', quantity: 1, course: 1 }, { product_id: '4590', quantity: 2 }], }); // 200// klient: viz /v2/docs/typescript // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const receipt = await api.post('/restaurants/123/receipts/preview', { order_type: 'dine_in', items: [{ product_id: '4567', quantity: 1, course: 1 }, { product_id: '4590', quantity: 2 }], }); // 200 ReceiptPreview// the client: see /v2/docs/typescript // the library adds the employee's token itself (after the employee signs in) const receipt = await api.post('/restaurants/123/receipts/preview', { order_type: 'dine_in', items: [{ product_id: '4567', quantity: 1, course: 1 }, { product_id: '4590', quantity: 2 }], }); // 200 ReceiptPreview// klient: viz /v2/docs/php // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) $receipt = $api->post('/restaurants/123/receipts/preview', [ 'order_type' => 'dine_in', 'items' => [ ['product_id' => '4567', 'quantity' => 1, 'course' => 1], ['product_id' => '4590', 'quantity' => 2], ], ]); // 200// the client: see /v2/docs/php // the library adds the employee's token itself (after the employee signs in) $receipt = $api->post('/restaurants/123/receipts/preview', [ 'order_type' => 'dine_in', 'items' => [ ['product_id' => '4567', 'quantity' => 1, 'course' => 1], ['product_id' => '4590', 'quantity' => 2], ], ]); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) ReceiptPreview receipt = api.post("/restaurants/123/receipts/preview", Json.parse(""" { "order_type": "dine_in", "items": [ {"product_id": "4567", "quantity": 1, "course": 1}, {"product_id": "4590", "quantity": 2} ] } """), ReceiptPreview::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) ReceiptPreview receipt = api.post("/restaurants/123/receipts/preview", Json.parse(""" { "order_type": "dine_in", "items": [ {"product_id": "4567", "quantity": 1, "course": 1}, {"product_id": "4590", "quantity": 2} ] } """), ReceiptPreview::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) val receipt = api.post("/restaurants/123/receipts/preview", mapOf( "order_type" to "dine_in", "items" to listOf( mapOf("product_id" to "4567", "quantity" to 1, "course" to 1), mapOf("product_id" to "4590", "quantity" to 2), ), ), ReceiptPreview::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) val receipt = api.post("/restaurants/123/receipts/preview", mapOf( "order_type" to "dine_in", "items" to listOf( mapOf("product_id" to "4567", "quantity" to 1, "course" to 1), mapOf("product_id" to "4590", "quantity" to 2), ), ), ReceiptPreview::fromJson) // 200// klient: viz /v2/docs/csharp // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) var receipt = await api.PostAsync<ReceiptPreview>("/restaurants/123/receipts/preview", new { order_type = "dine_in", items = new object[] { new { product_id = "4567", quantity = 1, course = 1 }, new { product_id = "4590", quantity = 2 }, }, }); // 200// the client: see /v2/docs/csharp // the library adds the employee's token itself (after the employee signs in) var receipt = await api.PostAsync<ReceiptPreview>("/restaurants/123/receipts/preview", new { order_type = "dine_in", items = new object[] { new { product_id = "4567", quantity = 1, course = 1 }, new { product_id = "4590", quantity = 2 }, }, }); // 200# klient: viz /v2/docs/python # token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) receipt = api.post('/restaurants/123/receipts/preview', { 'order_type': 'dine_in', 'items': [ {'product_id': '4567', 'quantity': 1, 'course': 1}, {'product_id': '4590', 'quantity': 2}, ], }) # 200# the client: see /v2/docs/python # the library adds the employee's token itself (after the employee signs in) receipt = api.post('/restaurants/123/receipts/preview', { 'order_type': 'dine_in', 'items': [ {'product_id': '4567', 'quantity': 1, 'course': 1}, {'product_id': '4590', 'quantity': 2}, ], }) # 200// klient: viz /v2/docs/swift // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) let receipt: ReceiptPreview = try await api.post("/restaurants/123/receipts/preview", body: [ "order_type": "dine_in", "items": [ ["product_id": "4567", "quantity": 1, "course": 1], ["product_id": "4590", "quantity": 2], ], ]) // 200// the client: see /v2/docs/swift // the library adds the employee's token itself (after the employee signs in) let receipt: ReceiptPreview = try await api.post("/restaurants/123/receipts/preview", body: [ "order_type": "dine_in", "items": [ ["product_id": "4567", "quantity": 1, "course": 1], ["product_id": "4590", "quantity": 2], ], ]) // 200// klient: viz /v2/docs/dart // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) final receipt = pr.ReceiptPreview.fromJson(await api.post('/restaurants/123/receipts/preview', { 'order_type': 'dine_in', 'items': [ {'product_id': '4567', 'quantity': 1, 'course': 1}, {'product_id': '4590', 'quantity': 2}, ], })); // 200// the client: see /v2/docs/dart // the library adds the employee's token itself (after the employee signs in) final receipt = pr.ReceiptPreview.fromJson(await api.post('/restaurants/123/receipts/preview', { 'order_type': 'dine_in', 'items': [ {'product_id': '4567', 'quantity': 1, 'course': 1}, {'product_id': '4590', 'quantity': 2}, ], })); // 200// klient: viz /v2/docs/go // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) res, err := api.Post(ctx, "/restaurants/123/receipts/preview", map[string]any{ "order_type": "dine_in", "items": []any{ map[string]any{"product_id": "4567", "quantity": 1, "course": 1}, map[string]any{"product_id": "4590", "quantity": 2}, }, }, nil) var receipt model.ReceiptPreview // 200 if err == nil { err = res.Decode(&receipt) }// the client: see /v2/docs/go // the library adds the employee's token itself (after the employee signs in) res, err := api.Post(ctx, "/restaurants/123/receipts/preview", map[string]any{ "order_type": "dine_in", "items": []any{ map[string]any{"product_id": "4567", "quantity": 1, "course": 1}, map[string]any{"product_id": "4590", "quantity": 2}, }, }, nil) var receipt model.ReceiptPreview // 200 if err == nil { err = res.Decode(&receipt) }Příklad odpovědi 200Example answer 200
{ "lines": [ { "id": "1", "type": "product", "product_id": "4567", "name": "Svíčková na smetaně, houskový knedlík", "variant": "full", "quantity": 1, "unit_price": { "amount": 19900, "currency": "CZK" }, "catalog_unit_price": { "amount": 19900, "currency": "CZK" }, "price_source": "catalog", "at_employee_price": false, "packaging_unit_price": null, "vat_rate": "12", "add_ons": [], "note": null, "course": 1, "total": { "amount": 19900, "currency": "CZK" }, "voucher_code": null }, { "id": "2", "type": "product", "product_id": "4590", "name": "Pivo 12° 0,5 l", "variant": "full", "quantity": 2, "unit_price": { "amount": 6900, "currency": "CZK" }, "catalog_unit_price": { "amount": 6900, "currency": "CZK" }, "price_source": "catalog", "at_employee_price": false, "packaging_unit_price": null, "vat_rate": "21", "add_ons": [], "note": null, "course": 0, "total": { "amount": 13800, "currency": "CZK" }, "voucher_code": null } ], "discounts": [], "totals": { "items": { "amount": 33700, "currency": "CZK" }, "charges": { "amount": 0, "currency": "CZK" }, "discounts": { "amount": 0, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "total": { "amount": 33700, "currency": "CZK" }, "vat": [ { "rate": "21", "base": { "amount": 11405, "currency": "CZK" }, "vat": { "amount": 2395, "currency": "CZK" }, "total": { "amount": 13800, "currency": "CZK" } }, { "rate": "12", "base": { "amount": 17768, "currency": "CZK" }, "vat": { "amount": 2132, "currency": "CZK" }, "total": { "amount": 19900, "currency": "CZK" } } ] }, "price_differences": [], "cash_amount_due": { "amount": 33700, "currency": "CZK" }, "eet_recorded": true } -
Vystavte účtenku
Issue the receipt
POST /restaurants/{restaurant_id}/receipts · createReceipt
idje UUID ze zařízení: opakování (i po výpadku sítě) účtenku nezdvojí a vrátí ji se stavem200. Server ji zaeviduje v EET 2.0 sám.idis a UUID made on the device: a repeat (even after a network outage) never issues it twice and returns it with200. The server records it in EET 2.0 itself.curl "https://api.mujprofirest.cz/v2/restaurants/123/receipts" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "id": "01a318f0-a0c0-750d-8c36-65b69d55462d", "number": 1001, "issued_at": "2027-01-15T12:03:18+01:00", "table_name": "Stůl 4", "order_type": "dine_in", "tab_id": "01a318f0-a0c0-7834-8f31-7973aa8bb418", "tab_version": 3, "items": [ {"product_id": "4567", "quantity": 1, "course": 1}, {"product_id": "4590", "quantity": 2} ], "payments": [ { "method": "cash", "amount": {"amount": 33700, "currency": "CZK"}, "tendered": {"amount": 40000, "currency": "CZK"} } ] }'curl "https://api.mujprofirest.cz/v2/restaurants/123/receipts" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "id": "01a318f0-a0c0-750d-8c36-65b69d55462d", "number": 1001, "issued_at": "2027-01-15T12:03:18+01:00", "table_name": "Stůl 4", "order_type": "dine_in", "tab_id": "01a318f0-a0c0-7834-8f31-7973aa8bb418", "tab_version": 3, "items": [ {"product_id": "4567", "quantity": 1, "course": 1}, {"product_id": "4590", "quantity": 2} ], "payments": [ { "method": "cash", "amount": {"amount": 33700, "currency": "CZK"}, "tendered": {"amount": 40000, "currency": "CZK"} } ] }'// klient: viz /v2/docs/js // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const receipt = await api.post('/restaurants/123/receipts', { id: '01a318f0-a0c0-750d-8c36-65b69d55462d', number: 1001, issued_at: '2027-01-15T12:03:18+01:00', table_name: 'Stůl 4', order_type: 'dine_in', tab_id: '01a318f0-a0c0-7834-8f31-7973aa8bb418', tab_version: 3, items: [{ product_id: '4567', quantity: 1, course: 1 }, { product_id: '4590', quantity: 2 }], payments: [ { method: 'cash', amount: { amount: 33700, currency: 'CZK' }, tendered: { amount: 40000, currency: 'CZK' }, }, ], }); // 201// the client: see /v2/docs/js // the library adds the employee's token itself (after the employee signs in) const receipt = await api.post('/restaurants/123/receipts', { id: '01a318f0-a0c0-750d-8c36-65b69d55462d', number: 1001, issued_at: '2027-01-15T12:03:18+01:00', table_name: 'Stůl 4', order_type: 'dine_in', tab_id: '01a318f0-a0c0-7834-8f31-7973aa8bb418', tab_version: 3, items: [{ product_id: '4567', quantity: 1, course: 1 }, { product_id: '4590', quantity: 2 }], payments: [ { method: 'cash', amount: { amount: 33700, currency: 'CZK' }, tendered: { amount: 40000, currency: 'CZK' }, }, ], }); // 201// klient: viz /v2/docs/typescript // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const receipt = await api.post('/restaurants/123/receipts', { id: '01a318f0-a0c0-750d-8c36-65b69d55462d', number: 1001, issued_at: '2027-01-15T12:03:18+01:00', table_name: 'Stůl 4', order_type: 'dine_in', tab_id: '01a318f0-a0c0-7834-8f31-7973aa8bb418', tab_version: 3, items: [{ product_id: '4567', quantity: 1, course: 1 }, { product_id: '4590', quantity: 2 }], payments: [ { method: 'cash', amount: { amount: 33700, currency: 'CZK' }, tendered: { amount: 40000, currency: 'CZK' }, }, ], }); // 201 Receipt// the client: see /v2/docs/typescript // the library adds the employee's token itself (after the employee signs in) const receipt = await api.post('/restaurants/123/receipts', { id: '01a318f0-a0c0-750d-8c36-65b69d55462d', number: 1001, issued_at: '2027-01-15T12:03:18+01:00', table_name: 'Stůl 4', order_type: 'dine_in', tab_id: '01a318f0-a0c0-7834-8f31-7973aa8bb418', tab_version: 3, items: [{ product_id: '4567', quantity: 1, course: 1 }, { product_id: '4590', quantity: 2 }], payments: [ { method: 'cash', amount: { amount: 33700, currency: 'CZK' }, tendered: { amount: 40000, currency: 'CZK' }, }, ], }); // 201 Receipt// klient: viz /v2/docs/php // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) $receipt = $api->post('/restaurants/123/receipts', [ 'id' => '01a318f0-a0c0-750d-8c36-65b69d55462d', 'number' => 1001, 'issued_at' => '2027-01-15T12:03:18+01:00', 'table_name' => 'Stůl 4', 'order_type' => 'dine_in', 'tab_id' => '01a318f0-a0c0-7834-8f31-7973aa8bb418', 'tab_version' => 3, 'items' => [ ['product_id' => '4567', 'quantity' => 1, 'course' => 1], ['product_id' => '4590', 'quantity' => 2], ], 'payments' => [ [ 'method' => 'cash', 'amount' => ['amount' => 33700, 'currency' => 'CZK'], 'tendered' => ['amount' => 40000, 'currency' => 'CZK'], ], ], ]); // 201// the client: see /v2/docs/php // the library adds the employee's token itself (after the employee signs in) $receipt = $api->post('/restaurants/123/receipts', [ 'id' => '01a318f0-a0c0-750d-8c36-65b69d55462d', 'number' => 1001, 'issued_at' => '2027-01-15T12:03:18+01:00', 'table_name' => 'Stůl 4', 'order_type' => 'dine_in', 'tab_id' => '01a318f0-a0c0-7834-8f31-7973aa8bb418', 'tab_version' => 3, 'items' => [ ['product_id' => '4567', 'quantity' => 1, 'course' => 1], ['product_id' => '4590', 'quantity' => 2], ], 'payments' => [ [ 'method' => 'cash', 'amount' => ['amount' => 33700, 'currency' => 'CZK'], 'tendered' => ['amount' => 40000, 'currency' => 'CZK'], ], ], ]); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) Receipt receipt = api.post("/restaurants/123/receipts", Json.parse(""" { "id": "01a318f0-a0c0-750d-8c36-65b69d55462d", "number": 1001, "issued_at": "2027-01-15T12:03:18+01:00", "table_name": "Stůl 4", "order_type": "dine_in", "tab_id": "01a318f0-a0c0-7834-8f31-7973aa8bb418", "tab_version": 3, "items": [ {"product_id": "4567", "quantity": 1, "course": 1}, {"product_id": "4590", "quantity": 2} ], "payments": [ { "method": "cash", "amount": {"amount": 33700, "currency": "CZK"}, "tendered": {"amount": 40000, "currency": "CZK"} } ] } """), Receipt::fromJson); // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) Receipt receipt = api.post("/restaurants/123/receipts", Json.parse(""" { "id": "01a318f0-a0c0-750d-8c36-65b69d55462d", "number": 1001, "issued_at": "2027-01-15T12:03:18+01:00", "table_name": "Stůl 4", "order_type": "dine_in", "tab_id": "01a318f0-a0c0-7834-8f31-7973aa8bb418", "tab_version": 3, "items": [ {"product_id": "4567", "quantity": 1, "course": 1}, {"product_id": "4590", "quantity": 2} ], "payments": [ { "method": "cash", "amount": {"amount": 33700, "currency": "CZK"}, "tendered": {"amount": 40000, "currency": "CZK"} } ] } """), Receipt::fromJson); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) val receipt = api.post("/restaurants/123/receipts", mapOf( "id" to "01a318f0-a0c0-750d-8c36-65b69d55462d", "number" to 1001, "issued_at" to "2027-01-15T12:03:18+01:00", "table_name" to "Stůl 4", "order_type" to "dine_in", "tab_id" to "01a318f0-a0c0-7834-8f31-7973aa8bb418", "tab_version" to 3, "items" to listOf( mapOf("product_id" to "4567", "quantity" to 1, "course" to 1), mapOf("product_id" to "4590", "quantity" to 2), ), "payments" to listOf( mapOf( "method" to "cash", "amount" to mapOf("amount" to 33700, "currency" to "CZK"), "tendered" to mapOf("amount" to 40000, "currency" to "CZK"), ), ), ), Receipt::fromJson) // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) val receipt = api.post("/restaurants/123/receipts", mapOf( "id" to "01a318f0-a0c0-750d-8c36-65b69d55462d", "number" to 1001, "issued_at" to "2027-01-15T12:03:18+01:00", "table_name" to "Stůl 4", "order_type" to "dine_in", "tab_id" to "01a318f0-a0c0-7834-8f31-7973aa8bb418", "tab_version" to 3, "items" to listOf( mapOf("product_id" to "4567", "quantity" to 1, "course" to 1), mapOf("product_id" to "4590", "quantity" to 2), ), "payments" to listOf( mapOf( "method" to "cash", "amount" to mapOf("amount" to 33700, "currency" to "CZK"), "tendered" to mapOf("amount" to 40000, "currency" to "CZK"), ), ), ), Receipt::fromJson) // 201// klient: viz /v2/docs/csharp // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) var receipt = await api.PostAsync<Receipt>("/restaurants/123/receipts", new { id = "01a318f0-a0c0-750d-8c36-65b69d55462d", number = 1001, issued_at = "2027-01-15T12:03:18+01:00", table_name = "Stůl 4", order_type = "dine_in", tab_id = "01a318f0-a0c0-7834-8f31-7973aa8bb418", tab_version = 3, items = new object[] { new { product_id = "4567", quantity = 1, course = 1 }, new { product_id = "4590", quantity = 2 }, }, payments = new object[] { new { method = "cash", amount = new { amount = 33700, currency = "CZK" }, tendered = new { amount = 40000, currency = "CZK" }, }, }, }); // 201// the client: see /v2/docs/csharp // the library adds the employee's token itself (after the employee signs in) var receipt = await api.PostAsync<Receipt>("/restaurants/123/receipts", new { id = "01a318f0-a0c0-750d-8c36-65b69d55462d", number = 1001, issued_at = "2027-01-15T12:03:18+01:00", table_name = "Stůl 4", order_type = "dine_in", tab_id = "01a318f0-a0c0-7834-8f31-7973aa8bb418", tab_version = 3, items = new object[] { new { product_id = "4567", quantity = 1, course = 1 }, new { product_id = "4590", quantity = 2 }, }, payments = new object[] { new { method = "cash", amount = new { amount = 33700, currency = "CZK" }, tendered = new { amount = 40000, currency = "CZK" }, }, }, }); // 201# klient: viz /v2/docs/python # token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) receipt = api.post('/restaurants/123/receipts', { 'id': '01a318f0-a0c0-750d-8c36-65b69d55462d', 'number': 1001, 'issued_at': '2027-01-15T12:03:18+01:00', 'table_name': 'Stůl 4', 'order_type': 'dine_in', 'tab_id': '01a318f0-a0c0-7834-8f31-7973aa8bb418', 'tab_version': 3, 'items': [ {'product_id': '4567', 'quantity': 1, 'course': 1}, {'product_id': '4590', 'quantity': 2}, ], 'payments': [ { 'method': 'cash', 'amount': {'amount': 33700, 'currency': 'CZK'}, 'tendered': {'amount': 40000, 'currency': 'CZK'}, }, ], }) # 201# the client: see /v2/docs/python # the library adds the employee's token itself (after the employee signs in) receipt = api.post('/restaurants/123/receipts', { 'id': '01a318f0-a0c0-750d-8c36-65b69d55462d', 'number': 1001, 'issued_at': '2027-01-15T12:03:18+01:00', 'table_name': 'Stůl 4', 'order_type': 'dine_in', 'tab_id': '01a318f0-a0c0-7834-8f31-7973aa8bb418', 'tab_version': 3, 'items': [ {'product_id': '4567', 'quantity': 1, 'course': 1}, {'product_id': '4590', 'quantity': 2}, ], 'payments': [ { 'method': 'cash', 'amount': {'amount': 33700, 'currency': 'CZK'}, 'tendered': {'amount': 40000, 'currency': 'CZK'}, }, ], }) # 201// klient: viz /v2/docs/swift // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) let receipt: Receipt = try await api.post("/restaurants/123/receipts", body: [ "id": "01a318f0-a0c0-750d-8c36-65b69d55462d", "number": 1001, "issued_at": "2027-01-15T12:03:18+01:00", "table_name": "Stůl 4", "order_type": "dine_in", "tab_id": "01a318f0-a0c0-7834-8f31-7973aa8bb418", "tab_version": 3, "items": [ ["product_id": "4567", "quantity": 1, "course": 1], ["product_id": "4590", "quantity": 2], ], "payments": [ [ "method": "cash", "amount": ["amount": 33700, "currency": "CZK"], "tendered": ["amount": 40000, "currency": "CZK"], ], ], ]) // 201// the client: see /v2/docs/swift // the library adds the employee's token itself (after the employee signs in) let receipt: Receipt = try await api.post("/restaurants/123/receipts", body: [ "id": "01a318f0-a0c0-750d-8c36-65b69d55462d", "number": 1001, "issued_at": "2027-01-15T12:03:18+01:00", "table_name": "Stůl 4", "order_type": "dine_in", "tab_id": "01a318f0-a0c0-7834-8f31-7973aa8bb418", "tab_version": 3, "items": [ ["product_id": "4567", "quantity": 1, "course": 1], ["product_id": "4590", "quantity": 2], ], "payments": [ [ "method": "cash", "amount": ["amount": 33700, "currency": "CZK"], "tendered": ["amount": 40000, "currency": "CZK"], ], ], ]) // 201// klient: viz /v2/docs/dart // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) final receipt = pr.Receipt.fromJson(await api.post('/restaurants/123/receipts', { 'id': '01a318f0-a0c0-750d-8c36-65b69d55462d', 'number': 1001, 'issued_at': '2027-01-15T12:03:18+01:00', 'table_name': 'Stůl 4', 'order_type': 'dine_in', 'tab_id': '01a318f0-a0c0-7834-8f31-7973aa8bb418', 'tab_version': 3, 'items': [ {'product_id': '4567', 'quantity': 1, 'course': 1}, {'product_id': '4590', 'quantity': 2}, ], 'payments': [ { 'method': 'cash', 'amount': {'amount': 33700, 'currency': 'CZK'}, 'tendered': {'amount': 40000, 'currency': 'CZK'}, }, ], })); // 201// the client: see /v2/docs/dart // the library adds the employee's token itself (after the employee signs in) final receipt = pr.Receipt.fromJson(await api.post('/restaurants/123/receipts', { 'id': '01a318f0-a0c0-750d-8c36-65b69d55462d', 'number': 1001, 'issued_at': '2027-01-15T12:03:18+01:00', 'table_name': 'Stůl 4', 'order_type': 'dine_in', 'tab_id': '01a318f0-a0c0-7834-8f31-7973aa8bb418', 'tab_version': 3, 'items': [ {'product_id': '4567', 'quantity': 1, 'course': 1}, {'product_id': '4590', 'quantity': 2}, ], 'payments': [ { 'method': 'cash', 'amount': {'amount': 33700, 'currency': 'CZK'}, 'tendered': {'amount': 40000, 'currency': 'CZK'}, }, ], })); // 201// klient: viz /v2/docs/go // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) res, err := api.Post(ctx, "/restaurants/123/receipts", map[string]any{ "id": "01a318f0-a0c0-750d-8c36-65b69d55462d", "number": 1001, "issued_at": "2027-01-15T12:03:18+01:00", "table_name": "Stůl 4", "order_type": "dine_in", "tab_id": "01a318f0-a0c0-7834-8f31-7973aa8bb418", "tab_version": 3, "items": []any{ map[string]any{"product_id": "4567", "quantity": 1, "course": 1}, map[string]any{"product_id": "4590", "quantity": 2}, }, "payments": []any{ map[string]any{ "method": "cash", "amount": map[string]any{"amount": 33700, "currency": "CZK"}, "tendered": map[string]any{"amount": 40000, "currency": "CZK"}, }, }, }, nil) var receipt model.Receipt // 201 if err == nil { err = res.Decode(&receipt) }// the client: see /v2/docs/go // the library adds the employee's token itself (after the employee signs in) res, err := api.Post(ctx, "/restaurants/123/receipts", map[string]any{ "id": "01a318f0-a0c0-750d-8c36-65b69d55462d", "number": 1001, "issued_at": "2027-01-15T12:03:18+01:00", "table_name": "Stůl 4", "order_type": "dine_in", "tab_id": "01a318f0-a0c0-7834-8f31-7973aa8bb418", "tab_version": 3, "items": []any{ map[string]any{"product_id": "4567", "quantity": 1, "course": 1}, map[string]any{"product_id": "4590", "quantity": 2}, }, "payments": []any{ map[string]any{ "method": "cash", "amount": map[string]any{"amount": 33700, "currency": "CZK"}, "tendered": map[string]any{"amount": 40000, "currency": "CZK"}, }, }, }, nil) var receipt model.Receipt // 201 if err == nil { err = res.Decode(&receipt) }Příklad odpovědi 200Example answer 200
{ "id": "01a318f0-a0c0-750d-8c36-65b69d55462d", "restaurant_id": "123", "device_id": "512", "number": 1001, "kind": "sale", "status": "issued", "issued_at": "2027-01-15T12:03:18+01:00", "received_at": "2027-01-15T12:03:19+01:00", "offline": false, "issued_by": { "id": "58", "name": "Jana Dvořáková" }, "approved_by": null, "table_name": "Stůl 4", "order_type": "dine_in", "customer_id": null, "note": null, "lines": [ { "id": "1", "type": "product", "product_id": "4567", "name": "Svíčková na smetaně, houskový knedlík", "variant": "full", "quantity": 1, "unit_price": { "amount": 19900, "currency": "CZK" }, "catalog_unit_price": { "amount": 19900, "currency": "CZK" }, "price_source": "catalog", "at_employee_price": false, "packaging_unit_price": null, "vat_rate": "12", "add_ons": [], "note": null, "course": 1, "total": { "amount": 19900, "currency": "CZK" }, "voucher_code": null }, { "id": "2", "type": "product", "product_id": "4590", "name": "Pivo 12° 0,5 l", "variant": "full", "quantity": 2, "unit_price": { "amount": 6900, "currency": "CZK" }, "catalog_unit_price": { "amount": 6900, "currency": "CZK" }, "price_source": "catalog", "at_employee_price": false, "packaging_unit_price": null, "vat_rate": "21", "add_ons": [], "note": null, "course": 0, "total": { "amount": 13800, "currency": "CZK" }, "voucher_code": null } ], "discounts": [], "totals": { "items": { "amount": 33700, "currency": "CZK" }, "charges": { "amount": 0, "currency": "CZK" }, "discounts": { "amount": 0, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "total": { "amount": 33700, "currency": "CZK" }, "vat": [ { "rate": "21", "base": { "amount": 11405, "currency": "CZK" }, "vat": { "amount": 2395, "currency": "CZK" }, "total": { "amount": 13800, "currency": "CZK" } }, { "rate": "12", "base": { "amount": 17768, "currency": "CZK" }, "vat": { "amount": 2132, "currency": "CZK" }, "total": { "amount": 19900, "currency": "CZK" } } ] }, "payments": [ { "id": "1", "method": "cash", "amount": { "amount": 33700, "currency": "CZK" }, "tip": { "amount": 0, "currency": "CZK" }, "tendered": { "amount": 40000, "currency": "CZK" }, "change": { "amount": 6300, "currency": "CZK" }, "voucher_code": null, "reference": null, "terminal": null } ], "tips": { "amount": 0, "currency": "CZK" }, "price_differences": [], "kitchen_number": null, "cancels": null, "cancelled_by": null, "eet": { "status": "accepted", "total": { "amount": 33700, "currency": "CZK" }, "prepaid_issued": null, "prepaid_used": null, "register_id": "POS-512", "sequence": "1001", "unit_id": "273", "sold_at": "2027-01-15T12:03:18+01:00", "pok": "6a1f0c2e-58b3-4d7e-9a41-0f2c7b9d3e5a-03", "environment": "production", "error": null, "warnings": [], "deadline_at": "2027-01-17T12:03:18+01:00" }, "shift_closed_at": null } -
Storno
A cancellation
POST /restaurants/{restaurant_id}/receipts/{receipt_id}/storno · cancelReceipt
Kdo smí stornovat, nastavuje provozovna (
pos.receipt_cancel_byv nastavení zařízení): obsluha, nebo jen vedoucí pokladny (rolepos_managernebo jeho PIN vmanager_credential). Vznikne storno doklad se zápornými částkami.Who may cancel is set by the restaurant (
pos.receipt_cancel_byin the device settings): the staff, or only a register manager (thepos_managerrole or their PIN inmanager_credential). It creates a cancellation document with negative amounts.curl "https://api.mujprofirest.cz/v2/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "id": "01a318f0-a0c0-70e0-bba9-8720b58925a1", "number": 1003, "reason": "Chybně namarkováno – patří ke stolu 5", "restock": true }'curl "https://api.mujprofirest.cz/v2/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "id": "01a318f0-a0c0-70e0-bba9-8720b58925a1", "number": 1003, "reason": "Chybně namarkováno – patří ke stolu 5", "restock": true }'// klient: viz /v2/docs/js // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const receipt = await api.post('/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno', { id: '01a318f0-a0c0-70e0-bba9-8720b58925a1', number: 1003, reason: 'Chybně namarkováno – patří ke stolu 5', restock: true, }); // 201// the client: see /v2/docs/js // the library adds the employee's token itself (after the employee signs in) const receipt = await api.post('/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno', { id: '01a318f0-a0c0-70e0-bba9-8720b58925a1', number: 1003, reason: 'Chybně namarkováno – patří ke stolu 5', restock: true, }); // 201// klient: viz /v2/docs/typescript // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const receipt = await api.post('/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno', { id: '01a318f0-a0c0-70e0-bba9-8720b58925a1', number: 1003, reason: 'Chybně namarkováno – patří ke stolu 5', restock: true, }); // 201 Receipt// the client: see /v2/docs/typescript // the library adds the employee's token itself (after the employee signs in) const receipt = await api.post('/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno', { id: '01a318f0-a0c0-70e0-bba9-8720b58925a1', number: 1003, reason: 'Chybně namarkováno – patří ke stolu 5', restock: true, }); // 201 Receipt// klient: viz /v2/docs/php // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) $receipt = $api->post('/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno', [ 'id' => '01a318f0-a0c0-70e0-bba9-8720b58925a1', 'number' => 1003, 'reason' => 'Chybně namarkováno – patří ke stolu 5', 'restock' => true, ]); // 201// the client: see /v2/docs/php // the library adds the employee's token itself (after the employee signs in) $receipt = $api->post('/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno', [ 'id' => '01a318f0-a0c0-70e0-bba9-8720b58925a1', 'number' => 1003, 'reason' => 'Chybně namarkováno – patří ke stolu 5', 'restock' => true, ]); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) Receipt receipt = api.post("/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno", Json.parse(""" { "id": "01a318f0-a0c0-70e0-bba9-8720b58925a1", "number": 1003, "reason": "Chybně namarkováno – patří ke stolu 5", "restock": true } """), Receipt::fromJson); // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) Receipt receipt = api.post("/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno", Json.parse(""" { "id": "01a318f0-a0c0-70e0-bba9-8720b58925a1", "number": 1003, "reason": "Chybně namarkováno – patří ke stolu 5", "restock": true } """), Receipt::fromJson); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) val receipt = api.post("/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno", mapOf( "id" to "01a318f0-a0c0-70e0-bba9-8720b58925a1", "number" to 1003, "reason" to "Chybně namarkováno – patří ke stolu 5", "restock" to true, ), Receipt::fromJson) // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) val receipt = api.post("/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno", mapOf( "id" to "01a318f0-a0c0-70e0-bba9-8720b58925a1", "number" to 1003, "reason" to "Chybně namarkováno – patří ke stolu 5", "restock" to true, ), Receipt::fromJson) // 201// klient: viz /v2/docs/csharp // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) var receipt = await api.PostAsync<Receipt>("/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno", new { id = "01a318f0-a0c0-70e0-bba9-8720b58925a1", number = 1003, reason = "Chybně namarkováno – patří ke stolu 5", restock = true, }); // 201// the client: see /v2/docs/csharp // the library adds the employee's token itself (after the employee signs in) var receipt = await api.PostAsync<Receipt>("/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno", new { id = "01a318f0-a0c0-70e0-bba9-8720b58925a1", number = 1003, reason = "Chybně namarkováno – patří ke stolu 5", restock = true, }); // 201# klient: viz /v2/docs/python # token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) receipt = api.post('/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno', { 'id': '01a318f0-a0c0-70e0-bba9-8720b58925a1', 'number': 1003, 'reason': 'Chybně namarkováno – patří ke stolu 5', 'restock': True, }) # 201# the client: see /v2/docs/python # the library adds the employee's token itself (after the employee signs in) receipt = api.post('/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno', { 'id': '01a318f0-a0c0-70e0-bba9-8720b58925a1', 'number': 1003, 'reason': 'Chybně namarkováno – patří ke stolu 5', 'restock': True, }) # 201// klient: viz /v2/docs/swift // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) let receipt: Receipt = try await api.post("/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno", body: [ "id": "01a318f0-a0c0-70e0-bba9-8720b58925a1", "number": 1003, "reason": "Chybně namarkováno – patří ke stolu 5", "restock": true, ]) // 201// the client: see /v2/docs/swift // the library adds the employee's token itself (after the employee signs in) let receipt: Receipt = try await api.post("/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno", body: [ "id": "01a318f0-a0c0-70e0-bba9-8720b58925a1", "number": 1003, "reason": "Chybně namarkováno – patří ke stolu 5", "restock": true, ]) // 201// klient: viz /v2/docs/dart // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) final receipt = pr.Receipt.fromJson(await api.post('/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno', { 'id': '01a318f0-a0c0-70e0-bba9-8720b58925a1', 'number': 1003, 'reason': 'Chybně namarkováno – patří ke stolu 5', 'restock': true, })); // 201// the client: see /v2/docs/dart // the library adds the employee's token itself (after the employee signs in) final receipt = pr.Receipt.fromJson(await api.post('/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno', { 'id': '01a318f0-a0c0-70e0-bba9-8720b58925a1', 'number': 1003, 'reason': 'Chybně namarkováno – patří ke stolu 5', 'restock': true, })); // 201// klient: viz /v2/docs/go // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) res, err := api.Post(ctx, "/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno", map[string]any{ "id": "01a318f0-a0c0-70e0-bba9-8720b58925a1", "number": 1003, "reason": "Chybně namarkováno – patří ke stolu 5", "restock": true, }, nil) var receipt model.Receipt // 201 if err == nil { err = res.Decode(&receipt) }// the client: see /v2/docs/go // the library adds the employee's token itself (after the employee signs in) res, err := api.Post(ctx, "/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/storno", map[string]any{ "id": "01a318f0-a0c0-70e0-bba9-8720b58925a1", "number": 1003, "reason": "Chybně namarkováno – patří ke stolu 5", "restock": true, }, nil) var receipt model.Receipt // 201 if err == nil { err = res.Decode(&receipt) }Příklad odpovědi 200Example answer 200
{ "id": "01a318f0-a0c0-70e0-bba9-8720b58925a1", "restaurant_id": "123", "device_id": "512", "number": 1003, "kind": "storno", "status": "issued", "issued_at": "2027-01-15T12:10:44+01:00", "received_at": "2027-01-15T12:10:44+01:00", "offline": false, "issued_by": { "id": "61", "name": "Petr Novák" }, "approved_by": null, "table_name": "Stůl 4", "order_type": "dine_in", "customer_id": null, "note": null, "lines": [ { "id": "1", "type": "product", "product_id": "4567", "name": "Svíčková na smetaně, houskový knedlík", "variant": "full", "quantity": -1, "unit_price": { "amount": 19900, "currency": "CZK" }, "catalog_unit_price": { "amount": 19900, "currency": "CZK" }, "price_source": "catalog", "at_employee_price": false, "packaging_unit_price": null, "vat_rate": "12", "add_ons": [], "note": null, "course": 1, "total": { "amount": -19900, "currency": "CZK" }, "voucher_code": null }, { "id": "2", "type": "product", "product_id": "4590", "name": "Pivo 12° 0,5 l", "variant": "full", "quantity": -2, "unit_price": { "amount": 6900, "currency": "CZK" }, "catalog_unit_price": { "amount": 6900, "currency": "CZK" }, "price_source": "catalog", "at_employee_price": false, "packaging_unit_price": null, "vat_rate": "21", "add_ons": [], "note": null, "course": 0, "total": { "amount": -13800, "currency": "CZK" }, "voucher_code": null } ], "discounts": [], "totals": { "items": { "amount": -33700, "currency": "CZK" }, "charges": { "amount": 0, "currency": "CZK" }, "discounts": { "amount": 0, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "total": { "amount": -33700, "currency": "CZK" }, "vat": [ { "rate": "21", "base": { "amount": -11405, "currency": "CZK" }, "vat": { "amount": -2395, "currency": "CZK" }, "total": { "amount": -13800, "currency": "CZK" } }, { "rate": "12", "base": { "amount": -17768, "currency": "CZK" }, "vat": { "amount": -2132, "currency": "CZK" }, "total": { "amount": -19900, "currency": "CZK" } } ] }, "payments": [ { "id": "1", "method": "cash", "amount": { "amount": -33700, "currency": "CZK" }, "tip": { "amount": 0, "currency": "CZK" }, "tendered": null, "change": null, "voucher_code": null, "reference": null, "terminal": null } ], "tips": { "amount": 0, "currency": "CZK" }, "price_differences": [], "kitchen_number": null, "cancels": "01a318f0-a0c0-750d-8c36-65b69d55462d", "cancelled_by": null, "eet": { "status": "accepted", "total": { "amount": -33700, "currency": "CZK" }, "prepaid_issued": null, "prepaid_used": null, "register_id": "POS-512", "sequence": "1003", "unit_id": "273", "sold_at": "2027-01-15T12:10:44+01:00", "pok": "3d7b1a90-6c2e-4f85-b1d3-9e0a7c5f2b46-03", "environment": "production", "error": null, "warnings": [], "deadline_at": "2027-01-17T12:10:44+01:00" }, "shift_closed_at": null } -
Změna platby
Changing the payment
POST /restaurants/{restaurant_id}/receipts/{receipt_id}/payment-change · changeReceiptPayment
Zvolila obsluha hotovost a zákazník platil kartou? Platbu změňte bez storna – účtenka si nechá číslo i částku. Mění se platby hotově, stravenkami, na firemní účet a fakturou, do uzávěrky směny; platby kartou a dárkovým voucherem zůstávají.
The employee chose cash and the customer paid by card? Change the payment without a cancellation – the receipt keeps its number and amount. Cash, meal voucher, company account and invoice payments change, until the shift close; card and gift voucher payments stay.
curl "https://api.mujprofirest.cz/v2/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "id": "01a318f0-a0c0-7b2e-b422-5663a54604b9", "reason": "Omylem hotově, platil kartou", "payments": [ { "method": "card", "amount": {"amount": 33700, "currency": "CZK"}, "terminal": { "provider": "csob", "transaction_id": "0011245611", "card_number_masked": "**** **** **** 1187", "auth_code": "B3M8T1", "response_code": "00" } } ] }'curl "https://api.mujprofirest.cz/v2/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "id": "01a318f0-a0c0-7b2e-b422-5663a54604b9", "reason": "Omylem hotově, platil kartou", "payments": [ { "method": "card", "amount": {"amount": 33700, "currency": "CZK"}, "terminal": { "provider": "csob", "transaction_id": "0011245611", "card_number_masked": "**** **** **** 1187", "auth_code": "B3M8T1", "response_code": "00" } } ] }'// klient: viz /v2/docs/js // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const receiptPayment = await api.post('/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change', { id: '01a318f0-a0c0-7b2e-b422-5663a54604b9', reason: 'Omylem hotově, platil kartou', payments: [ { method: 'card', amount: { amount: 33700, currency: 'CZK' }, terminal: { provider: 'csob', transaction_id: '0011245611', card_number_masked: '**** **** **** 1187', auth_code: 'B3M8T1', response_code: '00', }, }, ], }); // 200// the client: see /v2/docs/js // the library adds the employee's token itself (after the employee signs in) const receiptPayment = await api.post('/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change', { id: '01a318f0-a0c0-7b2e-b422-5663a54604b9', reason: 'Omylem hotově, platil kartou', payments: [ { method: 'card', amount: { amount: 33700, currency: 'CZK' }, terminal: { provider: 'csob', transaction_id: '0011245611', card_number_masked: '**** **** **** 1187', auth_code: 'B3M8T1', response_code: '00', }, }, ], }); // 200// klient: viz /v2/docs/typescript // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const receiptPayment = await api.post('/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change', { id: '01a318f0-a0c0-7b2e-b422-5663a54604b9', reason: 'Omylem hotově, platil kartou', payments: [ { method: 'card', amount: { amount: 33700, currency: 'CZK' }, terminal: { provider: 'csob', transaction_id: '0011245611', card_number_masked: '**** **** **** 1187', auth_code: 'B3M8T1', response_code: '00', }, }, ], }); // 200 Receipt// the client: see /v2/docs/typescript // the library adds the employee's token itself (after the employee signs in) const receiptPayment = await api.post('/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change', { id: '01a318f0-a0c0-7b2e-b422-5663a54604b9', reason: 'Omylem hotově, platil kartou', payments: [ { method: 'card', amount: { amount: 33700, currency: 'CZK' }, terminal: { provider: 'csob', transaction_id: '0011245611', card_number_masked: '**** **** **** 1187', auth_code: 'B3M8T1', response_code: '00', }, }, ], }); // 200 Receipt// klient: viz /v2/docs/php // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) $receiptPayment = $api->post('/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change', [ 'id' => '01a318f0-a0c0-7b2e-b422-5663a54604b9', 'reason' => 'Omylem hotově, platil kartou', 'payments' => [ [ 'method' => 'card', 'amount' => ['amount' => 33700, 'currency' => 'CZK'], 'terminal' => [ 'provider' => 'csob', 'transaction_id' => '0011245611', 'card_number_masked' => '**** **** **** 1187', 'auth_code' => 'B3M8T1', 'response_code' => '00', ], ], ], ]); // 200// the client: see /v2/docs/php // the library adds the employee's token itself (after the employee signs in) $receiptPayment = $api->post('/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change', [ 'id' => '01a318f0-a0c0-7b2e-b422-5663a54604b9', 'reason' => 'Omylem hotově, platil kartou', 'payments' => [ [ 'method' => 'card', 'amount' => ['amount' => 33700, 'currency' => 'CZK'], 'terminal' => [ 'provider' => 'csob', 'transaction_id' => '0011245611', 'card_number_masked' => '**** **** **** 1187', 'auth_code' => 'B3M8T1', 'response_code' => '00', ], ], ], ]); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) Receipt receiptPayment = api.post("/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change", Json.parse(""" { "id": "01a318f0-a0c0-7b2e-b422-5663a54604b9", "reason": "Omylem hotově, platil kartou", "payments": [ { "method": "card", "amount": {"amount": 33700, "currency": "CZK"}, "terminal": { "provider": "csob", "transaction_id": "0011245611", "card_number_masked": "**** **** **** 1187", "auth_code": "B3M8T1", "response_code": "00" } } ] } """), Receipt::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) Receipt receiptPayment = api.post("/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change", Json.parse(""" { "id": "01a318f0-a0c0-7b2e-b422-5663a54604b9", "reason": "Omylem hotově, platil kartou", "payments": [ { "method": "card", "amount": {"amount": 33700, "currency": "CZK"}, "terminal": { "provider": "csob", "transaction_id": "0011245611", "card_number_masked": "**** **** **** 1187", "auth_code": "B3M8T1", "response_code": "00" } } ] } """), Receipt::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) val receiptPayment = api.post("/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change", mapOf( "id" to "01a318f0-a0c0-7b2e-b422-5663a54604b9", "reason" to "Omylem hotově, platil kartou", "payments" to listOf( mapOf( "method" to "card", "amount" to mapOf("amount" to 33700, "currency" to "CZK"), "terminal" to mapOf( "provider" to "csob", "transaction_id" to "0011245611", "card_number_masked" to "**** **** **** 1187", "auth_code" to "B3M8T1", "response_code" to "00", ), ), ), ), Receipt::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) val receiptPayment = api.post("/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change", mapOf( "id" to "01a318f0-a0c0-7b2e-b422-5663a54604b9", "reason" to "Omylem hotově, platil kartou", "payments" to listOf( mapOf( "method" to "card", "amount" to mapOf("amount" to 33700, "currency" to "CZK"), "terminal" to mapOf( "provider" to "csob", "transaction_id" to "0011245611", "card_number_masked" to "**** **** **** 1187", "auth_code" to "B3M8T1", "response_code" to "00", ), ), ), ), Receipt::fromJson) // 200// klient: viz /v2/docs/csharp // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) var receiptPayment = await api.PostAsync<Receipt>("/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change", new { id = "01a318f0-a0c0-7b2e-b422-5663a54604b9", reason = "Omylem hotově, platil kartou", payments = new object[] { new { method = "card", amount = new { amount = 33700, currency = "CZK" }, terminal = new { provider = "csob", transaction_id = "0011245611", card_number_masked = "**** **** **** 1187", auth_code = "B3M8T1", response_code = "00", }, }, }, }); // 200// the client: see /v2/docs/csharp // the library adds the employee's token itself (after the employee signs in) var receiptPayment = await api.PostAsync<Receipt>("/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change", new { id = "01a318f0-a0c0-7b2e-b422-5663a54604b9", reason = "Omylem hotově, platil kartou", payments = new object[] { new { method = "card", amount = new { amount = 33700, currency = "CZK" }, terminal = new { provider = "csob", transaction_id = "0011245611", card_number_masked = "**** **** **** 1187", auth_code = "B3M8T1", response_code = "00", }, }, }, }); // 200# klient: viz /v2/docs/python # token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) receipt_payment = api.post('/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change', { 'id': '01a318f0-a0c0-7b2e-b422-5663a54604b9', 'reason': 'Omylem hotově, platil kartou', 'payments': [ { 'method': 'card', 'amount': {'amount': 33700, 'currency': 'CZK'}, 'terminal': { 'provider': 'csob', 'transaction_id': '0011245611', 'card_number_masked': '**** **** **** 1187', 'auth_code': 'B3M8T1', 'response_code': '00', }, }, ], }) # 200# the client: see /v2/docs/python # the library adds the employee's token itself (after the employee signs in) receipt_payment = api.post('/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change', { 'id': '01a318f0-a0c0-7b2e-b422-5663a54604b9', 'reason': 'Omylem hotově, platil kartou', 'payments': [ { 'method': 'card', 'amount': {'amount': 33700, 'currency': 'CZK'}, 'terminal': { 'provider': 'csob', 'transaction_id': '0011245611', 'card_number_masked': '**** **** **** 1187', 'auth_code': 'B3M8T1', 'response_code': '00', }, }, ], }) # 200// klient: viz /v2/docs/swift // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) let receiptPayment: Receipt = try await api.post("/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change", body: [ "id": "01a318f0-a0c0-7b2e-b422-5663a54604b9", "reason": "Omylem hotově, platil kartou", "payments": [ [ "method": "card", "amount": ["amount": 33700, "currency": "CZK"], "terminal": [ "provider": "csob", "transaction_id": "0011245611", "card_number_masked": "**** **** **** 1187", "auth_code": "B3M8T1", "response_code": "00", ], ], ], ]) // 200// the client: see /v2/docs/swift // the library adds the employee's token itself (after the employee signs in) let receiptPayment: Receipt = try await api.post("/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change", body: [ "id": "01a318f0-a0c0-7b2e-b422-5663a54604b9", "reason": "Omylem hotově, platil kartou", "payments": [ [ "method": "card", "amount": ["amount": 33700, "currency": "CZK"], "terminal": [ "provider": "csob", "transaction_id": "0011245611", "card_number_masked": "**** **** **** 1187", "auth_code": "B3M8T1", "response_code": "00", ], ], ], ]) // 200// klient: viz /v2/docs/dart // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) final receiptPayment = pr.Receipt.fromJson(await api.post('/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change', { 'id': '01a318f0-a0c0-7b2e-b422-5663a54604b9', 'reason': 'Omylem hotově, platil kartou', 'payments': [ { 'method': 'card', 'amount': {'amount': 33700, 'currency': 'CZK'}, 'terminal': { 'provider': 'csob', 'transaction_id': '0011245611', 'card_number_masked': '**** **** **** 1187', 'auth_code': 'B3M8T1', 'response_code': '00', }, }, ], })); // 200// the client: see /v2/docs/dart // the library adds the employee's token itself (after the employee signs in) final receiptPayment = pr.Receipt.fromJson(await api.post('/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change', { 'id': '01a318f0-a0c0-7b2e-b422-5663a54604b9', 'reason': 'Omylem hotově, platil kartou', 'payments': [ { 'method': 'card', 'amount': {'amount': 33700, 'currency': 'CZK'}, 'terminal': { 'provider': 'csob', 'transaction_id': '0011245611', 'card_number_masked': '**** **** **** 1187', 'auth_code': 'B3M8T1', 'response_code': '00', }, }, ], })); // 200// klient: viz /v2/docs/go // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) res, err := api.Post(ctx, "/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change", map[string]any{ "id": "01a318f0-a0c0-7b2e-b422-5663a54604b9", "reason": "Omylem hotově, platil kartou", "payments": []any{ map[string]any{ "method": "card", "amount": map[string]any{"amount": 33700, "currency": "CZK"}, "terminal": map[string]any{ "provider": "csob", "transaction_id": "0011245611", "card_number_masked": "**** **** **** 1187", "auth_code": "B3M8T1", "response_code": "00", }, }, }, }, nil) var receiptPayment model.Receipt // 200 if err == nil { err = res.Decode(&receiptPayment) }// the client: see /v2/docs/go // the library adds the employee's token itself (after the employee signs in) res, err := api.Post(ctx, "/restaurants/123/receipts/01a318f0-a0c0-750d-8c36-65b69d55462d/payment-change", map[string]any{ "id": "01a318f0-a0c0-7b2e-b422-5663a54604b9", "reason": "Omylem hotově, platil kartou", "payments": []any{ map[string]any{ "method": "card", "amount": map[string]any{"amount": 33700, "currency": "CZK"}, "terminal": map[string]any{ "provider": "csob", "transaction_id": "0011245611", "card_number_masked": "**** **** **** 1187", "auth_code": "B3M8T1", "response_code": "00", }, }, }, }, nil) var receiptPayment model.Receipt // 200 if err == nil { err = res.Decode(&receiptPayment) }Příklad odpovědi 200Example answer 200
{ "id": "01a318f0-a0c0-750d-8c36-65b69d55462d", "restaurant_id": "123", "device_id": "512", "number": 1001, "kind": "sale", "status": "issued", "issued_at": "2027-01-15T12:03:18+01:00", "received_at": "2027-01-15T12:03:19+01:00", "offline": false, "issued_by": { "id": "58", "name": "Jana Dvořáková" }, "approved_by": null, "table_name": "Stůl 4", "order_type": "dine_in", "customer_id": null, "note": null, "lines": [ { "id": "1", "type": "product", "product_id": "4567", "name": "Svíčková na smetaně, houskový knedlík", "variant": "full", "quantity": 1, "unit_price": { "amount": 19900, "currency": "CZK" }, "catalog_unit_price": { "amount": 19900, "currency": "CZK" }, "price_source": "catalog", "at_employee_price": false, "packaging_unit_price": null, "vat_rate": "12", "add_ons": [], "note": null, "course": 1, "total": { "amount": 19900, "currency": "CZK" }, "voucher_code": null }, { "id": "2", "type": "product", "product_id": "4590", "name": "Pivo 12° 0,5 l", "variant": "full", "quantity": 2, "unit_price": { "amount": 6900, "currency": "CZK" }, "catalog_unit_price": { "amount": 6900, "currency": "CZK" }, "price_source": "catalog", "at_employee_price": false, "packaging_unit_price": null, "vat_rate": "21", "add_ons": [], "note": null, "course": 0, "total": { "amount": 13800, "currency": "CZK" }, "voucher_code": null } ], "discounts": [], "totals": { "items": { "amount": 33700, "currency": "CZK" }, "charges": { "amount": 0, "currency": "CZK" }, "discounts": { "amount": 0, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "total": { "amount": 33700, "currency": "CZK" }, "vat": [ { "rate": "21", "base": { "amount": 11405, "currency": "CZK" }, "vat": { "amount": 2395, "currency": "CZK" }, "total": { "amount": 13800, "currency": "CZK" } }, { "rate": "12", "base": { "amount": 17768, "currency": "CZK" }, "vat": { "amount": 2132, "currency": "CZK" }, "total": { "amount": 19900, "currency": "CZK" } } ] }, "payments": [ { "id": "1", "method": "card", "amount": { "amount": 33700, "currency": "CZK" }, "tip": { "amount": 0, "currency": "CZK" }, "tendered": null, "change": null, "voucher_code": null, "reference": null, "terminal": { "provider": "csob", "transaction_id": "0011245611", "card_number_masked": "**** **** **** 1187", "auth_code": "B3M8T1" } } ], "tips": { "amount": 0, "currency": "CZK" }, "price_differences": [], "kitchen_number": null, "cancels": null, "cancelled_by": null, "eet": { "status": "accepted", "total": { "amount": 33700, "currency": "CZK" }, "prepaid_issued": null, "prepaid_used": null, "register_id": "POS-512", "sequence": "1001", "unit_id": "273", "sold_at": "2027-01-15T12:03:18+01:00", "pok": "6a1f0c2e-58b3-4d7e-9a41-0f2c7b9d3e5a-03", "environment": "production", "error": null, "warnings": [], "deadline_at": "2027-01-17T12:03:18+01:00" }, "shift_closed_at": null } -
Vklad a výběr
Deposits and withdrawals
POST /restaurants/{restaurant_id}/cash-movements · createCashMovement
Drobné na směnu, odvod do banky nebo nákup z kasy jdou do pokladní knihy provozovny; výběr a výdaj schvaluje vedoucí. Uzávěrka je připočte k očekávané hotovosti.
Change for the shift, money to the bank or a purchase from the drawer go to the restaurant's cash book; a withdrawal and an expense need a manager. The close counts them into the expected cash.
curl "https://api.mujprofirest.cz/v2/restaurants/123/cash-movements" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "id": "01a318f0-a0c0-7f0d-91ef-e936a0196e90", "kind": "withdrawal", "amount": {"amount": 1500000, "currency": "CZK"}, "note": "Odvod tržby do banky", "document": null, "occurred_at": null, "manager_credential": null }'curl "https://api.mujprofirest.cz/v2/restaurants/123/cash-movements" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "id": "01a318f0-a0c0-7f0d-91ef-e936a0196e90", "kind": "withdrawal", "amount": {"amount": 1500000, "currency": "CZK"}, "note": "Odvod tržby do banky", "document": null, "occurred_at": null, "manager_credential": null }'// klient: viz /v2/docs/js // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const cashMovement = await api.post('/restaurants/123/cash-movements', { id: '01a318f0-a0c0-7f0d-91ef-e936a0196e90', kind: 'withdrawal', amount: { amount: 1500000, currency: 'CZK' }, note: 'Odvod tržby do banky', document: null, occurred_at: null, manager_credential: null, }); // 201// the client: see /v2/docs/js // the library adds the employee's token itself (after the employee signs in) const cashMovement = await api.post('/restaurants/123/cash-movements', { id: '01a318f0-a0c0-7f0d-91ef-e936a0196e90', kind: 'withdrawal', amount: { amount: 1500000, currency: 'CZK' }, note: 'Odvod tržby do banky', document: null, occurred_at: null, manager_credential: null, }); // 201// klient: viz /v2/docs/typescript // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const cashMovement = await api.post('/restaurants/123/cash-movements', { id: '01a318f0-a0c0-7f0d-91ef-e936a0196e90', kind: 'withdrawal', amount: { amount: 1500000, currency: 'CZK' }, note: 'Odvod tržby do banky', document: null, occurred_at: null, manager_credential: null, }); // 201 CashMovement// the client: see /v2/docs/typescript // the library adds the employee's token itself (after the employee signs in) const cashMovement = await api.post('/restaurants/123/cash-movements', { id: '01a318f0-a0c0-7f0d-91ef-e936a0196e90', kind: 'withdrawal', amount: { amount: 1500000, currency: 'CZK' }, note: 'Odvod tržby do banky', document: null, occurred_at: null, manager_credential: null, }); // 201 CashMovement// klient: viz /v2/docs/php // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) $cashMovement = $api->post('/restaurants/123/cash-movements', [ 'id' => '01a318f0-a0c0-7f0d-91ef-e936a0196e90', 'kind' => 'withdrawal', 'amount' => ['amount' => 1500000, 'currency' => 'CZK'], 'note' => 'Odvod tržby do banky', 'document' => null, 'occurred_at' => null, 'manager_credential' => null, ]); // 201// the client: see /v2/docs/php // the library adds the employee's token itself (after the employee signs in) $cashMovement = $api->post('/restaurants/123/cash-movements', [ 'id' => '01a318f0-a0c0-7f0d-91ef-e936a0196e90', 'kind' => 'withdrawal', 'amount' => ['amount' => 1500000, 'currency' => 'CZK'], 'note' => 'Odvod tržby do banky', 'document' => null, 'occurred_at' => null, 'manager_credential' => null, ]); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) CashMovement cashMovement = api.post("/restaurants/123/cash-movements", Json.parse(""" { "id": "01a318f0-a0c0-7f0d-91ef-e936a0196e90", "kind": "withdrawal", "amount": {"amount": 1500000, "currency": "CZK"}, "note": "Odvod tržby do banky", "document": null, "occurred_at": null, "manager_credential": null } """), CashMovement::fromJson); // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) CashMovement cashMovement = api.post("/restaurants/123/cash-movements", Json.parse(""" { "id": "01a318f0-a0c0-7f0d-91ef-e936a0196e90", "kind": "withdrawal", "amount": {"amount": 1500000, "currency": "CZK"}, "note": "Odvod tržby do banky", "document": null, "occurred_at": null, "manager_credential": null } """), CashMovement::fromJson); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) val cashMovement = api.post("/restaurants/123/cash-movements", mapOf( "id" to "01a318f0-a0c0-7f0d-91ef-e936a0196e90", "kind" to "withdrawal", "amount" to mapOf("amount" to 1500000, "currency" to "CZK"), "note" to "Odvod tržby do banky", "document" to null, "occurred_at" to null, "manager_credential" to null, ), CashMovement::fromJson) // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) val cashMovement = api.post("/restaurants/123/cash-movements", mapOf( "id" to "01a318f0-a0c0-7f0d-91ef-e936a0196e90", "kind" to "withdrawal", "amount" to mapOf("amount" to 1500000, "currency" to "CZK"), "note" to "Odvod tržby do banky", "document" to null, "occurred_at" to null, "manager_credential" to null, ), CashMovement::fromJson) // 201// klient: viz /v2/docs/csharp // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) var cashMovement = await api.PostAsync<CashMovement>("/restaurants/123/cash-movements", new { id = "01a318f0-a0c0-7f0d-91ef-e936a0196e90", kind = "withdrawal", amount = new { amount = 1500000, currency = "CZK" }, note = "Odvod tržby do banky", document = (object?)null, occurred_at = (object?)null, manager_credential = (object?)null, }); // 201// the client: see /v2/docs/csharp // the library adds the employee's token itself (after the employee signs in) var cashMovement = await api.PostAsync<CashMovement>("/restaurants/123/cash-movements", new { id = "01a318f0-a0c0-7f0d-91ef-e936a0196e90", kind = "withdrawal", amount = new { amount = 1500000, currency = "CZK" }, note = "Odvod tržby do banky", document = (object?)null, occurred_at = (object?)null, manager_credential = (object?)null, }); // 201# klient: viz /v2/docs/python # token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) cash_movement = api.post('/restaurants/123/cash-movements', { 'id': '01a318f0-a0c0-7f0d-91ef-e936a0196e90', 'kind': 'withdrawal', 'amount': {'amount': 1500000, 'currency': 'CZK'}, 'note': 'Odvod tržby do banky', 'document': None, 'occurred_at': None, 'manager_credential': None, }) # 201# the client: see /v2/docs/python # the library adds the employee's token itself (after the employee signs in) cash_movement = api.post('/restaurants/123/cash-movements', { 'id': '01a318f0-a0c0-7f0d-91ef-e936a0196e90', 'kind': 'withdrawal', 'amount': {'amount': 1500000, 'currency': 'CZK'}, 'note': 'Odvod tržby do banky', 'document': None, 'occurred_at': None, 'manager_credential': None, }) # 201// klient: viz /v2/docs/swift // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) let cashMovement: CashMovement = try await api.post("/restaurants/123/cash-movements", body: [ "id": "01a318f0-a0c0-7f0d-91ef-e936a0196e90", "kind": "withdrawal", "amount": ["amount": 1500000, "currency": "CZK"], "note": "Odvod tržby do banky", "document": nil, "occurred_at": nil, "manager_credential": nil, ]) // 201// the client: see /v2/docs/swift // the library adds the employee's token itself (after the employee signs in) let cashMovement: CashMovement = try await api.post("/restaurants/123/cash-movements", body: [ "id": "01a318f0-a0c0-7f0d-91ef-e936a0196e90", "kind": "withdrawal", "amount": ["amount": 1500000, "currency": "CZK"], "note": "Odvod tržby do banky", "document": nil, "occurred_at": nil, "manager_credential": nil, ]) // 201// klient: viz /v2/docs/dart // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) final cashMovement = pr.CashMovement.fromJson(await api.post('/restaurants/123/cash-movements', { 'id': '01a318f0-a0c0-7f0d-91ef-e936a0196e90', 'kind': 'withdrawal', 'amount': {'amount': 1500000, 'currency': 'CZK'}, 'note': 'Odvod tržby do banky', 'document': null, 'occurred_at': null, 'manager_credential': null, })); // 201// the client: see /v2/docs/dart // the library adds the employee's token itself (after the employee signs in) final cashMovement = pr.CashMovement.fromJson(await api.post('/restaurants/123/cash-movements', { 'id': '01a318f0-a0c0-7f0d-91ef-e936a0196e90', 'kind': 'withdrawal', 'amount': {'amount': 1500000, 'currency': 'CZK'}, 'note': 'Odvod tržby do banky', 'document': null, 'occurred_at': null, 'manager_credential': null, })); // 201// klient: viz /v2/docs/go // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) res, err := api.Post(ctx, "/restaurants/123/cash-movements", map[string]any{ "id": "01a318f0-a0c0-7f0d-91ef-e936a0196e90", "kind": "withdrawal", "amount": map[string]any{"amount": 1500000, "currency": "CZK"}, "note": "Odvod tržby do banky", "document": nil, "occurred_at": nil, "manager_credential": nil, }, nil) var cashMovement model.CashMovement // 201 if err == nil { err = res.Decode(&cashMovement) }// the client: see /v2/docs/go // the library adds the employee's token itself (after the employee signs in) res, err := api.Post(ctx, "/restaurants/123/cash-movements", map[string]any{ "id": "01a318f0-a0c0-7f0d-91ef-e936a0196e90", "kind": "withdrawal", "amount": map[string]any{"amount": 1500000, "currency": "CZK"}, "note": "Odvod tržby do banky", "document": nil, "occurred_at": nil, "manager_credential": nil, }, nil) var cashMovement model.CashMovement // 201 if err == nil { err = res.Decode(&cashMovement) }Příklad odpovědi 200Example answer 200
{ "id": "01a318f0-a0c0-7f0d-91ef-e936a0196e90", "number": "8812", "kind": "withdrawal", "amount": { "amount": 1500000, "currency": "CZK" }, "note": "Odvod tržby do banky", "document": null, "occurred_at": "2027-01-15T16:05:12+01:00", "recorded_at": "2027-01-15T16:05:12+01:00", "recorded_by": { "id": "61", "name": "Petr Novák" }, "approved_by": { "id": "61", "name": "Petr Novák" }, "device_id": "512" } -
Uzávěrka
Closing the shift
POST /restaurants/{restaurant_id}/pos-shift/close · closePosShift
Součty spočítá server; pošlete přepočítanou hotovost a dostanete rozdíl.
The server computes the totals; send the counted cash and get the difference.
curl "https://api.mujprofirest.cz/v2/restaurants/123/pos-shift/close" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "id": "01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33", "counted_cash": {"amount": 734300, "currency": "CZK"}, "note": "Chybí 4 Kč." }'curl "https://api.mujprofirest.cz/v2/restaurants/123/pos-shift/close" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "id": "01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33", "counted_cash": {"amount": 734300, "currency": "CZK"}, "note": "Chybí 4 Kč." }'// klient: viz /v2/docs/js // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const posShift = await api.post('/restaurants/123/pos-shift/close', { id: '01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33', counted_cash: { amount: 734300, currency: 'CZK' }, note: 'Chybí 4 Kč.', }); // 201// the client: see /v2/docs/js // the library adds the employee's token itself (after the employee signs in) const posShift = await api.post('/restaurants/123/pos-shift/close', { id: '01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33', counted_cash: { amount: 734300, currency: 'CZK' }, note: 'Chybí 4 Kč.', }); // 201// klient: viz /v2/docs/typescript // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const posShift = await api.post('/restaurants/123/pos-shift/close', { id: '01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33', counted_cash: { amount: 734300, currency: 'CZK' }, note: 'Chybí 4 Kč.', }); // 201 PosShiftClose// the client: see /v2/docs/typescript // the library adds the employee's token itself (after the employee signs in) const posShift = await api.post('/restaurants/123/pos-shift/close', { id: '01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33', counted_cash: { amount: 734300, currency: 'CZK' }, note: 'Chybí 4 Kč.', }); // 201 PosShiftClose// klient: viz /v2/docs/php // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) $posShift = $api->post('/restaurants/123/pos-shift/close', [ 'id' => '01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33', 'counted_cash' => ['amount' => 734300, 'currency' => 'CZK'], 'note' => 'Chybí 4 Kč.', ]); // 201// the client: see /v2/docs/php // the library adds the employee's token itself (after the employee signs in) $posShift = $api->post('/restaurants/123/pos-shift/close', [ 'id' => '01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33', 'counted_cash' => ['amount' => 734300, 'currency' => 'CZK'], 'note' => 'Chybí 4 Kč.', ]); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) PosShiftClose posShift = api.post("/restaurants/123/pos-shift/close", Json.parse(""" { "id": "01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33", "counted_cash": {"amount": 734300, "currency": "CZK"}, "note": "Chybí 4 Kč." } """), PosShiftClose::fromJson); // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) PosShiftClose posShift = api.post("/restaurants/123/pos-shift/close", Json.parse(""" { "id": "01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33", "counted_cash": {"amount": 734300, "currency": "CZK"}, "note": "Chybí 4 Kč." } """), PosShiftClose::fromJson); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) val posShift = api.post("/restaurants/123/pos-shift/close", mapOf( "id" to "01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33", "counted_cash" to mapOf("amount" to 734300, "currency" to "CZK"), "note" to "Chybí 4 Kč.", ), PosShiftClose::fromJson) // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) val posShift = api.post("/restaurants/123/pos-shift/close", mapOf( "id" to "01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33", "counted_cash" to mapOf("amount" to 734300, "currency" to "CZK"), "note" to "Chybí 4 Kč.", ), PosShiftClose::fromJson) // 201// klient: viz /v2/docs/csharp // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) var posShift = await api.PostAsync<PosShiftClose>("/restaurants/123/pos-shift/close", new { id = "01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33", counted_cash = new { amount = 734300, currency = "CZK" }, note = "Chybí 4 Kč.", }); // 201// the client: see /v2/docs/csharp // the library adds the employee's token itself (after the employee signs in) var posShift = await api.PostAsync<PosShiftClose>("/restaurants/123/pos-shift/close", new { id = "01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33", counted_cash = new { amount = 734300, currency = "CZK" }, note = "Chybí 4 Kč.", }); // 201# klient: viz /v2/docs/python # token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) pos_shift = api.post('/restaurants/123/pos-shift/close', { 'id': '01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33', 'counted_cash': {'amount': 734300, 'currency': 'CZK'}, 'note': 'Chybí 4 Kč.', }) # 201# the client: see /v2/docs/python # the library adds the employee's token itself (after the employee signs in) pos_shift = api.post('/restaurants/123/pos-shift/close', { 'id': '01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33', 'counted_cash': {'amount': 734300, 'currency': 'CZK'}, 'note': 'Chybí 4 Kč.', }) # 201// klient: viz /v2/docs/swift // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) let posShift: PosShiftClose = try await api.post("/restaurants/123/pos-shift/close", body: [ "id": "01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33", "counted_cash": ["amount": 734300, "currency": "CZK"], "note": "Chybí 4 Kč.", ]) // 201// the client: see /v2/docs/swift // the library adds the employee's token itself (after the employee signs in) let posShift: PosShiftClose = try await api.post("/restaurants/123/pos-shift/close", body: [ "id": "01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33", "counted_cash": ["amount": 734300, "currency": "CZK"], "note": "Chybí 4 Kč.", ]) // 201// klient: viz /v2/docs/dart // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) final posShift = pr.PosShiftClose.fromJson(await api.post('/restaurants/123/pos-shift/close', { 'id': '01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33', 'counted_cash': {'amount': 734300, 'currency': 'CZK'}, 'note': 'Chybí 4 Kč.', })); // 201// the client: see /v2/docs/dart // the library adds the employee's token itself (after the employee signs in) final posShift = pr.PosShiftClose.fromJson(await api.post('/restaurants/123/pos-shift/close', { 'id': '01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33', 'counted_cash': {'amount': 734300, 'currency': 'CZK'}, 'note': 'Chybí 4 Kč.', })); // 201// klient: viz /v2/docs/go // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) res, err := api.Post(ctx, "/restaurants/123/pos-shift/close", map[string]any{ "id": "01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33", "counted_cash": map[string]any{"amount": 734300, "currency": "CZK"}, "note": "Chybí 4 Kč.", }, nil) var posShift model.PosShiftClose // 201 if err == nil { err = res.Decode(&posShift) }// the client: see /v2/docs/go // the library adds the employee's token itself (after the employee signs in) res, err := api.Post(ctx, "/restaurants/123/pos-shift/close", map[string]any{ "id": "01a318f0-a0c0-7ce8-9a4a-c5d2d2497f33", "counted_cash": map[string]any{"amount": 734300, "currency": "CZK"}, "note": "Chybí 4 Kč.", }, nil) var posShift model.PosShiftClose // 201 if err == nil { err = res.Decode(&posShift) }Příklad odpovědi 200Example answer 200
{ "id": "01a318f0-a0c0-7031-8216-27bad8f984d8", "device_id": "512", "closed_at": "2027-01-15T22:15:40+01:00", "closed_by": { "id": "61", "name": "Petr Novák" }, "summary": { "device_id": "512", "opened_at": "2027-01-15T11:48:02+01:00", "receipts": { "sales": 1, "storno": 1 }, "totals": { "sales": { "amount": 10000, "currency": "CZK" }, "storno": { "amount": 10000, "currency": "CZK" }, "net": { "amount": 10000, "currency": "CZK" } }, "payments": [ { "method": "cash", "amount": { "amount": 10000, "currency": "CZK" }, "tips": { "amount": 10000, "currency": "CZK" }, "count": 1 } ], "tips": { "amount": 10000, "currency": "CZK" }, "vat": [ { "rate": "12", "base": { "amount": 10000, "currency": "CZK" }, "vat": { "amount": 10000, "currency": "CZK" }, "total": { "amount": 10000, "currency": "CZK" } } ], "vouchers": { "sold": { "amount": 10000, "currency": "CZK" }, "redeemed": { "amount": 10000, "currency": "CZK" } }, "eet": { "pending": 1, "rejected": 1 }, "open_tabs": { "count": 1, "total": { "amount": 10000, "currency": "CZK" } }, "cash_movements": { "count": 1, "deposits": { "amount": 10000, "currency": "CZK" }, "incomes": { "amount": 10000, "currency": "CZK" }, "withdrawals": { "amount": 10000, "currency": "CZK" }, "expenses": { "amount": 10000, "currency": "CZK" }, "net": { "amount": 10000, "currency": "CZK" } }, "device_ids": [ "20330" ], "by_device": [ { "device_id": "512", "name": "Pokladna u baru", "receipts": { "sales": 1, "storno": 1 }, "net": { "amount": 10000, "currency": "CZK" }, "payments": [ { "method": "cash", "amount": { "amount": 10000, "currency": "CZK" }, "tips": { "amount": 10000, "currency": "CZK" }, "count": 1 } ] } ], "by_employee": [ { "employee": { "id": "58", "name": "Jana Dvořáková" }, "receipts": { "sales": 1, "storno": 1 }, "net": { "amount": 10000, "currency": "CZK" }, "payments": [ { "method": "cash", "amount": { "amount": 10000, "currency": "CZK" }, "tips": { "amount": 10000, "currency": "CZK" }, "count": 1 } ] } ] }, "cash_expected": { "amount": 10000, "currency": "CZK" }, "counted_cash": { "amount": 10000, "currency": "CZK" }, "cash_difference": { "amount": 10000, "currency": "CZK" }, "note": null }
Scénář
Scenario
Kuchyňský displej
A kitchen display
Vlastní zařízení ProfirestuProfirest's own deviceDisplej ukazuje bony ze všech zdrojů – pokladna, e-shop, rozvozové platformy – a hlásí, co je hotové. Výroba se dá rozdělit na stanoviště (gril, pizza) a výdej.
The display shows tickets from every source – the register, the e-shop, delivery platforms – and reports what is done. Production can be split into stations (grill, pizza) and the hand-out.
-
Bony na displeji
Tickets on the display
GET /restaurants/{restaurant_id}/kitchen/tickets · listKitchenTickets
view=activejsou bony k přípravě,preordersobjednávky na později ahistoryhotové. Ptejte se sIf-None-Match. Bon nese ceny položek a účtenku k tisku pro rozvoz (receipt) – nepočítejte ji v aplikaci. Rozvoz nese i rozvozovou zónu (delivery_zone) pro souhrn podle zón; ten nabídněte, jen kdyžlistDeliveryZonesnějaké zóny vrací.view=activeare tickets to prepare,preordersorders for later andhistorythe finished ones. Ask withIf-None-Match. A ticket carries the prices of the items and the receipt to print for a delivery (receipt) – do not compute it in the application. A delivery also carries its delivery zone (delivery_zone) for a summary by zones; offer it only whenlistDeliveryZonesreturns some zones.curl "https://api.mujprofirest.cz/v2/restaurants/123/kitchen/tickets?view=active&area=kitchen" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/kitchen/tickets?view=active&area=kitchen" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const { data, next_cursor } = await api.get('/restaurants/123/kitchen/tickets', { query: { view: 'active', area: 'kitchen' } }); // 200// the client: see /v2/docs/js const { data, next_cursor } = await api.get('/restaurants/123/kitchen/tickets', { query: { view: 'active', area: 'kitchen' } }); // 200// klient: viz /v2/docs/typescript const { data, next_cursor } = await api.get('/restaurants/123/kitchen/tickets', { query: { view: 'active', area: 'kitchen' } }); // 200 KitchenTicketPage// the client: see /v2/docs/typescript const { data, next_cursor } = await api.get('/restaurants/123/kitchen/tickets', { query: { view: 'active', area: 'kitchen' } }); // 200 KitchenTicketPage// klient: viz /v2/docs/php $page = $api->get( '/restaurants/123/kitchen/tickets', ['query' => ['view' => 'active', 'area' => 'kitchen']], ); // $page['data'], $page['next_cursor']// the client: see /v2/docs/php $page = $api->get( '/restaurants/123/kitchen/tickets', ['query' => ['view' => 'active', 'area' => 'kitchen']], ); // $page['data'], $page['next_cursor']// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) KitchenTicketPage listKitchenTickets = api.get( "/restaurants/123/kitchen/tickets", RequestOptions.builder().query("view", "active").query("area", "kitchen").build(), KitchenTicketPage::fromJson ); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) KitchenTicketPage listKitchenTickets = api.get( "/restaurants/123/kitchen/tickets", RequestOptions.builder().query("view", "active").query("area", "kitchen").build(), KitchenTicketPage::fromJson ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val listKitchenTickets = api.get( "/restaurants/123/kitchen/tickets", RequestOptions.builder().query("view", "active").query("area", "kitchen").build(), KitchenTicketPage::fromJson, ) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val listKitchenTickets = api.get( "/restaurants/123/kitchen/tickets", RequestOptions.builder().query("view", "active").query("area", "kitchen").build(), KitchenTicketPage::fromJson, ) // 200// klient: viz /v2/docs/csharp var listKitchenTickets = await api.GetAsync<KitchenTicketPage>( "/restaurants/123/kitchen/tickets", new RequestOptions { Query = new() { ["view"] = "active", ["area"] = "kitchen" } } ); // 200// the client: see /v2/docs/csharp var listKitchenTickets = await api.GetAsync<KitchenTicketPage>( "/restaurants/123/kitchen/tickets", new RequestOptions { Query = new() { ["view"] = "active", ["area"] = "kitchen" } } ); // 200# klient: viz /v2/docs/python page = api.get('/restaurants/123/kitchen/tickets', query={'view': 'active', 'area': 'kitchen'}) # page['data'], page['next_cursor']# the client: see /v2/docs/python page = api.get('/restaurants/123/kitchen/tickets', query={'view': 'active', 'area': 'kitchen'}) # page['data'], page['next_cursor']// klient: viz /v2/docs/swift let listKitchenTickets: KitchenTicketPage = try await api.get( "/restaurants/123/kitchen/tickets", options: .init(query: ["view": "active", "area": "kitchen"]) ) // 200// the client: see /v2/docs/swift let listKitchenTickets: KitchenTicketPage = try await api.get( "/restaurants/123/kitchen/tickets", options: .init(query: ["view": "active", "area": "kitchen"]) ) // 200// klient: viz /v2/docs/dart final listKitchenTickets = pr.KitchenTicketPage.fromJson(await api.get('/restaurants/123/kitchen/tickets', query: {'view': 'active', 'area': 'kitchen'})); // 200// the client: see /v2/docs/dart final listKitchenTickets = pr.KitchenTicketPage.fromJson(await api.get('/restaurants/123/kitchen/tickets', query: {'view': 'active', 'area': 'kitchen'})); // 200// klient: viz /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/kitchen/tickets", &profirest.RequestOptions{Query: map[string]any{"view": "active", "area": "kitchen"}}, ) var listKitchenTickets model.KitchenTicketPage // 200 if err == nil { err = res.Decode(&listKitchenTickets) }// the client: see /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/kitchen/tickets", &profirest.RequestOptions{Query: map[string]any{"view": "active", "area": "kitchen"}}, ) var listKitchenTickets model.KitchenTicketPage // 200 if err == nil { err = res.Decode(&listKitchenTickets) }Příklad odpovědi 200Example answer 200
{ "data": [ { "id": "77812", "order_id": "184223", "number": "027", "status": "preparing", "area": "kitchen", "source": "web", "platform": null, "name": "Jana Nováková", "fulfillment": "takeaway", "express": false, "customer": { "name": "Jana Nováková", "phone": "+420777123456", "not_delivered_count": 0, "last_not_delivered_at": null }, "delivery_address": null, "delivery_zone": null, "note": null, "payment_method": "cash", "total": { "amount": 39800, "currency": "CZK" }, "delivery_price": { "amount": 0, "currency": "CZK" }, "amount_due": { "amount": 39800, "currency": "CZK" }, "paid_by": null, "created_at": "2027-01-15T11:42:31+01:00", "scheduled_for": null, "printed": true, "courier": null, "not_delivered": null, "items": [ { "id": "52011", "product_id": "4567", "name": "Svíčková na smetaně, houskový knedlík", "kitchen_name": null, "note": null, "quantity": 2, "kind": "full", "charge": null, "course": 0, "category": { "id": "312", "name": "Hlavní jídla" }, "from_daily_menu": false, "station_id": "2", "status": "pending", "handed_out": false, "part": null, "size": null, "unit_price": { "amount": 19900, "currency": "CZK" }, "packaging_price": { "amount": 0, "currency": "CZK" }, "discount": { "amount": 0, "currency": "CZK" }, "gift": false, "vat_rate": "12", "removed_ingredients": [], "modifiers": [] } ], "receipt": { "items": { "amount": 39800, "currency": "CZK" }, "discounts": [], "delivery": { "amount": 0, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "adjustment": { "amount": 0, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" }, "to_pay": { "amount": 39800, "currency": "CZK" }, "vat": [ { "rate": "12", "base": { "amount": 35536, "currency": "CZK" }, "vat": { "amount": 4264, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" } } ], "document": { "title": "Účtenka", "number": "184223", "tax_document": "Zjednodušený daňový doklad" } } }, { "id": "77814", "order_id": "184230", "number": "029", "status": "received", "area": "kitchen", "source": "pos", "platform": null, "name": "Stůl 4", "fulfillment": "dine_in", "express": false, "customer": null, "delivery_address": null, "delivery_zone": null, "note": null, "payment_method": "cash", "total": { "amount": 19900, "currency": "CZK" }, "delivery_price": { "amount": 0, "currency": "CZK" }, "amount_due": { "amount": 0, "currency": "CZK" }, "paid_by": null, "created_at": "2027-01-15T11:51:40+01:00", "scheduled_for": null, "printed": false, "courier": null, "not_delivered": null, "items": [ { "id": "52020", "product_id": "4567", "name": "Svíčková na smetaně, houskový knedlík", "kitchen_name": null, "note": null, "quantity": 1, "kind": "full", "charge": null, "course": 1, "category": { "id": "312", "name": "Hlavní jídla" }, "from_daily_menu": false, "station_id": "2", "status": "pending", "handed_out": false, "part": null, "size": null, "unit_price": { "amount": 19900, "currency": "CZK" }, "packaging_price": { "amount": 0, "currency": "CZK" }, "discount": { "amount": 0, "currency": "CZK" }, "gift": false, "vat_rate": "12", "removed_ingredients": [], "modifiers": [] } ], "receipt": { "items": { "amount": 19900, "currency": "CZK" }, "discounts": [], "delivery": { "amount": 0, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "adjustment": { "amount": 0, "currency": "CZK" }, "total": { "amount": 19900, "currency": "CZK" }, "to_pay": { "amount": 19900, "currency": "CZK" }, "vat": [ { "rate": "12", "base": { "amount": 17768, "currency": "CZK" }, "vat": { "amount": 2132, "currency": "CZK" }, "total": { "amount": 19900, "currency": "CZK" } } ], "document": { "title": "Účtenka", "number": "184230", "tax_document": "Zjednodušený daňový doklad" } } }, { "id": "77815", "order_id": "184226", "number": "030", "status": "ready", "area": "kitchen", "source": "web", "platform": null, "name": "Jana Nováková", "fulfillment": "delivery", "express": false, "customer": { "name": "Jana Nováková", "phone": "+420777123456", "not_delivered_count": 0, "last_not_delivered_at": null }, "delivery_address": { "street": "Jeseniova 1196/52", "city": "Praha 3", "location": { "lat": 50.0833, "lon": 14.4667 } }, "delivery_zone": { "id": "21", "name": "Vinohrady do 3 km" }, "note": "3. patro, zvonek Nováková", "payment_method": "cash", "total": { "amount": 38600, "currency": "CZK" }, "delivery_price": { "amount": 4900, "currency": "CZK" }, "amount_due": { "amount": 38600, "currency": "CZK" }, "paid_by": null, "created_at": "2027-01-15T11:50:40+01:00", "scheduled_for": null, "printed": true, "courier": null, "not_delivered": null, "items": [ { "id": "52031", "product_id": "4571", "name": "Pizza Margherita", "kitchen_name": null, "note": "Nekrájet", "quantity": 1, "kind": "full", "charge": null, "course": 0, "category": { "id": "315", "name": "Pizza" }, "from_daily_menu": false, "station_id": "3", "status": "done", "handed_out": false, "part": null, "size": { "name": "Ø32cm", "dish_name": "Pizza Margherita" }, "unit_price": { "amount": 18900, "currency": "CZK" }, "packaging_price": { "amount": 0, "currency": "CZK" }, "discount": { "amount": 0, "currency": "CZK" }, "gift": false, "vat_rate": "12", "removed_ingredients": [], "modifiers": [ { "id": "52032", "charge": null, "product_id": "4602", "name": "Extra sýr", "kitchen_name": null, "note": null, "quantity": 1, "kind": "full", "status": "done", "handed_out": false, "part": null, "size": null, "unit_price": { "amount": 3000, "currency": "CZK" }, "packaging_price": { "amount": 0, "currency": "CZK" }, "discount": { "amount": 0, "currency": "CZK" }, "gift": false, "vat_rate": "12", "removed_ingredients": [] } ] }, { "id": "52033", "product_id": "4593", "name": "Domácí limonáda 0,4 l", "kitchen_name": null, "note": null, "quantity": 2, "kind": "full", "charge": null, "course": 0, "category": { "id": "320", "name": "Nápoje" }, "from_daily_menu": false, "station_id": null, "status": "done", "handed_out": false, "part": null, "size": null, "unit_price": { "amount": 5900, "currency": "CZK" }, "packaging_price": { "amount": 0, "currency": "CZK" }, "discount": { "amount": 0, "currency": "CZK" }, "gift": false, "vat_rate": "12", "removed_ingredients": [], "modifiers": [] } ], "receipt": { "items": { "amount": 33700, "currency": "CZK" }, "discounts": [], "delivery": { "amount": 4900, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "adjustment": { "amount": 0, "currency": "CZK" }, "total": { "amount": 38600, "currency": "CZK" }, "to_pay": { "amount": 38600, "currency": "CZK" }, "vat": [ { "rate": "12", "base": { "amount": 34464, "currency": "CZK" }, "vat": { "amount": 4136, "currency": "CZK" }, "total": { "amount": 38600, "currency": "CZK" } } ], "document": { "title": "Účtenka", "number": "184226", "tax_document": "Zjednodušený daňový doklad" } } } ], "next_cursor": null, "preorders_later": 2 } -
Změňte stav
Change the status
POST /restaurants/{restaurant_id}/kitchen/tickets/{ticket_id}/status · setKitchenTicketStatus
preparing,ready,delivered– zákazník e-shopu se o hotové objednávce dozví hned.preparing,ready,delivered– an e-shop customer learns about a ready order at once.curl "https://api.mujprofirest.cz/v2/restaurants/123/kitchen/tickets/77812/status" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7859-9873-bf7a7bca44e7" \ -H "Content-Type: application/json" \ -d '{"status": "ready"}'curl "https://api.mujprofirest.cz/v2/restaurants/123/kitchen/tickets/77812/status" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7859-9873-bf7a7bca44e7" \ -H "Content-Type: application/json" \ -d '{"status": "ready"}'// klient: viz /v2/docs/js // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const kitchenTicketStatus = await api.post('/restaurants/123/kitchen/tickets/77812/status', { status: 'ready' }); // 200// the client: see /v2/docs/js // the library adds the employee's token itself (after the employee signs in) const kitchenTicketStatus = await api.post('/restaurants/123/kitchen/tickets/77812/status', { status: 'ready' }); // 200// klient: viz /v2/docs/typescript // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const kitchenTicketStatus = await api.post('/restaurants/123/kitchen/tickets/77812/status', { status: 'ready' }); // 200 KitchenTicket// the client: see /v2/docs/typescript // the library adds the employee's token itself (after the employee signs in) const kitchenTicketStatus = await api.post('/restaurants/123/kitchen/tickets/77812/status', { status: 'ready' }); // 200 KitchenTicket// klient: viz /v2/docs/php // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) $kitchenTicketStatus = $api->post('/restaurants/123/kitchen/tickets/77812/status', ['status' => 'ready']); // 200// the client: see /v2/docs/php // the library adds the employee's token itself (after the employee signs in) $kitchenTicketStatus = $api->post('/restaurants/123/kitchen/tickets/77812/status', ['status' => 'ready']); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) KitchenTicket kitchenTicketStatus = api.post("/restaurants/123/kitchen/tickets/77812/status", Json.parse(""" {"status": "ready"} """), KitchenTicket::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) KitchenTicket kitchenTicketStatus = api.post("/restaurants/123/kitchen/tickets/77812/status", Json.parse(""" {"status": "ready"} """), KitchenTicket::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) val kitchenTicketStatus = api.post( "/restaurants/123/kitchen/tickets/77812/status", mapOf("status" to "ready"), KitchenTicket::fromJson, ) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) val kitchenTicketStatus = api.post( "/restaurants/123/kitchen/tickets/77812/status", mapOf("status" to "ready"), KitchenTicket::fromJson, ) // 200// klient: viz /v2/docs/csharp // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) var kitchenTicketStatus = await api.PostAsync<KitchenTicket>( "/restaurants/123/kitchen/tickets/77812/status", new { status = "ready" } ); // 200// the client: see /v2/docs/csharp // the library adds the employee's token itself (after the employee signs in) var kitchenTicketStatus = await api.PostAsync<KitchenTicket>( "/restaurants/123/kitchen/tickets/77812/status", new { status = "ready" } ); // 200# klient: viz /v2/docs/python # token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) kitchen_ticket_status = api.post('/restaurants/123/kitchen/tickets/77812/status', {'status': 'ready'}) # 200# the client: see /v2/docs/python # the library adds the employee's token itself (after the employee signs in) kitchen_ticket_status = api.post('/restaurants/123/kitchen/tickets/77812/status', {'status': 'ready'}) # 200// klient: viz /v2/docs/swift // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) let kitchenTicketStatus: KitchenTicket = try await api.post("/restaurants/123/kitchen/tickets/77812/status", body: ["status": "ready"]) // 200// the client: see /v2/docs/swift // the library adds the employee's token itself (after the employee signs in) let kitchenTicketStatus: KitchenTicket = try await api.post("/restaurants/123/kitchen/tickets/77812/status", body: ["status": "ready"]) // 200// klient: viz /v2/docs/dart // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) final kitchenTicketStatus = pr.KitchenTicket.fromJson(await api.post('/restaurants/123/kitchen/tickets/77812/status', {'status': 'ready'})); // 200// the client: see /v2/docs/dart // the library adds the employee's token itself (after the employee signs in) final kitchenTicketStatus = pr.KitchenTicket.fromJson(await api.post('/restaurants/123/kitchen/tickets/77812/status', {'status': 'ready'})); // 200// klient: viz /v2/docs/go // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) res, err := api.Post( ctx, "/restaurants/123/kitchen/tickets/77812/status", map[string]any{"status": "ready"}, nil, ) var kitchenTicketStatus model.KitchenTicket // 200 if err == nil { err = res.Decode(&kitchenTicketStatus) }// the client: see /v2/docs/go // the library adds the employee's token itself (after the employee signs in) res, err := api.Post( ctx, "/restaurants/123/kitchen/tickets/77812/status", map[string]any{"status": "ready"}, nil, ) var kitchenTicketStatus model.KitchenTicket // 200 if err == nil { err = res.Decode(&kitchenTicketStatus) }Příklad odpovědi 200Example answer 200
{ "id": "77812", "order_id": "184223", "number": "027", "status": "ready", "area": "kitchen", "source": "web", "platform": null, "name": "Jana Nováková", "fulfillment": "takeaway", "express": false, "customer": { "name": "Jana Nováková", "phone": "+420777123456", "not_delivered_count": 0, "last_not_delivered_at": null }, "delivery_address": null, "delivery_zone": null, "note": null, "payment_method": "cash", "total": { "amount": 39800, "currency": "CZK" }, "delivery_price": { "amount": 0, "currency": "CZK" }, "amount_due": { "amount": 39800, "currency": "CZK" }, "paid_by": null, "created_at": "2027-01-15T11:42:31+01:00", "scheduled_for": null, "printed": true, "courier": null, "not_delivered": null, "items": [ { "id": "52011", "product_id": "4567", "name": "Svíčková na smetaně, houskový knedlík", "kitchen_name": null, "note": null, "quantity": 2, "kind": "full", "charge": null, "course": 0, "category": { "id": "312", "name": "Hlavní jídla" }, "from_daily_menu": false, "station_id": "2", "status": "done", "handed_out": false, "part": null, "size": null, "unit_price": { "amount": 19900, "currency": "CZK" }, "packaging_price": { "amount": 0, "currency": "CZK" }, "discount": { "amount": 0, "currency": "CZK" }, "gift": false, "vat_rate": "12", "removed_ingredients": [], "modifiers": [] } ], "receipt": { "items": { "amount": 39800, "currency": "CZK" }, "discounts": [], "delivery": { "amount": 0, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "adjustment": { "amount": 0, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" }, "to_pay": { "amount": 39800, "currency": "CZK" }, "vat": [ { "rate": "12", "base": { "amount": 35536, "currency": "CZK" }, "vat": { "amount": 4264, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" } } ], "document": { "title": "Účtenka", "number": "184223", "tax_document": "Zjednodušený daňový doklad" } } } -
Výroba po stanovištích
Production by station
GET /restaurants/{restaurant_id}/kitchen/stations/{station_id}/tickets · listStationTickets
Každé stanoviště vidí jen své položky, rozdělené po chodech a kategoriích.
Every station sees only its items, split by courses and categories.
curl "https://api.mujprofirest.cz/v2/restaurants/123/kitchen/stations/2/tickets" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/kitchen/stations/2/tickets" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const listStationTickets = await api.get('/restaurants/123/kitchen/stations/2/tickets'); // 200// the client: see /v2/docs/js const listStationTickets = await api.get('/restaurants/123/kitchen/stations/2/tickets'); // 200// klient: viz /v2/docs/typescript const listStationTickets = await api.get('/restaurants/123/kitchen/stations/2/tickets'); // 200 StationTicketList// the client: see /v2/docs/typescript const listStationTickets = await api.get('/restaurants/123/kitchen/stations/2/tickets'); // 200 StationTicketList// klient: viz /v2/docs/php $listStationTickets = $api->get('/restaurants/123/kitchen/stations/2/tickets'); // 200// the client: see /v2/docs/php $listStationTickets = $api->get('/restaurants/123/kitchen/stations/2/tickets'); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) StationTicketList listStationTickets = api.get("/restaurants/123/kitchen/stations/2/tickets", StationTicketList::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) StationTicketList listStationTickets = api.get("/restaurants/123/kitchen/stations/2/tickets", StationTicketList::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val listStationTickets = api.get("/restaurants/123/kitchen/stations/2/tickets", StationTicketList::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val listStationTickets = api.get("/restaurants/123/kitchen/stations/2/tickets", StationTicketList::fromJson) // 200// klient: viz /v2/docs/csharp var listStationTickets = await api.GetAsync<StationTicketList>("/restaurants/123/kitchen/stations/2/tickets"); // 200// the client: see /v2/docs/csharp var listStationTickets = await api.GetAsync<StationTicketList>("/restaurants/123/kitchen/stations/2/tickets"); // 200# klient: viz /v2/docs/python list_station_tickets = api.get('/restaurants/123/kitchen/stations/2/tickets') # 200# the client: see /v2/docs/python list_station_tickets = api.get('/restaurants/123/kitchen/stations/2/tickets') # 200// klient: viz /v2/docs/swift let listStationTickets: StationTicketList = try await api.get("/restaurants/123/kitchen/stations/2/tickets") // 200// the client: see /v2/docs/swift let listStationTickets: StationTicketList = try await api.get("/restaurants/123/kitchen/stations/2/tickets") // 200// klient: viz /v2/docs/dart final listStationTickets = pr.StationTicketList.fromJson(await api.get('/restaurants/123/kitchen/stations/2/tickets')); // 200// the client: see /v2/docs/dart final listStationTickets = pr.StationTicketList.fromJson(await api.get('/restaurants/123/kitchen/stations/2/tickets')); // 200// klient: viz /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/kitchen/stations/2/tickets", nil) var listStationTickets model.StationTicketList // 200 if err == nil { err = res.Decode(&listStationTickets) }// the client: see /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/kitchen/stations/2/tickets", nil) var listStationTickets model.StationTicketList // 200 if err == nil { err = res.Decode(&listStationTickets) }Příklad odpovědi 200Example answer 200
{ "data": [ { "ticket": { "id": "77812", "order_id": "184223", "number": "027", "status": "preparing", "area": "kitchen", "source": "web", "platform": null, "name": "Jana Nováková", "fulfillment": "takeaway", "express": false, "customer": { "name": "Jana Nováková", "phone": "+420777123456", "not_delivered_count": 0, "last_not_delivered_at": null }, "delivery_address": null, "delivery_zone": null, "note": null, "payment_method": "cash", "total": { "amount": 39800, "currency": "CZK" }, "delivery_price": { "amount": 0, "currency": "CZK" }, "amount_due": { "amount": 39800, "currency": "CZK" }, "paid_by": null, "created_at": "2027-01-15T11:42:31+01:00", "scheduled_for": null, "printed": true, "courier": null, "not_delivered": null, "items": [ { "id": "52011", "product_id": "4567", "name": "Svíčková na smetaně, houskový knedlík", "kitchen_name": null, "note": null, "quantity": 2, "kind": "full", "charge": null, "course": 0, "category": { "id": "312", "name": "Hlavní jídla" }, "from_daily_menu": false, "station_id": "2", "status": "pending", "handed_out": false, "part": null, "size": null, "unit_price": { "amount": 19900, "currency": "CZK" }, "packaging_price": { "amount": 0, "currency": "CZK" }, "discount": { "amount": 0, "currency": "CZK" }, "gift": false, "vat_rate": "12", "removed_ingredients": [], "modifiers": [] } ], "receipt": { "items": { "amount": 39800, "currency": "CZK" }, "discounts": [], "delivery": { "amount": 0, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "adjustment": { "amount": 0, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" }, "to_pay": { "amount": 39800, "currency": "CZK" }, "vat": [ { "rate": "12", "base": { "amount": 35536, "currency": "CZK" }, "vat": { "amount": 4264, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" } } ], "document": { "title": "Účtenka", "number": "184223", "tax_document": "Zjednodušený daňový doklad" } } }, "working": true, "other_stations": [], "courses": [ { "course": 0, "done": false, "categories": [ { "id": "312", "name": "Hlavní jídla", "done": false, "item_ids": [ "52011" ] } ] } ] }, { "ticket": { "id": "77814", "order_id": "184230", "number": "029", "status": "received", "area": "kitchen", "source": "pos", "platform": null, "name": "Stůl 4", "fulfillment": "dine_in", "express": false, "customer": null, "delivery_address": null, "delivery_zone": null, "note": null, "payment_method": "cash", "total": { "amount": 19900, "currency": "CZK" }, "delivery_price": { "amount": 0, "currency": "CZK" }, "amount_due": { "amount": 0, "currency": "CZK" }, "paid_by": null, "created_at": "2027-01-15T11:51:40+01:00", "scheduled_for": null, "printed": false, "courier": null, "not_delivered": null, "items": [ { "id": "52020", "product_id": "4567", "name": "Svíčková na smetaně, houskový knedlík", "kitchen_name": null, "note": null, "quantity": 1, "kind": "full", "charge": null, "course": 1, "category": { "id": "312", "name": "Hlavní jídla" }, "from_daily_menu": false, "station_id": "2", "status": "pending", "handed_out": false, "part": null, "size": null, "unit_price": { "amount": 19900, "currency": "CZK" }, "packaging_price": { "amount": 0, "currency": "CZK" }, "discount": { "amount": 0, "currency": "CZK" }, "gift": false, "vat_rate": "12", "removed_ingredients": [], "modifiers": [] } ], "receipt": { "items": { "amount": 19900, "currency": "CZK" }, "discounts": [], "delivery": { "amount": 0, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "adjustment": { "amount": 0, "currency": "CZK" }, "total": { "amount": 19900, "currency": "CZK" }, "to_pay": { "amount": 19900, "currency": "CZK" }, "vat": [ { "rate": "12", "base": { "amount": 17768, "currency": "CZK" }, "vat": { "amount": 2132, "currency": "CZK" }, "total": { "amount": 19900, "currency": "CZK" } } ], "document": { "title": "Účtenka", "number": "184230", "tax_document": "Zjednodušený daňový doklad" } } }, "working": false, "other_stations": [ { "id": "3", "name": "Pizza" } ], "courses": [ { "course": 1, "done": false, "categories": [ { "id": "312", "name": "Hlavní jídla", "done": false, "item_ids": [ "52020" ] } ] } ] } ] } -
Odbavte chod
Complete a course
POST /restaurants/{restaurant_id}/kitchen/stations/{station_id}/tickets/{ticket_id}/complete · completeStationSegment
Celou objednávku, chod nebo kategorii. Omyl jde vrátit v historii stanoviště (undo).
The whole order, a course or a category. A mistake can be undone in the station's history.
curl "https://api.mujprofirest.cz/v2/restaurants/123/kitchen/stations/2/tickets/77812/complete" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7286-8f53-6133d6a059b4" \ -H "Content-Type: application/json" \ -d '{"scope": "order"}'curl "https://api.mujprofirest.cz/v2/restaurants/123/kitchen/stations/2/tickets/77812/complete" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7286-8f53-6133d6a059b4" \ -H "Content-Type: application/json" \ -d '{"scope": "order"}'// klient: viz /v2/docs/js // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const stationSegment = await api.post('/restaurants/123/kitchen/stations/2/tickets/77812/complete', { scope: 'order' }); // 201// the client: see /v2/docs/js // the library adds the employee's token itself (after the employee signs in) const stationSegment = await api.post('/restaurants/123/kitchen/stations/2/tickets/77812/complete', { scope: 'order' }); // 201// klient: viz /v2/docs/typescript // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const stationSegment = await api.post('/restaurants/123/kitchen/stations/2/tickets/77812/complete', { scope: 'order' }); // 201 ProductionAction// the client: see /v2/docs/typescript // the library adds the employee's token itself (after the employee signs in) const stationSegment = await api.post('/restaurants/123/kitchen/stations/2/tickets/77812/complete', { scope: 'order' }); // 201 ProductionAction// klient: viz /v2/docs/php // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) $stationSegment = $api->post('/restaurants/123/kitchen/stations/2/tickets/77812/complete', ['scope' => 'order']); // 201// the client: see /v2/docs/php // the library adds the employee's token itself (after the employee signs in) $stationSegment = $api->post('/restaurants/123/kitchen/stations/2/tickets/77812/complete', ['scope' => 'order']); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) ProductionAction stationSegment = api.post("/restaurants/123/kitchen/stations/2/tickets/77812/complete", Json.parse(""" {"scope": "order"} """), ProductionAction::fromJson); // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) ProductionAction stationSegment = api.post("/restaurants/123/kitchen/stations/2/tickets/77812/complete", Json.parse(""" {"scope": "order"} """), ProductionAction::fromJson); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) val stationSegment = api.post( "/restaurants/123/kitchen/stations/2/tickets/77812/complete", mapOf("scope" to "order"), ProductionAction::fromJson, ) // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) val stationSegment = api.post( "/restaurants/123/kitchen/stations/2/tickets/77812/complete", mapOf("scope" to "order"), ProductionAction::fromJson, ) // 201// klient: viz /v2/docs/csharp // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) var stationSegment = await api.PostAsync<ProductionAction>( "/restaurants/123/kitchen/stations/2/tickets/77812/complete", new { scope = "order" } ); // 201// the client: see /v2/docs/csharp // the library adds the employee's token itself (after the employee signs in) var stationSegment = await api.PostAsync<ProductionAction>( "/restaurants/123/kitchen/stations/2/tickets/77812/complete", new { scope = "order" } ); // 201# klient: viz /v2/docs/python # token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) station_segment = api.post('/restaurants/123/kitchen/stations/2/tickets/77812/complete', {'scope': 'order'}) # 201# the client: see /v2/docs/python # the library adds the employee's token itself (after the employee signs in) station_segment = api.post('/restaurants/123/kitchen/stations/2/tickets/77812/complete', {'scope': 'order'}) # 201// klient: viz /v2/docs/swift // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) let stationSegment: ProductionAction = try await api.post("/restaurants/123/kitchen/stations/2/tickets/77812/complete", body: ["scope": "order"]) // 201// the client: see /v2/docs/swift // the library adds the employee's token itself (after the employee signs in) let stationSegment: ProductionAction = try await api.post("/restaurants/123/kitchen/stations/2/tickets/77812/complete", body: ["scope": "order"]) // 201// klient: viz /v2/docs/dart // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) final stationSegment = pr.ProductionAction.fromJson(await api.post('/restaurants/123/kitchen/stations/2/tickets/77812/complete', {'scope': 'order'})); // 201// the client: see /v2/docs/dart // the library adds the employee's token itself (after the employee signs in) final stationSegment = pr.ProductionAction.fromJson(await api.post('/restaurants/123/kitchen/stations/2/tickets/77812/complete', {'scope': 'order'})); // 201// klient: viz /v2/docs/go // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) res, err := api.Post( ctx, "/restaurants/123/kitchen/stations/2/tickets/77812/complete", map[string]any{"scope": "order"}, nil, ) var stationSegment model.ProductionAction // 201 if err == nil { err = res.Decode(&stationSegment) }// the client: see /v2/docs/go // the library adds the employee's token itself (after the employee signs in) res, err := api.Post( ctx, "/restaurants/123/kitchen/stations/2/tickets/77812/complete", map[string]any{"scope": "order"}, nil, ) var stationSegment model.ProductionAction // 201 if err == nil { err = res.Decode(&stationSegment) }Příklad odpovědi 201Example answer 201
{ "id": "9921", "ticket_id": "77812", "kind": "production", "scope": "order", "name": "Celá objednávka", "item_count": 2, "undone": false, "created_at": "2027-01-15T11:57:02+01:00", "employee": { "id": "66", "name": "Lucie Svobodová" } } -
Výdej
Hand-out
POST /restaurants/{restaurant_id}/kitchen/tickets/{ticket_id}/handover · handOverTicketSegment
Výdejní okno potvrdí, co odešlo ke stolu nebo zákazníkovi.
The hand-out window confirms what went to the table or the customer.
curl "https://api.mujprofirest.cz/v2/restaurants/123/kitchen/tickets/77812/handover" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-76ca-9937-77abc3d63953" \ -H "Content-Type: application/json" \ -d '{"scope": "order"}'curl "https://api.mujprofirest.cz/v2/restaurants/123/kitchen/tickets/77812/handover" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-76ca-9937-77abc3d63953" \ -H "Content-Type: application/json" \ -d '{"scope": "order"}'// klient: viz /v2/docs/js // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const overTicketSegment = await api.post('/restaurants/123/kitchen/tickets/77812/handover', { scope: 'order' }); // 201// the client: see /v2/docs/js // the library adds the employee's token itself (after the employee signs in) const overTicketSegment = await api.post('/restaurants/123/kitchen/tickets/77812/handover', { scope: 'order' }); // 201// klient: viz /v2/docs/typescript // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const overTicketSegment = await api.post('/restaurants/123/kitchen/tickets/77812/handover', { scope: 'order' }); // 201 ProductionAction// the client: see /v2/docs/typescript // the library adds the employee's token itself (after the employee signs in) const overTicketSegment = await api.post('/restaurants/123/kitchen/tickets/77812/handover', { scope: 'order' }); // 201 ProductionAction// klient: viz /v2/docs/php // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) $overTicketSegment = $api->post('/restaurants/123/kitchen/tickets/77812/handover', ['scope' => 'order']); // 201// the client: see /v2/docs/php // the library adds the employee's token itself (after the employee signs in) $overTicketSegment = $api->post('/restaurants/123/kitchen/tickets/77812/handover', ['scope' => 'order']); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) ProductionAction overTicketSegment = api.post("/restaurants/123/kitchen/tickets/77812/handover", Json.parse(""" {"scope": "order"} """), ProductionAction::fromJson); // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) ProductionAction overTicketSegment = api.post("/restaurants/123/kitchen/tickets/77812/handover", Json.parse(""" {"scope": "order"} """), ProductionAction::fromJson); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) val overTicketSegment = api.post( "/restaurants/123/kitchen/tickets/77812/handover", mapOf("scope" to "order"), ProductionAction::fromJson, ) // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) val overTicketSegment = api.post( "/restaurants/123/kitchen/tickets/77812/handover", mapOf("scope" to "order"), ProductionAction::fromJson, ) // 201// klient: viz /v2/docs/csharp // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) var overTicketSegment = await api.PostAsync<ProductionAction>( "/restaurants/123/kitchen/tickets/77812/handover", new { scope = "order" } ); // 201// the client: see /v2/docs/csharp // the library adds the employee's token itself (after the employee signs in) var overTicketSegment = await api.PostAsync<ProductionAction>( "/restaurants/123/kitchen/tickets/77812/handover", new { scope = "order" } ); // 201# klient: viz /v2/docs/python # token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) over_ticket_segment = api.post('/restaurants/123/kitchen/tickets/77812/handover', {'scope': 'order'}) # 201# the client: see /v2/docs/python # the library adds the employee's token itself (after the employee signs in) over_ticket_segment = api.post('/restaurants/123/kitchen/tickets/77812/handover', {'scope': 'order'}) # 201// klient: viz /v2/docs/swift // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) let overTicketSegment: ProductionAction = try await api.post("/restaurants/123/kitchen/tickets/77812/handover", body: ["scope": "order"]) // 201// the client: see /v2/docs/swift // the library adds the employee's token itself (after the employee signs in) let overTicketSegment: ProductionAction = try await api.post("/restaurants/123/kitchen/tickets/77812/handover", body: ["scope": "order"]) // 201// klient: viz /v2/docs/dart // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) final overTicketSegment = pr.ProductionAction.fromJson(await api.post('/restaurants/123/kitchen/tickets/77812/handover', {'scope': 'order'})); // 201// the client: see /v2/docs/dart // the library adds the employee's token itself (after the employee signs in) final overTicketSegment = pr.ProductionAction.fromJson(await api.post('/restaurants/123/kitchen/tickets/77812/handover', {'scope': 'order'})); // 201// klient: viz /v2/docs/go // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) res, err := api.Post( ctx, "/restaurants/123/kitchen/tickets/77812/handover", map[string]any{"scope": "order"}, nil, ) var overTicketSegment model.ProductionAction // 201 if err == nil { err = res.Decode(&overTicketSegment) }// the client: see /v2/docs/go // the library adds the employee's token itself (after the employee signs in) res, err := api.Post( ctx, "/restaurants/123/kitchen/tickets/77812/handover", map[string]any{"scope": "order"}, nil, ) var overTicketSegment model.ProductionAction // 201 if err == nil { err = res.Decode(&overTicketSegment) }Příklad odpovědi 201Example answer 201
{ "id": "9930", "ticket_id": "77812", "kind": "handover", "scope": "order", "name": "Celá objednávka", "item_count": 2, "undone": false, "created_at": "2027-01-15T12:04:11+01:00", "employee": { "id": "58", "name": "Jana Dvořáková" } } -
Pořadník pro zákazníky
The queue for customers
GET /restaurants/{restaurant_id}/kitchen/queue · getKitchenQueue
Čísla „připravujeme“ a „hotovo“ pro obrazovku u výdeje.
The “preparing” and “ready” numbers for the screen at the counter.
curl "https://api.mujprofirest.cz/v2/restaurants/123/kitchen/queue" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/kitchen/queue" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const kitchenQueue = await api.get('/restaurants/123/kitchen/queue'); // 200// the client: see /v2/docs/js const kitchenQueue = await api.get('/restaurants/123/kitchen/queue'); // 200// klient: viz /v2/docs/typescript const kitchenQueue = await api.get('/restaurants/123/kitchen/queue'); // 200 KitchenQueue// the client: see /v2/docs/typescript const kitchenQueue = await api.get('/restaurants/123/kitchen/queue'); // 200 KitchenQueue// klient: viz /v2/docs/php $kitchenQueue = $api->get('/restaurants/123/kitchen/queue'); // 200// the client: see /v2/docs/php $kitchenQueue = $api->get('/restaurants/123/kitchen/queue'); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) KitchenQueue kitchenQueue = api.get("/restaurants/123/kitchen/queue", KitchenQueue::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) KitchenQueue kitchenQueue = api.get("/restaurants/123/kitchen/queue", KitchenQueue::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val kitchenQueue = api.get("/restaurants/123/kitchen/queue", KitchenQueue::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val kitchenQueue = api.get("/restaurants/123/kitchen/queue", KitchenQueue::fromJson) // 200// klient: viz /v2/docs/csharp var kitchenQueue = await api.GetAsync<KitchenQueue>("/restaurants/123/kitchen/queue"); // 200// the client: see /v2/docs/csharp var kitchenQueue = await api.GetAsync<KitchenQueue>("/restaurants/123/kitchen/queue"); // 200# klient: viz /v2/docs/python kitchen_queue = api.get('/restaurants/123/kitchen/queue') # 200# the client: see /v2/docs/python kitchen_queue = api.get('/restaurants/123/kitchen/queue') # 200// klient: viz /v2/docs/swift let kitchenQueue: KitchenQueue = try await api.get("/restaurants/123/kitchen/queue") // 200// the client: see /v2/docs/swift let kitchenQueue: KitchenQueue = try await api.get("/restaurants/123/kitchen/queue") // 200// klient: viz /v2/docs/dart final kitchenQueue = pr.KitchenQueue.fromJson(await api.get('/restaurants/123/kitchen/queue')); // 200// the client: see /v2/docs/dart final kitchenQueue = pr.KitchenQueue.fromJson(await api.get('/restaurants/123/kitchen/queue')); // 200// klient: viz /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/kitchen/queue", nil) var kitchenQueue model.KitchenQueue // 200 if err == nil { err = res.Decode(&kitchenQueue) }// the client: see /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/kitchen/queue", nil) var kitchenQueue model.KitchenQueue // 200 if err == nil { err = res.Decode(&kitchenQueue) }Příklad odpovědi 200Example answer 200
{ "preparing": [ { "ticket_id": "77812", "number": "027", "since": "2027-01-15T11:44:02+01:00" }, { "ticket_id": "77814", "number": "029", "since": "2027-01-15T11:52:00+01:00" } ], "ready": [ { "ticket_id": "77815", "number": "030", "since": "2027-01-15T11:58:20+01:00" } ] } -
Uzávěrka kuchyně
Closing the kitchen
POST /restaurants/{restaurant_id}/kitchen/shift/close · closeKitchenShift
Tržby podle plateb a kurýrů; číslování bonů začne znovu.
Takings by payment and courier; ticket numbering starts again.
curl "https://api.mujprofirest.cz/v2/restaurants/123/kitchen/shift/close" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7066-9b00-4e4d06fa5038" \ -H "Content-Type: application/json" \ -d '{"courier_id": null}'curl "https://api.mujprofirest.cz/v2/restaurants/123/kitchen/shift/close" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7066-9b00-4e4d06fa5038" \ -H "Content-Type: application/json" \ -d '{"courier_id": null}'// klient: viz /v2/docs/js // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const kitchenShift = await api.post('/restaurants/123/kitchen/shift/close', { courier_id: null }); // 201// the client: see /v2/docs/js // the library adds the employee's token itself (after the employee signs in) const kitchenShift = await api.post('/restaurants/123/kitchen/shift/close', { courier_id: null }); // 201// klient: viz /v2/docs/typescript // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const kitchenShift = await api.post('/restaurants/123/kitchen/shift/close', { courier_id: null }); // 201 KitchenShiftClose// the client: see /v2/docs/typescript // the library adds the employee's token itself (after the employee signs in) const kitchenShift = await api.post('/restaurants/123/kitchen/shift/close', { courier_id: null }); // 201 KitchenShiftClose// klient: viz /v2/docs/php // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) $kitchenShift = $api->post('/restaurants/123/kitchen/shift/close', ['courier_id' => null]); // 201// the client: see /v2/docs/php // the library adds the employee's token itself (after the employee signs in) $kitchenShift = $api->post('/restaurants/123/kitchen/shift/close', ['courier_id' => null]); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) KitchenShiftClose kitchenShift = api.post("/restaurants/123/kitchen/shift/close", Json.parse(""" {"courier_id": null} """), KitchenShiftClose::fromJson); // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) KitchenShiftClose kitchenShift = api.post("/restaurants/123/kitchen/shift/close", Json.parse(""" {"courier_id": null} """), KitchenShiftClose::fromJson); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) val kitchenShift = api.post( "/restaurants/123/kitchen/shift/close", mapOf("courier_id" to null), KitchenShiftClose::fromJson, ) // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) val kitchenShift = api.post( "/restaurants/123/kitchen/shift/close", mapOf("courier_id" to null), KitchenShiftClose::fromJson, ) // 201// klient: viz /v2/docs/csharp // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) var kitchenShift = await api.PostAsync<KitchenShiftClose>( "/restaurants/123/kitchen/shift/close", new { courier_id = (object?)null } ); // 201// the client: see /v2/docs/csharp // the library adds the employee's token itself (after the employee signs in) var kitchenShift = await api.PostAsync<KitchenShiftClose>( "/restaurants/123/kitchen/shift/close", new { courier_id = (object?)null } ); // 201# klient: viz /v2/docs/python # token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) kitchen_shift = api.post('/restaurants/123/kitchen/shift/close', {'courier_id': None}) # 201# the client: see /v2/docs/python # the library adds the employee's token itself (after the employee signs in) kitchen_shift = api.post('/restaurants/123/kitchen/shift/close', {'courier_id': None}) # 201// klient: viz /v2/docs/swift // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) let kitchenShift: KitchenShiftClose = try await api.post("/restaurants/123/kitchen/shift/close", body: ["courier_id": nil]) // 201// the client: see /v2/docs/swift // the library adds the employee's token itself (after the employee signs in) let kitchenShift: KitchenShiftClose = try await api.post("/restaurants/123/kitchen/shift/close", body: ["courier_id": nil]) // 201// klient: viz /v2/docs/dart // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) final kitchenShift = pr.KitchenShiftClose.fromJson(await api.post('/restaurants/123/kitchen/shift/close', {'courier_id': null})); // 201// the client: see /v2/docs/dart // the library adds the employee's token itself (after the employee signs in) final kitchenShift = pr.KitchenShiftClose.fromJson(await api.post('/restaurants/123/kitchen/shift/close', {'courier_id': null})); // 201// klient: viz /v2/docs/go // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) res, err := api.Post(ctx, "/restaurants/123/kitchen/shift/close", map[string]any{"courier_id": nil}, nil) var kitchenShift model.KitchenShiftClose // 201 if err == nil { err = res.Decode(&kitchenShift) }// the client: see /v2/docs/go // the library adds the employee's token itself (after the employee signs in) res, err := api.Post(ctx, "/restaurants/123/kitchen/shift/close", map[string]any{"courier_id": nil}, nil) var kitchenShift model.KitchenShiftClose // 201 if err == nil { err = res.Decode(&kitchenShift) }Příklad odpovědi 201Example answer 201
{ "id": "1187", "closed_at": "2027-01-15T22:15:40+01:00", "closed_by": { "id": "61", "name": "Petr Novák" }, "closed_orders": 64, "numbering_reset": true, "summary": { "orders": 64, "completed": { "amount": 1954300, "currency": "CZK" }, "by_payment": { "cash": { "amount": 802100, "currency": "CZK" }, "card": { "amount": 1029500, "currency": "CZK" }, "meal_voucher": { "amount": 0, "currency": "CZK" }, "company_account": { "amount": 0, "currency": "CZK" }, "invoice": { "amount": 122700, "currency": "CZK" } }, "not_completed": { "amount": 0, "currency": "CZK" }, "not_delivered": { "orders": 1, "total": { "amount": 38600, "currency": "CZK" } }, "cancelled": { "amount": 18900, "currency": "CZK" }, "courier_id": null, "couriers": [ { "orders": 9, "completed": { "amount": 352800, "currency": "CZK" }, "by_payment": { "cash": { "amount": 214300, "currency": "CZK" }, "card": { "amount": 138500, "currency": "CZK" }, "meal_voucher": { "amount": 0, "currency": "CZK" }, "company_account": { "amount": 0, "currency": "CZK" }, "invoice": { "amount": 0, "currency": "CZK" } }, "not_completed": { "amount": 0, "currency": "CZK" }, "not_delivered": { "orders": 1, "total": { "amount": 38600, "currency": "CZK" } }, "cancelled": { "amount": 0, "currency": "CZK" }, "courier": { "id": "64", "name": "Tomáš Král" } } ] } }
Scénář
Scenario
Docházkový terminál
An attendance terminal
Vlastní zařízení ProfirestuProfirest's own deviceTerminál u vchodu: zaměstnanec se prokáže PINem nebo čipem a píchne příchod, přestávku nebo odchod. Bez sítě si záznamy podrží a pošle je dávkou.
A terminal at the entrance: an employee proves who they are with a PIN or a card and records an arrival, a break or a departure. Without a network it keeps the records and sends them in a batch.
-
Vzhled terminálu
The terminal's look
GET /restaurants/{restaurant_id}/attendance/terminal · getAttendanceTerminal
Logo, barvu, světlou nebo tmavou obrazovku a uvítání si provozovna nastaví v administraci;
nullznamená vzhled Profirestu. Odpověď si terminál uloží, ať nastartuje správně i bez sítě.The restaurant sets the logo, colour, light or dark screen and welcome line in the administration;
nullmeans Profirest's own look. The terminal keeps the answer so it starts right even without a network.curl "https://api.mujprofirest.cz/v2/restaurants/123/attendance/terminal" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/attendance/terminal" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const attendanceTerminal = await api.get('/restaurants/123/attendance/terminal'); // 200// the client: see /v2/docs/js const attendanceTerminal = await api.get('/restaurants/123/attendance/terminal'); // 200// klient: viz /v2/docs/typescript const attendanceTerminal = await api.get('/restaurants/123/attendance/terminal'); // 200 AttendanceTerminal// the client: see /v2/docs/typescript const attendanceTerminal = await api.get('/restaurants/123/attendance/terminal'); // 200 AttendanceTerminal// klient: viz /v2/docs/php $attendanceTerminal = $api->get('/restaurants/123/attendance/terminal'); // 200// the client: see /v2/docs/php $attendanceTerminal = $api->get('/restaurants/123/attendance/terminal'); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) AttendanceTerminal attendanceTerminal = api.get("/restaurants/123/attendance/terminal", AttendanceTerminal::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) AttendanceTerminal attendanceTerminal = api.get("/restaurants/123/attendance/terminal", AttendanceTerminal::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val attendanceTerminal = api.get("/restaurants/123/attendance/terminal", AttendanceTerminal::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val attendanceTerminal = api.get("/restaurants/123/attendance/terminal", AttendanceTerminal::fromJson) // 200// klient: viz /v2/docs/csharp var attendanceTerminal = await api.GetAsync<AttendanceTerminal>("/restaurants/123/attendance/terminal"); // 200// the client: see /v2/docs/csharp var attendanceTerminal = await api.GetAsync<AttendanceTerminal>("/restaurants/123/attendance/terminal"); // 200# klient: viz /v2/docs/python attendance_terminal = api.get('/restaurants/123/attendance/terminal') # 200# the client: see /v2/docs/python attendance_terminal = api.get('/restaurants/123/attendance/terminal') # 200// klient: viz /v2/docs/swift let attendanceTerminal: AttendanceTerminal = try await api.get("/restaurants/123/attendance/terminal") // 200// the client: see /v2/docs/swift let attendanceTerminal: AttendanceTerminal = try await api.get("/restaurants/123/attendance/terminal") // 200// klient: viz /v2/docs/dart final attendanceTerminal = pr.AttendanceTerminal.fromJson(await api.get('/restaurants/123/attendance/terminal')); // 200// the client: see /v2/docs/dart final attendanceTerminal = pr.AttendanceTerminal.fromJson(await api.get('/restaurants/123/attendance/terminal')); // 200// klient: viz /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/attendance/terminal", nil) var attendanceTerminal model.AttendanceTerminal // 200 if err == nil { err = res.Decode(&attendanceTerminal) }// the client: see /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/attendance/terminal", nil) var attendanceTerminal model.AttendanceTerminal // 200 if err == nil { err = res.Decode(&attendanceTerminal) }Příklad odpovědi 200Example answer 200
{ "restaurant_name": "Bistro U Lípy", "branding": { "logo_url": "https://www.mujprofirest.cz/uploads/terminal/123-logo.png", "accent_color": "#0e7c66", "theme": "light", "welcome_text": "Dobré ráno, ať se dnes daří!" }, "offline": { "allowed": true, "max_age_hours": 24 }, "absence_requests": { "enabled": true, "types": [ "holiday", "unpaid", "sick" ], "notice_days": 14, "max_days": 14, "horizon_days": 180 } } -
Kdo se smí píchat
Who may punch
GET /restaurants/{restaurant_id}/staff · listStaff
Seznam bez PINů – PIN ověřuje jen server.
A list without PINs – only the server checks a PIN.
curl "https://api.mujprofirest.cz/v2/restaurants/123/staff" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/staff" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const { data, next_cursor } = await api.get('/restaurants/123/staff'); // 200// the client: see /v2/docs/js const { data, next_cursor } = await api.get('/restaurants/123/staff'); // 200// klient: viz /v2/docs/typescript const { data, next_cursor } = await api.get('/restaurants/123/staff'); // 200 StaffMemberPage// the client: see /v2/docs/typescript const { data, next_cursor } = await api.get('/restaurants/123/staff'); // 200 StaffMemberPage// klient: viz /v2/docs/php $page = $api->get('/restaurants/123/staff'); // $page['data'], $page['next_cursor']// the client: see /v2/docs/php $page = $api->get('/restaurants/123/staff'); // $page['data'], $page['next_cursor']// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) StaffMemberPage listStaff = api.get("/restaurants/123/staff", StaffMemberPage::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) StaffMemberPage listStaff = api.get("/restaurants/123/staff", StaffMemberPage::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val listStaff = api.get("/restaurants/123/staff", StaffMemberPage::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val listStaff = api.get("/restaurants/123/staff", StaffMemberPage::fromJson) // 200// klient: viz /v2/docs/csharp var listStaff = await api.GetAsync<StaffMemberPage>("/restaurants/123/staff"); // 200// the client: see /v2/docs/csharp var listStaff = await api.GetAsync<StaffMemberPage>("/restaurants/123/staff"); // 200# klient: viz /v2/docs/python page = api.get('/restaurants/123/staff') # page['data'], page['next_cursor']# the client: see /v2/docs/python page = api.get('/restaurants/123/staff') # page['data'], page['next_cursor']// klient: viz /v2/docs/swift let listStaff: StaffMemberPage = try await api.get("/restaurants/123/staff") // 200// the client: see /v2/docs/swift let listStaff: StaffMemberPage = try await api.get("/restaurants/123/staff") // 200// klient: viz /v2/docs/dart final listStaff = pr.StaffMemberPage.fromJson(await api.get('/restaurants/123/staff')); // 200// the client: see /v2/docs/dart final listStaff = pr.StaffMemberPage.fromJson(await api.get('/restaurants/123/staff')); // 200// klient: viz /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/staff", nil) var listStaff model.StaffMemberPage // 200 if err == nil { err = res.Decode(&listStaff) }// the client: see /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/staff", nil) var listStaff model.StaffMemberPage // 200 if err == nil { err = res.Decode(&listStaff) }Příklad odpovědi 200Example answer 200
{ "data": [ { "id": "58", "name": "Jana Dvořáková", "roles": [ "pos" ], "attendance": { "enabled": true }, "sign_in": { "pin": true, "card": true }, "offline_approval": { "salt": "pHk3r9QnW1xY0aBcDeFgHw", "iterations": 100000, "check": 141 }, "offline_sign_in": { "salt": "pHk3r9QnW1xY0aBcDeFgHw", "iterations": 100000, "check": 141 } }, { "id": "61", "name": "Petr Novák", "roles": [ "pos", "pos_manager", "kitchen_manager" ], "attendance": { "enabled": true }, "sign_in": { "pin": true, "card": true }, "offline_approval": { "salt": "pHk3r9QnW1xY0aBcDeFgHw", "iterations": 100000, "check": 141 }, "offline_sign_in": { "salt": "pHk3r9QnW1xY0aBcDeFgHw", "iterations": 100000, "check": 141 } }, { "id": "66", "name": "Lucie Svobodová", "roles": [ "kitchen" ], "attendance": { "enabled": true }, "sign_in": { "pin": true, "card": true }, "offline_approval": { "salt": "pHk3r9QnW1xY0aBcDeFgHw", "iterations": 100000, "check": 141 }, "offline_sign_in": { "salt": "pHk3r9QnW1xY0aBcDeFgHw", "iterations": 100000, "check": 141 } }, { "id": "64", "name": "Tomáš Král", "roles": [], "attendance": { "enabled": true }, "sign_in": { "pin": true, "card": false }, "offline_approval": { "salt": "pHk3r9QnW1xY0aBcDeFgHw", "iterations": 100000, "check": 141 }, "offline_sign_in": { "salt": "pHk3r9QnW1xY0aBcDeFgHw", "iterations": 100000, "check": 141 } } ], "next_cursor": null } -
Píchnutí
A punch
POST /restaurants/{restaurant_id}/attendance/punches · createAttendancePunch
idje UUID z terminálu: stejné píchnutí poslané dvakrát se zapíše jednou. Stav, který nedává smysl (odchod bez příchodu), skončí409 attendance_state_conflict.idis a UUID made on the terminal: the same punch sent twice is recorded once. A state that makes no sense (leaving without arriving) ends with409 attendance_state_conflict.curl "https://api.mujprofirest.cz/v2/restaurants/123/attendance/punches" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "id": "01a318f0-a0c0-7ee7-995a-8607b7545591", "type": "clock_in", "credential": {"method": "pin", "secret": "4321"} }'curl "https://api.mujprofirest.cz/v2/restaurants/123/attendance/punches" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "id": "01a318f0-a0c0-7ee7-995a-8607b7545591", "type": "clock_in", "credential": {"method": "pin", "secret": "4321"} }'// klient: viz /v2/docs/js const attendancePunch = await api.post('/restaurants/123/attendance/punches', { id: '01a318f0-a0c0-7ee7-995a-8607b7545591', type: 'clock_in', credential: { method: 'pin', secret: '4321' }, }); // 201// the client: see /v2/docs/js const attendancePunch = await api.post('/restaurants/123/attendance/punches', { id: '01a318f0-a0c0-7ee7-995a-8607b7545591', type: 'clock_in', credential: { method: 'pin', secret: '4321' }, }); // 201// klient: viz /v2/docs/typescript const attendancePunch = await api.post('/restaurants/123/attendance/punches', { id: '01a318f0-a0c0-7ee7-995a-8607b7545591', type: 'clock_in', credential: { method: 'pin', secret: '4321' }, }); // 201 AttendancePunch// the client: see /v2/docs/typescript const attendancePunch = await api.post('/restaurants/123/attendance/punches', { id: '01a318f0-a0c0-7ee7-995a-8607b7545591', type: 'clock_in', credential: { method: 'pin', secret: '4321' }, }); // 201 AttendancePunch// klient: viz /v2/docs/php $attendancePunch = $api->post('/restaurants/123/attendance/punches', [ 'id' => '01a318f0-a0c0-7ee7-995a-8607b7545591', 'type' => 'clock_in', 'credential' => ['method' => 'pin', 'secret' => '4321'], ]); // 201// the client: see /v2/docs/php $attendancePunch = $api->post('/restaurants/123/attendance/punches', [ 'id' => '01a318f0-a0c0-7ee7-995a-8607b7545591', 'type' => 'clock_in', 'credential' => ['method' => 'pin', 'secret' => '4321'], ]); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) AttendancePunch attendancePunch = api.post("/restaurants/123/attendance/punches", Json.parse(""" { "id": "01a318f0-a0c0-7ee7-995a-8607b7545591", "type": "clock_in", "credential": {"method": "pin", "secret": "4321"} } """), AttendancePunch::fromJson); // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) AttendancePunch attendancePunch = api.post("/restaurants/123/attendance/punches", Json.parse(""" { "id": "01a318f0-a0c0-7ee7-995a-8607b7545591", "type": "clock_in", "credential": {"method": "pin", "secret": "4321"} } """), AttendancePunch::fromJson); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val attendancePunch = api.post("/restaurants/123/attendance/punches", mapOf( "id" to "01a318f0-a0c0-7ee7-995a-8607b7545591", "type" to "clock_in", "credential" to mapOf("method" to "pin", "secret" to "4321"), ), AttendancePunch::fromJson) // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val attendancePunch = api.post("/restaurants/123/attendance/punches", mapOf( "id" to "01a318f0-a0c0-7ee7-995a-8607b7545591", "type" to "clock_in", "credential" to mapOf("method" to "pin", "secret" to "4321"), ), AttendancePunch::fromJson) // 201// klient: viz /v2/docs/csharp var attendancePunch = await api.PostAsync<AttendancePunch>("/restaurants/123/attendance/punches", new { id = "01a318f0-a0c0-7ee7-995a-8607b7545591", type = "clock_in", credential = new { method = "pin", secret = "4321" }, }); // 201// the client: see /v2/docs/csharp var attendancePunch = await api.PostAsync<AttendancePunch>("/restaurants/123/attendance/punches", new { id = "01a318f0-a0c0-7ee7-995a-8607b7545591", type = "clock_in", credential = new { method = "pin", secret = "4321" }, }); // 201# klient: viz /v2/docs/python attendance_punch = api.post('/restaurants/123/attendance/punches', { 'id': '01a318f0-a0c0-7ee7-995a-8607b7545591', 'type': 'clock_in', 'credential': {'method': 'pin', 'secret': '4321'}, }) # 201# the client: see /v2/docs/python attendance_punch = api.post('/restaurants/123/attendance/punches', { 'id': '01a318f0-a0c0-7ee7-995a-8607b7545591', 'type': 'clock_in', 'credential': {'method': 'pin', 'secret': '4321'}, }) # 201// klient: viz /v2/docs/swift let attendancePunch: AttendancePunch = try await api.post("/restaurants/123/attendance/punches", body: [ "id": "01a318f0-a0c0-7ee7-995a-8607b7545591", "type": "clock_in", "credential": ["method": "pin", "secret": "4321"], ]) // 201// the client: see /v2/docs/swift let attendancePunch: AttendancePunch = try await api.post("/restaurants/123/attendance/punches", body: [ "id": "01a318f0-a0c0-7ee7-995a-8607b7545591", "type": "clock_in", "credential": ["method": "pin", "secret": "4321"], ]) // 201// klient: viz /v2/docs/dart final attendancePunch = pr.AttendancePunch.fromJson(await api.post('/restaurants/123/attendance/punches', { 'id': '01a318f0-a0c0-7ee7-995a-8607b7545591', 'type': 'clock_in', 'credential': {'method': 'pin', 'secret': '4321'}, })); // 201// the client: see /v2/docs/dart final attendancePunch = pr.AttendancePunch.fromJson(await api.post('/restaurants/123/attendance/punches', { 'id': '01a318f0-a0c0-7ee7-995a-8607b7545591', 'type': 'clock_in', 'credential': {'method': 'pin', 'secret': '4321'}, })); // 201// klient: viz /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/attendance/punches", map[string]any{ "id": "01a318f0-a0c0-7ee7-995a-8607b7545591", "type": "clock_in", "credential": map[string]any{"method": "pin", "secret": "4321"}, }, nil) var attendancePunch model.AttendancePunch // 201 if err == nil { err = res.Decode(&attendancePunch) }// the client: see /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/attendance/punches", map[string]any{ "id": "01a318f0-a0c0-7ee7-995a-8607b7545591", "type": "clock_in", "credential": map[string]any{"method": "pin", "secret": "4321"}, }, nil) var attendancePunch model.AttendancePunch // 201 if err == nil { err = res.Decode(&attendancePunch) }Příklad odpovědi 200Example answer 200
{ "id": "01a318f0-a0c0-7ee7-995a-8607b7545591", "employee": { "id": "58", "name": "Jana Dvořáková" }, "type": "clock_in", "occurred_at": "2027-01-15T09:58:12+01:00", "received_at": "2027-01-15T09:58:13+01:00", "offline": false, "state": "working", "shift": { "started_at": "2027-01-15T09:58:12+01:00", "ended_at": null, "break_minutes": null, "worked_minutes": null } } -
Kdo je v práci
Who is at work
GET /restaurants/{restaurant_id}/attendance/presence · listAttendancePresence
Pro obrazovku terminálu nebo vedoucího.
For the terminal's screen or the manager.
curl "https://api.mujprofirest.cz/v2/restaurants/123/attendance/presence" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/attendance/presence" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const { data, next_cursor } = await api.get('/restaurants/123/attendance/presence'); // 200// the client: see /v2/docs/js const { data, next_cursor } = await api.get('/restaurants/123/attendance/presence'); // 200// klient: viz /v2/docs/typescript const { data, next_cursor } = await api.get('/restaurants/123/attendance/presence'); // 200 AttendancePresencePage// the client: see /v2/docs/typescript const { data, next_cursor } = await api.get('/restaurants/123/attendance/presence'); // 200 AttendancePresencePage// klient: viz /v2/docs/php $page = $api->get('/restaurants/123/attendance/presence'); // $page['data'], $page['next_cursor']// the client: see /v2/docs/php $page = $api->get('/restaurants/123/attendance/presence'); // $page['data'], $page['next_cursor']// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) AttendancePresencePage listAttendancePresence = api.get("/restaurants/123/attendance/presence", AttendancePresencePage::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) AttendancePresencePage listAttendancePresence = api.get("/restaurants/123/attendance/presence", AttendancePresencePage::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val listAttendancePresence = api.get("/restaurants/123/attendance/presence", AttendancePresencePage::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val listAttendancePresence = api.get("/restaurants/123/attendance/presence", AttendancePresencePage::fromJson) // 200// klient: viz /v2/docs/csharp var listAttendancePresence = await api.GetAsync<AttendancePresencePage>("/restaurants/123/attendance/presence"); // 200// the client: see /v2/docs/csharp var listAttendancePresence = await api.GetAsync<AttendancePresencePage>("/restaurants/123/attendance/presence"); // 200# klient: viz /v2/docs/python page = api.get('/restaurants/123/attendance/presence') # page['data'], page['next_cursor']# the client: see /v2/docs/python page = api.get('/restaurants/123/attendance/presence') # page['data'], page['next_cursor']// klient: viz /v2/docs/swift let listAttendancePresence: AttendancePresencePage = try await api.get("/restaurants/123/attendance/presence") // 200// the client: see /v2/docs/swift let listAttendancePresence: AttendancePresencePage = try await api.get("/restaurants/123/attendance/presence") // 200// klient: viz /v2/docs/dart final listAttendancePresence = pr.AttendancePresencePage.fromJson(await api.get('/restaurants/123/attendance/presence')); // 200// the client: see /v2/docs/dart final listAttendancePresence = pr.AttendancePresencePage.fromJson(await api.get('/restaurants/123/attendance/presence')); // 200// klient: viz /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/attendance/presence", nil) var listAttendancePresence model.AttendancePresencePage // 200 if err == nil { err = res.Decode(&listAttendancePresence) }// the client: see /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/attendance/presence", nil) var listAttendancePresence model.AttendancePresencePage // 200 if err == nil { err = res.Decode(&listAttendancePresence) }Příklad odpovědi 200Example answer 200
{ "data": [ { "employee": { "id": "58", "name": "Jana Dvořáková" }, "state": "working", "since": "2027-01-15T09:58:12+01:00", "shift_started_at": "2027-01-15T09:58:12+01:00" }, { "employee": { "id": "66", "name": "Lucie Svobodová" }, "state": "on_break", "since": "2027-01-15T11:30:05+01:00", "shift_started_at": "2027-01-15T08:00:40+01:00" }, { "employee": { "id": "61", "name": "Petr Novák" }, "state": "off", "since": null, "shift_started_at": null } ], "next_cursor": null } -
Záznamy z výpadku
Records from an outage
POST /restaurants/{restaurant_id}/attendance/punches/batch · createAttendancePunchBatch
Každý záznam má vlastní výsledek:
created,duplicateneborejecteds chybou. Odeslané záznamy (s PINy) na zařízení hned smažte.Every record has its own result:
created,duplicateorrejectedwith a problem. Delete the sent records (with PINs) from the device at once.curl "https://api.mujprofirest.cz/v2/restaurants/123/attendance/punches/batch" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "items": [ { "id": "01a318f0-a0c0-7659-af30-64e055b22d85", "type": "break_start", "occurred_at": "2027-01-15T11:30:05+01:00", "credential": {"method": "card", "secret": "04B7C2D9E1"} }, { "id": "01a318f0-a0c0-7804-a3a6-4d8707f841b2", "type": "break_end", "occurred_at": "2027-01-15T11:45:10+01:00", "credential": {"method": "card", "secret": "04B7C2D9E1"} }, { "id": "01a318f0-a0c0-791a-b9db-5935f9c3e239", "type": "clock_in", "occurred_at": "2027-01-15T11:47:00+01:00", "credential": {"method": "pin", "secret": "9999"} } ] }'curl "https://api.mujprofirest.cz/v2/restaurants/123/attendance/punches/batch" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "items": [ { "id": "01a318f0-a0c0-7659-af30-64e055b22d85", "type": "break_start", "occurred_at": "2027-01-15T11:30:05+01:00", "credential": {"method": "card", "secret": "04B7C2D9E1"} }, { "id": "01a318f0-a0c0-7804-a3a6-4d8707f841b2", "type": "break_end", "occurred_at": "2027-01-15T11:45:10+01:00", "credential": {"method": "card", "secret": "04B7C2D9E1"} }, { "id": "01a318f0-a0c0-791a-b9db-5935f9c3e239", "type": "clock_in", "occurred_at": "2027-01-15T11:47:00+01:00", "credential": {"method": "pin", "secret": "9999"} } ] }'// klient: viz /v2/docs/js const attendancePunchBatch = await api.post('/restaurants/123/attendance/punches/batch', { items: [ { id: '01a318f0-a0c0-7659-af30-64e055b22d85', type: 'break_start', occurred_at: '2027-01-15T11:30:05+01:00', credential: { method: 'card', secret: '04B7C2D9E1' }, }, { id: '01a318f0-a0c0-7804-a3a6-4d8707f841b2', type: 'break_end', occurred_at: '2027-01-15T11:45:10+01:00', credential: { method: 'card', secret: '04B7C2D9E1' }, }, { id: '01a318f0-a0c0-791a-b9db-5935f9c3e239', type: 'clock_in', occurred_at: '2027-01-15T11:47:00+01:00', credential: { method: 'pin', secret: '9999' }, }, ], }); // 200// the client: see /v2/docs/js const attendancePunchBatch = await api.post('/restaurants/123/attendance/punches/batch', { items: [ { id: '01a318f0-a0c0-7659-af30-64e055b22d85', type: 'break_start', occurred_at: '2027-01-15T11:30:05+01:00', credential: { method: 'card', secret: '04B7C2D9E1' }, }, { id: '01a318f0-a0c0-7804-a3a6-4d8707f841b2', type: 'break_end', occurred_at: '2027-01-15T11:45:10+01:00', credential: { method: 'card', secret: '04B7C2D9E1' }, }, { id: '01a318f0-a0c0-791a-b9db-5935f9c3e239', type: 'clock_in', occurred_at: '2027-01-15T11:47:00+01:00', credential: { method: 'pin', secret: '9999' }, }, ], }); // 200// klient: viz /v2/docs/typescript const attendancePunchBatch = await api.post('/restaurants/123/attendance/punches/batch', { items: [ { id: '01a318f0-a0c0-7659-af30-64e055b22d85', type: 'break_start', occurred_at: '2027-01-15T11:30:05+01:00', credential: { method: 'card', secret: '04B7C2D9E1' }, }, { id: '01a318f0-a0c0-7804-a3a6-4d8707f841b2', type: 'break_end', occurred_at: '2027-01-15T11:45:10+01:00', credential: { method: 'card', secret: '04B7C2D9E1' }, }, { id: '01a318f0-a0c0-791a-b9db-5935f9c3e239', type: 'clock_in', occurred_at: '2027-01-15T11:47:00+01:00', credential: { method: 'pin', secret: '9999' }, }, ], }); // 200 AttendancePunchBatchResult// the client: see /v2/docs/typescript const attendancePunchBatch = await api.post('/restaurants/123/attendance/punches/batch', { items: [ { id: '01a318f0-a0c0-7659-af30-64e055b22d85', type: 'break_start', occurred_at: '2027-01-15T11:30:05+01:00', credential: { method: 'card', secret: '04B7C2D9E1' }, }, { id: '01a318f0-a0c0-7804-a3a6-4d8707f841b2', type: 'break_end', occurred_at: '2027-01-15T11:45:10+01:00', credential: { method: 'card', secret: '04B7C2D9E1' }, }, { id: '01a318f0-a0c0-791a-b9db-5935f9c3e239', type: 'clock_in', occurred_at: '2027-01-15T11:47:00+01:00', credential: { method: 'pin', secret: '9999' }, }, ], }); // 200 AttendancePunchBatchResult// klient: viz /v2/docs/php $attendancePunchBatch = $api->post('/restaurants/123/attendance/punches/batch', [ 'items' => [ [ 'id' => '01a318f0-a0c0-7659-af30-64e055b22d85', 'type' => 'break_start', 'occurred_at' => '2027-01-15T11:30:05+01:00', 'credential' => ['method' => 'card', 'secret' => '04B7C2D9E1'], ], [ 'id' => '01a318f0-a0c0-7804-a3a6-4d8707f841b2', 'type' => 'break_end', 'occurred_at' => '2027-01-15T11:45:10+01:00', 'credential' => ['method' => 'card', 'secret' => '04B7C2D9E1'], ], [ 'id' => '01a318f0-a0c0-791a-b9db-5935f9c3e239', 'type' => 'clock_in', 'occurred_at' => '2027-01-15T11:47:00+01:00', 'credential' => ['method' => 'pin', 'secret' => '9999'], ], ], ]); // 200// the client: see /v2/docs/php $attendancePunchBatch = $api->post('/restaurants/123/attendance/punches/batch', [ 'items' => [ [ 'id' => '01a318f0-a0c0-7659-af30-64e055b22d85', 'type' => 'break_start', 'occurred_at' => '2027-01-15T11:30:05+01:00', 'credential' => ['method' => 'card', 'secret' => '04B7C2D9E1'], ], [ 'id' => '01a318f0-a0c0-7804-a3a6-4d8707f841b2', 'type' => 'break_end', 'occurred_at' => '2027-01-15T11:45:10+01:00', 'credential' => ['method' => 'card', 'secret' => '04B7C2D9E1'], ], [ 'id' => '01a318f0-a0c0-791a-b9db-5935f9c3e239', 'type' => 'clock_in', 'occurred_at' => '2027-01-15T11:47:00+01:00', 'credential' => ['method' => 'pin', 'secret' => '9999'], ], ], ]); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) AttendancePunchBatchResult attendancePunchBatch = api.post("/restaurants/123/attendance/punches/batch", Json.parse(""" { "items": [ { "id": "01a318f0-a0c0-7659-af30-64e055b22d85", "type": "break_start", "occurred_at": "2027-01-15T11:30:05+01:00", "credential": {"method": "card", "secret": "04B7C2D9E1"} }, { "id": "01a318f0-a0c0-7804-a3a6-4d8707f841b2", "type": "break_end", "occurred_at": "2027-01-15T11:45:10+01:00", "credential": {"method": "card", "secret": "04B7C2D9E1"} }, { "id": "01a318f0-a0c0-791a-b9db-5935f9c3e239", "type": "clock_in", "occurred_at": "2027-01-15T11:47:00+01:00", "credential": {"method": "pin", "secret": "9999"} } ] } """), AttendancePunchBatchResult::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) AttendancePunchBatchResult attendancePunchBatch = api.post("/restaurants/123/attendance/punches/batch", Json.parse(""" { "items": [ { "id": "01a318f0-a0c0-7659-af30-64e055b22d85", "type": "break_start", "occurred_at": "2027-01-15T11:30:05+01:00", "credential": {"method": "card", "secret": "04B7C2D9E1"} }, { "id": "01a318f0-a0c0-7804-a3a6-4d8707f841b2", "type": "break_end", "occurred_at": "2027-01-15T11:45:10+01:00", "credential": {"method": "card", "secret": "04B7C2D9E1"} }, { "id": "01a318f0-a0c0-791a-b9db-5935f9c3e239", "type": "clock_in", "occurred_at": "2027-01-15T11:47:00+01:00", "credential": {"method": "pin", "secret": "9999"} } ] } """), AttendancePunchBatchResult::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val attendancePunchBatch = api.post("/restaurants/123/attendance/punches/batch", mapOf( "items" to listOf( mapOf( "id" to "01a318f0-a0c0-7659-af30-64e055b22d85", "type" to "break_start", "occurred_at" to "2027-01-15T11:30:05+01:00", "credential" to mapOf("method" to "card", "secret" to "04B7C2D9E1"), ), mapOf( "id" to "01a318f0-a0c0-7804-a3a6-4d8707f841b2", "type" to "break_end", "occurred_at" to "2027-01-15T11:45:10+01:00", "credential" to mapOf("method" to "card", "secret" to "04B7C2D9E1"), ), mapOf( "id" to "01a318f0-a0c0-791a-b9db-5935f9c3e239", "type" to "clock_in", "occurred_at" to "2027-01-15T11:47:00+01:00", "credential" to mapOf("method" to "pin", "secret" to "9999"), ), ), ), AttendancePunchBatchResult::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val attendancePunchBatch = api.post("/restaurants/123/attendance/punches/batch", mapOf( "items" to listOf( mapOf( "id" to "01a318f0-a0c0-7659-af30-64e055b22d85", "type" to "break_start", "occurred_at" to "2027-01-15T11:30:05+01:00", "credential" to mapOf("method" to "card", "secret" to "04B7C2D9E1"), ), mapOf( "id" to "01a318f0-a0c0-7804-a3a6-4d8707f841b2", "type" to "break_end", "occurred_at" to "2027-01-15T11:45:10+01:00", "credential" to mapOf("method" to "card", "secret" to "04B7C2D9E1"), ), mapOf( "id" to "01a318f0-a0c0-791a-b9db-5935f9c3e239", "type" to "clock_in", "occurred_at" to "2027-01-15T11:47:00+01:00", "credential" to mapOf("method" to "pin", "secret" to "9999"), ), ), ), AttendancePunchBatchResult::fromJson) // 200// klient: viz /v2/docs/csharp var attendancePunchBatch = await api.PostAsync<AttendancePunchBatchResult>("/restaurants/123/attendance/punches/batch", new { items = new object[] { new { id = "01a318f0-a0c0-7659-af30-64e055b22d85", type = "break_start", occurred_at = "2027-01-15T11:30:05+01:00", credential = new { method = "card", secret = "04B7C2D9E1" }, }, new { id = "01a318f0-a0c0-7804-a3a6-4d8707f841b2", type = "break_end", occurred_at = "2027-01-15T11:45:10+01:00", credential = new { method = "card", secret = "04B7C2D9E1" }, }, new { id = "01a318f0-a0c0-791a-b9db-5935f9c3e239", type = "clock_in", occurred_at = "2027-01-15T11:47:00+01:00", credential = new { method = "pin", secret = "9999" }, }, }, }); // 200// the client: see /v2/docs/csharp var attendancePunchBatch = await api.PostAsync<AttendancePunchBatchResult>("/restaurants/123/attendance/punches/batch", new { items = new object[] { new { id = "01a318f0-a0c0-7659-af30-64e055b22d85", type = "break_start", occurred_at = "2027-01-15T11:30:05+01:00", credential = new { method = "card", secret = "04B7C2D9E1" }, }, new { id = "01a318f0-a0c0-7804-a3a6-4d8707f841b2", type = "break_end", occurred_at = "2027-01-15T11:45:10+01:00", credential = new { method = "card", secret = "04B7C2D9E1" }, }, new { id = "01a318f0-a0c0-791a-b9db-5935f9c3e239", type = "clock_in", occurred_at = "2027-01-15T11:47:00+01:00", credential = new { method = "pin", secret = "9999" }, }, }, }); // 200# klient: viz /v2/docs/python attendance_punch_batch = api.post('/restaurants/123/attendance/punches/batch', { 'items': [ { 'id': '01a318f0-a0c0-7659-af30-64e055b22d85', 'type': 'break_start', 'occurred_at': '2027-01-15T11:30:05+01:00', 'credential': {'method': 'card', 'secret': '04B7C2D9E1'}, }, { 'id': '01a318f0-a0c0-7804-a3a6-4d8707f841b2', 'type': 'break_end', 'occurred_at': '2027-01-15T11:45:10+01:00', 'credential': {'method': 'card', 'secret': '04B7C2D9E1'}, }, { 'id': '01a318f0-a0c0-791a-b9db-5935f9c3e239', 'type': 'clock_in', 'occurred_at': '2027-01-15T11:47:00+01:00', 'credential': {'method': 'pin', 'secret': '9999'}, }, ], }) # 200# the client: see /v2/docs/python attendance_punch_batch = api.post('/restaurants/123/attendance/punches/batch', { 'items': [ { 'id': '01a318f0-a0c0-7659-af30-64e055b22d85', 'type': 'break_start', 'occurred_at': '2027-01-15T11:30:05+01:00', 'credential': {'method': 'card', 'secret': '04B7C2D9E1'}, }, { 'id': '01a318f0-a0c0-7804-a3a6-4d8707f841b2', 'type': 'break_end', 'occurred_at': '2027-01-15T11:45:10+01:00', 'credential': {'method': 'card', 'secret': '04B7C2D9E1'}, }, { 'id': '01a318f0-a0c0-791a-b9db-5935f9c3e239', 'type': 'clock_in', 'occurred_at': '2027-01-15T11:47:00+01:00', 'credential': {'method': 'pin', 'secret': '9999'}, }, ], }) # 200// klient: viz /v2/docs/swift let attendancePunchBatch: AttendancePunchBatchResult = try await api.post("/restaurants/123/attendance/punches/batch", body: [ "items": [ [ "id": "01a318f0-a0c0-7659-af30-64e055b22d85", "type": "break_start", "occurred_at": "2027-01-15T11:30:05+01:00", "credential": ["method": "card", "secret": "04B7C2D9E1"], ], [ "id": "01a318f0-a0c0-7804-a3a6-4d8707f841b2", "type": "break_end", "occurred_at": "2027-01-15T11:45:10+01:00", "credential": ["method": "card", "secret": "04B7C2D9E1"], ], [ "id": "01a318f0-a0c0-791a-b9db-5935f9c3e239", "type": "clock_in", "occurred_at": "2027-01-15T11:47:00+01:00", "credential": ["method": "pin", "secret": "9999"], ], ], ]) // 200// the client: see /v2/docs/swift let attendancePunchBatch: AttendancePunchBatchResult = try await api.post("/restaurants/123/attendance/punches/batch", body: [ "items": [ [ "id": "01a318f0-a0c0-7659-af30-64e055b22d85", "type": "break_start", "occurred_at": "2027-01-15T11:30:05+01:00", "credential": ["method": "card", "secret": "04B7C2D9E1"], ], [ "id": "01a318f0-a0c0-7804-a3a6-4d8707f841b2", "type": "break_end", "occurred_at": "2027-01-15T11:45:10+01:00", "credential": ["method": "card", "secret": "04B7C2D9E1"], ], [ "id": "01a318f0-a0c0-791a-b9db-5935f9c3e239", "type": "clock_in", "occurred_at": "2027-01-15T11:47:00+01:00", "credential": ["method": "pin", "secret": "9999"], ], ], ]) // 200// klient: viz /v2/docs/dart final attendancePunchBatch = pr.AttendancePunchBatchResult.fromJson(await api.post('/restaurants/123/attendance/punches/batch', { 'items': [ { 'id': '01a318f0-a0c0-7659-af30-64e055b22d85', 'type': 'break_start', 'occurred_at': '2027-01-15T11:30:05+01:00', 'credential': {'method': 'card', 'secret': '04B7C2D9E1'}, }, { 'id': '01a318f0-a0c0-7804-a3a6-4d8707f841b2', 'type': 'break_end', 'occurred_at': '2027-01-15T11:45:10+01:00', 'credential': {'method': 'card', 'secret': '04B7C2D9E1'}, }, { 'id': '01a318f0-a0c0-791a-b9db-5935f9c3e239', 'type': 'clock_in', 'occurred_at': '2027-01-15T11:47:00+01:00', 'credential': {'method': 'pin', 'secret': '9999'}, }, ], })); // 200// the client: see /v2/docs/dart final attendancePunchBatch = pr.AttendancePunchBatchResult.fromJson(await api.post('/restaurants/123/attendance/punches/batch', { 'items': [ { 'id': '01a318f0-a0c0-7659-af30-64e055b22d85', 'type': 'break_start', 'occurred_at': '2027-01-15T11:30:05+01:00', 'credential': {'method': 'card', 'secret': '04B7C2D9E1'}, }, { 'id': '01a318f0-a0c0-7804-a3a6-4d8707f841b2', 'type': 'break_end', 'occurred_at': '2027-01-15T11:45:10+01:00', 'credential': {'method': 'card', 'secret': '04B7C2D9E1'}, }, { 'id': '01a318f0-a0c0-791a-b9db-5935f9c3e239', 'type': 'clock_in', 'occurred_at': '2027-01-15T11:47:00+01:00', 'credential': {'method': 'pin', 'secret': '9999'}, }, ], })); // 200// klient: viz /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/attendance/punches/batch", map[string]any{ "items": []any{ map[string]any{ "id": "01a318f0-a0c0-7659-af30-64e055b22d85", "type": "break_start", "occurred_at": "2027-01-15T11:30:05+01:00", "credential": map[string]any{"method": "card", "secret": "04B7C2D9E1"}, }, map[string]any{ "id": "01a318f0-a0c0-7804-a3a6-4d8707f841b2", "type": "break_end", "occurred_at": "2027-01-15T11:45:10+01:00", "credential": map[string]any{"method": "card", "secret": "04B7C2D9E1"}, }, map[string]any{ "id": "01a318f0-a0c0-791a-b9db-5935f9c3e239", "type": "clock_in", "occurred_at": "2027-01-15T11:47:00+01:00", "credential": map[string]any{"method": "pin", "secret": "9999"}, }, }, }, nil) var attendancePunchBatch model.AttendancePunchBatchResult // 200 if err == nil { err = res.Decode(&attendancePunchBatch) }// the client: see /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/attendance/punches/batch", map[string]any{ "items": []any{ map[string]any{ "id": "01a318f0-a0c0-7659-af30-64e055b22d85", "type": "break_start", "occurred_at": "2027-01-15T11:30:05+01:00", "credential": map[string]any{"method": "card", "secret": "04B7C2D9E1"}, }, map[string]any{ "id": "01a318f0-a0c0-7804-a3a6-4d8707f841b2", "type": "break_end", "occurred_at": "2027-01-15T11:45:10+01:00", "credential": map[string]any{"method": "card", "secret": "04B7C2D9E1"}, }, map[string]any{ "id": "01a318f0-a0c0-791a-b9db-5935f9c3e239", "type": "clock_in", "occurred_at": "2027-01-15T11:47:00+01:00", "credential": map[string]any{"method": "pin", "secret": "9999"}, }, }, }, nil) var attendancePunchBatch model.AttendancePunchBatchResult // 200 if err == nil { err = res.Decode(&attendancePunchBatch) }Příklad odpovědi 200Example answer 200
{ "results": [ { "id": "01a318f0-a0c0-7659-af30-64e055b22d85", "status": "created", "retryable": false, "punch": { "id": "01a318f0-a0c0-7659-af30-64e055b22d85", "employee": { "id": "66", "name": "Lucie Svobodová" }, "type": "break_start", "occurred_at": "2027-01-15T11:30:05+01:00", "received_at": "2027-01-15T11:52:30+01:00", "offline": true, "state": "on_break", "shift": { "started_at": "2027-01-15T08:00:40+01:00", "ended_at": null, "break_minutes": null, "worked_minutes": null } }, "problem": null, "employee": null }, { "id": "01a318f0-a0c0-7804-a3a6-4d8707f841b2", "status": "duplicate", "retryable": false, "punch": { "id": "01a318f0-a0c0-7804-a3a6-4d8707f841b2", "employee": { "id": "66", "name": "Lucie Svobodová" }, "type": "break_end", "occurred_at": "2027-01-15T11:45:10+01:00", "received_at": "2027-01-15T11:52:30+01:00", "offline": true, "state": "working", "shift": { "started_at": "2027-01-15T08:00:40+01:00", "ended_at": null, "break_minutes": 15, "worked_minutes": null } }, "problem": null, "employee": null }, { "id": "01a318f0-a0c0-791a-b9db-5935f9c3e239", "status": "rejected", "retryable": false, "punch": null, "problem": { "type": "https://api.mujprofirest.cz/v2/docs/errors#staff_credentials_invalid", "title": "Špatný PIN nebo neznámý čip", "status": 422, "code": "staff_credentials_invalid", "detail": null, "instance": null, "request_id": "7c9e6679a1f04d3b8e2b5f0a4c1d2e3f", "errors": [], "existing_id": null, "candidates": [], "paid_by": null }, "employee": null } ] }
Scénář
Scenario
Rozvoz
Deliveries
Vlastní zařízení ProfirestuProfirest's own deviceKurýr začne směnu, dispečink mu sestaví trasu z hotových objednávek a kurýr hlásí doručení.
A courier starts the shift, the dispatcher builds a route from ready orders and the courier reports the deliveries.
-
Kurýři
Couriers
GET /restaurants/{restaurant_id}/couriers · listCouriers
Kdo je na směně a kolik má otevřených tras.
Who is on shift and how many open routes they have.
curl "https://api.mujprofirest.cz/v2/restaurants/123/couriers" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/couriers" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const { data, next_cursor } = await api.get('/restaurants/123/couriers'); // 200// the client: see /v2/docs/js const { data, next_cursor } = await api.get('/restaurants/123/couriers'); // 200// klient: viz /v2/docs/typescript const { data, next_cursor } = await api.get('/restaurants/123/couriers'); // 200 CourierPage// the client: see /v2/docs/typescript const { data, next_cursor } = await api.get('/restaurants/123/couriers'); // 200 CourierPage// klient: viz /v2/docs/php $page = $api->get('/restaurants/123/couriers'); // $page['data'], $page['next_cursor']// the client: see /v2/docs/php $page = $api->get('/restaurants/123/couriers'); // $page['data'], $page['next_cursor']// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) CourierPage listCouriers = api.get("/restaurants/123/couriers", CourierPage::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) CourierPage listCouriers = api.get("/restaurants/123/couriers", CourierPage::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val listCouriers = api.get("/restaurants/123/couriers", CourierPage::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val listCouriers = api.get("/restaurants/123/couriers", CourierPage::fromJson) // 200// klient: viz /v2/docs/csharp var listCouriers = await api.GetAsync<CourierPage>("/restaurants/123/couriers"); // 200// the client: see /v2/docs/csharp var listCouriers = await api.GetAsync<CourierPage>("/restaurants/123/couriers"); // 200# klient: viz /v2/docs/python page = api.get('/restaurants/123/couriers') # page['data'], page['next_cursor']# the client: see /v2/docs/python page = api.get('/restaurants/123/couriers') # page['data'], page['next_cursor']// klient: viz /v2/docs/swift let listCouriers: CourierPage = try await api.get("/restaurants/123/couriers") // 200// the client: see /v2/docs/swift let listCouriers: CourierPage = try await api.get("/restaurants/123/couriers") // 200// klient: viz /v2/docs/dart final listCouriers = pr.CourierPage.fromJson(await api.get('/restaurants/123/couriers')); // 200// the client: see /v2/docs/dart final listCouriers = pr.CourierPage.fromJson(await api.get('/restaurants/123/couriers')); // 200// klient: viz /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/couriers", nil) var listCouriers model.CourierPage // 200 if err == nil { err = res.Decode(&listCouriers) }// the client: see /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/couriers", nil) var listCouriers model.CourierPage // 200 if err == nil { err = res.Decode(&listCouriers) }Příklad odpovědi 200Example answer 200
{ "data": [ { "employee": { "id": "64", "name": "Tomáš Král" }, "on_shift": true, "on_shift_since": "2027-01-15T10:30:00+01:00", "open_routes": 1 }, { "employee": { "id": "68", "name": "Martin Beneš" }, "on_shift": false, "on_shift_since": null, "open_routes": 0 } ], "next_cursor": null } -
Začátek směny
Starting the shift
PUT /restaurants/{restaurant_id}/couriers/{employee_id}/shift · startCourierShift
Kurýr se přihlásí na zařízení a začne směnu.
The courier signs in on the device and starts the shift.
curl -X PUT "https://api.mujprofirest.cz/v2/restaurants/123/couriers/64/shift" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN"curl -X PUT "https://api.mujprofirest.cz/v2/restaurants/123/couriers/64/shift" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN"// klient: viz /v2/docs/js // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const courierShift = await api.put('/restaurants/123/couriers/64/shift', null); // 200// the client: see /v2/docs/js // the library adds the employee's token itself (after the employee signs in) const courierShift = await api.put('/restaurants/123/couriers/64/shift', null); // 200// klient: viz /v2/docs/typescript // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const courierShift = await api.put('/restaurants/123/couriers/64/shift', null); // 200 Courier// the client: see /v2/docs/typescript // the library adds the employee's token itself (after the employee signs in) const courierShift = await api.put('/restaurants/123/couriers/64/shift', null); // 200 Courier// klient: viz /v2/docs/php // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) $courierShift = $api->put('/restaurants/123/couriers/64/shift', null); // 200// the client: see /v2/docs/php // the library adds the employee's token itself (after the employee signs in) $courierShift = $api->put('/restaurants/123/couriers/64/shift', null); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) Courier courierShift = api.put("/restaurants/123/couriers/64/shift", null, Courier::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) Courier courierShift = api.put("/restaurants/123/couriers/64/shift", null, Courier::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) val courierShift = api.put("/restaurants/123/couriers/64/shift", null, Courier::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) val courierShift = api.put("/restaurants/123/couriers/64/shift", null, Courier::fromJson) // 200// klient: viz /v2/docs/csharp // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) var courierShift = await api.PutAsync<Courier>("/restaurants/123/couriers/64/shift", (object?)null); // 200// the client: see /v2/docs/csharp // the library adds the employee's token itself (after the employee signs in) var courierShift = await api.PutAsync<Courier>("/restaurants/123/couriers/64/shift", (object?)null); // 200# klient: viz /v2/docs/python # token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) courier_shift = api.put('/restaurants/123/couriers/64/shift', None) # 200# the client: see /v2/docs/python # the library adds the employee's token itself (after the employee signs in) courier_shift = api.put('/restaurants/123/couriers/64/shift', None) # 200// klient: viz /v2/docs/swift // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) let courierShift: Courier = try await api.put("/restaurants/123/couriers/64/shift", body: nil) // 200// the client: see /v2/docs/swift // the library adds the employee's token itself (after the employee signs in) let courierShift: Courier = try await api.put("/restaurants/123/couriers/64/shift", body: nil) // 200// klient: viz /v2/docs/dart // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) final courierShift = pr.Courier.fromJson(await api.put('/restaurants/123/couriers/64/shift', null)); // 200// the client: see /v2/docs/dart // the library adds the employee's token itself (after the employee signs in) final courierShift = pr.Courier.fromJson(await api.put('/restaurants/123/couriers/64/shift', null)); // 200// klient: viz /v2/docs/go // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) res, err := api.Put(ctx, "/restaurants/123/couriers/64/shift", nil, nil) var courierShift model.Courier // 200 if err == nil { err = res.Decode(&courierShift) }// the client: see /v2/docs/go // the library adds the employee's token itself (after the employee signs in) res, err := api.Put(ctx, "/restaurants/123/couriers/64/shift", nil, nil) var courierShift model.Courier // 200 if err == nil { err = res.Decode(&courierShift) }Příklad odpovědi 200Example answer 200
{ "employee": { "id": "64", "name": "Tomáš Král" }, "on_shift": true, "on_shift_since": "2027-01-15T10:30:00+01:00", "open_routes": 0 } -
Trasa
A route
POST /restaurants/{restaurant_id}/delivery-routes · createDeliveryRoute
Hotové bony k rozvozu pro jednoho kurýra.
Ready delivery tickets for one courier.
curl "https://api.mujprofirest.cz/v2/restaurants/123/delivery-routes" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7cc6-882f-c95de1e2352a" \ -H "Content-Type: application/json" \ -d '{"courier_id": "64", "ticket_ids": ["77815"]}'curl "https://api.mujprofirest.cz/v2/restaurants/123/delivery-routes" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7cc6-882f-c95de1e2352a" \ -H "Content-Type: application/json" \ -d '{"courier_id": "64", "ticket_ids": ["77815"]}'// klient: viz /v2/docs/js // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const deliveryRoute = await api.post('/restaurants/123/delivery-routes', { courier_id: '64', ticket_ids: ['77815'] }); // 201// the client: see /v2/docs/js // the library adds the employee's token itself (after the employee signs in) const deliveryRoute = await api.post('/restaurants/123/delivery-routes', { courier_id: '64', ticket_ids: ['77815'] }); // 201// klient: viz /v2/docs/typescript // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const deliveryRoute = await api.post('/restaurants/123/delivery-routes', { courier_id: '64', ticket_ids: ['77815'] }); // 201 DeliveryRoute// the client: see /v2/docs/typescript // the library adds the employee's token itself (after the employee signs in) const deliveryRoute = await api.post('/restaurants/123/delivery-routes', { courier_id: '64', ticket_ids: ['77815'] }); // 201 DeliveryRoute// klient: viz /v2/docs/php // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) $deliveryRoute = $api->post('/restaurants/123/delivery-routes', ['courier_id' => '64', 'ticket_ids' => ['77815']]); // 201// the client: see /v2/docs/php // the library adds the employee's token itself (after the employee signs in) $deliveryRoute = $api->post('/restaurants/123/delivery-routes', ['courier_id' => '64', 'ticket_ids' => ['77815']]); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) DeliveryRoute deliveryRoute = api.post("/restaurants/123/delivery-routes", Json.parse(""" {"courier_id": "64", "ticket_ids": ["77815"]} """), DeliveryRoute::fromJson); // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) DeliveryRoute deliveryRoute = api.post("/restaurants/123/delivery-routes", Json.parse(""" {"courier_id": "64", "ticket_ids": ["77815"]} """), DeliveryRoute::fromJson); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) val deliveryRoute = api.post( "/restaurants/123/delivery-routes", mapOf("courier_id" to "64", "ticket_ids" to listOf("77815")), DeliveryRoute::fromJson, ) // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) val deliveryRoute = api.post( "/restaurants/123/delivery-routes", mapOf("courier_id" to "64", "ticket_ids" to listOf("77815")), DeliveryRoute::fromJson, ) // 201// klient: viz /v2/docs/csharp // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) var deliveryRoute = await api.PostAsync<DeliveryRoute>( "/restaurants/123/delivery-routes", new { courier_id = "64", ticket_ids = new[] { "77815" } } ); // 201// the client: see /v2/docs/csharp // the library adds the employee's token itself (after the employee signs in) var deliveryRoute = await api.PostAsync<DeliveryRoute>( "/restaurants/123/delivery-routes", new { courier_id = "64", ticket_ids = new[] { "77815" } } ); // 201# klient: viz /v2/docs/python # token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) delivery_route = api.post('/restaurants/123/delivery-routes', {'courier_id': '64', 'ticket_ids': ['77815']}) # 201# the client: see /v2/docs/python # the library adds the employee's token itself (after the employee signs in) delivery_route = api.post('/restaurants/123/delivery-routes', {'courier_id': '64', 'ticket_ids': ['77815']}) # 201// klient: viz /v2/docs/swift // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) let deliveryRoute: DeliveryRoute = try await api.post("/restaurants/123/delivery-routes", body: ["courier_id": "64", "ticket_ids": ["77815"]]) // 201// the client: see /v2/docs/swift // the library adds the employee's token itself (after the employee signs in) let deliveryRoute: DeliveryRoute = try await api.post("/restaurants/123/delivery-routes", body: ["courier_id": "64", "ticket_ids": ["77815"]]) // 201// klient: viz /v2/docs/dart // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) final deliveryRoute = pr.DeliveryRoute.fromJson(await api.post('/restaurants/123/delivery-routes', {'courier_id': '64', 'ticket_ids': ['77815']})); // 201// the client: see /v2/docs/dart // the library adds the employee's token itself (after the employee signs in) final deliveryRoute = pr.DeliveryRoute.fromJson(await api.post('/restaurants/123/delivery-routes', {'courier_id': '64', 'ticket_ids': ['77815']})); // 201// klient: viz /v2/docs/go // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) res, err := api.Post( ctx, "/restaurants/123/delivery-routes", map[string]any{"courier_id": "64", "ticket_ids": []any{"77815"}}, nil, ) var deliveryRoute model.DeliveryRoute // 201 if err == nil { err = res.Decode(&deliveryRoute) }// the client: see /v2/docs/go // the library adds the employee's token itself (after the employee signs in) res, err := api.Post( ctx, "/restaurants/123/delivery-routes", map[string]any{"courier_id": "64", "ticket_ids": []any{"77815"}}, nil, ) var deliveryRoute model.DeliveryRoute // 201 if err == nil { err = res.Decode(&deliveryRoute) }Příklad odpovědi 201Example answer 201
{ "id": "3307", "courier": { "id": "64", "name": "Tomáš Král" }, "status": "open", "created_at": "2027-01-15T12:06:40+01:00", "completed_at": null, "tickets": [ { "id": "77815", "order_id": "184226", "number": "030", "status": "out_for_delivery", "area": "kitchen", "source": "web", "platform": null, "name": "Jana Nováková", "fulfillment": "delivery", "express": false, "customer": { "name": "Jana Nováková", "phone": "+420777123456", "not_delivered_count": 0, "last_not_delivered_at": null }, "delivery_address": { "street": "Jeseniova 1196/52", "city": "Praha 3", "location": { "lat": 50.0833, "lon": 14.4667 } }, "delivery_zone": { "id": "21", "name": "Vinohrady do 3 km" }, "note": "3. patro, zvonek Nováková", "payment_method": "cash", "total": { "amount": 38600, "currency": "CZK" }, "delivery_price": { "amount": 4900, "currency": "CZK" }, "amount_due": { "amount": 38600, "currency": "CZK" }, "paid_by": null, "created_at": "2027-01-15T11:50:40+01:00", "scheduled_for": null, "printed": true, "courier": { "id": "64", "name": "Tomáš Král" }, "not_delivered": null, "items": [ { "id": "52031", "product_id": "4571", "name": "Pizza Margherita", "kitchen_name": null, "note": "Nekrájet", "quantity": 1, "kind": "full", "charge": null, "course": 0, "category": { "id": "315", "name": "Pizza" }, "from_daily_menu": false, "station_id": "3", "status": "done", "handed_out": false, "part": null, "size": { "name": "Ø32cm", "dish_name": "Pizza Margherita" }, "unit_price": { "amount": 18900, "currency": "CZK" }, "packaging_price": { "amount": 0, "currency": "CZK" }, "discount": { "amount": 0, "currency": "CZK" }, "gift": false, "vat_rate": "12", "removed_ingredients": [], "modifiers": [ { "id": "52032", "charge": null, "product_id": "4602", "name": "Extra sýr", "kitchen_name": null, "note": null, "quantity": 1, "kind": "full", "status": "done", "handed_out": false, "part": null, "size": null, "unit_price": { "amount": 3000, "currency": "CZK" }, "packaging_price": { "amount": 0, "currency": "CZK" }, "discount": { "amount": 0, "currency": "CZK" }, "gift": false, "vat_rate": "12", "removed_ingredients": [] } ] }, { "id": "52033", "product_id": "4593", "name": "Domácí limonáda 0,4 l", "kitchen_name": null, "note": null, "quantity": 2, "kind": "full", "charge": null, "course": 0, "category": { "id": "320", "name": "Nápoje" }, "from_daily_menu": false, "station_id": null, "status": "done", "handed_out": false, "part": null, "size": null, "unit_price": { "amount": 5900, "currency": "CZK" }, "packaging_price": { "amount": 0, "currency": "CZK" }, "discount": { "amount": 0, "currency": "CZK" }, "gift": false, "vat_rate": "12", "removed_ingredients": [], "modifiers": [] } ], "receipt": { "items": { "amount": 33700, "currency": "CZK" }, "discounts": [], "delivery": { "amount": 4900, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "adjustment": { "amount": 0, "currency": "CZK" }, "total": { "amount": 38600, "currency": "CZK" }, "to_pay": { "amount": 38600, "currency": "CZK" }, "vat": [ { "rate": "12", "base": { "amount": 34464, "currency": "CZK" }, "vat": { "amount": 4136, "currency": "CZK" }, "total": { "amount": 38600, "currency": "CZK" } } ], "document": { "title": "Účtenka", "number": "184226", "tax_document": "Zjednodušený daňový doklad" } } } ] } -
Doručeno
Delivered
POST /restaurants/{restaurant_id}/delivery-routes/{route_id}/tickets/{ticket_id}/delivered · markTicketDelivered
Po posledním doručení se trasa uzavře sama.
After the last delivery the route closes itself.
curl -X POST "https://api.mujprofirest.cz/v2/restaurants/123/delivery-routes/3307/tickets/77815/delivered" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7086-a0c0-a5560bd45149"curl -X POST "https://api.mujprofirest.cz/v2/restaurants/123/delivery-routes/3307/tickets/77815/delivered" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7086-a0c0-a5560bd45149"// klient: viz /v2/docs/js // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const ticketDelivered = await api.post('/restaurants/123/delivery-routes/3307/tickets/77815/delivered', null); // 200// the client: see /v2/docs/js // the library adds the employee's token itself (after the employee signs in) const ticketDelivered = await api.post('/restaurants/123/delivery-routes/3307/tickets/77815/delivered', null); // 200// klient: viz /v2/docs/typescript // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const ticketDelivered = await api.post('/restaurants/123/delivery-routes/3307/tickets/77815/delivered', null); // 200 DeliveryRoute// the client: see /v2/docs/typescript // the library adds the employee's token itself (after the employee signs in) const ticketDelivered = await api.post('/restaurants/123/delivery-routes/3307/tickets/77815/delivered', null); // 200 DeliveryRoute// klient: viz /v2/docs/php // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) $ticketDelivered = $api->post('/restaurants/123/delivery-routes/3307/tickets/77815/delivered', null); // 200// the client: see /v2/docs/php // the library adds the employee's token itself (after the employee signs in) $ticketDelivered = $api->post('/restaurants/123/delivery-routes/3307/tickets/77815/delivered', null); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) DeliveryRoute ticketDelivered = api.post( "/restaurants/123/delivery-routes/3307/tickets/77815/delivered", null, DeliveryRoute::fromJson ); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) DeliveryRoute ticketDelivered = api.post( "/restaurants/123/delivery-routes/3307/tickets/77815/delivered", null, DeliveryRoute::fromJson ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) val ticketDelivered = api.post( "/restaurants/123/delivery-routes/3307/tickets/77815/delivered", null, DeliveryRoute::fromJson, ) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) val ticketDelivered = api.post( "/restaurants/123/delivery-routes/3307/tickets/77815/delivered", null, DeliveryRoute::fromJson, ) // 200// klient: viz /v2/docs/csharp // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) var ticketDelivered = await api.PostAsync<DeliveryRoute>( "/restaurants/123/delivery-routes/3307/tickets/77815/delivered", (object?)null ); // 200// the client: see /v2/docs/csharp // the library adds the employee's token itself (after the employee signs in) var ticketDelivered = await api.PostAsync<DeliveryRoute>( "/restaurants/123/delivery-routes/3307/tickets/77815/delivered", (object?)null ); // 200# klient: viz /v2/docs/python # token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) ticket_delivered = api.post('/restaurants/123/delivery-routes/3307/tickets/77815/delivered', None) # 200# the client: see /v2/docs/python # the library adds the employee's token itself (after the employee signs in) ticket_delivered = api.post('/restaurants/123/delivery-routes/3307/tickets/77815/delivered', None) # 200// klient: viz /v2/docs/swift // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) let ticketDelivered: DeliveryRoute = try await api.post("/restaurants/123/delivery-routes/3307/tickets/77815/delivered", body: nil) // 200// the client: see /v2/docs/swift // the library adds the employee's token itself (after the employee signs in) let ticketDelivered: DeliveryRoute = try await api.post("/restaurants/123/delivery-routes/3307/tickets/77815/delivered", body: nil) // 200// klient: viz /v2/docs/dart // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) final ticketDelivered = pr.DeliveryRoute.fromJson(await api.post('/restaurants/123/delivery-routes/3307/tickets/77815/delivered', null)); // 200// the client: see /v2/docs/dart // the library adds the employee's token itself (after the employee signs in) final ticketDelivered = pr.DeliveryRoute.fromJson(await api.post('/restaurants/123/delivery-routes/3307/tickets/77815/delivered', null)); // 200// klient: viz /v2/docs/go // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) res, err := api.Post(ctx, "/restaurants/123/delivery-routes/3307/tickets/77815/delivered", nil, nil) var ticketDelivered model.DeliveryRoute // 200 if err == nil { err = res.Decode(&ticketDelivered) }// the client: see /v2/docs/go // the library adds the employee's token itself (after the employee signs in) res, err := api.Post(ctx, "/restaurants/123/delivery-routes/3307/tickets/77815/delivered", nil, nil) var ticketDelivered model.DeliveryRoute // 200 if err == nil { err = res.Decode(&ticketDelivered) }Příklad odpovědi 200Example answer 200
{ "id": "3307", "courier": { "id": "64", "name": "Tomáš Král" }, "status": "completed", "created_at": "2027-01-15T12:06:40+01:00", "completed_at": "2027-01-15T12:31:10+01:00", "tickets": [ { "id": "77815", "order_id": "184226", "number": "030", "status": "delivered", "area": "kitchen", "source": "web", "platform": null, "name": "Jana Nováková", "fulfillment": "delivery", "express": false, "customer": { "name": "Jana Nováková", "phone": "+420777123456", "not_delivered_count": 0, "last_not_delivered_at": null }, "delivery_address": { "street": "Jeseniova 1196/52", "city": "Praha 3", "location": { "lat": 50.0833, "lon": 14.4667 } }, "delivery_zone": { "id": "21", "name": "Vinohrady do 3 km" }, "note": "3. patro, zvonek Nováková", "payment_method": "cash", "total": { "amount": 38600, "currency": "CZK" }, "delivery_price": { "amount": 4900, "currency": "CZK" }, "amount_due": { "amount": 38600, "currency": "CZK" }, "paid_by": null, "created_at": "2027-01-15T11:50:40+01:00", "scheduled_for": null, "printed": true, "courier": { "id": "64", "name": "Tomáš Král" }, "not_delivered": null, "items": [ { "id": "52031", "product_id": "4571", "name": "Pizza Margherita", "kitchen_name": null, "note": "Nekrájet", "quantity": 1, "kind": "full", "charge": null, "course": 0, "category": { "id": "315", "name": "Pizza" }, "from_daily_menu": false, "station_id": "3", "status": "done", "handed_out": false, "part": null, "size": { "name": "Ø32cm", "dish_name": "Pizza Margherita" }, "unit_price": { "amount": 18900, "currency": "CZK" }, "packaging_price": { "amount": 0, "currency": "CZK" }, "discount": { "amount": 0, "currency": "CZK" }, "gift": false, "vat_rate": "12", "removed_ingredients": [], "modifiers": [ { "id": "52032", "charge": null, "product_id": "4602", "name": "Extra sýr", "kitchen_name": null, "note": null, "quantity": 1, "kind": "full", "status": "done", "handed_out": false, "part": null, "size": null, "unit_price": { "amount": 3000, "currency": "CZK" }, "packaging_price": { "amount": 0, "currency": "CZK" }, "discount": { "amount": 0, "currency": "CZK" }, "gift": false, "vat_rate": "12", "removed_ingredients": [] } ] }, { "id": "52033", "product_id": "4593", "name": "Domácí limonáda 0,4 l", "kitchen_name": null, "note": null, "quantity": 2, "kind": "full", "charge": null, "course": 0, "category": { "id": "320", "name": "Nápoje" }, "from_daily_menu": false, "station_id": null, "status": "done", "handed_out": false, "part": null, "size": null, "unit_price": { "amount": 5900, "currency": "CZK" }, "packaging_price": { "amount": 0, "currency": "CZK" }, "discount": { "amount": 0, "currency": "CZK" }, "gift": false, "vat_rate": "12", "removed_ingredients": [], "modifiers": [] } ], "receipt": { "items": { "amount": 33700, "currency": "CZK" }, "discounts": [], "delivery": { "amount": 4900, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "adjustment": { "amount": 0, "currency": "CZK" }, "total": { "amount": 38600, "currency": "CZK" }, "to_pay": { "amount": 38600, "currency": "CZK" }, "vat": [ { "rate": "12", "base": { "amount": 34464, "currency": "CZK" }, "vat": { "amount": 4136, "currency": "CZK" }, "total": { "amount": 38600, "currency": "CZK" } } ], "document": { "title": "Účtenka", "number": "184226", "tax_document": "Zjednodušený daňový doklad" } } } ] } -
Konec směny
Ending the shift
DELETE /restaurants/{restaurant_id}/couriers/{employee_id}/shift · endCourierShift
Tržby kurýra ukáže uzávěrka kuchyně.
The kitchen closing shows the courier's takings.
curl -X DELETE "https://api.mujprofirest.cz/v2/restaurants/123/couriers/64/shift" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN"curl -X DELETE "https://api.mujprofirest.cz/v2/restaurants/123/couriers/64/shift" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN"// klient: viz /v2/docs/js // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) await api.delete('/restaurants/123/couriers/64/shift');// the client: see /v2/docs/js // the library adds the employee's token itself (after the employee signs in) await api.delete('/restaurants/123/couriers/64/shift');// klient: viz /v2/docs/typescript // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) await api.delete('/restaurants/123/couriers/64/shift');// the client: see /v2/docs/typescript // the library adds the employee's token itself (after the employee signs in) await api.delete('/restaurants/123/couriers/64/shift');// klient: viz /v2/docs/php // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) $api->delete('/restaurants/123/couriers/64/shift');// the client: see /v2/docs/php // the library adds the employee's token itself (after the employee signs in) $api->delete('/restaurants/123/couriers/64/shift');// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) api.delete("/restaurants/123/couriers/64/shift");// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) api.delete("/restaurants/123/couriers/64/shift");// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) api.delete("/restaurants/123/couriers/64/shift")// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) api.delete("/restaurants/123/couriers/64/shift")// klient: viz /v2/docs/csharp // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) await api.DeleteAsync("/restaurants/123/couriers/64/shift");// the client: see /v2/docs/csharp // the library adds the employee's token itself (after the employee signs in) await api.DeleteAsync("/restaurants/123/couriers/64/shift");# klient: viz /v2/docs/python # token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) api.delete('/restaurants/123/couriers/64/shift')# the client: see /v2/docs/python # the library adds the employee's token itself (after the employee signs in) api.delete('/restaurants/123/couriers/64/shift')// klient: viz /v2/docs/swift // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) try await api.delete("/restaurants/123/couriers/64/shift")// the client: see /v2/docs/swift // the library adds the employee's token itself (after the employee signs in) try await api.delete("/restaurants/123/couriers/64/shift")// klient: viz /v2/docs/dart // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) await api.delete('/restaurants/123/couriers/64/shift');// the client: see /v2/docs/dart // the library adds the employee's token itself (after the employee signs in) await api.delete('/restaurants/123/couriers/64/shift');// klient: viz /v2/docs/go // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) _, err := api.Delete(ctx, "/restaurants/123/couriers/64/shift", nil)// the client: see /v2/docs/go // the library adds the employee's token itself (after the employee signs in) _, err := api.Delete(ctx, "/restaurants/123/couriers/64/shift", nil)
Scénář
Scenario
Stav, chyby a logy zařízení
State, errors and logs of a device
Vlastní zařízení ProfirestuProfirest's own deviceZařízení si log drží u sebe (černá skříňka, 14 dní). Serveru každou minutu přihlásí stav, chyby pošle hned, a celý log nahraje jen na vyžádání – podpora nebo provozovna o něj požádá v administraci a soubory dorazí do pár minut.
The device keeps its log on itself (a black box, 14 days). It checks its state in with the server every minute, reports errors at once and uploads the whole log only when asked – support or the restaurant asks in the administration and the files arrive within minutes.
-
Každou minutu přihlaste stav
Check the state in every minute
POST /restaurants/{restaurant_id}/device-checkin · checkInDevice
Verze, síť, fronty čekající na odeslání, poslední záloha, připojené telefony číšníků (
peers) a volná počítadla. Odpověď nesecommands; výsledky příkazů hlaste v dalším check-inu. Když příkaz čeká, nese každá odpověď API hlavičkuProfirest-Commands: pending– přihlaste stav hned.Versions, network, the queues waiting to be sent, the last backup, the waiters' phones connected to the register (
peers) and free counters. The answer carriescommands; report their results in the next check-in. While a command waits, every answer of the API carries the headerProfirest-Commands: pending– check in at once.curl "https://api.mujprofirest.cz/v2/restaurants/123/device-checkin" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "role": "register", "app_version": "26.10.3", "os_version": "Android 13", "device_model": "Sunmi T2s", "sent_at": "2027-01-15T12:01:00+01:00", "uptime_seconds": 41820, "battery": {"percent": 100, "charging": true}, "network": {"type": "wifi", "ip": "192.168.1.57", "signal_dbm": -58}, "queues": { "receipts": {"count": 0, "oldest_at": null}, "payments": {"count": 1, "oldest_at": "2027-01-15T11:58:40+01:00"}, "print_jobs": {"count": 0, "oldest_at": null} }, "last_backup_at": "2027-01-15T03:00:12+01:00", "last_sync_at": "2027-01-15T12:00:48+01:00", "log_store": { "segments": 2016, "bytes": 22806528, "oldest_at": "2027-01-01T12:00:00+01:00", "errors_today": 1 }, "counters": {"polls": 3312, "broadcasts": 148, "errors": 1, "socket_reconnects": 2}, "peers": [ { "key": "9bb5f040", "name": "Jana", "role": "waiter", "app_version": "26.10.3", "connected": true, "last_seen_at": "2027-01-15T12:00:58+01:00", "log_store": true }, { "key": "c17d02aa", "name": "Petr", "role": "waiter", "app_version": "26.10.3", "connected": false, "last_seen_at": "2027-01-15T11:20:03+01:00", "log_store": true } ], "command_results": [{"command_id": "c-5d10b9", "status": "done", "message": null}] }'curl "https://api.mujprofirest.cz/v2/restaurants/123/device-checkin" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "role": "register", "app_version": "26.10.3", "os_version": "Android 13", "device_model": "Sunmi T2s", "sent_at": "2027-01-15T12:01:00+01:00", "uptime_seconds": 41820, "battery": {"percent": 100, "charging": true}, "network": {"type": "wifi", "ip": "192.168.1.57", "signal_dbm": -58}, "queues": { "receipts": {"count": 0, "oldest_at": null}, "payments": {"count": 1, "oldest_at": "2027-01-15T11:58:40+01:00"}, "print_jobs": {"count": 0, "oldest_at": null} }, "last_backup_at": "2027-01-15T03:00:12+01:00", "last_sync_at": "2027-01-15T12:00:48+01:00", "log_store": { "segments": 2016, "bytes": 22806528, "oldest_at": "2027-01-01T12:00:00+01:00", "errors_today": 1 }, "counters": {"polls": 3312, "broadcasts": 148, "errors": 1, "socket_reconnects": 2}, "peers": [ { "key": "9bb5f040", "name": "Jana", "role": "waiter", "app_version": "26.10.3", "connected": true, "last_seen_at": "2027-01-15T12:00:58+01:00", "log_store": true }, { "key": "c17d02aa", "name": "Petr", "role": "waiter", "app_version": "26.10.3", "connected": false, "last_seen_at": "2027-01-15T11:20:03+01:00", "log_store": true } ], "command_results": [{"command_id": "c-5d10b9", "status": "done", "message": null}] }'// klient: viz /v2/docs/js const inDevice = await api.post('/restaurants/123/device-checkin', { role: 'register', app_version: '26.10.3', os_version: 'Android 13', device_model: 'Sunmi T2s', sent_at: '2027-01-15T12:01:00+01:00', uptime_seconds: 41820, battery: { percent: 100, charging: true }, network: { type: 'wifi', ip: '192.168.1.57', signal_dbm: -58 }, queues: { receipts: { count: 0, oldest_at: null }, payments: { count: 1, oldest_at: '2027-01-15T11:58:40+01:00' }, print_jobs: { count: 0, oldest_at: null }, }, last_backup_at: '2027-01-15T03:00:12+01:00', last_sync_at: '2027-01-15T12:00:48+01:00', log_store: { segments: 2016, bytes: 22806528, oldest_at: '2027-01-01T12:00:00+01:00', errors_today: 1, }, counters: { polls: 3312, broadcasts: 148, errors: 1, socket_reconnects: 2 }, peers: [ { key: '9bb5f040', name: 'Jana', role: 'waiter', app_version: '26.10.3', connected: true, last_seen_at: '2027-01-15T12:00:58+01:00', log_store: true, }, { key: 'c17d02aa', name: 'Petr', role: 'waiter', app_version: '26.10.3', connected: false, last_seen_at: '2027-01-15T11:20:03+01:00', log_store: true, }, ], command_results: [{ command_id: 'c-5d10b9', status: 'done', message: null }], }); // 200// the client: see /v2/docs/js const inDevice = await api.post('/restaurants/123/device-checkin', { role: 'register', app_version: '26.10.3', os_version: 'Android 13', device_model: 'Sunmi T2s', sent_at: '2027-01-15T12:01:00+01:00', uptime_seconds: 41820, battery: { percent: 100, charging: true }, network: { type: 'wifi', ip: '192.168.1.57', signal_dbm: -58 }, queues: { receipts: { count: 0, oldest_at: null }, payments: { count: 1, oldest_at: '2027-01-15T11:58:40+01:00' }, print_jobs: { count: 0, oldest_at: null }, }, last_backup_at: '2027-01-15T03:00:12+01:00', last_sync_at: '2027-01-15T12:00:48+01:00', log_store: { segments: 2016, bytes: 22806528, oldest_at: '2027-01-01T12:00:00+01:00', errors_today: 1, }, counters: { polls: 3312, broadcasts: 148, errors: 1, socket_reconnects: 2 }, peers: [ { key: '9bb5f040', name: 'Jana', role: 'waiter', app_version: '26.10.3', connected: true, last_seen_at: '2027-01-15T12:00:58+01:00', log_store: true, }, { key: 'c17d02aa', name: 'Petr', role: 'waiter', app_version: '26.10.3', connected: false, last_seen_at: '2027-01-15T11:20:03+01:00', log_store: true, }, ], command_results: [{ command_id: 'c-5d10b9', status: 'done', message: null }], }); // 200// klient: viz /v2/docs/typescript const inDevice = await api.post('/restaurants/123/device-checkin', { role: 'register', app_version: '26.10.3', os_version: 'Android 13', device_model: 'Sunmi T2s', sent_at: '2027-01-15T12:01:00+01:00', uptime_seconds: 41820, battery: { percent: 100, charging: true }, network: { type: 'wifi', ip: '192.168.1.57', signal_dbm: -58 }, queues: { receipts: { count: 0, oldest_at: null }, payments: { count: 1, oldest_at: '2027-01-15T11:58:40+01:00' }, print_jobs: { count: 0, oldest_at: null }, }, last_backup_at: '2027-01-15T03:00:12+01:00', last_sync_at: '2027-01-15T12:00:48+01:00', log_store: { segments: 2016, bytes: 22806528, oldest_at: '2027-01-01T12:00:00+01:00', errors_today: 1, }, counters: { polls: 3312, broadcasts: 148, errors: 1, socket_reconnects: 2 }, peers: [ { key: '9bb5f040', name: 'Jana', role: 'waiter', app_version: '26.10.3', connected: true, last_seen_at: '2027-01-15T12:00:58+01:00', log_store: true, }, { key: 'c17d02aa', name: 'Petr', role: 'waiter', app_version: '26.10.3', connected: false, last_seen_at: '2027-01-15T11:20:03+01:00', log_store: true, }, ], command_results: [{ command_id: 'c-5d10b9', status: 'done', message: null }], }); // 200 DeviceCheckInResult// the client: see /v2/docs/typescript const inDevice = await api.post('/restaurants/123/device-checkin', { role: 'register', app_version: '26.10.3', os_version: 'Android 13', device_model: 'Sunmi T2s', sent_at: '2027-01-15T12:01:00+01:00', uptime_seconds: 41820, battery: { percent: 100, charging: true }, network: { type: 'wifi', ip: '192.168.1.57', signal_dbm: -58 }, queues: { receipts: { count: 0, oldest_at: null }, payments: { count: 1, oldest_at: '2027-01-15T11:58:40+01:00' }, print_jobs: { count: 0, oldest_at: null }, }, last_backup_at: '2027-01-15T03:00:12+01:00', last_sync_at: '2027-01-15T12:00:48+01:00', log_store: { segments: 2016, bytes: 22806528, oldest_at: '2027-01-01T12:00:00+01:00', errors_today: 1, }, counters: { polls: 3312, broadcasts: 148, errors: 1, socket_reconnects: 2 }, peers: [ { key: '9bb5f040', name: 'Jana', role: 'waiter', app_version: '26.10.3', connected: true, last_seen_at: '2027-01-15T12:00:58+01:00', log_store: true, }, { key: 'c17d02aa', name: 'Petr', role: 'waiter', app_version: '26.10.3', connected: false, last_seen_at: '2027-01-15T11:20:03+01:00', log_store: true, }, ], command_results: [{ command_id: 'c-5d10b9', status: 'done', message: null }], }); // 200 DeviceCheckInResult// klient: viz /v2/docs/php $inDevice = $api->post('/restaurants/123/device-checkin', [ 'role' => 'register', 'app_version' => '26.10.3', 'os_version' => 'Android 13', 'device_model' => 'Sunmi T2s', 'sent_at' => '2027-01-15T12:01:00+01:00', 'uptime_seconds' => 41820, 'battery' => ['percent' => 100, 'charging' => true], 'network' => ['type' => 'wifi', 'ip' => '192.168.1.57', 'signal_dbm' => -58], 'queues' => [ 'receipts' => ['count' => 0, 'oldest_at' => null], 'payments' => ['count' => 1, 'oldest_at' => '2027-01-15T11:58:40+01:00'], 'print_jobs' => ['count' => 0, 'oldest_at' => null], ], 'last_backup_at' => '2027-01-15T03:00:12+01:00', 'last_sync_at' => '2027-01-15T12:00:48+01:00', 'log_store' => [ 'segments' => 2016, 'bytes' => 22806528, 'oldest_at' => '2027-01-01T12:00:00+01:00', 'errors_today' => 1, ], 'counters' => ['polls' => 3312, 'broadcasts' => 148, 'errors' => 1, 'socket_reconnects' => 2], 'peers' => [ [ 'key' => '9bb5f040', 'name' => 'Jana', 'role' => 'waiter', 'app_version' => '26.10.3', 'connected' => true, 'last_seen_at' => '2027-01-15T12:00:58+01:00', 'log_store' => true, ], [ 'key' => 'c17d02aa', 'name' => 'Petr', 'role' => 'waiter', 'app_version' => '26.10.3', 'connected' => false, 'last_seen_at' => '2027-01-15T11:20:03+01:00', 'log_store' => true, ], ], 'command_results' => [['command_id' => 'c-5d10b9', 'status' => 'done', 'message' => null]], ]); // 200// the client: see /v2/docs/php $inDevice = $api->post('/restaurants/123/device-checkin', [ 'role' => 'register', 'app_version' => '26.10.3', 'os_version' => 'Android 13', 'device_model' => 'Sunmi T2s', 'sent_at' => '2027-01-15T12:01:00+01:00', 'uptime_seconds' => 41820, 'battery' => ['percent' => 100, 'charging' => true], 'network' => ['type' => 'wifi', 'ip' => '192.168.1.57', 'signal_dbm' => -58], 'queues' => [ 'receipts' => ['count' => 0, 'oldest_at' => null], 'payments' => ['count' => 1, 'oldest_at' => '2027-01-15T11:58:40+01:00'], 'print_jobs' => ['count' => 0, 'oldest_at' => null], ], 'last_backup_at' => '2027-01-15T03:00:12+01:00', 'last_sync_at' => '2027-01-15T12:00:48+01:00', 'log_store' => [ 'segments' => 2016, 'bytes' => 22806528, 'oldest_at' => '2027-01-01T12:00:00+01:00', 'errors_today' => 1, ], 'counters' => ['polls' => 3312, 'broadcasts' => 148, 'errors' => 1, 'socket_reconnects' => 2], 'peers' => [ [ 'key' => '9bb5f040', 'name' => 'Jana', 'role' => 'waiter', 'app_version' => '26.10.3', 'connected' => true, 'last_seen_at' => '2027-01-15T12:00:58+01:00', 'log_store' => true, ], [ 'key' => 'c17d02aa', 'name' => 'Petr', 'role' => 'waiter', 'app_version' => '26.10.3', 'connected' => false, 'last_seen_at' => '2027-01-15T11:20:03+01:00', 'log_store' => true, ], ], 'command_results' => [['command_id' => 'c-5d10b9', 'status' => 'done', 'message' => null]], ]); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) DeviceCheckInResult inDevice = api.post("/restaurants/123/device-checkin", Json.parse(""" { "role": "register", "app_version": "26.10.3", "os_version": "Android 13", "device_model": "Sunmi T2s", "sent_at": "2027-01-15T12:01:00+01:00", "uptime_seconds": 41820, "battery": {"percent": 100, "charging": true}, "network": {"type": "wifi", "ip": "192.168.1.57", "signal_dbm": -58}, "queues": { "receipts": {"count": 0, "oldest_at": null}, "payments": {"count": 1, "oldest_at": "2027-01-15T11:58:40+01:00"}, "print_jobs": {"count": 0, "oldest_at": null} }, "last_backup_at": "2027-01-15T03:00:12+01:00", "last_sync_at": "2027-01-15T12:00:48+01:00", "log_store": { "segments": 2016, "bytes": 22806528, "oldest_at": "2027-01-01T12:00:00+01:00", "errors_today": 1 }, "counters": {"polls": 3312, "broadcasts": 148, "errors": 1, "socket_reconnects": 2}, "peers": [ { "key": "9bb5f040", "name": "Jana", "role": "waiter", "app_version": "26.10.3", "connected": true, "last_seen_at": "2027-01-15T12:00:58+01:00", "log_store": true }, { "key": "c17d02aa", "name": "Petr", "role": "waiter", "app_version": "26.10.3", "connected": false, "last_seen_at": "2027-01-15T11:20:03+01:00", "log_store": true } ], "command_results": [{"command_id": "c-5d10b9", "status": "done", "message": null}] } """), DeviceCheckInResult::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) DeviceCheckInResult inDevice = api.post("/restaurants/123/device-checkin", Json.parse(""" { "role": "register", "app_version": "26.10.3", "os_version": "Android 13", "device_model": "Sunmi T2s", "sent_at": "2027-01-15T12:01:00+01:00", "uptime_seconds": 41820, "battery": {"percent": 100, "charging": true}, "network": {"type": "wifi", "ip": "192.168.1.57", "signal_dbm": -58}, "queues": { "receipts": {"count": 0, "oldest_at": null}, "payments": {"count": 1, "oldest_at": "2027-01-15T11:58:40+01:00"}, "print_jobs": {"count": 0, "oldest_at": null} }, "last_backup_at": "2027-01-15T03:00:12+01:00", "last_sync_at": "2027-01-15T12:00:48+01:00", "log_store": { "segments": 2016, "bytes": 22806528, "oldest_at": "2027-01-01T12:00:00+01:00", "errors_today": 1 }, "counters": {"polls": 3312, "broadcasts": 148, "errors": 1, "socket_reconnects": 2}, "peers": [ { "key": "9bb5f040", "name": "Jana", "role": "waiter", "app_version": "26.10.3", "connected": true, "last_seen_at": "2027-01-15T12:00:58+01:00", "log_store": true }, { "key": "c17d02aa", "name": "Petr", "role": "waiter", "app_version": "26.10.3", "connected": false, "last_seen_at": "2027-01-15T11:20:03+01:00", "log_store": true } ], "command_results": [{"command_id": "c-5d10b9", "status": "done", "message": null}] } """), DeviceCheckInResult::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val inDevice = api.post("/restaurants/123/device-checkin", mapOf( "role" to "register", "app_version" to "26.10.3", "os_version" to "Android 13", "device_model" to "Sunmi T2s", "sent_at" to "2027-01-15T12:01:00+01:00", "uptime_seconds" to 41820, "battery" to mapOf("percent" to 100, "charging" to true), "network" to mapOf("type" to "wifi", "ip" to "192.168.1.57", "signal_dbm" to -58), "queues" to mapOf( "receipts" to mapOf("count" to 0, "oldest_at" to null), "payments" to mapOf("count" to 1, "oldest_at" to "2027-01-15T11:58:40+01:00"), "print_jobs" to mapOf("count" to 0, "oldest_at" to null), ), "last_backup_at" to "2027-01-15T03:00:12+01:00", "last_sync_at" to "2027-01-15T12:00:48+01:00", "log_store" to mapOf( "segments" to 2016, "bytes" to 22806528, "oldest_at" to "2027-01-01T12:00:00+01:00", "errors_today" to 1, ), "counters" to mapOf("polls" to 3312, "broadcasts" to 148, "errors" to 1, "socket_reconnects" to 2), "peers" to listOf( mapOf( "key" to "9bb5f040", "name" to "Jana", "role" to "waiter", "app_version" to "26.10.3", "connected" to true, "last_seen_at" to "2027-01-15T12:00:58+01:00", "log_store" to true, ), mapOf( "key" to "c17d02aa", "name" to "Petr", "role" to "waiter", "app_version" to "26.10.3", "connected" to false, "last_seen_at" to "2027-01-15T11:20:03+01:00", "log_store" to true, ), ), "command_results" to listOf(mapOf("command_id" to "c-5d10b9", "status" to "done", "message" to null)), ), DeviceCheckInResult::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val inDevice = api.post("/restaurants/123/device-checkin", mapOf( "role" to "register", "app_version" to "26.10.3", "os_version" to "Android 13", "device_model" to "Sunmi T2s", "sent_at" to "2027-01-15T12:01:00+01:00", "uptime_seconds" to 41820, "battery" to mapOf("percent" to 100, "charging" to true), "network" to mapOf("type" to "wifi", "ip" to "192.168.1.57", "signal_dbm" to -58), "queues" to mapOf( "receipts" to mapOf("count" to 0, "oldest_at" to null), "payments" to mapOf("count" to 1, "oldest_at" to "2027-01-15T11:58:40+01:00"), "print_jobs" to mapOf("count" to 0, "oldest_at" to null), ), "last_backup_at" to "2027-01-15T03:00:12+01:00", "last_sync_at" to "2027-01-15T12:00:48+01:00", "log_store" to mapOf( "segments" to 2016, "bytes" to 22806528, "oldest_at" to "2027-01-01T12:00:00+01:00", "errors_today" to 1, ), "counters" to mapOf("polls" to 3312, "broadcasts" to 148, "errors" to 1, "socket_reconnects" to 2), "peers" to listOf( mapOf( "key" to "9bb5f040", "name" to "Jana", "role" to "waiter", "app_version" to "26.10.3", "connected" to true, "last_seen_at" to "2027-01-15T12:00:58+01:00", "log_store" to true, ), mapOf( "key" to "c17d02aa", "name" to "Petr", "role" to "waiter", "app_version" to "26.10.3", "connected" to false, "last_seen_at" to "2027-01-15T11:20:03+01:00", "log_store" to true, ), ), "command_results" to listOf(mapOf("command_id" to "c-5d10b9", "status" to "done", "message" to null)), ), DeviceCheckInResult::fromJson) // 200// klient: viz /v2/docs/csharp var inDevice = await api.PostAsync<DeviceCheckInResult>("/restaurants/123/device-checkin", new { role = "register", app_version = "26.10.3", os_version = "Android 13", device_model = "Sunmi T2s", sent_at = "2027-01-15T12:01:00+01:00", uptime_seconds = 41820, battery = new { percent = 100, charging = true }, network = new { type = "wifi", ip = "192.168.1.57", signal_dbm = -58 }, queues = new { receipts = new { count = 0, oldest_at = (object?)null }, payments = new { count = 1, oldest_at = "2027-01-15T11:58:40+01:00" }, print_jobs = new { count = 0, oldest_at = (object?)null }, }, last_backup_at = "2027-01-15T03:00:12+01:00", last_sync_at = "2027-01-15T12:00:48+01:00", log_store = new { segments = 2016, bytes = 22806528, oldest_at = "2027-01-01T12:00:00+01:00", errors_today = 1, }, counters = new { polls = 3312, broadcasts = 148, errors = 1, socket_reconnects = 2 }, peers = new object[] { new { key = "9bb5f040", name = "Jana", role = "waiter", app_version = "26.10.3", connected = true, last_seen_at = "2027-01-15T12:00:58+01:00", log_store = true, }, new { key = "c17d02aa", name = "Petr", role = "waiter", app_version = "26.10.3", connected = false, last_seen_at = "2027-01-15T11:20:03+01:00", log_store = true, }, }, command_results = new object[] { new { command_id = "c-5d10b9", status = "done", message = (object?)null }, }, }); // 200// the client: see /v2/docs/csharp var inDevice = await api.PostAsync<DeviceCheckInResult>("/restaurants/123/device-checkin", new { role = "register", app_version = "26.10.3", os_version = "Android 13", device_model = "Sunmi T2s", sent_at = "2027-01-15T12:01:00+01:00", uptime_seconds = 41820, battery = new { percent = 100, charging = true }, network = new { type = "wifi", ip = "192.168.1.57", signal_dbm = -58 }, queues = new { receipts = new { count = 0, oldest_at = (object?)null }, payments = new { count = 1, oldest_at = "2027-01-15T11:58:40+01:00" }, print_jobs = new { count = 0, oldest_at = (object?)null }, }, last_backup_at = "2027-01-15T03:00:12+01:00", last_sync_at = "2027-01-15T12:00:48+01:00", log_store = new { segments = 2016, bytes = 22806528, oldest_at = "2027-01-01T12:00:00+01:00", errors_today = 1, }, counters = new { polls = 3312, broadcasts = 148, errors = 1, socket_reconnects = 2 }, peers = new object[] { new { key = "9bb5f040", name = "Jana", role = "waiter", app_version = "26.10.3", connected = true, last_seen_at = "2027-01-15T12:00:58+01:00", log_store = true, }, new { key = "c17d02aa", name = "Petr", role = "waiter", app_version = "26.10.3", connected = false, last_seen_at = "2027-01-15T11:20:03+01:00", log_store = true, }, }, command_results = new object[] { new { command_id = "c-5d10b9", status = "done", message = (object?)null }, }, }); // 200# klient: viz /v2/docs/python in_device = api.post('/restaurants/123/device-checkin', { 'role': 'register', 'app_version': '26.10.3', 'os_version': 'Android 13', 'device_model': 'Sunmi T2s', 'sent_at': '2027-01-15T12:01:00+01:00', 'uptime_seconds': 41820, 'battery': {'percent': 100, 'charging': True}, 'network': {'type': 'wifi', 'ip': '192.168.1.57', 'signal_dbm': -58}, 'queues': { 'receipts': {'count': 0, 'oldest_at': None}, 'payments': {'count': 1, 'oldest_at': '2027-01-15T11:58:40+01:00'}, 'print_jobs': {'count': 0, 'oldest_at': None}, }, 'last_backup_at': '2027-01-15T03:00:12+01:00', 'last_sync_at': '2027-01-15T12:00:48+01:00', 'log_store': { 'segments': 2016, 'bytes': 22806528, 'oldest_at': '2027-01-01T12:00:00+01:00', 'errors_today': 1, }, 'counters': {'polls': 3312, 'broadcasts': 148, 'errors': 1, 'socket_reconnects': 2}, 'peers': [ { 'key': '9bb5f040', 'name': 'Jana', 'role': 'waiter', 'app_version': '26.10.3', 'connected': True, 'last_seen_at': '2027-01-15T12:00:58+01:00', 'log_store': True, }, { 'key': 'c17d02aa', 'name': 'Petr', 'role': 'waiter', 'app_version': '26.10.3', 'connected': False, 'last_seen_at': '2027-01-15T11:20:03+01:00', 'log_store': True, }, ], 'command_results': [{'command_id': 'c-5d10b9', 'status': 'done', 'message': None}], }) # 200# the client: see /v2/docs/python in_device = api.post('/restaurants/123/device-checkin', { 'role': 'register', 'app_version': '26.10.3', 'os_version': 'Android 13', 'device_model': 'Sunmi T2s', 'sent_at': '2027-01-15T12:01:00+01:00', 'uptime_seconds': 41820, 'battery': {'percent': 100, 'charging': True}, 'network': {'type': 'wifi', 'ip': '192.168.1.57', 'signal_dbm': -58}, 'queues': { 'receipts': {'count': 0, 'oldest_at': None}, 'payments': {'count': 1, 'oldest_at': '2027-01-15T11:58:40+01:00'}, 'print_jobs': {'count': 0, 'oldest_at': None}, }, 'last_backup_at': '2027-01-15T03:00:12+01:00', 'last_sync_at': '2027-01-15T12:00:48+01:00', 'log_store': { 'segments': 2016, 'bytes': 22806528, 'oldest_at': '2027-01-01T12:00:00+01:00', 'errors_today': 1, }, 'counters': {'polls': 3312, 'broadcasts': 148, 'errors': 1, 'socket_reconnects': 2}, 'peers': [ { 'key': '9bb5f040', 'name': 'Jana', 'role': 'waiter', 'app_version': '26.10.3', 'connected': True, 'last_seen_at': '2027-01-15T12:00:58+01:00', 'log_store': True, }, { 'key': 'c17d02aa', 'name': 'Petr', 'role': 'waiter', 'app_version': '26.10.3', 'connected': False, 'last_seen_at': '2027-01-15T11:20:03+01:00', 'log_store': True, }, ], 'command_results': [{'command_id': 'c-5d10b9', 'status': 'done', 'message': None}], }) # 200// klient: viz /v2/docs/swift let inDevice: DeviceCheckInResult = try await api.post("/restaurants/123/device-checkin", body: [ "role": "register", "app_version": "26.10.3", "os_version": "Android 13", "device_model": "Sunmi T2s", "sent_at": "2027-01-15T12:01:00+01:00", "uptime_seconds": 41820, "battery": ["percent": 100, "charging": true], "network": ["type": "wifi", "ip": "192.168.1.57", "signal_dbm": -58], "queues": [ "receipts": ["count": 0, "oldest_at": nil], "payments": ["count": 1, "oldest_at": "2027-01-15T11:58:40+01:00"], "print_jobs": ["count": 0, "oldest_at": nil], ], "last_backup_at": "2027-01-15T03:00:12+01:00", "last_sync_at": "2027-01-15T12:00:48+01:00", "log_store": [ "segments": 2016, "bytes": 22806528, "oldest_at": "2027-01-01T12:00:00+01:00", "errors_today": 1, ], "counters": ["polls": 3312, "broadcasts": 148, "errors": 1, "socket_reconnects": 2], "peers": [ [ "key": "9bb5f040", "name": "Jana", "role": "waiter", "app_version": "26.10.3", "connected": true, "last_seen_at": "2027-01-15T12:00:58+01:00", "log_store": true, ], [ "key": "c17d02aa", "name": "Petr", "role": "waiter", "app_version": "26.10.3", "connected": false, "last_seen_at": "2027-01-15T11:20:03+01:00", "log_store": true, ], ], "command_results": [["command_id": "c-5d10b9", "status": "done", "message": nil]], ]) // 200// the client: see /v2/docs/swift let inDevice: DeviceCheckInResult = try await api.post("/restaurants/123/device-checkin", body: [ "role": "register", "app_version": "26.10.3", "os_version": "Android 13", "device_model": "Sunmi T2s", "sent_at": "2027-01-15T12:01:00+01:00", "uptime_seconds": 41820, "battery": ["percent": 100, "charging": true], "network": ["type": "wifi", "ip": "192.168.1.57", "signal_dbm": -58], "queues": [ "receipts": ["count": 0, "oldest_at": nil], "payments": ["count": 1, "oldest_at": "2027-01-15T11:58:40+01:00"], "print_jobs": ["count": 0, "oldest_at": nil], ], "last_backup_at": "2027-01-15T03:00:12+01:00", "last_sync_at": "2027-01-15T12:00:48+01:00", "log_store": [ "segments": 2016, "bytes": 22806528, "oldest_at": "2027-01-01T12:00:00+01:00", "errors_today": 1, ], "counters": ["polls": 3312, "broadcasts": 148, "errors": 1, "socket_reconnects": 2], "peers": [ [ "key": "9bb5f040", "name": "Jana", "role": "waiter", "app_version": "26.10.3", "connected": true, "last_seen_at": "2027-01-15T12:00:58+01:00", "log_store": true, ], [ "key": "c17d02aa", "name": "Petr", "role": "waiter", "app_version": "26.10.3", "connected": false, "last_seen_at": "2027-01-15T11:20:03+01:00", "log_store": true, ], ], "command_results": [["command_id": "c-5d10b9", "status": "done", "message": nil]], ]) // 200// klient: viz /v2/docs/dart final inDevice = pr.DeviceCheckInResult.fromJson(await api.post('/restaurants/123/device-checkin', { 'role': 'register', 'app_version': '26.10.3', 'os_version': 'Android 13', 'device_model': 'Sunmi T2s', 'sent_at': '2027-01-15T12:01:00+01:00', 'uptime_seconds': 41820, 'battery': {'percent': 100, 'charging': true}, 'network': {'type': 'wifi', 'ip': '192.168.1.57', 'signal_dbm': -58}, 'queues': { 'receipts': {'count': 0, 'oldest_at': null}, 'payments': {'count': 1, 'oldest_at': '2027-01-15T11:58:40+01:00'}, 'print_jobs': {'count': 0, 'oldest_at': null}, }, 'last_backup_at': '2027-01-15T03:00:12+01:00', 'last_sync_at': '2027-01-15T12:00:48+01:00', 'log_store': { 'segments': 2016, 'bytes': 22806528, 'oldest_at': '2027-01-01T12:00:00+01:00', 'errors_today': 1, }, 'counters': {'polls': 3312, 'broadcasts': 148, 'errors': 1, 'socket_reconnects': 2}, 'peers': [ { 'key': '9bb5f040', 'name': 'Jana', 'role': 'waiter', 'app_version': '26.10.3', 'connected': true, 'last_seen_at': '2027-01-15T12:00:58+01:00', 'log_store': true, }, { 'key': 'c17d02aa', 'name': 'Petr', 'role': 'waiter', 'app_version': '26.10.3', 'connected': false, 'last_seen_at': '2027-01-15T11:20:03+01:00', 'log_store': true, }, ], 'command_results': [{'command_id': 'c-5d10b9', 'status': 'done', 'message': null}], })); // 200// the client: see /v2/docs/dart final inDevice = pr.DeviceCheckInResult.fromJson(await api.post('/restaurants/123/device-checkin', { 'role': 'register', 'app_version': '26.10.3', 'os_version': 'Android 13', 'device_model': 'Sunmi T2s', 'sent_at': '2027-01-15T12:01:00+01:00', 'uptime_seconds': 41820, 'battery': {'percent': 100, 'charging': true}, 'network': {'type': 'wifi', 'ip': '192.168.1.57', 'signal_dbm': -58}, 'queues': { 'receipts': {'count': 0, 'oldest_at': null}, 'payments': {'count': 1, 'oldest_at': '2027-01-15T11:58:40+01:00'}, 'print_jobs': {'count': 0, 'oldest_at': null}, }, 'last_backup_at': '2027-01-15T03:00:12+01:00', 'last_sync_at': '2027-01-15T12:00:48+01:00', 'log_store': { 'segments': 2016, 'bytes': 22806528, 'oldest_at': '2027-01-01T12:00:00+01:00', 'errors_today': 1, }, 'counters': {'polls': 3312, 'broadcasts': 148, 'errors': 1, 'socket_reconnects': 2}, 'peers': [ { 'key': '9bb5f040', 'name': 'Jana', 'role': 'waiter', 'app_version': '26.10.3', 'connected': true, 'last_seen_at': '2027-01-15T12:00:58+01:00', 'log_store': true, }, { 'key': 'c17d02aa', 'name': 'Petr', 'role': 'waiter', 'app_version': '26.10.3', 'connected': false, 'last_seen_at': '2027-01-15T11:20:03+01:00', 'log_store': true, }, ], 'command_results': [{'command_id': 'c-5d10b9', 'status': 'done', 'message': null}], })); // 200// klient: viz /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/device-checkin", map[string]any{ "role": "register", "app_version": "26.10.3", "os_version": "Android 13", "device_model": "Sunmi T2s", "sent_at": "2027-01-15T12:01:00+01:00", "uptime_seconds": 41820, "battery": map[string]any{"percent": 100, "charging": true}, "network": map[string]any{"type": "wifi", "ip": "192.168.1.57", "signal_dbm": -58}, "queues": map[string]any{ "receipts": map[string]any{"count": 0, "oldest_at": nil}, "payments": map[string]any{"count": 1, "oldest_at": "2027-01-15T11:58:40+01:00"}, "print_jobs": map[string]any{"count": 0, "oldest_at": nil}, }, "last_backup_at": "2027-01-15T03:00:12+01:00", "last_sync_at": "2027-01-15T12:00:48+01:00", "log_store": map[string]any{ "segments": 2016, "bytes": 22806528, "oldest_at": "2027-01-01T12:00:00+01:00", "errors_today": 1, }, "counters": map[string]any{"polls": 3312, "broadcasts": 148, "errors": 1, "socket_reconnects": 2}, "peers": []any{ map[string]any{ "key": "9bb5f040", "name": "Jana", "role": "waiter", "app_version": "26.10.3", "connected": true, "last_seen_at": "2027-01-15T12:00:58+01:00", "log_store": true, }, map[string]any{ "key": "c17d02aa", "name": "Petr", "role": "waiter", "app_version": "26.10.3", "connected": false, "last_seen_at": "2027-01-15T11:20:03+01:00", "log_store": true, }, }, "command_results": []any{map[string]any{"command_id": "c-5d10b9", "status": "done", "message": nil}}, }, nil) var inDevice model.DeviceCheckInResult // 200 if err == nil { err = res.Decode(&inDevice) }// the client: see /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/device-checkin", map[string]any{ "role": "register", "app_version": "26.10.3", "os_version": "Android 13", "device_model": "Sunmi T2s", "sent_at": "2027-01-15T12:01:00+01:00", "uptime_seconds": 41820, "battery": map[string]any{"percent": 100, "charging": true}, "network": map[string]any{"type": "wifi", "ip": "192.168.1.57", "signal_dbm": -58}, "queues": map[string]any{ "receipts": map[string]any{"count": 0, "oldest_at": nil}, "payments": map[string]any{"count": 1, "oldest_at": "2027-01-15T11:58:40+01:00"}, "print_jobs": map[string]any{"count": 0, "oldest_at": nil}, }, "last_backup_at": "2027-01-15T03:00:12+01:00", "last_sync_at": "2027-01-15T12:00:48+01:00", "log_store": map[string]any{ "segments": 2016, "bytes": 22806528, "oldest_at": "2027-01-01T12:00:00+01:00", "errors_today": 1, }, "counters": map[string]any{"polls": 3312, "broadcasts": 148, "errors": 1, "socket_reconnects": 2}, "peers": []any{ map[string]any{ "key": "9bb5f040", "name": "Jana", "role": "waiter", "app_version": "26.10.3", "connected": true, "last_seen_at": "2027-01-15T12:00:58+01:00", "log_store": true, }, map[string]any{ "key": "c17d02aa", "name": "Petr", "role": "waiter", "app_version": "26.10.3", "connected": false, "last_seen_at": "2027-01-15T11:20:03+01:00", "log_store": true, }, }, "command_results": []any{map[string]any{"command_id": "c-5d10b9", "status": "done", "message": nil}}, }, nil) var inDevice model.DeviceCheckInResult // 200 if err == nil { err = res.Decode(&inDevice) }Příklad odpovědi 200Example answer 200
{ "server_time": "2027-01-15T12:01:00+01:00", "api_target": { "target": "v2", "base_url": "https://api.mujprofirest.cz/v2" }, "next_in_seconds": 60, "commands": [ { "id": "c-8f2c1a", "type": "upload_logs", "created_at": "2027-01-15T12:00:35+01:00", "expires_at": "2027-01-16T12:00:35+01:00", "upload_logs": { "request_id": "3105", "reason": "karta stržena, stůl 11", "from": "2027-01-14T12:00:00+01:00", "to": "2027-01-15T12:00:00+01:00", "detail": "full", "uploads": [ { "upload_id": "7742", "peer_key": null, "token": "pfl_6Y0Bl8pbgLgDKJGhWSHjW3CGQWKaO2bukl9Z2gxAUPA", "upload_url": "https://api.mujprofirest.cz/v2/log-uploads/7742", "max_part_bytes": 4194304, "expires_at": "2027-01-16T12:00:35+01:00" }, { "upload_id": "7743", "peer_key": "9bb5f040", "token": "pfl_kUeD_3Y4izx2yb8cvfgBkOe-ZP05gv7dvaNvonfEzvg", "upload_url": "https://api.mujprofirest.cz/v2/log-uploads/7743", "max_part_bytes": 4194304, "expires_at": "2027-01-16T12:00:35+01:00" } ] }, "live_logs": null } ] } -
Chybu pošlete hned
Report an error at once
POST /restaurants/{restaurant_id}/device-errors · reportDeviceError
S ~30 řádky logu před ní a s ID, která v tu chvíli platila (směna, účet, platba, požadavek) – stejná ID na kase i u číšníka skládají příběh. Tajemství maskujte před odesláním. Nejvýš 60 za hodinu.
With ~30 log lines before it and the IDs valid at the time (shift, tab, payment, request) – the same IDs on the register and the waiter's phone tell the story. Mask secrets before sending. At most 60 an hour.
curl "https://api.mujprofirest.cz/v2/restaurants/123/device-errors" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "id": "01a318f0-a0c0-7b57-8364-1e6fc225f5ce", "occurred_at": "2027-01-15T11:56:17+01:00", "level": "error", "code": "SOCK.timeout", "area": "SOCK", "event": "req.timeout", "message": "Pay bez odpovědi 20 s (b7e1)", "peer_key": "9bb5f040", "employee_name": "Jana", "app_version": "26.10.3", "refs": { "session": "s-3f9a", "tab": "o-7c21", "payment": "p-8f2c", "request": "b7e1", "broadcast": null }, "context": [ "{\"t\":\"11:55:36.920\",\"seq\":48200,\"l\":\"I\",\"a\":\"UI\",\"e\":\"tap\",\"sess\":\"s-3f9a\",\"ord\":\"o-7c21\",\"intent\":\"PayCard\",\"sum\":25000}", "{\"t\":\"11:55:57.703\",\"seq\":48204,\"l\":\"I\",\"a\":\"PAY\",\"e\":\"terminal.ok\",\"pay\":\"p-8f2c\",\"auth\":\"1dc15286\",\"pan\":\"****4821\",\"ms\":20742}", "{\"t\":\"11:55:57.750\",\"seq\":48206,\"l\":\"I\",\"a\":\"SOCK\",\"e\":\"req.send\",\"ord\":\"o-7c21\",\"pay\":\"p-8f2c\",\"rid\":\"b7e1\",\"op\":\"Pay\",\"kb\":1.9}", "{\"t\":\"11:56:16.004\",\"seq\":48208,\"l\":\"I\",\"a\":\"ENV\",\"e\":\"net.change\",\"from\":\"wifi\",\"to\":\"lte\",\"ip\":\"10.21.4.88\"}" ], "stack": null }'curl "https://api.mujprofirest.cz/v2/restaurants/123/device-errors" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "id": "01a318f0-a0c0-7b57-8364-1e6fc225f5ce", "occurred_at": "2027-01-15T11:56:17+01:00", "level": "error", "code": "SOCK.timeout", "area": "SOCK", "event": "req.timeout", "message": "Pay bez odpovědi 20 s (b7e1)", "peer_key": "9bb5f040", "employee_name": "Jana", "app_version": "26.10.3", "refs": { "session": "s-3f9a", "tab": "o-7c21", "payment": "p-8f2c", "request": "b7e1", "broadcast": null }, "context": [ "{\"t\":\"11:55:36.920\",\"seq\":48200,\"l\":\"I\",\"a\":\"UI\",\"e\":\"tap\",\"sess\":\"s-3f9a\",\"ord\":\"o-7c21\",\"intent\":\"PayCard\",\"sum\":25000}", "{\"t\":\"11:55:57.703\",\"seq\":48204,\"l\":\"I\",\"a\":\"PAY\",\"e\":\"terminal.ok\",\"pay\":\"p-8f2c\",\"auth\":\"1dc15286\",\"pan\":\"****4821\",\"ms\":20742}", "{\"t\":\"11:55:57.750\",\"seq\":48206,\"l\":\"I\",\"a\":\"SOCK\",\"e\":\"req.send\",\"ord\":\"o-7c21\",\"pay\":\"p-8f2c\",\"rid\":\"b7e1\",\"op\":\"Pay\",\"kb\":1.9}", "{\"t\":\"11:56:16.004\",\"seq\":48208,\"l\":\"I\",\"a\":\"ENV\",\"e\":\"net.change\",\"from\":\"wifi\",\"to\":\"lte\",\"ip\":\"10.21.4.88\"}" ], "stack": null }'// klient: viz /v2/docs/js const deviceError = await api.post('/restaurants/123/device-errors', { id: '01a318f0-a0c0-7b57-8364-1e6fc225f5ce', occurred_at: '2027-01-15T11:56:17+01:00', level: 'error', code: 'SOCK.timeout', area: 'SOCK', event: 'req.timeout', message: 'Pay bez odpovědi 20 s (b7e1)', peer_key: '9bb5f040', employee_name: 'Jana', app_version: '26.10.3', refs: { session: 's-3f9a', tab: 'o-7c21', payment: 'p-8f2c', request: 'b7e1', broadcast: null, }, context: [ '{"t":"11:55:36.920","seq":48200,"l":"I","a":"UI","e":"tap","sess":"s-3f9a","ord":"o-7c21","intent":"PayCard","sum":25000}', '{"t":"11:55:57.703","seq":48204,"l":"I","a":"PAY","e":"terminal.ok","pay":"p-8f2c","auth":"1dc15286","pan":"****4821","ms":20742}', '{"t":"11:55:57.750","seq":48206,"l":"I","a":"SOCK","e":"req.send","ord":"o-7c21","pay":"p-8f2c","rid":"b7e1","op":"Pay","kb":1.9}', '{"t":"11:56:16.004","seq":48208,"l":"I","a":"ENV","e":"net.change","from":"wifi","to":"lte","ip":"10.21.4.88"}', ], stack: null, }); // 201// the client: see /v2/docs/js const deviceError = await api.post('/restaurants/123/device-errors', { id: '01a318f0-a0c0-7b57-8364-1e6fc225f5ce', occurred_at: '2027-01-15T11:56:17+01:00', level: 'error', code: 'SOCK.timeout', area: 'SOCK', event: 'req.timeout', message: 'Pay bez odpovědi 20 s (b7e1)', peer_key: '9bb5f040', employee_name: 'Jana', app_version: '26.10.3', refs: { session: 's-3f9a', tab: 'o-7c21', payment: 'p-8f2c', request: 'b7e1', broadcast: null, }, context: [ '{"t":"11:55:36.920","seq":48200,"l":"I","a":"UI","e":"tap","sess":"s-3f9a","ord":"o-7c21","intent":"PayCard","sum":25000}', '{"t":"11:55:57.703","seq":48204,"l":"I","a":"PAY","e":"terminal.ok","pay":"p-8f2c","auth":"1dc15286","pan":"****4821","ms":20742}', '{"t":"11:55:57.750","seq":48206,"l":"I","a":"SOCK","e":"req.send","ord":"o-7c21","pay":"p-8f2c","rid":"b7e1","op":"Pay","kb":1.9}', '{"t":"11:56:16.004","seq":48208,"l":"I","a":"ENV","e":"net.change","from":"wifi","to":"lte","ip":"10.21.4.88"}', ], stack: null, }); // 201// klient: viz /v2/docs/typescript const deviceError = await api.post('/restaurants/123/device-errors', { id: '01a318f0-a0c0-7b57-8364-1e6fc225f5ce', occurred_at: '2027-01-15T11:56:17+01:00', level: 'error', code: 'SOCK.timeout', area: 'SOCK', event: 'req.timeout', message: 'Pay bez odpovědi 20 s (b7e1)', peer_key: '9bb5f040', employee_name: 'Jana', app_version: '26.10.3', refs: { session: 's-3f9a', tab: 'o-7c21', payment: 'p-8f2c', request: 'b7e1', broadcast: null, }, context: [ '{"t":"11:55:36.920","seq":48200,"l":"I","a":"UI","e":"tap","sess":"s-3f9a","ord":"o-7c21","intent":"PayCard","sum":25000}', '{"t":"11:55:57.703","seq":48204,"l":"I","a":"PAY","e":"terminal.ok","pay":"p-8f2c","auth":"1dc15286","pan":"****4821","ms":20742}', '{"t":"11:55:57.750","seq":48206,"l":"I","a":"SOCK","e":"req.send","ord":"o-7c21","pay":"p-8f2c","rid":"b7e1","op":"Pay","kb":1.9}', '{"t":"11:56:16.004","seq":48208,"l":"I","a":"ENV","e":"net.change","from":"wifi","to":"lte","ip":"10.21.4.88"}', ], stack: null, }); // 201 DeviceErrorResult// the client: see /v2/docs/typescript const deviceError = await api.post('/restaurants/123/device-errors', { id: '01a318f0-a0c0-7b57-8364-1e6fc225f5ce', occurred_at: '2027-01-15T11:56:17+01:00', level: 'error', code: 'SOCK.timeout', area: 'SOCK', event: 'req.timeout', message: 'Pay bez odpovědi 20 s (b7e1)', peer_key: '9bb5f040', employee_name: 'Jana', app_version: '26.10.3', refs: { session: 's-3f9a', tab: 'o-7c21', payment: 'p-8f2c', request: 'b7e1', broadcast: null, }, context: [ '{"t":"11:55:36.920","seq":48200,"l":"I","a":"UI","e":"tap","sess":"s-3f9a","ord":"o-7c21","intent":"PayCard","sum":25000}', '{"t":"11:55:57.703","seq":48204,"l":"I","a":"PAY","e":"terminal.ok","pay":"p-8f2c","auth":"1dc15286","pan":"****4821","ms":20742}', '{"t":"11:55:57.750","seq":48206,"l":"I","a":"SOCK","e":"req.send","ord":"o-7c21","pay":"p-8f2c","rid":"b7e1","op":"Pay","kb":1.9}', '{"t":"11:56:16.004","seq":48208,"l":"I","a":"ENV","e":"net.change","from":"wifi","to":"lte","ip":"10.21.4.88"}', ], stack: null, }); // 201 DeviceErrorResult// klient: viz /v2/docs/php $deviceError = $api->post('/restaurants/123/device-errors', [ 'id' => '01a318f0-a0c0-7b57-8364-1e6fc225f5ce', 'occurred_at' => '2027-01-15T11:56:17+01:00', 'level' => 'error', 'code' => 'SOCK.timeout', 'area' => 'SOCK', 'event' => 'req.timeout', 'message' => 'Pay bez odpovědi 20 s (b7e1)', 'peer_key' => '9bb5f040', 'employee_name' => 'Jana', 'app_version' => '26.10.3', 'refs' => [ 'session' => 's-3f9a', 'tab' => 'o-7c21', 'payment' => 'p-8f2c', 'request' => 'b7e1', 'broadcast' => null, ], 'context' => [ '{"t":"11:55:36.920","seq":48200,"l":"I","a":"UI","e":"tap","sess":"s-3f9a","ord":"o-7c21","intent":"PayCard","sum":25000}', '{"t":"11:55:57.703","seq":48204,"l":"I","a":"PAY","e":"terminal.ok","pay":"p-8f2c","auth":"1dc15286","pan":"****4821","ms":20742}', '{"t":"11:55:57.750","seq":48206,"l":"I","a":"SOCK","e":"req.send","ord":"o-7c21","pay":"p-8f2c","rid":"b7e1","op":"Pay","kb":1.9}', '{"t":"11:56:16.004","seq":48208,"l":"I","a":"ENV","e":"net.change","from":"wifi","to":"lte","ip":"10.21.4.88"}', ], 'stack' => null, ]); // 201// the client: see /v2/docs/php $deviceError = $api->post('/restaurants/123/device-errors', [ 'id' => '01a318f0-a0c0-7b57-8364-1e6fc225f5ce', 'occurred_at' => '2027-01-15T11:56:17+01:00', 'level' => 'error', 'code' => 'SOCK.timeout', 'area' => 'SOCK', 'event' => 'req.timeout', 'message' => 'Pay bez odpovědi 20 s (b7e1)', 'peer_key' => '9bb5f040', 'employee_name' => 'Jana', 'app_version' => '26.10.3', 'refs' => [ 'session' => 's-3f9a', 'tab' => 'o-7c21', 'payment' => 'p-8f2c', 'request' => 'b7e1', 'broadcast' => null, ], 'context' => [ '{"t":"11:55:36.920","seq":48200,"l":"I","a":"UI","e":"tap","sess":"s-3f9a","ord":"o-7c21","intent":"PayCard","sum":25000}', '{"t":"11:55:57.703","seq":48204,"l":"I","a":"PAY","e":"terminal.ok","pay":"p-8f2c","auth":"1dc15286","pan":"****4821","ms":20742}', '{"t":"11:55:57.750","seq":48206,"l":"I","a":"SOCK","e":"req.send","ord":"o-7c21","pay":"p-8f2c","rid":"b7e1","op":"Pay","kb":1.9}', '{"t":"11:56:16.004","seq":48208,"l":"I","a":"ENV","e":"net.change","from":"wifi","to":"lte","ip":"10.21.4.88"}', ], 'stack' => null, ]); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) DeviceErrorResult deviceError = api.post("/restaurants/123/device-errors", Json.parse(""" { "id": "01a318f0-a0c0-7b57-8364-1e6fc225f5ce", "occurred_at": "2027-01-15T11:56:17+01:00", "level": "error", "code": "SOCK.timeout", "area": "SOCK", "event": "req.timeout", "message": "Pay bez odpovědi 20 s (b7e1)", "peer_key": "9bb5f040", "employee_name": "Jana", "app_version": "26.10.3", "refs": { "session": "s-3f9a", "tab": "o-7c21", "payment": "p-8f2c", "request": "b7e1", "broadcast": null }, "context": [ "{\\"t\\":\\"11:55:36.920\\",\\"seq\\":48200,\\"l\\":\\"I\\",\\"a\\":\\"UI\\",\\"e\\":\\"tap\\",\\"sess\\":\\"s-3f9a\\",\\"ord\\":\\"o-7c21\\",\\"intent\\":\\"PayCard\\",\\"sum\\":25000}", "{\\"t\\":\\"11:55:57.703\\",\\"seq\\":48204,\\"l\\":\\"I\\",\\"a\\":\\"PAY\\",\\"e\\":\\"terminal.ok\\",\\"pay\\":\\"p-8f2c\\",\\"auth\\":\\"1dc15286\\",\\"pan\\":\\"****4821\\",\\"ms\\":20742}", "{\\"t\\":\\"11:55:57.750\\",\\"seq\\":48206,\\"l\\":\\"I\\",\\"a\\":\\"SOCK\\",\\"e\\":\\"req.send\\",\\"ord\\":\\"o-7c21\\",\\"pay\\":\\"p-8f2c\\",\\"rid\\":\\"b7e1\\",\\"op\\":\\"Pay\\",\\"kb\\":1.9}", "{\\"t\\":\\"11:56:16.004\\",\\"seq\\":48208,\\"l\\":\\"I\\",\\"a\\":\\"ENV\\",\\"e\\":\\"net.change\\",\\"from\\":\\"wifi\\",\\"to\\":\\"lte\\",\\"ip\\":\\"10.21.4.88\\"}" ], "stack": null } """), DeviceErrorResult::fromJson); // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) DeviceErrorResult deviceError = api.post("/restaurants/123/device-errors", Json.parse(""" { "id": "01a318f0-a0c0-7b57-8364-1e6fc225f5ce", "occurred_at": "2027-01-15T11:56:17+01:00", "level": "error", "code": "SOCK.timeout", "area": "SOCK", "event": "req.timeout", "message": "Pay bez odpovědi 20 s (b7e1)", "peer_key": "9bb5f040", "employee_name": "Jana", "app_version": "26.10.3", "refs": { "session": "s-3f9a", "tab": "o-7c21", "payment": "p-8f2c", "request": "b7e1", "broadcast": null }, "context": [ "{\\"t\\":\\"11:55:36.920\\",\\"seq\\":48200,\\"l\\":\\"I\\",\\"a\\":\\"UI\\",\\"e\\":\\"tap\\",\\"sess\\":\\"s-3f9a\\",\\"ord\\":\\"o-7c21\\",\\"intent\\":\\"PayCard\\",\\"sum\\":25000}", "{\\"t\\":\\"11:55:57.703\\",\\"seq\\":48204,\\"l\\":\\"I\\",\\"a\\":\\"PAY\\",\\"e\\":\\"terminal.ok\\",\\"pay\\":\\"p-8f2c\\",\\"auth\\":\\"1dc15286\\",\\"pan\\":\\"****4821\\",\\"ms\\":20742}", "{\\"t\\":\\"11:55:57.750\\",\\"seq\\":48206,\\"l\\":\\"I\\",\\"a\\":\\"SOCK\\",\\"e\\":\\"req.send\\",\\"ord\\":\\"o-7c21\\",\\"pay\\":\\"p-8f2c\\",\\"rid\\":\\"b7e1\\",\\"op\\":\\"Pay\\",\\"kb\\":1.9}", "{\\"t\\":\\"11:56:16.004\\",\\"seq\\":48208,\\"l\\":\\"I\\",\\"a\\":\\"ENV\\",\\"e\\":\\"net.change\\",\\"from\\":\\"wifi\\",\\"to\\":\\"lte\\",\\"ip\\":\\"10.21.4.88\\"}" ], "stack": null } """), DeviceErrorResult::fromJson); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val deviceError = api.post("/restaurants/123/device-errors", mapOf( "id" to "01a318f0-a0c0-7b57-8364-1e6fc225f5ce", "occurred_at" to "2027-01-15T11:56:17+01:00", "level" to "error", "code" to "SOCK.timeout", "area" to "SOCK", "event" to "req.timeout", "message" to "Pay bez odpovědi 20 s (b7e1)", "peer_key" to "9bb5f040", "employee_name" to "Jana", "app_version" to "26.10.3", "refs" to mapOf( "session" to "s-3f9a", "tab" to "o-7c21", "payment" to "p-8f2c", "request" to "b7e1", "broadcast" to null, ), "context" to listOf( "{\"t\":\"11:55:36.920\",\"seq\":48200,\"l\":\"I\",\"a\":\"UI\",\"e\":\"tap\",\"sess\":\"s-3f9a\",\"ord\":\"o-7c21\",\"intent\":\"PayCard\",\"sum\":25000}", "{\"t\":\"11:55:57.703\",\"seq\":48204,\"l\":\"I\",\"a\":\"PAY\",\"e\":\"terminal.ok\",\"pay\":\"p-8f2c\",\"auth\":\"1dc15286\",\"pan\":\"****4821\",\"ms\":20742}", "{\"t\":\"11:55:57.750\",\"seq\":48206,\"l\":\"I\",\"a\":\"SOCK\",\"e\":\"req.send\",\"ord\":\"o-7c21\",\"pay\":\"p-8f2c\",\"rid\":\"b7e1\",\"op\":\"Pay\",\"kb\":1.9}", "{\"t\":\"11:56:16.004\",\"seq\":48208,\"l\":\"I\",\"a\":\"ENV\",\"e\":\"net.change\",\"from\":\"wifi\",\"to\":\"lte\",\"ip\":\"10.21.4.88\"}", ), "stack" to null, ), DeviceErrorResult::fromJson) // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val deviceError = api.post("/restaurants/123/device-errors", mapOf( "id" to "01a318f0-a0c0-7b57-8364-1e6fc225f5ce", "occurred_at" to "2027-01-15T11:56:17+01:00", "level" to "error", "code" to "SOCK.timeout", "area" to "SOCK", "event" to "req.timeout", "message" to "Pay bez odpovědi 20 s (b7e1)", "peer_key" to "9bb5f040", "employee_name" to "Jana", "app_version" to "26.10.3", "refs" to mapOf( "session" to "s-3f9a", "tab" to "o-7c21", "payment" to "p-8f2c", "request" to "b7e1", "broadcast" to null, ), "context" to listOf( "{\"t\":\"11:55:36.920\",\"seq\":48200,\"l\":\"I\",\"a\":\"UI\",\"e\":\"tap\",\"sess\":\"s-3f9a\",\"ord\":\"o-7c21\",\"intent\":\"PayCard\",\"sum\":25000}", "{\"t\":\"11:55:57.703\",\"seq\":48204,\"l\":\"I\",\"a\":\"PAY\",\"e\":\"terminal.ok\",\"pay\":\"p-8f2c\",\"auth\":\"1dc15286\",\"pan\":\"****4821\",\"ms\":20742}", "{\"t\":\"11:55:57.750\",\"seq\":48206,\"l\":\"I\",\"a\":\"SOCK\",\"e\":\"req.send\",\"ord\":\"o-7c21\",\"pay\":\"p-8f2c\",\"rid\":\"b7e1\",\"op\":\"Pay\",\"kb\":1.9}", "{\"t\":\"11:56:16.004\",\"seq\":48208,\"l\":\"I\",\"a\":\"ENV\",\"e\":\"net.change\",\"from\":\"wifi\",\"to\":\"lte\",\"ip\":\"10.21.4.88\"}", ), "stack" to null, ), DeviceErrorResult::fromJson) // 201// klient: viz /v2/docs/csharp var deviceError = await api.PostAsync<DeviceErrorResult>("/restaurants/123/device-errors", new { id = "01a318f0-a0c0-7b57-8364-1e6fc225f5ce", occurred_at = "2027-01-15T11:56:17+01:00", level = "error", code = "SOCK.timeout", area = "SOCK", @event = "req.timeout", message = "Pay bez odpovědi 20 s (b7e1)", peer_key = "9bb5f040", employee_name = "Jana", app_version = "26.10.3", refs = new { session = "s-3f9a", tab = "o-7c21", payment = "p-8f2c", request = "b7e1", broadcast = (object?)null, }, context = new[] { "{\"t\":\"11:55:36.920\",\"seq\":48200,\"l\":\"I\",\"a\":\"UI\",\"e\":\"tap\",\"sess\":\"s-3f9a\",\"ord\":\"o-7c21\",\"intent\":\"PayCard\",\"sum\":25000}", "{\"t\":\"11:55:57.703\",\"seq\":48204,\"l\":\"I\",\"a\":\"PAY\",\"e\":\"terminal.ok\",\"pay\":\"p-8f2c\",\"auth\":\"1dc15286\",\"pan\":\"****4821\",\"ms\":20742}", "{\"t\":\"11:55:57.750\",\"seq\":48206,\"l\":\"I\",\"a\":\"SOCK\",\"e\":\"req.send\",\"ord\":\"o-7c21\",\"pay\":\"p-8f2c\",\"rid\":\"b7e1\",\"op\":\"Pay\",\"kb\":1.9}", "{\"t\":\"11:56:16.004\",\"seq\":48208,\"l\":\"I\",\"a\":\"ENV\",\"e\":\"net.change\",\"from\":\"wifi\",\"to\":\"lte\",\"ip\":\"10.21.4.88\"}", }, stack = (object?)null, }); // 201// the client: see /v2/docs/csharp var deviceError = await api.PostAsync<DeviceErrorResult>("/restaurants/123/device-errors", new { id = "01a318f0-a0c0-7b57-8364-1e6fc225f5ce", occurred_at = "2027-01-15T11:56:17+01:00", level = "error", code = "SOCK.timeout", area = "SOCK", @event = "req.timeout", message = "Pay bez odpovědi 20 s (b7e1)", peer_key = "9bb5f040", employee_name = "Jana", app_version = "26.10.3", refs = new { session = "s-3f9a", tab = "o-7c21", payment = "p-8f2c", request = "b7e1", broadcast = (object?)null, }, context = new[] { "{\"t\":\"11:55:36.920\",\"seq\":48200,\"l\":\"I\",\"a\":\"UI\",\"e\":\"tap\",\"sess\":\"s-3f9a\",\"ord\":\"o-7c21\",\"intent\":\"PayCard\",\"sum\":25000}", "{\"t\":\"11:55:57.703\",\"seq\":48204,\"l\":\"I\",\"a\":\"PAY\",\"e\":\"terminal.ok\",\"pay\":\"p-8f2c\",\"auth\":\"1dc15286\",\"pan\":\"****4821\",\"ms\":20742}", "{\"t\":\"11:55:57.750\",\"seq\":48206,\"l\":\"I\",\"a\":\"SOCK\",\"e\":\"req.send\",\"ord\":\"o-7c21\",\"pay\":\"p-8f2c\",\"rid\":\"b7e1\",\"op\":\"Pay\",\"kb\":1.9}", "{\"t\":\"11:56:16.004\",\"seq\":48208,\"l\":\"I\",\"a\":\"ENV\",\"e\":\"net.change\",\"from\":\"wifi\",\"to\":\"lte\",\"ip\":\"10.21.4.88\"}", }, stack = (object?)null, }); // 201# klient: viz /v2/docs/python device_error = api.post('/restaurants/123/device-errors', { 'id': '01a318f0-a0c0-7b57-8364-1e6fc225f5ce', 'occurred_at': '2027-01-15T11:56:17+01:00', 'level': 'error', 'code': 'SOCK.timeout', 'area': 'SOCK', 'event': 'req.timeout', 'message': 'Pay bez odpovědi 20 s (b7e1)', 'peer_key': '9bb5f040', 'employee_name': 'Jana', 'app_version': '26.10.3', 'refs': { 'session': 's-3f9a', 'tab': 'o-7c21', 'payment': 'p-8f2c', 'request': 'b7e1', 'broadcast': None, }, 'context': [ '{"t":"11:55:36.920","seq":48200,"l":"I","a":"UI","e":"tap","sess":"s-3f9a","ord":"o-7c21","intent":"PayCard","sum":25000}', '{"t":"11:55:57.703","seq":48204,"l":"I","a":"PAY","e":"terminal.ok","pay":"p-8f2c","auth":"1dc15286","pan":"****4821","ms":20742}', '{"t":"11:55:57.750","seq":48206,"l":"I","a":"SOCK","e":"req.send","ord":"o-7c21","pay":"p-8f2c","rid":"b7e1","op":"Pay","kb":1.9}', '{"t":"11:56:16.004","seq":48208,"l":"I","a":"ENV","e":"net.change","from":"wifi","to":"lte","ip":"10.21.4.88"}', ], 'stack': None, }) # 201# the client: see /v2/docs/python device_error = api.post('/restaurants/123/device-errors', { 'id': '01a318f0-a0c0-7b57-8364-1e6fc225f5ce', 'occurred_at': '2027-01-15T11:56:17+01:00', 'level': 'error', 'code': 'SOCK.timeout', 'area': 'SOCK', 'event': 'req.timeout', 'message': 'Pay bez odpovědi 20 s (b7e1)', 'peer_key': '9bb5f040', 'employee_name': 'Jana', 'app_version': '26.10.3', 'refs': { 'session': 's-3f9a', 'tab': 'o-7c21', 'payment': 'p-8f2c', 'request': 'b7e1', 'broadcast': None, }, 'context': [ '{"t":"11:55:36.920","seq":48200,"l":"I","a":"UI","e":"tap","sess":"s-3f9a","ord":"o-7c21","intent":"PayCard","sum":25000}', '{"t":"11:55:57.703","seq":48204,"l":"I","a":"PAY","e":"terminal.ok","pay":"p-8f2c","auth":"1dc15286","pan":"****4821","ms":20742}', '{"t":"11:55:57.750","seq":48206,"l":"I","a":"SOCK","e":"req.send","ord":"o-7c21","pay":"p-8f2c","rid":"b7e1","op":"Pay","kb":1.9}', '{"t":"11:56:16.004","seq":48208,"l":"I","a":"ENV","e":"net.change","from":"wifi","to":"lte","ip":"10.21.4.88"}', ], 'stack': None, }) # 201// klient: viz /v2/docs/swift let deviceError: DeviceErrorResult = try await api.post("/restaurants/123/device-errors", body: [ "id": "01a318f0-a0c0-7b57-8364-1e6fc225f5ce", "occurred_at": "2027-01-15T11:56:17+01:00", "level": "error", "code": "SOCK.timeout", "area": "SOCK", "event": "req.timeout", "message": "Pay bez odpovědi 20 s (b7e1)", "peer_key": "9bb5f040", "employee_name": "Jana", "app_version": "26.10.3", "refs": [ "session": "s-3f9a", "tab": "o-7c21", "payment": "p-8f2c", "request": "b7e1", "broadcast": nil, ], "context": [ "{\"t\":\"11:55:36.920\",\"seq\":48200,\"l\":\"I\",\"a\":\"UI\",\"e\":\"tap\",\"sess\":\"s-3f9a\",\"ord\":\"o-7c21\",\"intent\":\"PayCard\",\"sum\":25000}", "{\"t\":\"11:55:57.703\",\"seq\":48204,\"l\":\"I\",\"a\":\"PAY\",\"e\":\"terminal.ok\",\"pay\":\"p-8f2c\",\"auth\":\"1dc15286\",\"pan\":\"****4821\",\"ms\":20742}", "{\"t\":\"11:55:57.750\",\"seq\":48206,\"l\":\"I\",\"a\":\"SOCK\",\"e\":\"req.send\",\"ord\":\"o-7c21\",\"pay\":\"p-8f2c\",\"rid\":\"b7e1\",\"op\":\"Pay\",\"kb\":1.9}", "{\"t\":\"11:56:16.004\",\"seq\":48208,\"l\":\"I\",\"a\":\"ENV\",\"e\":\"net.change\",\"from\":\"wifi\",\"to\":\"lte\",\"ip\":\"10.21.4.88\"}", ], "stack": nil, ]) // 201// the client: see /v2/docs/swift let deviceError: DeviceErrorResult = try await api.post("/restaurants/123/device-errors", body: [ "id": "01a318f0-a0c0-7b57-8364-1e6fc225f5ce", "occurred_at": "2027-01-15T11:56:17+01:00", "level": "error", "code": "SOCK.timeout", "area": "SOCK", "event": "req.timeout", "message": "Pay bez odpovědi 20 s (b7e1)", "peer_key": "9bb5f040", "employee_name": "Jana", "app_version": "26.10.3", "refs": [ "session": "s-3f9a", "tab": "o-7c21", "payment": "p-8f2c", "request": "b7e1", "broadcast": nil, ], "context": [ "{\"t\":\"11:55:36.920\",\"seq\":48200,\"l\":\"I\",\"a\":\"UI\",\"e\":\"tap\",\"sess\":\"s-3f9a\",\"ord\":\"o-7c21\",\"intent\":\"PayCard\",\"sum\":25000}", "{\"t\":\"11:55:57.703\",\"seq\":48204,\"l\":\"I\",\"a\":\"PAY\",\"e\":\"terminal.ok\",\"pay\":\"p-8f2c\",\"auth\":\"1dc15286\",\"pan\":\"****4821\",\"ms\":20742}", "{\"t\":\"11:55:57.750\",\"seq\":48206,\"l\":\"I\",\"a\":\"SOCK\",\"e\":\"req.send\",\"ord\":\"o-7c21\",\"pay\":\"p-8f2c\",\"rid\":\"b7e1\",\"op\":\"Pay\",\"kb\":1.9}", "{\"t\":\"11:56:16.004\",\"seq\":48208,\"l\":\"I\",\"a\":\"ENV\",\"e\":\"net.change\",\"from\":\"wifi\",\"to\":\"lte\",\"ip\":\"10.21.4.88\"}", ], "stack": nil, ]) // 201// klient: viz /v2/docs/dart final deviceError = pr.DeviceErrorResult.fromJson(await api.post('/restaurants/123/device-errors', { 'id': '01a318f0-a0c0-7b57-8364-1e6fc225f5ce', 'occurred_at': '2027-01-15T11:56:17+01:00', 'level': 'error', 'code': 'SOCK.timeout', 'area': 'SOCK', 'event': 'req.timeout', 'message': 'Pay bez odpovědi 20 s (b7e1)', 'peer_key': '9bb5f040', 'employee_name': 'Jana', 'app_version': '26.10.3', 'refs': { 'session': 's-3f9a', 'tab': 'o-7c21', 'payment': 'p-8f2c', 'request': 'b7e1', 'broadcast': null, }, 'context': [ '{"t":"11:55:36.920","seq":48200,"l":"I","a":"UI","e":"tap","sess":"s-3f9a","ord":"o-7c21","intent":"PayCard","sum":25000}', '{"t":"11:55:57.703","seq":48204,"l":"I","a":"PAY","e":"terminal.ok","pay":"p-8f2c","auth":"1dc15286","pan":"****4821","ms":20742}', '{"t":"11:55:57.750","seq":48206,"l":"I","a":"SOCK","e":"req.send","ord":"o-7c21","pay":"p-8f2c","rid":"b7e1","op":"Pay","kb":1.9}', '{"t":"11:56:16.004","seq":48208,"l":"I","a":"ENV","e":"net.change","from":"wifi","to":"lte","ip":"10.21.4.88"}', ], 'stack': null, })); // 201// the client: see /v2/docs/dart final deviceError = pr.DeviceErrorResult.fromJson(await api.post('/restaurants/123/device-errors', { 'id': '01a318f0-a0c0-7b57-8364-1e6fc225f5ce', 'occurred_at': '2027-01-15T11:56:17+01:00', 'level': 'error', 'code': 'SOCK.timeout', 'area': 'SOCK', 'event': 'req.timeout', 'message': 'Pay bez odpovědi 20 s (b7e1)', 'peer_key': '9bb5f040', 'employee_name': 'Jana', 'app_version': '26.10.3', 'refs': { 'session': 's-3f9a', 'tab': 'o-7c21', 'payment': 'p-8f2c', 'request': 'b7e1', 'broadcast': null, }, 'context': [ '{"t":"11:55:36.920","seq":48200,"l":"I","a":"UI","e":"tap","sess":"s-3f9a","ord":"o-7c21","intent":"PayCard","sum":25000}', '{"t":"11:55:57.703","seq":48204,"l":"I","a":"PAY","e":"terminal.ok","pay":"p-8f2c","auth":"1dc15286","pan":"****4821","ms":20742}', '{"t":"11:55:57.750","seq":48206,"l":"I","a":"SOCK","e":"req.send","ord":"o-7c21","pay":"p-8f2c","rid":"b7e1","op":"Pay","kb":1.9}', '{"t":"11:56:16.004","seq":48208,"l":"I","a":"ENV","e":"net.change","from":"wifi","to":"lte","ip":"10.21.4.88"}', ], 'stack': null, })); // 201// klient: viz /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/device-errors", map[string]any{ "id": "01a318f0-a0c0-7b57-8364-1e6fc225f5ce", "occurred_at": "2027-01-15T11:56:17+01:00", "level": "error", "code": "SOCK.timeout", "area": "SOCK", "event": "req.timeout", "message": "Pay bez odpovědi 20 s (b7e1)", "peer_key": "9bb5f040", "employee_name": "Jana", "app_version": "26.10.3", "refs": map[string]any{ "session": "s-3f9a", "tab": "o-7c21", "payment": "p-8f2c", "request": "b7e1", "broadcast": nil, }, "context": []any{ "{\"t\":\"11:55:36.920\",\"seq\":48200,\"l\":\"I\",\"a\":\"UI\",\"e\":\"tap\",\"sess\":\"s-3f9a\",\"ord\":\"o-7c21\",\"intent\":\"PayCard\",\"sum\":25000}", "{\"t\":\"11:55:57.703\",\"seq\":48204,\"l\":\"I\",\"a\":\"PAY\",\"e\":\"terminal.ok\",\"pay\":\"p-8f2c\",\"auth\":\"1dc15286\",\"pan\":\"****4821\",\"ms\":20742}", "{\"t\":\"11:55:57.750\",\"seq\":48206,\"l\":\"I\",\"a\":\"SOCK\",\"e\":\"req.send\",\"ord\":\"o-7c21\",\"pay\":\"p-8f2c\",\"rid\":\"b7e1\",\"op\":\"Pay\",\"kb\":1.9}", "{\"t\":\"11:56:16.004\",\"seq\":48208,\"l\":\"I\",\"a\":\"ENV\",\"e\":\"net.change\",\"from\":\"wifi\",\"to\":\"lte\",\"ip\":\"10.21.4.88\"}", }, "stack": nil, }, nil) var deviceError model.DeviceErrorResult // 201 if err == nil { err = res.Decode(&deviceError) }// the client: see /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/device-errors", map[string]any{ "id": "01a318f0-a0c0-7b57-8364-1e6fc225f5ce", "occurred_at": "2027-01-15T11:56:17+01:00", "level": "error", "code": "SOCK.timeout", "area": "SOCK", "event": "req.timeout", "message": "Pay bez odpovědi 20 s (b7e1)", "peer_key": "9bb5f040", "employee_name": "Jana", "app_version": "26.10.3", "refs": map[string]any{ "session": "s-3f9a", "tab": "o-7c21", "payment": "p-8f2c", "request": "b7e1", "broadcast": nil, }, "context": []any{ "{\"t\":\"11:55:36.920\",\"seq\":48200,\"l\":\"I\",\"a\":\"UI\",\"e\":\"tap\",\"sess\":\"s-3f9a\",\"ord\":\"o-7c21\",\"intent\":\"PayCard\",\"sum\":25000}", "{\"t\":\"11:55:57.703\",\"seq\":48204,\"l\":\"I\",\"a\":\"PAY\",\"e\":\"terminal.ok\",\"pay\":\"p-8f2c\",\"auth\":\"1dc15286\",\"pan\":\"****4821\",\"ms\":20742}", "{\"t\":\"11:55:57.750\",\"seq\":48206,\"l\":\"I\",\"a\":\"SOCK\",\"e\":\"req.send\",\"ord\":\"o-7c21\",\"pay\":\"p-8f2c\",\"rid\":\"b7e1\",\"op\":\"Pay\",\"kb\":1.9}", "{\"t\":\"11:56:16.004\",\"seq\":48208,\"l\":\"I\",\"a\":\"ENV\",\"e\":\"net.change\",\"from\":\"wifi\",\"to\":\"lte\",\"ip\":\"10.21.4.88\"}", }, "stack": nil, }, nil) var deviceError model.DeviceErrorResult // 201 if err == nil { err = res.Decode(&deviceError) }Příklad odpovědi 200Example answer 200
{ "id": "90115", "received_at": "2027-01-15T11:56:18+01:00" } -
Na příkaz upload_logs nahrajte log po částech
On upload_logs upload the log in parts
PUT /log-uploads/{upload_id}/parts/{part} · putLogUploadPart
Pro každý cíl z příkazu: gzip NDJSON za období
from–to, části do 4 MB, každá část úplný proud gzip (server je jen zřetězí). Token cíle (pfl_…) jeAuthorization– telefon číšníka nepotřebuje vlastní token, cíl mu předá kasa po místní síti. Nahrávejte mimo frontu objednávek a během placení pozastavte.For every target of the command: gzip NDJSON for the period
from–to, parts up to 4 MB, each part a complete gzip stream (the server just concatenates them). The token of the target (pfl_…) is theAuthorization– a waiter's phone needs no token of its own, the register hands the target over on the local network. Upload outside the queue of orders and pause while the staff pays.curl -X PUT "https://api.mujprofirest.cz/v2/log-uploads/7742/parts/3" \ -H "Authorization: Bearer $UPLOAD_TOKEN" \ -H "Content-Type: application/gzip" \ --data-binary @log-cast-3.gzcurl -X PUT "https://api.mujprofirest.cz/v2/log-uploads/7742/parts/3" \ -H "Authorization: Bearer $UPLOAD_TOKEN" \ -H "Content-Type: application/gzip" \ --data-binary @log-cast-3.gz// klient: viz /v2/docs/js // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování const logUploadPart = await api.put('/log-uploads/7742/parts/3', partBlob, { contentType: 'application/gzip', auth: false, headers: { Authorization: 'Bearer ' + uploadToken }, }); // 200// the client: see /v2/docs/js // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too const logUploadPart = await api.put('/log-uploads/7742/parts/3', partBlob, { contentType: 'application/gzip', auth: false, headers: { Authorization: 'Bearer ' + uploadToken }, }); // 200// klient: viz /v2/docs/typescript // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování const logUploadPart = await api.put('/log-uploads/7742/parts/3', partBlob, { contentType: 'application/gzip', auth: false, headers: { Authorization: 'Bearer ' + uploadToken }, }); // 200 LogUploadStatus// the client: see /v2/docs/typescript // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too const logUploadPart = await api.put('/log-uploads/7742/parts/3', partBlob, { contentType: 'application/gzip', auth: false, headers: { Authorization: 'Bearer ' + uploadToken }, }); // 200 LogUploadStatus// klient: viz /v2/docs/php // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování $upload = $api->put('/log-uploads/7742/parts/3', file_get_contents('log-cast-3.gz'), ['contentType' => 'application/gzip', 'auth' => false, 'headers' => ['Authorization' => 'Bearer ' . $uploadToken]]);// the client: see /v2/docs/php // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too $upload = $api->put('/log-uploads/7742/parts/3', file_get_contents('log-cast-3.gz'), ['contentType' => 'application/gzip', 'auth' => false, 'headers' => ['Authorization' => 'Bearer ' . $uploadToken]]);// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování Object upload = api.put("/log-uploads/7742/parts/3", Files.readAllBytes(Path.of("log-cast-3.gz")), RequestOptions.builder().contentType("application/gzip").auth(false).header("Authorization", "Bearer " + uploadToken).build());// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too Object upload = api.put("/log-uploads/7742/parts/3", Files.readAllBytes(Path.of("log-cast-3.gz")), RequestOptions.builder().contentType("application/gzip").auth(false).header("Authorization", "Bearer " + uploadToken).build());// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování val upload = api.put("/log-uploads/7742/parts/3", File("log-cast-3.gz").readBytes(), RequestOptions.builder().contentType("application/gzip").auth(false).header("Authorization", "Bearer " + uploadToken).build())// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too val upload = api.put("/log-uploads/7742/parts/3", File("log-cast-3.gz").readBytes(), RequestOptions.builder().contentType("application/gzip").auth(false).header("Authorization", "Bearer " + uploadToken).build())// klient: viz /v2/docs/csharp // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování await using var part = File.OpenRead("log-cast-3.gz"); var upload = await api.PutAsync("/log-uploads/7742/parts/3", part, new RequestOptions { ContentType = "application/gzip", Auth = false, Headers = new() { ["Authorization"] = "Bearer " + uploadToken } });// the client: see /v2/docs/csharp // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too await using var part = File.OpenRead("log-cast-3.gz"); var upload = await api.PutAsync("/log-uploads/7742/parts/3", part, new RequestOptions { ContentType = "application/gzip", Auth = false, Headers = new() { ["Authorization"] = "Bearer " + uploadToken } });# klient: viz /v2/docs/python # token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování with open('log-cast-3.gz', 'rb') as fh: upload = api.put('/log-uploads/7742/parts/3', fh, content_type='application/gzip', auth=False, headers={'Authorization': 'Bearer ' + upload_token})# the client: see /v2/docs/python # the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too with open('log-cast-3.gz', 'rb') as fh: upload = api.put('/log-uploads/7742/parts/3', fh, content_type='application/gzip', auth=False, headers={'Authorization': 'Bearer ' + upload_token})// klient: viz /v2/docs/swift // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování let upload = try await api.put("/log-uploads/7742/parts/3", body: .data(try Data(contentsOf: partURL), contentType: "application/gzip"), options: .init(headers: ["Authorization": "Bearer \(uploadToken)"], auth: false))// the client: see /v2/docs/swift // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too let upload = try await api.put("/log-uploads/7742/parts/3", body: .data(try Data(contentsOf: partURL), contentType: "application/gzip"), options: .init(headers: ["Authorization": "Bearer \(uploadToken)"], auth: false))// klient: viz /v2/docs/dart // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování final upload = await api.put('/log-uploads/7742/parts/3', await File('log-cast-3.gz').readAsBytes(), contentType: 'application/gzip', auth: false, headers: {'Authorization': 'Bearer $uploadToken'});// the client: see /v2/docs/dart // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too final upload = await api.put('/log-uploads/7742/parts/3', await File('log-cast-3.gz').readAsBytes(), contentType: 'application/gzip', auth: false, headers: {'Authorization': 'Bearer $uploadToken'});// klient: viz /v2/docs/go // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování part, err := os.ReadFile("log-cast-3.gz") res, err := api.Put(ctx, "/log-uploads/7742/parts/3", part, &profirest.RequestOptions{ContentType: "application/gzip", NoAuth: true, Header: http.Header{"Authorization": {"Bearer " + uploadToken}}})// the client: see /v2/docs/go // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too part, err := os.ReadFile("log-cast-3.gz") res, err := api.Put(ctx, "/log-uploads/7742/parts/3", part, &profirest.RequestOptions{ContentType: "application/gzip", NoAuth: true, Header: http.Header{"Authorization": {"Bearer " + uploadToken}}})Příklad odpovědi 200Example answer 200
{ "id": "7742", "request_id": "3105", "status": "uploading", "parts_received": [ 1, 2, 3 ], "parts_expected": null, "bytes": 4718592, "from": "2027-01-14T12:00:00+01:00", "to": "2027-01-15T12:00:00+01:00", "detail": "full", "max_part_bytes": 4194304, "expires_at": "2027-01-16T12:00:35+01:00" } -
Dokončete nahrávání
Finish the upload
POST /log-uploads/{upload_id}/complete · completeLogUpload
partsříká, kolik částí jste poslali; chybějící vrátí422 upload_incompletes čísly vdetail. Po přerušení se zeptejtegetLogUpload, které části server má, a pošlete jen zbytek.partssays how many parts you sent; missing ones answer422 upload_incompletewith the numbers indetail. After an interruption askgetLogUploadwhich parts the server has and send only the rest.curl "https://api.mujprofirest.cz/v2/log-uploads/7742/complete" \ -H "Authorization: Bearer $UPLOAD_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "parts": 3, "lines": 184210, "from": "2027-01-14T12:00:00+01:00", "to": "2027-01-15T11:59:58+01:00", "sha256": null }'curl "https://api.mujprofirest.cz/v2/log-uploads/7742/complete" \ -H "Authorization: Bearer $UPLOAD_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "parts": 3, "lines": 184210, "from": "2027-01-14T12:00:00+01:00", "to": "2027-01-15T11:59:58+01:00", "sha256": null }'// klient: viz /v2/docs/js // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování const logUpload = await api.post('/log-uploads/7742/complete', { parts: 3, lines: 184210, from: '2027-01-14T12:00:00+01:00', to: '2027-01-15T11:59:58+01:00', sha256: null, }, { auth: false, headers: { Authorization: 'Bearer ' + uploadToken } }); // 200// the client: see /v2/docs/js // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too const logUpload = await api.post('/log-uploads/7742/complete', { parts: 3, lines: 184210, from: '2027-01-14T12:00:00+01:00', to: '2027-01-15T11:59:58+01:00', sha256: null, }, { auth: false, headers: { Authorization: 'Bearer ' + uploadToken } }); // 200// klient: viz /v2/docs/typescript // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování const logUpload = await api.post('/log-uploads/7742/complete', { parts: 3, lines: 184210, from: '2027-01-14T12:00:00+01:00', to: '2027-01-15T11:59:58+01:00', sha256: null, }, { auth: false, headers: { Authorization: 'Bearer ' + uploadToken } }); // 200 LogUploadStatus// the client: see /v2/docs/typescript // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too const logUpload = await api.post('/log-uploads/7742/complete', { parts: 3, lines: 184210, from: '2027-01-14T12:00:00+01:00', to: '2027-01-15T11:59:58+01:00', sha256: null, }, { auth: false, headers: { Authorization: 'Bearer ' + uploadToken } }); // 200 LogUploadStatus// klient: viz /v2/docs/php // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování $logUpload = $api->post('/log-uploads/7742/complete', [ 'parts' => 3, 'lines' => 184210, 'from' => '2027-01-14T12:00:00+01:00', 'to' => '2027-01-15T11:59:58+01:00', 'sha256' => null, ], ['auth' => false, 'headers' => ['Authorization' => 'Bearer ' . $uploadToken]]); // 200// the client: see /v2/docs/php // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too $logUpload = $api->post('/log-uploads/7742/complete', [ 'parts' => 3, 'lines' => 184210, 'from' => '2027-01-14T12:00:00+01:00', 'to' => '2027-01-15T11:59:58+01:00', 'sha256' => null, ], ['auth' => false, 'headers' => ['Authorization' => 'Bearer ' . $uploadToken]]); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování LogUploadStatus logUpload = api.post("/log-uploads/7742/complete", Json.parse(""" { "parts": 3, "lines": 184210, "from": "2027-01-14T12:00:00+01:00", "to": "2027-01-15T11:59:58+01:00", "sha256": null } """), RequestOptions.builder().auth(false).header("Authorization", "Bearer " + uploadToken).build(), LogUploadStatus::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too LogUploadStatus logUpload = api.post("/log-uploads/7742/complete", Json.parse(""" { "parts": 3, "lines": 184210, "from": "2027-01-14T12:00:00+01:00", "to": "2027-01-15T11:59:58+01:00", "sha256": null } """), RequestOptions.builder().auth(false).header("Authorization", "Bearer " + uploadToken).build(), LogUploadStatus::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování val logUpload = api.post("/log-uploads/7742/complete", mapOf( "parts" to 3, "lines" to 184210, "from" to "2027-01-14T12:00:00+01:00", "to" to "2027-01-15T11:59:58+01:00", "sha256" to null, ), RequestOptions.builder().auth(false).header("Authorization", "Bearer " + uploadToken).build(), LogUploadStatus::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too val logUpload = api.post("/log-uploads/7742/complete", mapOf( "parts" to 3, "lines" to 184210, "from" to "2027-01-14T12:00:00+01:00", "to" to "2027-01-15T11:59:58+01:00", "sha256" to null, ), RequestOptions.builder().auth(false).header("Authorization", "Bearer " + uploadToken).build(), LogUploadStatus::fromJson) // 200// klient: viz /v2/docs/csharp // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování var logUpload = await api.PostAsync<LogUploadStatus>("/log-uploads/7742/complete", new { parts = 3, lines = 184210, from = "2027-01-14T12:00:00+01:00", to = "2027-01-15T11:59:58+01:00", sha256 = (object?)null, }, new RequestOptions { Auth = false, Headers = new() { ["Authorization"] = "Bearer " + uploadToken } }); // 200// the client: see /v2/docs/csharp // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too var logUpload = await api.PostAsync<LogUploadStatus>("/log-uploads/7742/complete", new { parts = 3, lines = 184210, from = "2027-01-14T12:00:00+01:00", to = "2027-01-15T11:59:58+01:00", sha256 = (object?)null, }, new RequestOptions { Auth = false, Headers = new() { ["Authorization"] = "Bearer " + uploadToken } }); // 200# klient: viz /v2/docs/python # token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování log_upload = api.post('/log-uploads/7742/complete', { 'parts': 3, 'lines': 184210, 'from': '2027-01-14T12:00:00+01:00', 'to': '2027-01-15T11:59:58+01:00', 'sha256': None, }, auth=False, headers={'Authorization': 'Bearer ' + upload_token}) # 200# the client: see /v2/docs/python # the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too log_upload = api.post('/log-uploads/7742/complete', { 'parts': 3, 'lines': 184210, 'from': '2027-01-14T12:00:00+01:00', 'to': '2027-01-15T11:59:58+01:00', 'sha256': None, }, auth=False, headers={'Authorization': 'Bearer ' + upload_token}) # 200// klient: viz /v2/docs/swift // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování let logUpload: LogUploadStatus = try await api.post("/log-uploads/7742/complete", body: [ "parts": 3, "lines": 184210, "from": "2027-01-14T12:00:00+01:00", "to": "2027-01-15T11:59:58+01:00", "sha256": nil, ], options: .init(headers: ["Authorization": "Bearer \(uploadToken)"], auth: false)) // 200// the client: see /v2/docs/swift // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too let logUpload: LogUploadStatus = try await api.post("/log-uploads/7742/complete", body: [ "parts": 3, "lines": 184210, "from": "2027-01-14T12:00:00+01:00", "to": "2027-01-15T11:59:58+01:00", "sha256": nil, ], options: .init(headers: ["Authorization": "Bearer \(uploadToken)"], auth: false)) // 200// klient: viz /v2/docs/dart // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování final logUpload = pr.LogUploadStatus.fromJson(await api.post('/log-uploads/7742/complete', { 'parts': 3, 'lines': 184210, 'from': '2027-01-14T12:00:00+01:00', 'to': '2027-01-15T11:59:58+01:00', 'sha256': null, }, auth: false, headers: {'Authorization': 'Bearer $uploadToken'})); // 200// the client: see /v2/docs/dart // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too final logUpload = pr.LogUploadStatus.fromJson(await api.post('/log-uploads/7742/complete', { 'parts': 3, 'lines': 184210, 'from': '2027-01-14T12:00:00+01:00', 'to': '2027-01-15T11:59:58+01:00', 'sha256': null, }, auth: false, headers: {'Authorization': 'Bearer $uploadToken'})); // 200// klient: viz /v2/docs/go // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování res, err := api.Post(ctx, "/log-uploads/7742/complete", map[string]any{ "parts": 3, "lines": 184210, "from": "2027-01-14T12:00:00+01:00", "to": "2027-01-15T11:59:58+01:00", "sha256": nil, }, &profirest.RequestOptions{NoAuth: true, Header: http.Header{"Authorization": {"Bearer " + uploadToken}}}) var logUpload model.LogUploadStatus // 200 if err == nil { err = res.Decode(&logUpload) }// the client: see /v2/docs/go // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too res, err := api.Post(ctx, "/log-uploads/7742/complete", map[string]any{ "parts": 3, "lines": 184210, "from": "2027-01-14T12:00:00+01:00", "to": "2027-01-15T11:59:58+01:00", "sha256": nil, }, &profirest.RequestOptions{NoAuth: true, Header: http.Header{"Authorization": {"Bearer " + uploadToken}}}) var logUpload model.LogUploadStatus // 200 if err == nil { err = res.Decode(&logUpload) }Příklad odpovědi 200Example answer 200
{ "id": "7742", "request_id": "3105", "status": "done", "parts_received": [ 1, 2, 3 ], "parts_expected": 3, "bytes": 4718592, "from": "2027-01-14T12:00:00+01:00", "to": "2027-01-15T12:00:00+01:00", "detail": "full", "max_part_bytes": 4194304, "expires_at": "2027-01-16T12:00:35+01:00" } -
Co nejde, vzdejte
Give up what cannot be served
POST /log-uploads/{upload_id}/abort · abortLogUpload
no_data(úložiště nesahá tak daleko),unsupported(stará verze),failedsmessage. Podpora vidí důvod u žádosti.no_data(the log store does not reach that far),unsupported(an old version),failedwith amessage. Support sees the reason at the request.curl "https://api.mujprofirest.cz/v2/log-uploads/7743/abort" \ -H "Authorization: Bearer $UPLOAD_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "reason": "no_data", "message": "Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00." }'curl "https://api.mujprofirest.cz/v2/log-uploads/7743/abort" \ -H "Authorization: Bearer $UPLOAD_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "reason": "no_data", "message": "Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00." }'// klient: viz /v2/docs/js // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování const abortLogUpload = await api.post('/log-uploads/7743/abort', { reason: 'no_data', message: 'Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00.', }, { auth: false, headers: { Authorization: 'Bearer ' + uploadToken } }); // 200// the client: see /v2/docs/js // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too const abortLogUpload = await api.post('/log-uploads/7743/abort', { reason: 'no_data', message: 'Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00.', }, { auth: false, headers: { Authorization: 'Bearer ' + uploadToken } }); // 200// klient: viz /v2/docs/typescript // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování const abortLogUpload = await api.post('/log-uploads/7743/abort', { reason: 'no_data', message: 'Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00.', }, { auth: false, headers: { Authorization: 'Bearer ' + uploadToken } }); // 200 LogUploadStatus// the client: see /v2/docs/typescript // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too const abortLogUpload = await api.post('/log-uploads/7743/abort', { reason: 'no_data', message: 'Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00.', }, { auth: false, headers: { Authorization: 'Bearer ' + uploadToken } }); // 200 LogUploadStatus// klient: viz /v2/docs/php // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování $abortLogUpload = $api->post('/log-uploads/7743/abort', [ 'reason' => 'no_data', 'message' => 'Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00.', ], ['auth' => false, 'headers' => ['Authorization' => 'Bearer ' . $uploadToken]]); // 200// the client: see /v2/docs/php // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too $abortLogUpload = $api->post('/log-uploads/7743/abort', [ 'reason' => 'no_data', 'message' => 'Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00.', ], ['auth' => false, 'headers' => ['Authorization' => 'Bearer ' . $uploadToken]]); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování LogUploadStatus abortLogUpload = api.post("/log-uploads/7743/abort", Json.parse(""" { "reason": "no_data", "message": "Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00." } """), RequestOptions.builder().auth(false).header("Authorization", "Bearer " + uploadToken).build(), LogUploadStatus::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too LogUploadStatus abortLogUpload = api.post("/log-uploads/7743/abort", Json.parse(""" { "reason": "no_data", "message": "Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00." } """), RequestOptions.builder().auth(false).header("Authorization", "Bearer " + uploadToken).build(), LogUploadStatus::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování val abortLogUpload = api.post("/log-uploads/7743/abort", mapOf( "reason" to "no_data", "message" to "Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00.", ), RequestOptions.builder().auth(false).header("Authorization", "Bearer " + uploadToken).build(), LogUploadStatus::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too val abortLogUpload = api.post("/log-uploads/7743/abort", mapOf( "reason" to "no_data", "message" to "Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00.", ), RequestOptions.builder().auth(false).header("Authorization", "Bearer " + uploadToken).build(), LogUploadStatus::fromJson) // 200// klient: viz /v2/docs/csharp // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování var abortLogUpload = await api.PostAsync<LogUploadStatus>("/log-uploads/7743/abort", new { reason = "no_data", message = "Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00.", }, new RequestOptions { Auth = false, Headers = new() { ["Authorization"] = "Bearer " + uploadToken } }); // 200// the client: see /v2/docs/csharp // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too var abortLogUpload = await api.PostAsync<LogUploadStatus>("/log-uploads/7743/abort", new { reason = "no_data", message = "Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00.", }, new RequestOptions { Auth = false, Headers = new() { ["Authorization"] = "Bearer " + uploadToken } }); // 200# klient: viz /v2/docs/python # token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování abort_log_upload = api.post('/log-uploads/7743/abort', { 'reason': 'no_data', 'message': 'Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00.', }, auth=False, headers={'Authorization': 'Bearer ' + upload_token}) # 200# the client: see /v2/docs/python # the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too abort_log_upload = api.post('/log-uploads/7743/abort', { 'reason': 'no_data', 'message': 'Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00.', }, auth=False, headers={'Authorization': 'Bearer ' + upload_token}) # 200// klient: viz /v2/docs/swift // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování let abortLogUpload: LogUploadStatus = try await api.post("/log-uploads/7743/abort", body: [ "reason": "no_data", "message": "Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00.", ], options: .init(headers: ["Authorization": "Bearer \(uploadToken)"], auth: false)) // 200// the client: see /v2/docs/swift // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too let abortLogUpload: LogUploadStatus = try await api.post("/log-uploads/7743/abort", body: [ "reason": "no_data", "message": "Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00.", ], options: .init(headers: ["Authorization": "Bearer \(uploadToken)"], auth: false)) // 200// klient: viz /v2/docs/dart // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování final abortLogUpload = pr.LogUploadStatus.fromJson(await api.post('/log-uploads/7743/abort', { 'reason': 'no_data', 'message': 'Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00.', }, auth: false, headers: {'Authorization': 'Bearer $uploadToken'})); // 200// the client: see /v2/docs/dart // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too final abortLogUpload = pr.LogUploadStatus.fromJson(await api.post('/log-uploads/7743/abort', { 'reason': 'no_data', 'message': 'Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00.', }, auth: false, headers: {'Authorization': 'Bearer $uploadToken'})); // 200// klient: viz /v2/docs/go // token cíle pfl_ z příkazu upload_logs (LogUploadTarget.token) místo tokenu zařízení – jde i bez párování res, err := api.Post(ctx, "/log-uploads/7743/abort", map[string]any{ "reason": "no_data", "message": "Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00.", }, &profirest.RequestOptions{NoAuth: true, Header: http.Header{"Authorization": {"Bearer " + uploadToken}}}) var abortLogUpload model.LogUploadStatus // 200 if err == nil { err = res.Decode(&abortLogUpload) }// the client: see /v2/docs/go // the target's pfl_ token from the upload_logs command (LogUploadTarget.token) instead of the device's token – works unpaired too res, err := api.Post(ctx, "/log-uploads/7743/abort", map[string]any{ "reason": "no_data", "message": "Úložiště začíná 15. 1. 06:10, žádaný začátek je 14. 1. 12:00.", }, &profirest.RequestOptions{NoAuth: true, Header: http.Header{"Authorization": {"Bearer " + uploadToken}}}) var abortLogUpload model.LogUploadStatus // 200 if err == nil { err = res.Decode(&abortLogUpload) }Příklad odpovědi 200Example answer 200
{ "id": "7743", "request_id": "3105", "status": "no_data", "parts_received": [], "parts_expected": null, "bytes": 0, "from": "2027-01-14T12:00:00+01:00", "to": "2027-01-15T12:00:00+01:00", "detail": "full", "max_part_bytes": 4194304, "expires_at": "2027-01-16T12:00:35+01:00" }
Scénář
Scenario
Zákazníci, body a vouchery
Customers, points and vouchers
Partner s oprávněním customers:writeA partner with customers:writeZákazník se pozná podle ověřeného telefonu – bez hesel. Body a vouchery pak platí v e-shopu i na pokladně.
A customer is known by a verified phone number – no passwords. Points and vouchers then work in the e-shop and at the register alike.
-
Nový zákazník
A new customer
POST /customers · createCustomer
Patří celému účtu, ne jedné provozovně. Stejný telefon podruhé vrátí
409sexisting_id.Belongs to the whole account, not to one restaurant. The same phone again returns
409withexisting_id.curl "https://api.mujprofirest.cz/v2/customers" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7881-8c62-365d5eae28e4" \ -H "Content-Type: application/json" \ -d '{ "phone": "+420777123456", "name": "Jana Nováková", "email": "jana.novakova@example.cz", "external_id": "zakaznik-881", "metadata": {"newsletter": "ano"} }'curl "https://api.mujprofirest.cz/v2/customers" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7881-8c62-365d5eae28e4" \ -H "Content-Type: application/json" \ -d '{ "phone": "+420777123456", "name": "Jana Nováková", "email": "jana.novakova@example.cz", "external_id": "zakaznik-881", "metadata": {"newsletter": "ano"} }'// klient: viz /v2/docs/js const customer = await api.post('/customers', { phone: '+420777123456', name: 'Jana Nováková', email: 'jana.novakova@example.cz', external_id: 'zakaznik-881', metadata: { newsletter: 'ano' }, }); // 201// the client: see /v2/docs/js const customer = await api.post('/customers', { phone: '+420777123456', name: 'Jana Nováková', email: 'jana.novakova@example.cz', external_id: 'zakaznik-881', metadata: { newsletter: 'ano' }, }); // 201// klient: viz /v2/docs/typescript const customer = await api.post('/customers', { phone: '+420777123456', name: 'Jana Nováková', email: 'jana.novakova@example.cz', external_id: 'zakaznik-881', metadata: { newsletter: 'ano' }, }); // 201 Customer// the client: see /v2/docs/typescript const customer = await api.post('/customers', { phone: '+420777123456', name: 'Jana Nováková', email: 'jana.novakova@example.cz', external_id: 'zakaznik-881', metadata: { newsletter: 'ano' }, }); // 201 Customer// klient: viz /v2/docs/php $customer = $api->post('/customers', [ 'phone' => '+420777123456', 'name' => 'Jana Nováková', 'email' => 'jana.novakova@example.cz', 'external_id' => 'zakaznik-881', 'metadata' => ['newsletter' => 'ano'], ]); // 201// the client: see /v2/docs/php $customer = $api->post('/customers', [ 'phone' => '+420777123456', 'name' => 'Jana Nováková', 'email' => 'jana.novakova@example.cz', 'external_id' => 'zakaznik-881', 'metadata' => ['newsletter' => 'ano'], ]); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) Customer customer = api.post("/customers", Json.parse(""" { "phone": "+420777123456", "name": "Jana Nováková", "email": "jana.novakova@example.cz", "external_id": "zakaznik-881", "metadata": {"newsletter": "ano"} } """), Customer::fromJson); // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) Customer customer = api.post("/customers", Json.parse(""" { "phone": "+420777123456", "name": "Jana Nováková", "email": "jana.novakova@example.cz", "external_id": "zakaznik-881", "metadata": {"newsletter": "ano"} } """), Customer::fromJson); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val customer = api.post("/customers", mapOf( "phone" to "+420777123456", "name" to "Jana Nováková", "email" to "jana.novakova@example.cz", "external_id" to "zakaznik-881", "metadata" to mapOf("newsletter" to "ano"), ), Customer::fromJson) // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val customer = api.post("/customers", mapOf( "phone" to "+420777123456", "name" to "Jana Nováková", "email" to "jana.novakova@example.cz", "external_id" to "zakaznik-881", "metadata" to mapOf("newsletter" to "ano"), ), Customer::fromJson) // 201// klient: viz /v2/docs/csharp var customer = await api.PostAsync<Customer>("/customers", new { phone = "+420777123456", name = "Jana Nováková", email = "jana.novakova@example.cz", external_id = "zakaznik-881", metadata = new { newsletter = "ano" }, }); // 201// the client: see /v2/docs/csharp var customer = await api.PostAsync<Customer>("/customers", new { phone = "+420777123456", name = "Jana Nováková", email = "jana.novakova@example.cz", external_id = "zakaznik-881", metadata = new { newsletter = "ano" }, }); // 201# klient: viz /v2/docs/python customer = api.post('/customers', { 'phone': '+420777123456', 'name': 'Jana Nováková', 'email': 'jana.novakova@example.cz', 'external_id': 'zakaznik-881', 'metadata': {'newsletter': 'ano'}, }) # 201# the client: see /v2/docs/python customer = api.post('/customers', { 'phone': '+420777123456', 'name': 'Jana Nováková', 'email': 'jana.novakova@example.cz', 'external_id': 'zakaznik-881', 'metadata': {'newsletter': 'ano'}, }) # 201// klient: viz /v2/docs/swift let customer: Customer = try await api.post("/customers", body: [ "phone": "+420777123456", "name": "Jana Nováková", "email": "jana.novakova@example.cz", "external_id": "zakaznik-881", "metadata": ["newsletter": "ano"], ]) // 201// the client: see /v2/docs/swift let customer: Customer = try await api.post("/customers", body: [ "phone": "+420777123456", "name": "Jana Nováková", "email": "jana.novakova@example.cz", "external_id": "zakaznik-881", "metadata": ["newsletter": "ano"], ]) // 201// klient: viz /v2/docs/dart final customer = pr.Customer.fromJson(await api.post('/customers', { 'phone': '+420777123456', 'name': 'Jana Nováková', 'email': 'jana.novakova@example.cz', 'external_id': 'zakaznik-881', 'metadata': {'newsletter': 'ano'}, })); // 201// the client: see /v2/docs/dart final customer = pr.Customer.fromJson(await api.post('/customers', { 'phone': '+420777123456', 'name': 'Jana Nováková', 'email': 'jana.novakova@example.cz', 'external_id': 'zakaznik-881', 'metadata': {'newsletter': 'ano'}, })); // 201// klient: viz /v2/docs/go res, err := api.Post(ctx, "/customers", map[string]any{ "phone": "+420777123456", "name": "Jana Nováková", "email": "jana.novakova@example.cz", "external_id": "zakaznik-881", "metadata": map[string]any{"newsletter": "ano"}, }, nil) var customer model.Customer // 201 if err == nil { err = res.Decode(&customer) }// the client: see /v2/docs/go res, err := api.Post(ctx, "/customers", map[string]any{ "phone": "+420777123456", "name": "Jana Nováková", "email": "jana.novakova@example.cz", "external_id": "zakaznik-881", "metadata": map[string]any{"newsletter": "ano"}, }, nil) var customer model.Customer // 201 if err == nil { err = res.Decode(&customer) }Příklad odpovědi 201Example answer 201
{ "id": "90321", "phone": "+420777123456", "name": "Jana Nováková", "email": "jana.novakova@example.cz", "phone_verified": false, "created_at": "2027-01-15T11:40:12+01:00", "external_id": "zakaznik-881", "metadata": { "newsletter": "ano" } } -
Ověřovací SMS
A verification SMS
POST /customers/{customer_id}/phone-verification · startPhoneVerification
Šest číslic SMS; znovu poslat jde až po
resend_after.Six digits by SMS; sending again works only after
resend_after.curl -X POST "https://api.mujprofirest.cz/v2/customers/90321/phone-verification" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-76ba-b77b-97ea44c8e4ec"curl -X POST "https://api.mujprofirest.cz/v2/customers/90321/phone-verification" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-76ba-b77b-97ea44c8e4ec"// klient: viz /v2/docs/js const phoneVerification = await api.post('/customers/90321/phone-verification', null); // 201// the client: see /v2/docs/js const phoneVerification = await api.post('/customers/90321/phone-verification', null); // 201// klient: viz /v2/docs/typescript const phoneVerification = await api.post('/customers/90321/phone-verification', null); // 201 PhoneVerification// the client: see /v2/docs/typescript const phoneVerification = await api.post('/customers/90321/phone-verification', null); // 201 PhoneVerification// klient: viz /v2/docs/php $phoneVerification = $api->post('/customers/90321/phone-verification', null); // 201// the client: see /v2/docs/php $phoneVerification = $api->post('/customers/90321/phone-verification', null); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) PhoneVerification phoneVerification = api.post("/customers/90321/phone-verification", null, PhoneVerification::fromJson); // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) PhoneVerification phoneVerification = api.post("/customers/90321/phone-verification", null, PhoneVerification::fromJson); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val phoneVerification = api.post("/customers/90321/phone-verification", null, PhoneVerification::fromJson) // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val phoneVerification = api.post("/customers/90321/phone-verification", null, PhoneVerification::fromJson) // 201// klient: viz /v2/docs/csharp var phoneVerification = await api.PostAsync<PhoneVerification>("/customers/90321/phone-verification", (object?)null); // 201// the client: see /v2/docs/csharp var phoneVerification = await api.PostAsync<PhoneVerification>("/customers/90321/phone-verification", (object?)null); // 201# klient: viz /v2/docs/python phone_verification = api.post('/customers/90321/phone-verification', None) # 201# the client: see /v2/docs/python phone_verification = api.post('/customers/90321/phone-verification', None) # 201// klient: viz /v2/docs/swift let phoneVerification: PhoneVerification = try await api.post("/customers/90321/phone-verification", body: nil) // 201// the client: see /v2/docs/swift let phoneVerification: PhoneVerification = try await api.post("/customers/90321/phone-verification", body: nil) // 201// klient: viz /v2/docs/dart final phoneVerification = pr.PhoneVerification.fromJson(await api.post('/customers/90321/phone-verification', null)); // 201// the client: see /v2/docs/dart final phoneVerification = pr.PhoneVerification.fromJson(await api.post('/customers/90321/phone-verification', null)); // 201// klient: viz /v2/docs/go res, err := api.Post(ctx, "/customers/90321/phone-verification", nil, nil) var phoneVerification model.PhoneVerification // 201 if err == nil { err = res.Decode(&phoneVerification) }// the client: see /v2/docs/go res, err := api.Post(ctx, "/customers/90321/phone-verification", nil, nil) var phoneVerification model.PhoneVerification // 201 if err == nil { err = res.Decode(&phoneVerification) }Příklad odpovědi 201Example answer 201
{ "id": "7731", "expires_at": "2027-01-15T11:52:00+01:00", "resend_after": "2027-01-15T11:43:00+01:00" } -
Potvrzení kódu
Confirming the code
POST /customers/{customer_id}/phone-verification/confirm · confirmPhoneVerification
Teprve ověřený zákazník sbírá body a smí je uplatnit.
Only a verified customer collects and redeems points.
curl "https://api.mujprofirest.cz/v2/customers/90321/phone-verification/confirm" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7fd7-98d5-af2f103c0a77" \ -H "Content-Type: application/json" \ -d '{"code": "482913"}'curl "https://api.mujprofirest.cz/v2/customers/90321/phone-verification/confirm" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7fd7-98d5-af2f103c0a77" \ -H "Content-Type: application/json" \ -d '{"code": "482913"}'// klient: viz /v2/docs/js const phoneVerification = await api.post('/customers/90321/phone-verification/confirm', { code: '482913' }); // 200// the client: see /v2/docs/js const phoneVerification = await api.post('/customers/90321/phone-verification/confirm', { code: '482913' }); // 200// klient: viz /v2/docs/typescript const phoneVerification = await api.post('/customers/90321/phone-verification/confirm', { code: '482913' }); // 200 Customer// the client: see /v2/docs/typescript const phoneVerification = await api.post('/customers/90321/phone-verification/confirm', { code: '482913' }); // 200 Customer// klient: viz /v2/docs/php $phoneVerification = $api->post('/customers/90321/phone-verification/confirm', ['code' => '482913']); // 200// the client: see /v2/docs/php $phoneVerification = $api->post('/customers/90321/phone-verification/confirm', ['code' => '482913']); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) Customer phoneVerification = api.post("/customers/90321/phone-verification/confirm", Json.parse(""" {"code": "482913"} """), Customer::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) Customer phoneVerification = api.post("/customers/90321/phone-verification/confirm", Json.parse(""" {"code": "482913"} """), Customer::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val phoneVerification = api.post( "/customers/90321/phone-verification/confirm", mapOf("code" to "482913"), Customer::fromJson, ) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val phoneVerification = api.post( "/customers/90321/phone-verification/confirm", mapOf("code" to "482913"), Customer::fromJson, ) // 200// klient: viz /v2/docs/csharp var phoneVerification = await api.PostAsync<Customer>("/customers/90321/phone-verification/confirm", new { code = "482913" }); // 200// the client: see /v2/docs/csharp var phoneVerification = await api.PostAsync<Customer>("/customers/90321/phone-verification/confirm", new { code = "482913" }); // 200# klient: viz /v2/docs/python phone_verification = api.post('/customers/90321/phone-verification/confirm', {'code': '482913'}) # 200# the client: see /v2/docs/python phone_verification = api.post('/customers/90321/phone-verification/confirm', {'code': '482913'}) # 200// klient: viz /v2/docs/swift let phoneVerification: Customer = try await api.post("/customers/90321/phone-verification/confirm", body: ["code": "482913"]) // 200// the client: see /v2/docs/swift let phoneVerification: Customer = try await api.post("/customers/90321/phone-verification/confirm", body: ["code": "482913"]) // 200// klient: viz /v2/docs/dart final phoneVerification = pr.Customer.fromJson(await api.post('/customers/90321/phone-verification/confirm', {'code': '482913'})); // 200// the client: see /v2/docs/dart final phoneVerification = pr.Customer.fromJson(await api.post('/customers/90321/phone-verification/confirm', {'code': '482913'})); // 200// klient: viz /v2/docs/go res, err := api.Post(ctx, "/customers/90321/phone-verification/confirm", map[string]any{"code": "482913"}, nil) var phoneVerification model.Customer // 200 if err == nil { err = res.Decode(&phoneVerification) }// the client: see /v2/docs/go res, err := api.Post(ctx, "/customers/90321/phone-verification/confirm", map[string]any{"code": "482913"}, nil) var phoneVerification model.Customer // 200 if err == nil { err = res.Decode(&phoneVerification) }Příklad odpovědi 200Example answer 200
{ "id": "90321", "phone": "+420777123456", "name": "Jana Nováková", "email": "jana.novakova@example.cz", "phone_verified": true, "created_at": "2026-11-28T18:20:00+01:00", "external_id": "zakaznik-881", "metadata": { "newsletter": "ano" } } -
Věrnostní body
Loyalty points
GET /customers/{customer_id}/loyalty · getCustomerLoyalty
Stav bodů a jejich hodnota v penězích.
The points and their value in money.
curl "https://api.mujprofirest.cz/v2/customers/90321/loyalty" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/customers/90321/loyalty" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const customerLoyalty = await api.get('/customers/90321/loyalty'); // 200// the client: see /v2/docs/js const customerLoyalty = await api.get('/customers/90321/loyalty'); // 200// klient: viz /v2/docs/typescript const customerLoyalty = await api.get('/customers/90321/loyalty'); // 200 Loyalty// the client: see /v2/docs/typescript const customerLoyalty = await api.get('/customers/90321/loyalty'); // 200 Loyalty// klient: viz /v2/docs/php $customerLoyalty = $api->get('/customers/90321/loyalty'); // 200// the client: see /v2/docs/php $customerLoyalty = $api->get('/customers/90321/loyalty'); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) Loyalty customerLoyalty = api.get("/customers/90321/loyalty", Loyalty::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) Loyalty customerLoyalty = api.get("/customers/90321/loyalty", Loyalty::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val customerLoyalty = api.get("/customers/90321/loyalty", Loyalty::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val customerLoyalty = api.get("/customers/90321/loyalty", Loyalty::fromJson) // 200// klient: viz /v2/docs/csharp var customerLoyalty = await api.GetAsync<Loyalty>("/customers/90321/loyalty"); // 200// the client: see /v2/docs/csharp var customerLoyalty = await api.GetAsync<Loyalty>("/customers/90321/loyalty"); // 200# klient: viz /v2/docs/python customer_loyalty = api.get('/customers/90321/loyalty') # 200# the client: see /v2/docs/python customer_loyalty = api.get('/customers/90321/loyalty') # 200// klient: viz /v2/docs/swift let customerLoyalty: Loyalty = try await api.get("/customers/90321/loyalty") // 200// the client: see /v2/docs/swift let customerLoyalty: Loyalty = try await api.get("/customers/90321/loyalty") // 200// klient: viz /v2/docs/dart final customerLoyalty = pr.Loyalty.fromJson(await api.get('/customers/90321/loyalty')); // 200// the client: see /v2/docs/dart final customerLoyalty = pr.Loyalty.fromJson(await api.get('/customers/90321/loyalty')); // 200// klient: viz /v2/docs/go res, err := api.Get(ctx, "/customers/90321/loyalty", nil) var customerLoyalty model.Loyalty // 200 if err == nil { err = res.Decode(&customerLoyalty) }// the client: see /v2/docs/go res, err := api.Get(ctx, "/customers/90321/loyalty", nil) var customerLoyalty model.Loyalty // 200 if err == nil { err = res.Decode(&customerLoyalty) }Příklad odpovědi 200Example answer 200
{ "customer_id": "90321", "points": 120, "points_value": { "amount": 12000, "currency": "CZK" }, "redeemable": false } -
Dárkový voucher
A gift voucher
POST /restaurants/{restaurant_id}/vouchers/check · checkVoucher
Zůstatek a platnost před zaplacením; samotné uplatnění je platba v nabídce (
vouchers).The balance and validity before paying; redeeming it is a payment in the quote (
vouchers).curl "https://api.mujprofirest.cz/v2/restaurants/123/vouchers/check" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-792f-b84a-1627013a144c" \ -H "Content-Type: application/json" \ -d '{"code": "KX7-9QD"}'curl "https://api.mujprofirest.cz/v2/restaurants/123/vouchers/check" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-792f-b84a-1627013a144c" \ -H "Content-Type: application/json" \ -d '{"code": "KX7-9QD"}'// klient: viz /v2/docs/js const voucher = await api.post('/restaurants/123/vouchers/check', { code: 'KX7-9QD' }); // 200// the client: see /v2/docs/js const voucher = await api.post('/restaurants/123/vouchers/check', { code: 'KX7-9QD' }); // 200// klient: viz /v2/docs/typescript const voucher = await api.post('/restaurants/123/vouchers/check', { code: 'KX7-9QD' }); // 200 Voucher// the client: see /v2/docs/typescript const voucher = await api.post('/restaurants/123/vouchers/check', { code: 'KX7-9QD' }); // 200 Voucher// klient: viz /v2/docs/php $voucher = $api->post('/restaurants/123/vouchers/check', ['code' => 'KX7-9QD']); // 200// the client: see /v2/docs/php $voucher = $api->post('/restaurants/123/vouchers/check', ['code' => 'KX7-9QD']); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) Voucher voucher = api.post("/restaurants/123/vouchers/check", Json.parse(""" {"code": "KX7-9QD"} """), Voucher::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) Voucher voucher = api.post("/restaurants/123/vouchers/check", Json.parse(""" {"code": "KX7-9QD"} """), Voucher::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val voucher = api.post("/restaurants/123/vouchers/check", mapOf("code" to "KX7-9QD"), Voucher::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val voucher = api.post("/restaurants/123/vouchers/check", mapOf("code" to "KX7-9QD"), Voucher::fromJson) // 200// klient: viz /v2/docs/csharp var voucher = await api.PostAsync<Voucher>("/restaurants/123/vouchers/check", new { code = "KX7-9QD" }); // 200// the client: see /v2/docs/csharp var voucher = await api.PostAsync<Voucher>("/restaurants/123/vouchers/check", new { code = "KX7-9QD" }); // 200# klient: viz /v2/docs/python voucher = api.post('/restaurants/123/vouchers/check', {'code': 'KX7-9QD'}) # 200# the client: see /v2/docs/python voucher = api.post('/restaurants/123/vouchers/check', {'code': 'KX7-9QD'}) # 200// klient: viz /v2/docs/swift let voucher: Voucher = try await api.post("/restaurants/123/vouchers/check", body: ["code": "KX7-9QD"]) // 200// the client: see /v2/docs/swift let voucher: Voucher = try await api.post("/restaurants/123/vouchers/check", body: ["code": "KX7-9QD"]) // 200// klient: viz /v2/docs/dart final voucher = pr.Voucher.fromJson(await api.post('/restaurants/123/vouchers/check', {'code': 'KX7-9QD'})); // 200// the client: see /v2/docs/dart final voucher = pr.Voucher.fromJson(await api.post('/restaurants/123/vouchers/check', {'code': 'KX7-9QD'})); // 200// klient: viz /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/vouchers/check", map[string]any{"code": "KX7-9QD"}, nil) var voucher model.Voucher // 200 if err == nil { err = res.Decode(&voucher) }// the client: see /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/vouchers/check", map[string]any{"code": "KX7-9QD"}, nil) var voucher model.Voucher // 200 if err == nil { err = res.Decode(&voucher) }Příklad odpovědi 200Example answer 200
{ "code": "KX7-***", "status": "active", "value": { "amount": 50000, "currency": "CZK" }, "balance": { "amount": 30000, "currency": "CZK" }, "valid_until": "2027-06-30", "partial_redemption": true, "accepted_here": true }
Scénář
Scenario
Rezervace stolů a služeb
Reservations of tables and services
Rezervační platforma, web provozovny, aplikace obsluhy (reservations:read, reservations:write)A booking platform, the restaurant's website, an application of the staff (reservations:read, reservations:write)Host si vybere den, počet osob nebo službu a volný čas, vy rezervaci založíte a server ohlídá kapacitu – stůl, pracovník ani místnost nejsou nikdy rezervované dvakrát. Změny z administrace a pokladen vám chodí jako události.
The guest picks a day, the size of the party or a service and a free time, you create the reservation and the server keeps the capacity – a table, an employee or a room is never booked twice. Changes made in the administration and at the registers come to you as events.
-
Pravidla provozovny
The rules of the restaurant
GET /restaurants/{restaurant_id}/reservation-settings · getReservationSettings
Jestli přijímá online rezervace, jak dlouho se sedí, jak daleko dopředu a největší skupinu. Bez licence rezervací vrací operace
module_not_licensed.Whether it takes online reservations, how long guests sit, how far ahead and the biggest party. Without the reservation licence the operations answer
module_not_licensed.curl "https://api.mujprofirest.cz/v2/restaurants/123/reservation-settings" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/reservation-settings" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const reservationSettings = await api.get('/restaurants/123/reservation-settings'); // 200// the client: see /v2/docs/js const reservationSettings = await api.get('/restaurants/123/reservation-settings'); // 200// klient: viz /v2/docs/typescript const reservationSettings = await api.get('/restaurants/123/reservation-settings'); // 200 ReservationSettings// the client: see /v2/docs/typescript const reservationSettings = await api.get('/restaurants/123/reservation-settings'); // 200 ReservationSettings// klient: viz /v2/docs/php $reservationSettings = $api->get('/restaurants/123/reservation-settings'); // 200// the client: see /v2/docs/php $reservationSettings = $api->get('/restaurants/123/reservation-settings'); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) ReservationSettings reservationSettings = api.get("/restaurants/123/reservation-settings", ReservationSettings::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) ReservationSettings reservationSettings = api.get("/restaurants/123/reservation-settings", ReservationSettings::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val reservationSettings = api.get("/restaurants/123/reservation-settings", ReservationSettings::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val reservationSettings = api.get("/restaurants/123/reservation-settings", ReservationSettings::fromJson) // 200// klient: viz /v2/docs/csharp var reservationSettings = await api.GetAsync<ReservationSettings>("/restaurants/123/reservation-settings"); // 200// the client: see /v2/docs/csharp var reservationSettings = await api.GetAsync<ReservationSettings>("/restaurants/123/reservation-settings"); // 200# klient: viz /v2/docs/python reservation_settings = api.get('/restaurants/123/reservation-settings') # 200# the client: see /v2/docs/python reservation_settings = api.get('/restaurants/123/reservation-settings') # 200// klient: viz /v2/docs/swift let reservationSettings: ReservationSettings = try await api.get("/restaurants/123/reservation-settings") // 200// the client: see /v2/docs/swift let reservationSettings: ReservationSettings = try await api.get("/restaurants/123/reservation-settings") // 200// klient: viz /v2/docs/dart final reservationSettings = pr.ReservationSettings.fromJson(await api.get('/restaurants/123/reservation-settings')); // 200// the client: see /v2/docs/dart final reservationSettings = pr.ReservationSettings.fromJson(await api.get('/restaurants/123/reservation-settings')); // 200// klient: viz /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/reservation-settings", nil) var reservationSettings model.ReservationSettings // 200 if err == nil { err = res.Decode(&reservationSettings) }// the client: see /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/reservation-settings", nil) var reservationSettings model.ReservationSettings // 200 if err == nil { err = res.Decode(&reservationSettings) }Příklad odpovědi 200Example answer 200
{ "slot_step_minutes": 15, "table_durations": [ { "up_to_party_size": 2, "minutes": 90 }, { "up_to_party_size": 4, "minutes": 120 }, { "up_to_party_size": 99, "minutes": 150 } ], "table_buffer_minutes": 15, "last_seating_before_close_minutes": 30, "use_opening_hours": true, "max_guests_per_slot": 12, "closed_dates": [ "2027-02-14" ], "online": { "enabled": true, "confirmation": "auto", "confirm_within_minutes": 120, "lead_minutes": 60, "horizon_days": 60, "max_party_size": 8, "guest_cancel_hours": 2 }, "services_enabled": true, "deposit": { "mode": "from_party", "available": true, "from_party_size": 6, "per_person": { "amount": 20000, "currency": "CZK" }, "per_reservation": { "amount": 0, "currency": "CZK" }, "service_percent": 50, "pay_within_minutes": 60, "refund_until_hours": 24, "no_show_guests": true }, "reminders": { "email_hours": 24, "sms_hours": 3 }, "feedback_enabled": true, "guest_max_moves": 3 } -
Služby (salon, wellness)
Services (salon, wellness)
GET /restaurants/{restaurant_id}/reservation-services · listReservationServices
Délka, cena a pracovníci každé služby. U restaurace bez služeb prázdné.
Length, price and employees of every service. Empty for a restaurant without services.
curl "https://api.mujprofirest.cz/v2/restaurants/123/reservation-services" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/reservation-services" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const listReservationServices = await api.get('/restaurants/123/reservation-services'); // 200// the client: see /v2/docs/js const listReservationServices = await api.get('/restaurants/123/reservation-services'); // 200// klient: viz /v2/docs/typescript const listReservationServices = await api.get('/restaurants/123/reservation-services'); // 200 ReservationServiceList// the client: see /v2/docs/typescript const listReservationServices = await api.get('/restaurants/123/reservation-services'); // 200 ReservationServiceList// klient: viz /v2/docs/php $listReservationServices = $api->get('/restaurants/123/reservation-services'); // 200// the client: see /v2/docs/php $listReservationServices = $api->get('/restaurants/123/reservation-services'); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) ReservationServiceList listReservationServices = api.get("/restaurants/123/reservation-services", ReservationServiceList::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) ReservationServiceList listReservationServices = api.get("/restaurants/123/reservation-services", ReservationServiceList::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val listReservationServices = api.get("/restaurants/123/reservation-services", ReservationServiceList::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val listReservationServices = api.get("/restaurants/123/reservation-services", ReservationServiceList::fromJson) // 200// klient: viz /v2/docs/csharp var listReservationServices = await api.GetAsync<ReservationServiceList>("/restaurants/123/reservation-services"); // 200// the client: see /v2/docs/csharp var listReservationServices = await api.GetAsync<ReservationServiceList>("/restaurants/123/reservation-services"); // 200# klient: viz /v2/docs/python list_reservation_services = api.get('/restaurants/123/reservation-services') # 200# the client: see /v2/docs/python list_reservation_services = api.get('/restaurants/123/reservation-services') # 200// klient: viz /v2/docs/swift let listReservationServices: ReservationServiceList = try await api.get("/restaurants/123/reservation-services") // 200// the client: see /v2/docs/swift let listReservationServices: ReservationServiceList = try await api.get("/restaurants/123/reservation-services") // 200// klient: viz /v2/docs/dart final listReservationServices = pr.ReservationServiceList.fromJson(await api.get('/restaurants/123/reservation-services')); // 200// the client: see /v2/docs/dart final listReservationServices = pr.ReservationServiceList.fromJson(await api.get('/restaurants/123/reservation-services')); // 200// klient: viz /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/reservation-services", nil) var listReservationServices model.ReservationServiceList // 200 if err == nil { err = res.Decode(&listReservationServices) }// the client: see /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/reservation-services", nil) var listReservationServices model.ReservationServiceList // 200 if err == nil { err = res.Decode(&listReservationServices) }Příklad odpovědi 200Example answer 200
{ "data": [ { "id": "12", "name": "Pánský střih", "category": "Vlasy", "description": null, "duration_minutes": 30, "buffer_minutes": 10, "price": { "amount": 45000, "currency": "CZK" }, "max_party_size": 1, "online": true, "staff": [ { "id": "58", "name": "Jana Dvořáková" }, { "id": "61", "name": "Petr Novák" } ] } ] } -
Volné časy dne
Free times of a day
GET /restaurants/{restaurant_id}/reservation-availability · getReservationAvailability
Nabídněte jen časy s
available. Čas se pro vás nedrží – rezervaci založte hned po výběru.Offer only times with
available. A time is not held for you – create the reservation right after the choice.curl "https://api.mujprofirest.cz/v2/restaurants/123/reservation-availability?date=2027-01-15&party_size=4" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/reservation-availability?date=2027-01-15&party_size=4" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const reservationAvailability = await api.get( '/restaurants/123/reservation-availability', { query: { date: '2027-01-15', party_size: '4' } }, ); // 200// the client: see /v2/docs/js const reservationAvailability = await api.get( '/restaurants/123/reservation-availability', { query: { date: '2027-01-15', party_size: '4' } }, ); // 200// klient: viz /v2/docs/typescript const reservationAvailability = await api.get( '/restaurants/123/reservation-availability', { query: { date: '2027-01-15', party_size: '4' } }, ); // 200 ReservationAvailability// the client: see /v2/docs/typescript const reservationAvailability = await api.get( '/restaurants/123/reservation-availability', { query: { date: '2027-01-15', party_size: '4' } }, ); // 200 ReservationAvailability// klient: viz /v2/docs/php $reservationAvailability = $api->get( '/restaurants/123/reservation-availability', ['query' => ['date' => '2027-01-15', 'party_size' => '4']], ); // 200// the client: see /v2/docs/php $reservationAvailability = $api->get( '/restaurants/123/reservation-availability', ['query' => ['date' => '2027-01-15', 'party_size' => '4']], ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) ReservationAvailability reservationAvailability = api.get( "/restaurants/123/reservation-availability", RequestOptions.builder().query("date", "2027-01-15").query("party_size", "4").build(), ReservationAvailability::fromJson ); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) ReservationAvailability reservationAvailability = api.get( "/restaurants/123/reservation-availability", RequestOptions.builder().query("date", "2027-01-15").query("party_size", "4").build(), ReservationAvailability::fromJson ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val reservationAvailability = api.get( "/restaurants/123/reservation-availability", RequestOptions.builder().query("date", "2027-01-15").query("party_size", "4").build(), ReservationAvailability::fromJson, ) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val reservationAvailability = api.get( "/restaurants/123/reservation-availability", RequestOptions.builder().query("date", "2027-01-15").query("party_size", "4").build(), ReservationAvailability::fromJson, ) // 200// klient: viz /v2/docs/csharp var reservationAvailability = await api.GetAsync<ReservationAvailability>( "/restaurants/123/reservation-availability", new RequestOptions { Query = new() { ["date"] = "2027-01-15", ["party_size"] = "4" } } ); // 200// the client: see /v2/docs/csharp var reservationAvailability = await api.GetAsync<ReservationAvailability>( "/restaurants/123/reservation-availability", new RequestOptions { Query = new() { ["date"] = "2027-01-15", ["party_size"] = "4" } } ); // 200# klient: viz /v2/docs/python reservation_availability = api.get( '/restaurants/123/reservation-availability', query={'date': '2027-01-15', 'party_size': '4'}, ) # 200# the client: see /v2/docs/python reservation_availability = api.get( '/restaurants/123/reservation-availability', query={'date': '2027-01-15', 'party_size': '4'}, ) # 200// klient: viz /v2/docs/swift let reservationAvailability: ReservationAvailability = try await api.get( "/restaurants/123/reservation-availability", options: .init(query: ["date": "2027-01-15", "party_size": "4"]) ) // 200// the client: see /v2/docs/swift let reservationAvailability: ReservationAvailability = try await api.get( "/restaurants/123/reservation-availability", options: .init(query: ["date": "2027-01-15", "party_size": "4"]) ) // 200// klient: viz /v2/docs/dart final reservationAvailability = pr.ReservationAvailability.fromJson(await api.get( '/restaurants/123/reservation-availability', query: {'date': '2027-01-15', 'party_size': '4'}, )); // 200// the client: see /v2/docs/dart final reservationAvailability = pr.ReservationAvailability.fromJson(await api.get( '/restaurants/123/reservation-availability', query: {'date': '2027-01-15', 'party_size': '4'}, )); // 200// klient: viz /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/reservation-availability", &profirest.RequestOptions{Query: map[string]any{"date": "2027-01-15", "party_size": "4"}}, ) var reservationAvailability model.ReservationAvailability // 200 if err == nil { err = res.Decode(&reservationAvailability) }// the client: see /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/reservation-availability", &profirest.RequestOptions{Query: map[string]any{"date": "2027-01-15", "party_size": "4"}}, ) var reservationAvailability model.ReservationAvailability // 200 if err == nil { err = res.Decode(&reservationAvailability) }Příklad odpovědi 200Example answer 200
{ "date": "2027-01-15", "slots": [ { "starts_at": "2027-01-15T18:45:00+01:00", "available": true, "reason": null, "table_ids": [ "7" ], "employee_id": null }, { "starts_at": "2027-01-15T19:00:00+01:00", "available": true, "reason": null, "table_ids": [ "4" ], "employee_id": null }, { "starts_at": "2027-01-15T19:15:00+01:00", "available": false, "reason": "no_table", "table_ids": [], "employee_id": null } ] } -
Založení
Creating it
POST /restaurants/{restaurant_id}/reservations · createReservation
S
Idempotency-Keya ideálně vlastnímuuid. Obsazený čas vrátí409 reservation_unavailable– načtěte volné časy znovu a nabídněte jiný. Rezervace může býtrequested, když provozovna potvrzuje ručně nebo chce zálohu.With an
Idempotency-Keyand ideally your ownuuid. A taken time answers409 reservation_unavailable– load the free times again and offer another one. The reservation may berequestedwhen the restaurant confirms by hand or wants a deposit.curl "https://api.mujprofirest.cz/v2/restaurants/123/reservations" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7e52-88f6-1277ae5c3ab5" \ -H "Content-Type: application/json" \ -d '{ "uuid": "01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf", "channel": "online", "kind": "table", "party_size": 4, "starts_at": "2027-01-15T19:00:00+01:00", "guest": { "name": "Jana Svobodová", "phone": "+420777123456", "email": "jana.svobodova@example.com" }, "note_guest": "U okna, slavíme narozeniny" }'curl "https://api.mujprofirest.cz/v2/restaurants/123/reservations" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7e52-88f6-1277ae5c3ab5" \ -H "Content-Type: application/json" \ -d '{ "uuid": "01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf", "channel": "online", "kind": "table", "party_size": 4, "starts_at": "2027-01-15T19:00:00+01:00", "guest": { "name": "Jana Svobodová", "phone": "+420777123456", "email": "jana.svobodova@example.com" }, "note_guest": "U okna, slavíme narozeniny" }'// klient: viz /v2/docs/js const reservation = await api.post('/restaurants/123/reservations', { uuid: '01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf', channel: 'online', kind: 'table', party_size: 4, starts_at: '2027-01-15T19:00:00+01:00', guest: { name: 'Jana Svobodová', phone: '+420777123456', email: 'jana.svobodova@example.com', }, note_guest: 'U okna, slavíme narozeniny', }); // 201// the client: see /v2/docs/js const reservation = await api.post('/restaurants/123/reservations', { uuid: '01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf', channel: 'online', kind: 'table', party_size: 4, starts_at: '2027-01-15T19:00:00+01:00', guest: { name: 'Jana Svobodová', phone: '+420777123456', email: 'jana.svobodova@example.com', }, note_guest: 'U okna, slavíme narozeniny', }); // 201// klient: viz /v2/docs/typescript const reservation = await api.post('/restaurants/123/reservations', { uuid: '01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf', channel: 'online', kind: 'table', party_size: 4, starts_at: '2027-01-15T19:00:00+01:00', guest: { name: 'Jana Svobodová', phone: '+420777123456', email: 'jana.svobodova@example.com', }, note_guest: 'U okna, slavíme narozeniny', }); // 201 Reservation// the client: see /v2/docs/typescript const reservation = await api.post('/restaurants/123/reservations', { uuid: '01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf', channel: 'online', kind: 'table', party_size: 4, starts_at: '2027-01-15T19:00:00+01:00', guest: { name: 'Jana Svobodová', phone: '+420777123456', email: 'jana.svobodova@example.com', }, note_guest: 'U okna, slavíme narozeniny', }); // 201 Reservation// klient: viz /v2/docs/php $reservation = $api->post('/restaurants/123/reservations', [ 'uuid' => '01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf', 'channel' => 'online', 'kind' => 'table', 'party_size' => 4, 'starts_at' => '2027-01-15T19:00:00+01:00', 'guest' => [ 'name' => 'Jana Svobodová', 'phone' => '+420777123456', 'email' => 'jana.svobodova@example.com', ], 'note_guest' => 'U okna, slavíme narozeniny', ]); // 201// the client: see /v2/docs/php $reservation = $api->post('/restaurants/123/reservations', [ 'uuid' => '01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf', 'channel' => 'online', 'kind' => 'table', 'party_size' => 4, 'starts_at' => '2027-01-15T19:00:00+01:00', 'guest' => [ 'name' => 'Jana Svobodová', 'phone' => '+420777123456', 'email' => 'jana.svobodova@example.com', ], 'note_guest' => 'U okna, slavíme narozeniny', ]); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) Reservation reservation = api.post("/restaurants/123/reservations", Json.parse(""" { "uuid": "01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf", "channel": "online", "kind": "table", "party_size": 4, "starts_at": "2027-01-15T19:00:00+01:00", "guest": { "name": "Jana Svobodová", "phone": "+420777123456", "email": "jana.svobodova@example.com" }, "note_guest": "U okna, slavíme narozeniny" } """), Reservation::fromJson); // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) Reservation reservation = api.post("/restaurants/123/reservations", Json.parse(""" { "uuid": "01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf", "channel": "online", "kind": "table", "party_size": 4, "starts_at": "2027-01-15T19:00:00+01:00", "guest": { "name": "Jana Svobodová", "phone": "+420777123456", "email": "jana.svobodova@example.com" }, "note_guest": "U okna, slavíme narozeniny" } """), Reservation::fromJson); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val reservation = api.post("/restaurants/123/reservations", mapOf( "uuid" to "01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf", "channel" to "online", "kind" to "table", "party_size" to 4, "starts_at" to "2027-01-15T19:00:00+01:00", "guest" to mapOf( "name" to "Jana Svobodová", "phone" to "+420777123456", "email" to "jana.svobodova@example.com", ), "note_guest" to "U okna, slavíme narozeniny", ), Reservation::fromJson) // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val reservation = api.post("/restaurants/123/reservations", mapOf( "uuid" to "01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf", "channel" to "online", "kind" to "table", "party_size" to 4, "starts_at" to "2027-01-15T19:00:00+01:00", "guest" to mapOf( "name" to "Jana Svobodová", "phone" to "+420777123456", "email" to "jana.svobodova@example.com", ), "note_guest" to "U okna, slavíme narozeniny", ), Reservation::fromJson) // 201// klient: viz /v2/docs/csharp var reservation = await api.PostAsync<Reservation>("/restaurants/123/reservations", new { uuid = "01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf", channel = "online", kind = "table", party_size = 4, starts_at = "2027-01-15T19:00:00+01:00", guest = new { name = "Jana Svobodová", phone = "+420777123456", email = "jana.svobodova@example.com", }, note_guest = "U okna, slavíme narozeniny", }); // 201// the client: see /v2/docs/csharp var reservation = await api.PostAsync<Reservation>("/restaurants/123/reservations", new { uuid = "01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf", channel = "online", kind = "table", party_size = 4, starts_at = "2027-01-15T19:00:00+01:00", guest = new { name = "Jana Svobodová", phone = "+420777123456", email = "jana.svobodova@example.com", }, note_guest = "U okna, slavíme narozeniny", }); // 201# klient: viz /v2/docs/python reservation = api.post('/restaurants/123/reservations', { 'uuid': '01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf', 'channel': 'online', 'kind': 'table', 'party_size': 4, 'starts_at': '2027-01-15T19:00:00+01:00', 'guest': { 'name': 'Jana Svobodová', 'phone': '+420777123456', 'email': 'jana.svobodova@example.com', }, 'note_guest': 'U okna, slavíme narozeniny', }) # 201# the client: see /v2/docs/python reservation = api.post('/restaurants/123/reservations', { 'uuid': '01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf', 'channel': 'online', 'kind': 'table', 'party_size': 4, 'starts_at': '2027-01-15T19:00:00+01:00', 'guest': { 'name': 'Jana Svobodová', 'phone': '+420777123456', 'email': 'jana.svobodova@example.com', }, 'note_guest': 'U okna, slavíme narozeniny', }) # 201// klient: viz /v2/docs/swift let reservation: Reservation = try await api.post("/restaurants/123/reservations", body: [ "uuid": "01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf", "channel": "online", "kind": "table", "party_size": 4, "starts_at": "2027-01-15T19:00:00+01:00", "guest": [ "name": "Jana Svobodová", "phone": "+420777123456", "email": "jana.svobodova@example.com", ], "note_guest": "U okna, slavíme narozeniny", ]) // 201// the client: see /v2/docs/swift let reservation: Reservation = try await api.post("/restaurants/123/reservations", body: [ "uuid": "01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf", "channel": "online", "kind": "table", "party_size": 4, "starts_at": "2027-01-15T19:00:00+01:00", "guest": [ "name": "Jana Svobodová", "phone": "+420777123456", "email": "jana.svobodova@example.com", ], "note_guest": "U okna, slavíme narozeniny", ]) // 201// klient: viz /v2/docs/dart final reservation = pr.Reservation.fromJson(await api.post('/restaurants/123/reservations', { 'uuid': '01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf', 'channel': 'online', 'kind': 'table', 'party_size': 4, 'starts_at': '2027-01-15T19:00:00+01:00', 'guest': { 'name': 'Jana Svobodová', 'phone': '+420777123456', 'email': 'jana.svobodova@example.com', }, 'note_guest': 'U okna, slavíme narozeniny', })); // 201// the client: see /v2/docs/dart final reservation = pr.Reservation.fromJson(await api.post('/restaurants/123/reservations', { 'uuid': '01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf', 'channel': 'online', 'kind': 'table', 'party_size': 4, 'starts_at': '2027-01-15T19:00:00+01:00', 'guest': { 'name': 'Jana Svobodová', 'phone': '+420777123456', 'email': 'jana.svobodova@example.com', }, 'note_guest': 'U okna, slavíme narozeniny', })); // 201// klient: viz /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/reservations", map[string]any{ "uuid": "01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf", "channel": "online", "kind": "table", "party_size": 4, "starts_at": "2027-01-15T19:00:00+01:00", "guest": map[string]any{ "name": "Jana Svobodová", "phone": "+420777123456", "email": "jana.svobodova@example.com", }, "note_guest": "U okna, slavíme narozeniny", }, nil) var reservation model.Reservation // 201 if err == nil { err = res.Decode(&reservation) }// the client: see /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/reservations", map[string]any{ "uuid": "01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf", "channel": "online", "kind": "table", "party_size": 4, "starts_at": "2027-01-15T19:00:00+01:00", "guest": map[string]any{ "name": "Jana Svobodová", "phone": "+420777123456", "email": "jana.svobodova@example.com", }, "note_guest": "U okna, slavíme narozeniny", }, nil) var reservation model.Reservation // 201 if err == nil { err = res.Decode(&reservation) }Příklad odpovědi 201Example answer 201
{ "id": "5120", "uuid": "01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf", "restaurant_id": "123", "kind": "table", "status": "confirmed", "source": "online", "party_size": 4, "starts_at": "2027-01-15T19:00:00+01:00", "ends_at": "2027-01-15T21:00:00+01:00", "blocked_until": "2027-01-15T21:15:00+01:00", "table_ids": [ "4" ], "service_id": null, "employee_id": null, "employee_any": false, "resource_id": null, "guest": { "name": "Jana Svobodová", "phone": "+420777123456", "email": "jana.svobodova@example.com", "customer_id": null }, "note_guest": "U okna, slavíme narozeniny", "note_internal": null, "tags": [ "narozeniny" ], "deposit": { "amount": { "amount": 0, "currency": "CZK" }, "status": "none", "due_at": null }, "confirm_due_at": null, "tab_id": null, "cancel_reason": null, "version": 1, "created_at": "2027-01-15T11:40:12+01:00", "updated_at": "2027-01-15T11:40:12+01:00" } -
Sledujte změny
Follow the changes
GET /events · listEvents
reservation.status_changedřekne, že ji provozovna potvrdila, zrušila nebo že host přišel. Kontakty hosta v události nejsou – načtěte je přesgetReservation.reservation.status_changedtells you the restaurant confirmed or cancelled it or that the guest arrived. The guest's contacts are not in the event – read them withgetReservation.curl "https://api.mujprofirest.cz/v2/events?cursor=eyJzZXEiOjkxMDU1MH0&restaurant_id=123&limit=100" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/events?cursor=eyJzZXEiOjkxMDU1MH0&restaurant_id=123&limit=100" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const feed = api.watchEvents({ restaurantId: '123', onEvents: async (events) => { for (const event of events) handle(event); // kurzor se posune až potom }, onReset: () => reloadEverything(), // 410 cursor_expired: načtěte stav znovu });// the client: see /v2/docs/js const feed = api.watchEvents({ restaurantId: '123', onEvents: async (events) => { for (const event of events) handle(event); // the cursor moves only afterwards }, onReset: () => reloadEverything(), // 410 cursor_expired: reload the state });// klient: viz /v2/docs/typescript const feed = api.watchEvents({ restaurantId: '123', onEvents: async (events) => { for (const event of events) handle(event); // kurzor se posune až potom }, onReset: () => reloadEverything(), // 410 cursor_expired: načtěte stav znovu });// the client: see /v2/docs/typescript const feed = api.watchEvents({ restaurantId: '123', onEvents: async (events) => { for (const event of events) handle(event); // the cursor moves only afterwards }, onReset: () => reloadEverything(), // 410 cursor_expired: reload the state });// klient: viz /v2/docs/php $api->watchEvents([ 'restaurantId' => '123', 'onEvents' => function (array $events): void { foreach ($events as $event) { handle($event); } // kurzor se posune až potom }, 'onReset' => fn() => reloadEverything(), // 410 cursor_expired: načtěte stav znovu ])->run();// the client: see /v2/docs/php $api->watchEvents([ 'restaurantId' => '123', 'onEvents' => function (array $events): void { foreach ($events as $event) { handle($event); } // the cursor moves only afterwards }, 'onReset' => fn() => reloadEverything(), // 410 cursor_expired: reload the state ])->run();// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) EventWatcher feed = api.watchEvents(WatchOptions.builder() .restaurantId("123") .onEvents(events -> events.forEach(this::handle)) // kurzor se posune až potom .onReset(error -> reloadEverything()) // 410 cursor_expired: načtěte stav znovu .build()); feed.start();// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) EventWatcher feed = api.watchEvents(WatchOptions.builder() .restaurantId("123") .onEvents(events -> events.forEach(this::handle)) // the cursor moves only afterwards .onReset(error -> reloadEverything()) // 410 cursor_expired: reload the state .build()); feed.start();// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val feed = api.watchEvents(WatchOptions.builder() .restaurantId("123") .onEvents { events -> events.forEach { handle(it) } } // kurzor se posune až potom .onReset { reloadEverything() } // 410 cursor_expired: načtěte stav znovu .build()) feed.start()// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val feed = api.watchEvents(WatchOptions.builder() .restaurantId("123") .onEvents { events -> events.forEach { handle(it) } } // the cursor moves only afterwards .onReset { reloadEverything() } // 410 cursor_expired: reload the state .build()) feed.start()// klient: viz /v2/docs/csharp await api.WatchEventsAsync(new WatchOptions { RestaurantId = "123", OnEvents = async (events, ct) => { foreach (var e in events) await HandleAsync(e, ct); }, // kurzor se posune až potom OnReset = _ => ReloadEverythingAsync(), // 410 cursor_expired: načtěte stav znovu }, stoppingToken);// the client: see /v2/docs/csharp await api.WatchEventsAsync(new WatchOptions { RestaurantId = "123", OnEvents = async (events, ct) => { foreach (var e in events) await HandleAsync(e, ct); }, // the cursor moves only afterwards OnReset = _ => ReloadEverythingAsync(), // 410 cursor_expired: reload the state }, stoppingToken);# klient: viz /v2/docs/python feed = api.watch_events( lambda events: [handle(event) for event in events], # kurzor se posune až potom restaurant_id='123', on_reset=lambda error: reload_everything(), # 410 cursor_expired: načtěte stav znovu ) feed.start()# the client: see /v2/docs/python feed = api.watch_events( lambda events: [handle(event) for event in events], # the cursor moves only afterwards restaurant_id='123', on_reset=lambda error: reload_everything(), # 410 cursor_expired: reload the state ) feed.start()// klient: viz /v2/docs/swift let feed = api.watchEvents(.init( restaurantID: "123", onEvents: { events in for event in events { handle(event) } }, // kurzor se posune až potom onReset: { _ in reloadEverything() } // 410 cursor_expired: načtěte stav znovu )) // feed.cancel() čtení ukončí// the client: see /v2/docs/swift let feed = api.watchEvents(.init( restaurantID: "123", onEvents: { events in for event in events { handle(event) } }, // the cursor moves only afterwards onReset: { _ in reloadEverything() } // 410 cursor_expired: reload the state )) // feed.cancel() čtení ukončí// klient: viz /v2/docs/dart final feed = api.watchEvents( restaurantId: '123', onEvents: (events) async { for (final event in events) handle(event); }, // kurzor se posune až potom onReset: (error) => reloadEverything(), // 410 cursor_expired: načtěte stav znovu )..start();// the client: see /v2/docs/dart final feed = api.watchEvents( restaurantId: '123', onEvents: (events) async { for (final event in events) handle(event); }, // the cursor moves only afterwards onReset: (error) => reloadEverything(), // 410 cursor_expired: reload the state )..start();// klient: viz /v2/docs/go err := api.WatchEvents(ctx, profirest.WatchOptions{ RestaurantID: "123", OnEvents: func(ctx context.Context, events []model.Event) error { for _, event := range events { handle(event) // kurzor se posune až potom } return nil }, OnReset: func(*profirest.APIError) { reloadEverything() }, // 410 cursor_expired: načtěte stav znovu })// the client: see /v2/docs/go err := api.WatchEvents(ctx, profirest.WatchOptions{ RestaurantID: "123", OnEvents: func(ctx context.Context, events []model.Event) error { for _, event := range events { handle(event) // the cursor moves only afterwards } return nil }, OnReset: func(*profirest.APIError) { reloadEverything() }, // 410 cursor_expired: reload the state })Příklad odpovědi 200Example answer 200
{ "data": [ { "id": "910551", "api_version": "2", "sequence": 910551, "type": "order.created", "occurred_at": "2027-01-15T11:42:31+01:00", "connection_id": "2208", "account_id": "7", "restaurant_id": "123", "data": { "id": "184223", "restaurant_id": "123", "kitchen_number": "027", "status": "received", "status_changed_at": "2027-01-15T11:42:31+01:00", "created_at": "2027-01-15T11:42:31+01:00", "payment_deadline": null, "fulfillment": { "type": "pickup", "speed": "standard", "asap": true, "time": null, "estimated_at": "2027-01-15T12:05:00+01:00" }, "customer": { "customer_id": null, "name": "Jana Nováková", "phone": "+420777123456", "email": "jana.novakova@example.cz" }, "delivery": null, "lines": [ { "id": "1", "type": "product", "product_id": "4567", "name": "Svíčková na smetaně, houskový knedlík", "quantity": 2, "base_unit_price": { "amount": 19900, "currency": "CZK" }, "unit_price": { "amount": 19900, "currency": "CZK" }, "packaging_unit_price": null, "vat_rate": "12", "add_ons": [], "options": [], "parts": null, "removed_ingredients": [], "note": null, "total": { "amount": 39800, "currency": "CZK" }, "gift_of": null } ], "charges": [], "discounts": [], "totals": { "items": { "amount": 39800, "currency": "CZK" }, "charges": { "amount": 0, "currency": "CZK" }, "discounts": { "amount": 0, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" }, "vat": [ { "rate": "12", "base": { "amount": 35536, "currency": "CZK" }, "vat": { "amount": 4264, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" } } ] }, "payments": [ { "id": "301877", "method": "cash", "status": "unpaid", "amount": { "amount": 39800, "currency": "CZK" }, "provider": null, "reference": null, "voucher_code": null, "forfeited": null } ], "amount_to_collect": { "amount": 39800, "currency": "CZK" }, "loyalty_points_earned": null, "note": null, "cancellation": null, "external_id": "A-2027-000123", "metadata": { "branch": "praha-3" } } }, { "id": "910563", "api_version": "2", "sequence": 910563, "type": "order.status_changed", "occurred_at": "2027-01-15T11:44:02+01:00", "connection_id": "2208", "account_id": "7", "restaurant_id": "123", "data": { "id": "184223", "restaurant_id": "123", "kitchen_number": "027", "status": "preparing", "status_changed_at": "2027-01-15T11:44:02+01:00", "created_at": "2027-01-15T11:42:31+01:00", "payment_deadline": null, "fulfillment": { "type": "pickup", "speed": "standard", "asap": true, "time": null, "estimated_at": "2027-01-15T12:05:00+01:00" }, "customer": { "customer_id": null, "name": "Jana Nováková", "phone": "+420777123456", "email": "jana.novakova@example.cz" }, "delivery": null, "lines": [ { "id": "1", "type": "product", "product_id": "4567", "name": "Svíčková na smetaně, houskový knedlík", "quantity": 2, "base_unit_price": { "amount": 19900, "currency": "CZK" }, "unit_price": { "amount": 19900, "currency": "CZK" }, "packaging_unit_price": null, "vat_rate": "12", "add_ons": [], "options": [], "parts": null, "removed_ingredients": [], "note": null, "total": { "amount": 39800, "currency": "CZK" }, "gift_of": null } ], "charges": [], "discounts": [], "totals": { "items": { "amount": 39800, "currency": "CZK" }, "charges": { "amount": 0, "currency": "CZK" }, "discounts": { "amount": 0, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" }, "vat": [ { "rate": "12", "base": { "amount": 35536, "currency": "CZK" }, "vat": { "amount": 4264, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" } } ] }, "payments": [ { "id": "301877", "method": "cash", "status": "unpaid", "amount": { "amount": 39800, "currency": "CZK" }, "provider": null, "reference": null, "voucher_code": null, "forfeited": null } ], "amount_to_collect": { "amount": 39800, "currency": "CZK" }, "loyalty_points_earned": null, "note": null, "cancellation": null, "external_id": "A-2027-000123", "metadata": { "branch": "praha-3" } } }, { "id": "910570", "api_version": "2", "sequence": 910570, "type": "availability.changed", "occurred_at": "2027-01-15T11:45:10+01:00", "connection_id": "2208", "account_id": "7", "restaurant_id": "123", "data": { "restaurant_id": "123" } } ], "next_cursor": "eyJzZXEiOjkxMDU3MH0" } -
Zrušení hostem
Cancelled by the guest
POST /restaurants/{restaurant_id}/reservations/{reservation_id}/cancel · cancelReservation
S důvodem v
reason; ukončenou rezervaci vrátí409 reservation_state_conflict.With a
reason; a finished reservation answers409 reservation_state_conflict.curl "https://api.mujprofirest.cz/v2/restaurants/123/reservations/5120/cancel" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7ae7-8f65-832d26999a79" \ -H "Content-Type: application/json" \ -d '{"reason": "Host onemocněl"}'curl "https://api.mujprofirest.cz/v2/restaurants/123/reservations/5120/cancel" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7ae7-8f65-832d26999a79" \ -H "Content-Type: application/json" \ -d '{"reason": "Host onemocněl"}'// klient: viz /v2/docs/js const reservation = await api.post('/restaurants/123/reservations/5120/cancel', { reason: 'Host onemocněl' }); // 200// the client: see /v2/docs/js const reservation = await api.post('/restaurants/123/reservations/5120/cancel', { reason: 'Host onemocněl' }); // 200// klient: viz /v2/docs/typescript const reservation = await api.post('/restaurants/123/reservations/5120/cancel', { reason: 'Host onemocněl' }); // 200 Reservation// the client: see /v2/docs/typescript const reservation = await api.post('/restaurants/123/reservations/5120/cancel', { reason: 'Host onemocněl' }); // 200 Reservation// klient: viz /v2/docs/php $reservation = $api->post('/restaurants/123/reservations/5120/cancel', ['reason' => 'Host onemocněl']); // 200// the client: see /v2/docs/php $reservation = $api->post('/restaurants/123/reservations/5120/cancel', ['reason' => 'Host onemocněl']); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) Reservation reservation = api.post("/restaurants/123/reservations/5120/cancel", Json.parse(""" {"reason": "Host onemocněl"} """), Reservation::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) Reservation reservation = api.post("/restaurants/123/reservations/5120/cancel", Json.parse(""" {"reason": "Host onemocněl"} """), Reservation::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val reservation = api.post( "/restaurants/123/reservations/5120/cancel", mapOf("reason" to "Host onemocněl"), Reservation::fromJson, ) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val reservation = api.post( "/restaurants/123/reservations/5120/cancel", mapOf("reason" to "Host onemocněl"), Reservation::fromJson, ) // 200// klient: viz /v2/docs/csharp var reservation = await api.PostAsync<Reservation>( "/restaurants/123/reservations/5120/cancel", new { reason = "Host onemocněl" } ); // 200// the client: see /v2/docs/csharp var reservation = await api.PostAsync<Reservation>( "/restaurants/123/reservations/5120/cancel", new { reason = "Host onemocněl" } ); // 200# klient: viz /v2/docs/python reservation = api.post('/restaurants/123/reservations/5120/cancel', {'reason': 'Host onemocněl'}) # 200# the client: see /v2/docs/python reservation = api.post('/restaurants/123/reservations/5120/cancel', {'reason': 'Host onemocněl'}) # 200// klient: viz /v2/docs/swift let reservation: Reservation = try await api.post("/restaurants/123/reservations/5120/cancel", body: ["reason": "Host onemocněl"]) // 200// the client: see /v2/docs/swift let reservation: Reservation = try await api.post("/restaurants/123/reservations/5120/cancel", body: ["reason": "Host onemocněl"]) // 200// klient: viz /v2/docs/dart final reservation = pr.Reservation.fromJson(await api.post('/restaurants/123/reservations/5120/cancel', {'reason': 'Host onemocněl'})); // 200// the client: see /v2/docs/dart final reservation = pr.Reservation.fromJson(await api.post('/restaurants/123/reservations/5120/cancel', {'reason': 'Host onemocněl'})); // 200// klient: viz /v2/docs/go res, err := api.Post( ctx, "/restaurants/123/reservations/5120/cancel", map[string]any{"reason": "Host onemocněl"}, nil, ) var reservation model.Reservation // 200 if err == nil { err = res.Decode(&reservation) }// the client: see /v2/docs/go res, err := api.Post( ctx, "/restaurants/123/reservations/5120/cancel", map[string]any{"reason": "Host onemocněl"}, nil, ) var reservation model.Reservation // 200 if err == nil { err = res.Decode(&reservation) }Příklad odpovědi 200Example answer 200
{ "id": "5120", "uuid": "01a318f0-a0c0-7a44-8d8d-ba7e70efcfaf", "restaurant_id": "123", "kind": "table", "status": "cancelled", "source": "online", "party_size": 4, "starts_at": "2027-01-15T19:00:00+01:00", "ends_at": "2027-01-15T21:00:00+01:00", "blocked_until": "2027-01-15T21:15:00+01:00", "table_ids": [ "4" ], "service_id": null, "employee_id": null, "employee_any": false, "resource_id": null, "guest": { "name": "Jana Svobodová", "phone": "+420777123456", "email": "jana.svobodova@example.com", "customer_id": null }, "note_guest": "U okna, slavíme narozeniny", "note_internal": null, "tags": [ "narozeniny" ], "deposit": { "amount": { "amount": 0, "currency": "CZK" }, "status": "none", "due_at": null }, "confirm_due_at": null, "tab_id": null, "cancel_reason": "Host onemocněl", "version": 2, "created_at": "2027-01-15T11:40:12+01:00", "updated_at": "2027-01-15T11:40:12+01:00" } -
Které stoly jsou volné teď
Which tables are free now
GET /restaurants/{restaurant_id}/table-status · getTableStatus
Pro walk-in a obrazovky u vstupu: obsazené účtem i rezervací, s další rezervací dne. Hosty bez rezervace usadíte přes
createReservationschannel=staffawalk_in: true.For walk-ins and screens at the entrance: taken by a tab or a reservation, with the next reservation of the day. Seat guests without a reservation with
createReservation,channel=staffandwalk_in: true.curl "https://api.mujprofirest.cz/v2/restaurants/123/table-status" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/table-status" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const tableStatus = await api.get('/restaurants/123/table-status'); // 200// the client: see /v2/docs/js const tableStatus = await api.get('/restaurants/123/table-status'); // 200// klient: viz /v2/docs/typescript const tableStatus = await api.get('/restaurants/123/table-status'); // 200 TableStatus// the client: see /v2/docs/typescript const tableStatus = await api.get('/restaurants/123/table-status'); // 200 TableStatus// klient: viz /v2/docs/php $tableStatus = $api->get('/restaurants/123/table-status'); // 200// the client: see /v2/docs/php $tableStatus = $api->get('/restaurants/123/table-status'); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) TableStatus tableStatus = api.get("/restaurants/123/table-status", TableStatus::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) TableStatus tableStatus = api.get("/restaurants/123/table-status", TableStatus::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val tableStatus = api.get("/restaurants/123/table-status", TableStatus::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val tableStatus = api.get("/restaurants/123/table-status", TableStatus::fromJson) // 200// klient: viz /v2/docs/csharp var tableStatus = await api.GetAsync<TableStatus>("/restaurants/123/table-status"); // 200// the client: see /v2/docs/csharp var tableStatus = await api.GetAsync<TableStatus>("/restaurants/123/table-status"); // 200# klient: viz /v2/docs/python table_status = api.get('/restaurants/123/table-status') # 200# the client: see /v2/docs/python table_status = api.get('/restaurants/123/table-status') # 200// klient: viz /v2/docs/swift let tableStatus: TableStatus = try await api.get("/restaurants/123/table-status") // 200// the client: see /v2/docs/swift let tableStatus: TableStatus = try await api.get("/restaurants/123/table-status") // 200// klient: viz /v2/docs/dart final tableStatus = pr.TableStatus.fromJson(await api.get('/restaurants/123/table-status')); // 200// the client: see /v2/docs/dart final tableStatus = pr.TableStatus.fromJson(await api.get('/restaurants/123/table-status')); // 200// klient: viz /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/table-status", nil) var tableStatus model.TableStatus // 200 if err == nil { err = res.Decode(&tableStatus) }// the client: see /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/table-status", nil) var tableStatus model.TableStatus // 200 if err == nil { err = res.Decode(&tableStatus) }Příklad odpovědi 200Example answer 200
{ "at": "2027-01-15T18:40:00+01:00", "tables": [ { "id": "4", "name": "Stůl 4", "room": "Restaurace", "seats_min": 2, "seats_max": 4, "state": "reserved", "tab_id": null, "reservation_id": "5120", "next_reservation": null }, { "id": "7", "name": "Stůl 7", "room": "Restaurace", "seats_min": 2, "seats_max": 6, "state": "occupied", "tab_id": "01a318f0-a0c0-7b5f-897a-975233c4fa9d", "reservation_id": null, "next_reservation": { "id": "5133", "starts_at": "2027-01-15T20:30:00+01:00", "party_size": 6 } } ] } -
Kdo volá (aplikace obsluhy)
Who is calling (staff application)
GET /restaurants/{restaurant_id}/reservation-guest · getReservationGuest
Podle telefonu ukažte, kolikrát host přišel, nepřišel nebo zrušil, a jeho štítky (alergie, VIP).
By the phone number show how many times the guest came, did not come or cancelled, and their tags (allergies, VIP).
curl "https://api.mujprofirest.cz/v2/restaurants/123/reservation-guest?phone=%2B420777123456" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/reservation-guest?phone=%2B420777123456" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const reservationGuest = await api.get('/restaurants/123/reservation-guest', { query: { phone: '+420777123456' } }); // 200// the client: see /v2/docs/js const reservationGuest = await api.get('/restaurants/123/reservation-guest', { query: { phone: '+420777123456' } }); // 200// klient: viz /v2/docs/typescript const reservationGuest = await api.get('/restaurants/123/reservation-guest', { query: { phone: '+420777123456' } }); // 200 ReservationGuestHistory// the client: see /v2/docs/typescript const reservationGuest = await api.get('/restaurants/123/reservation-guest', { query: { phone: '+420777123456' } }); // 200 ReservationGuestHistory// klient: viz /v2/docs/php $reservationGuest = $api->get('/restaurants/123/reservation-guest', ['query' => ['phone' => '+420777123456']]); // 200// the client: see /v2/docs/php $reservationGuest = $api->get('/restaurants/123/reservation-guest', ['query' => ['phone' => '+420777123456']]); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) ReservationGuestHistory reservationGuest = api.get( "/restaurants/123/reservation-guest", RequestOptions.builder().query("phone", "+420777123456").build(), ReservationGuestHistory::fromJson ); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) ReservationGuestHistory reservationGuest = api.get( "/restaurants/123/reservation-guest", RequestOptions.builder().query("phone", "+420777123456").build(), ReservationGuestHistory::fromJson ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val reservationGuest = api.get( "/restaurants/123/reservation-guest", RequestOptions.builder().query("phone", "+420777123456").build(), ReservationGuestHistory::fromJson, ) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val reservationGuest = api.get( "/restaurants/123/reservation-guest", RequestOptions.builder().query("phone", "+420777123456").build(), ReservationGuestHistory::fromJson, ) // 200// klient: viz /v2/docs/csharp var reservationGuest = await api.GetAsync<ReservationGuestHistory>( "/restaurants/123/reservation-guest", new RequestOptions { Query = new() { ["phone"] = "+420777123456" } } ); // 200// the client: see /v2/docs/csharp var reservationGuest = await api.GetAsync<ReservationGuestHistory>( "/restaurants/123/reservation-guest", new RequestOptions { Query = new() { ["phone"] = "+420777123456" } } ); // 200# klient: viz /v2/docs/python reservation_guest = api.get('/restaurants/123/reservation-guest', query={'phone': '+420777123456'}) # 200# the client: see /v2/docs/python reservation_guest = api.get('/restaurants/123/reservation-guest', query={'phone': '+420777123456'}) # 200// klient: viz /v2/docs/swift let reservationGuest: ReservationGuestHistory = try await api.get("/restaurants/123/reservation-guest", options: .init(query: ["phone": "+420777123456"])) // 200// the client: see /v2/docs/swift let reservationGuest: ReservationGuestHistory = try await api.get("/restaurants/123/reservation-guest", options: .init(query: ["phone": "+420777123456"])) // 200// klient: viz /v2/docs/dart final reservationGuest = pr.ReservationGuestHistory.fromJson(await api.get('/restaurants/123/reservation-guest', query: {'phone': '+420777123456'})); // 200// the client: see /v2/docs/dart final reservationGuest = pr.ReservationGuestHistory.fromJson(await api.get('/restaurants/123/reservation-guest', query: {'phone': '+420777123456'})); // 200// klient: viz /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/reservation-guest", &profirest.RequestOptions{Query: map[string]any{"phone": "+420777123456"}}, ) var reservationGuest model.ReservationGuestHistory // 200 if err == nil { err = res.Decode(&reservationGuest) }// the client: see /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/reservation-guest", &profirest.RequestOptions{Query: map[string]any{"phone": "+420777123456"}}, ) var reservationGuest model.ReservationGuestHistory // 200 if err == nil { err = res.Decode(&reservationGuest) }Příklad odpovědi 200Example answer 200
{ "known": true, "name": "Jana Svobodová", "phone": "+420777123456", "email": "jana.svobodova@example.com", "visits": 7, "no_shows": 1, "cancelled": 1, "upcoming": 1, "last_visit_at": "2026-10-24T19:00:00+02:00", "tags": [ "narozeniny", "alergie: ořechy" ] } -
Čekací listina u dveří
The waiting list at the door
POST /restaurants/{restaurant_id}/waitlist · addToWaitlist
Host bez stolu jde na listinu; až se stůl uvolní,
notifyWaitlistEntrymu pošle SMS acloseWaitlistEntryho usadí (s rezervací hosta bez rezervace) nebo vyřadí.A guest without a table goes on the list; when a table is free,
notifyWaitlistEntrysends them an SMS andcloseWaitlistEntryseats them (with the walk-in reservation) or removes them.curl "https://api.mujprofirest.cz/v2/restaurants/123/waitlist" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7950-81cc-c942616c01ca" \ -H "Content-Type: application/json" \ -d '{ "name": "Rodina Nováková", "phone": "+420603123456", "party_size": 4, "note": "s kočárkem" }'curl "https://api.mujprofirest.cz/v2/restaurants/123/waitlist" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7950-81cc-c942616c01ca" \ -H "Content-Type: application/json" \ -d '{ "name": "Rodina Nováková", "phone": "+420603123456", "party_size": 4, "note": "s kočárkem" }'// klient: viz /v2/docs/js const toWaitlist = await api.post( '/restaurants/123/waitlist', { name: 'Rodina Nováková', phone: '+420603123456', party_size: 4, note: 's kočárkem' }, ); // 201// the client: see /v2/docs/js const toWaitlist = await api.post( '/restaurants/123/waitlist', { name: 'Rodina Nováková', phone: '+420603123456', party_size: 4, note: 's kočárkem' }, ); // 201// klient: viz /v2/docs/typescript const toWaitlist = await api.post( '/restaurants/123/waitlist', { name: 'Rodina Nováková', phone: '+420603123456', party_size: 4, note: 's kočárkem' }, ); // 201 WaitlistEntry// the client: see /v2/docs/typescript const toWaitlist = await api.post( '/restaurants/123/waitlist', { name: 'Rodina Nováková', phone: '+420603123456', party_size: 4, note: 's kočárkem' }, ); // 201 WaitlistEntry// klient: viz /v2/docs/php $toWaitlist = $api->post('/restaurants/123/waitlist', [ 'name' => 'Rodina Nováková', 'phone' => '+420603123456', 'party_size' => 4, 'note' => 's kočárkem', ]); // 201// the client: see /v2/docs/php $toWaitlist = $api->post('/restaurants/123/waitlist', [ 'name' => 'Rodina Nováková', 'phone' => '+420603123456', 'party_size' => 4, 'note' => 's kočárkem', ]); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) WaitlistEntry toWaitlist = api.post("/restaurants/123/waitlist", Json.parse(""" { "name": "Rodina Nováková", "phone": "+420603123456", "party_size": 4, "note": "s kočárkem" } """), WaitlistEntry::fromJson); // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) WaitlistEntry toWaitlist = api.post("/restaurants/123/waitlist", Json.parse(""" { "name": "Rodina Nováková", "phone": "+420603123456", "party_size": 4, "note": "s kočárkem" } """), WaitlistEntry::fromJson); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val toWaitlist = api.post("/restaurants/123/waitlist", mapOf( "name" to "Rodina Nováková", "phone" to "+420603123456", "party_size" to 4, "note" to "s kočárkem", ), WaitlistEntry::fromJson) // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val toWaitlist = api.post("/restaurants/123/waitlist", mapOf( "name" to "Rodina Nováková", "phone" to "+420603123456", "party_size" to 4, "note" to "s kočárkem", ), WaitlistEntry::fromJson) // 201// klient: viz /v2/docs/csharp var toWaitlist = await api.PostAsync<WaitlistEntry>("/restaurants/123/waitlist", new { name = "Rodina Nováková", phone = "+420603123456", party_size = 4, note = "s kočárkem", }); // 201// the client: see /v2/docs/csharp var toWaitlist = await api.PostAsync<WaitlistEntry>("/restaurants/123/waitlist", new { name = "Rodina Nováková", phone = "+420603123456", party_size = 4, note = "s kočárkem", }); // 201# klient: viz /v2/docs/python to_waitlist = api.post('/restaurants/123/waitlist', { 'name': 'Rodina Nováková', 'phone': '+420603123456', 'party_size': 4, 'note': 's kočárkem', }) # 201# the client: see /v2/docs/python to_waitlist = api.post('/restaurants/123/waitlist', { 'name': 'Rodina Nováková', 'phone': '+420603123456', 'party_size': 4, 'note': 's kočárkem', }) # 201// klient: viz /v2/docs/swift let toWaitlist: WaitlistEntry = try await api.post("/restaurants/123/waitlist", body: [ "name": "Rodina Nováková", "phone": "+420603123456", "party_size": 4, "note": "s kočárkem", ]) // 201// the client: see /v2/docs/swift let toWaitlist: WaitlistEntry = try await api.post("/restaurants/123/waitlist", body: [ "name": "Rodina Nováková", "phone": "+420603123456", "party_size": 4, "note": "s kočárkem", ]) // 201// klient: viz /v2/docs/dart final toWaitlist = pr.WaitlistEntry.fromJson(await api.post('/restaurants/123/waitlist', { 'name': 'Rodina Nováková', 'phone': '+420603123456', 'party_size': 4, 'note': 's kočárkem', })); // 201// the client: see /v2/docs/dart final toWaitlist = pr.WaitlistEntry.fromJson(await api.post('/restaurants/123/waitlist', { 'name': 'Rodina Nováková', 'phone': '+420603123456', 'party_size': 4, 'note': 's kočárkem', })); // 201// klient: viz /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/waitlist", map[string]any{ "name": "Rodina Nováková", "phone": "+420603123456", "party_size": 4, "note": "s kočárkem", }, nil) var toWaitlist model.WaitlistEntry // 201 if err == nil { err = res.Decode(&toWaitlist) }// the client: see /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/waitlist", map[string]any{ "name": "Rodina Nováková", "phone": "+420603123456", "party_size": 4, "note": "s kočárkem", }, nil) var toWaitlist model.WaitlistEntry // 201 if err == nil { err = res.Decode(&toWaitlist) }Příklad odpovědi 201Example answer 201
{ "id": "88", "name": "Rodina Nováková", "phone": "+420603123456", "party_size": 4, "note": "s kočárkem", "status": "waiting", "created_at": "2027-01-15T18:35:10+01:00", "notified_at": null, "can_sms": true } -
Záloha u rezervace z telefonu
A deposit for a booking by phone
POST /restaurants/{restaurant_id}/reservations/{reservation_id}/payment-link · sendReservationPaymentLink
Rezervace se zálohou čeká (
deposit.statuspending). Odkaz k zaplacení kartou dostane host e-mailem a vy ho máte i pro SMS; zálohu jde také odpustit přeswaiveReservationDeposit.A reservation with a deposit waits (
deposit.statuspending). The guest gets the link to pay by card by e-mail and you get it for an SMS too; the deposit can also be waived withwaiveReservationDeposit.curl -X POST "https://api.mujprofirest.cz/v2/restaurants/123/reservations/5120/payment-link" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7ccf-871c-3bcd8509ecf8"curl -X POST "https://api.mujprofirest.cz/v2/restaurants/123/reservations/5120/payment-link" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7ccf-871c-3bcd8509ecf8"// klient: viz /v2/docs/js const sendReservationPaymentLink = await api.post('/restaurants/123/reservations/5120/payment-link', null); // 200// the client: see /v2/docs/js const sendReservationPaymentLink = await api.post('/restaurants/123/reservations/5120/payment-link', null); // 200// klient: viz /v2/docs/typescript const sendReservationPaymentLink = await api.post('/restaurants/123/reservations/5120/payment-link', null); // 200 ReservationPaymentLink// the client: see /v2/docs/typescript const sendReservationPaymentLink = await api.post('/restaurants/123/reservations/5120/payment-link', null); // 200 ReservationPaymentLink// klient: viz /v2/docs/php $sendReservationPaymentLink = $api->post('/restaurants/123/reservations/5120/payment-link', null); // 200// the client: see /v2/docs/php $sendReservationPaymentLink = $api->post('/restaurants/123/reservations/5120/payment-link', null); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) ReservationPaymentLink sendReservationPaymentLink = api.post("/restaurants/123/reservations/5120/payment-link", null, ReservationPaymentLink::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) ReservationPaymentLink sendReservationPaymentLink = api.post("/restaurants/123/reservations/5120/payment-link", null, ReservationPaymentLink::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val sendReservationPaymentLink = api.post("/restaurants/123/reservations/5120/payment-link", null, ReservationPaymentLink::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val sendReservationPaymentLink = api.post("/restaurants/123/reservations/5120/payment-link", null, ReservationPaymentLink::fromJson) // 200// klient: viz /v2/docs/csharp var sendReservationPaymentLink = await api.PostAsync<ReservationPaymentLink>( "/restaurants/123/reservations/5120/payment-link", (object?)null ); // 200// the client: see /v2/docs/csharp var sendReservationPaymentLink = await api.PostAsync<ReservationPaymentLink>( "/restaurants/123/reservations/5120/payment-link", (object?)null ); // 200# klient: viz /v2/docs/python send_reservation_payment_link = api.post('/restaurants/123/reservations/5120/payment-link', None) # 200# the client: see /v2/docs/python send_reservation_payment_link = api.post('/restaurants/123/reservations/5120/payment-link', None) # 200// klient: viz /v2/docs/swift let sendReservationPaymentLink: ReservationPaymentLink = try await api.post("/restaurants/123/reservations/5120/payment-link", body: nil) // 200// the client: see /v2/docs/swift let sendReservationPaymentLink: ReservationPaymentLink = try await api.post("/restaurants/123/reservations/5120/payment-link", body: nil) // 200// klient: viz /v2/docs/dart final sendReservationPaymentLink = pr.ReservationPaymentLink.fromJson(await api.post('/restaurants/123/reservations/5120/payment-link', null)); // 200// the client: see /v2/docs/dart final sendReservationPaymentLink = pr.ReservationPaymentLink.fromJson(await api.post('/restaurants/123/reservations/5120/payment-link', null)); // 200// klient: viz /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/reservations/5120/payment-link", nil, nil) var sendReservationPaymentLink model.ReservationPaymentLink // 200 if err == nil { err = res.Decode(&sendReservationPaymentLink) }// the client: see /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/reservations/5120/payment-link", nil, nil) var sendReservationPaymentLink model.ReservationPaymentLink // 200 if err == nil { err = res.Decode(&sendReservationPaymentLink) }Příklad odpovědi 200Example answer 200
{ "url": "https://www.mujprofirest.cz/rezervace/sprava/4f1d0c9a7b2e8f61a3d5c7e9b0a2c4e6f8a1b3d5c7e9f0a2", "emailed": true, "due_at": "2027-01-15T12:40:12+01:00" } -
Přehled pro majitele a BI
Statistics for the owner and BI
GET /restaurants/{restaurant_id}/reservation-stats · getReservationStats
Stejná čísla jako Přehled v Knize rezervací: kolik hostů přišlo a kolik ne, odkud rezervace přišly, zálohy a hodnocení.
table_turnukáže, jak dlouho hosté skutečně sedí, a navrhne lepší dobu u stolu; pravidla záloh (i pro hosty, kteří už nepřišli) jsou vgetReservationSettings.The same numbers as the Overview of the reservation book: how many guests came and how many did not, where reservations came from, deposits and ratings.
table_turnshows how long guests really sit and suggests a better table time; the deposit rules (also for guests who did not come before) are ingetReservationSettings.curl "https://api.mujprofirest.cz/v2/restaurants/123/reservation-stats?from=2026-11-01&to=2026-11-30" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/reservation-stats?from=2026-11-01&to=2026-11-30" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const reservationStats = await api.get('/restaurants/123/reservation-stats', { query: { from: '2026-11-01', to: '2026-11-30' } }); // 200// the client: see /v2/docs/js const reservationStats = await api.get('/restaurants/123/reservation-stats', { query: { from: '2026-11-01', to: '2026-11-30' } }); // 200// klient: viz /v2/docs/typescript const reservationStats = await api.get('/restaurants/123/reservation-stats', { query: { from: '2026-11-01', to: '2026-11-30' } }); // 200 ReservationStats// the client: see /v2/docs/typescript const reservationStats = await api.get('/restaurants/123/reservation-stats', { query: { from: '2026-11-01', to: '2026-11-30' } }); // 200 ReservationStats// klient: viz /v2/docs/php $reservationStats = $api->get( '/restaurants/123/reservation-stats', ['query' => ['from' => '2026-11-01', 'to' => '2026-11-30']], ); // 200// the client: see /v2/docs/php $reservationStats = $api->get( '/restaurants/123/reservation-stats', ['query' => ['from' => '2026-11-01', 'to' => '2026-11-30']], ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) ReservationStats reservationStats = api.get( "/restaurants/123/reservation-stats", RequestOptions.builder().query("from", "2026-11-01").query("to", "2026-11-30").build(), ReservationStats::fromJson ); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) ReservationStats reservationStats = api.get( "/restaurants/123/reservation-stats", RequestOptions.builder().query("from", "2026-11-01").query("to", "2026-11-30").build(), ReservationStats::fromJson ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val reservationStats = api.get( "/restaurants/123/reservation-stats", RequestOptions.builder().query("from", "2026-11-01").query("to", "2026-11-30").build(), ReservationStats::fromJson, ) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val reservationStats = api.get( "/restaurants/123/reservation-stats", RequestOptions.builder().query("from", "2026-11-01").query("to", "2026-11-30").build(), ReservationStats::fromJson, ) // 200// klient: viz /v2/docs/csharp var reservationStats = await api.GetAsync<ReservationStats>( "/restaurants/123/reservation-stats", new RequestOptions { Query = new() { ["from"] = "2026-11-01", ["to"] = "2026-11-30" } } ); // 200// the client: see /v2/docs/csharp var reservationStats = await api.GetAsync<ReservationStats>( "/restaurants/123/reservation-stats", new RequestOptions { Query = new() { ["from"] = "2026-11-01", ["to"] = "2026-11-30" } } ); // 200# klient: viz /v2/docs/python reservation_stats = api.get('/restaurants/123/reservation-stats', query={'from': '2026-11-01', 'to': '2026-11-30'}) # 200# the client: see /v2/docs/python reservation_stats = api.get('/restaurants/123/reservation-stats', query={'from': '2026-11-01', 'to': '2026-11-30'}) # 200// klient: viz /v2/docs/swift let reservationStats: ReservationStats = try await api.get( "/restaurants/123/reservation-stats", options: .init(query: ["from": "2026-11-01", "to": "2026-11-30"]) ) // 200// the client: see /v2/docs/swift let reservationStats: ReservationStats = try await api.get( "/restaurants/123/reservation-stats", options: .init(query: ["from": "2026-11-01", "to": "2026-11-30"]) ) // 200// klient: viz /v2/docs/dart final reservationStats = pr.ReservationStats.fromJson(await api.get('/restaurants/123/reservation-stats', query: {'from': '2026-11-01', 'to': '2026-11-30'})); // 200// the client: see /v2/docs/dart final reservationStats = pr.ReservationStats.fromJson(await api.get('/restaurants/123/reservation-stats', query: {'from': '2026-11-01', 'to': '2026-11-30'})); // 200// klient: viz /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/reservation-stats", &profirest.RequestOptions{Query: map[string]any{"from": "2026-11-01", "to": "2026-11-30"}}, ) var reservationStats model.ReservationStats // 200 if err == nil { err = res.Decode(&reservationStats) }// the client: see /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/reservation-stats", &profirest.RequestOptions{Query: map[string]any{"from": "2026-11-01", "to": "2026-11-30"}}, ) var reservationStats model.ReservationStats // 200 if err == nil { err = res.Decode(&reservationStats) }Příklad odpovědi 200Example answer 200
{ "from": "2026-11-01", "to": "2026-11-30", "reservations": 412, "guests": 1386, "arrived": 371, "arrived_guests": 1251, "no_show": 9, "no_show_rate": 2.4, "cancelled": 24, "rejected": 2, "expired": 3, "upcoming": 0, "unresolved": 3, "avg_party_size": 3.4, "avg_lead_days": 4.2, "returning_guests": 58, "sources": [ { "source": "online", "count": 238 }, { "source": "phone", "count": 121 }, { "source": "admin", "count": 53 } ], "weekdays": [ 118, 132, 160, 201, 288, 310, 177 ], "hours": [ { "hour": 12, "guests": 214 }, { "hour": 18, "guests": 402 }, { "hour": 19, "guests": 466 }, { "hour": 20, "guests": 304 } ], "deposits": { "paid": { "amount": 1840000, "currency": "CZK" }, "refunded": { "amount": 120000, "currency": "CZK" }, "forfeited": { "amount": 60000, "currency": "CZK" } }, "ratings": { "count": 96, "average": 4.6, "low": 5 }, "services": [], "employees": [], "table_turn": { "measured": 342, "groups": [ { "up_to_party_size": 2, "planned_minutes": 90, "measured": 151, "median_minutes": 68 }, { "up_to_party_size": 4, "planned_minutes": 120, "measured": 140, "median_minutes": 112 }, { "up_to_party_size": 99, "planned_minutes": 150, "measured": 51, "median_minutes": 158 } ], "suggestions": [ { "up_to_party_size": 2, "planned_minutes": 90, "median_minutes": 68, "suggested_minutes": 75, "measured": 151 } ] } }
Scénář
Scenario
Útrata na pokoj (hotelová restaurace a bar)
Charging bills to a room (hotel restaurant and bar)
Pokladna hotelové restaurace nebo baru (lodging:read, lodging:write)The register of a hotel restaurant or bar (lodging:read, lodging:write)Ubytovaný host si dá večeři nebo drink a neplatí hned – obsluha útratu zapíše na jeho pokoj a host ji zaplatí při odjezdu na recepci. Útrata se objeví v účtu pokoje na plachtě i na vyúčtování.
A staying guest has dinner or a drink and does not pay at once – the staff charge it to the room and the guest pays at the reception at departure. The charge shows in the account of the room on the room plan and on the bill.
-
Má provozovna ubytování?
Does the restaurant have accommodation?
GET /restaurants/{restaurant_id}/device-settings · getDeviceSettings
Tlačítko „Na pokoj“ ukažte, jen když je
features.lodgingtrue. Jinak operace vracímodule_not_licensed.Show the „To the room“ button only when
features.lodgingistrue. Otherwise the operations answermodule_not_licensed.curl "https://api.mujprofirest.cz/v2/restaurants/123/device-settings" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/device-settings" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const deviceSettings = await api.get('/restaurants/123/device-settings'); // 200// the client: see /v2/docs/js const deviceSettings = await api.get('/restaurants/123/device-settings'); // 200// klient: viz /v2/docs/typescript const deviceSettings = await api.get('/restaurants/123/device-settings'); // 200 DeviceSettings// the client: see /v2/docs/typescript const deviceSettings = await api.get('/restaurants/123/device-settings'); // 200 DeviceSettings// klient: viz /v2/docs/php $deviceSettings = $api->get('/restaurants/123/device-settings'); // 200// the client: see /v2/docs/php $deviceSettings = $api->get('/restaurants/123/device-settings'); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) DeviceSettings deviceSettings = api.get("/restaurants/123/device-settings", DeviceSettings::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) DeviceSettings deviceSettings = api.get("/restaurants/123/device-settings", DeviceSettings::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val deviceSettings = api.get("/restaurants/123/device-settings", DeviceSettings::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val deviceSettings = api.get("/restaurants/123/device-settings", DeviceSettings::fromJson) // 200// klient: viz /v2/docs/csharp var deviceSettings = await api.GetAsync<DeviceSettings>("/restaurants/123/device-settings"); // 200// the client: see /v2/docs/csharp var deviceSettings = await api.GetAsync<DeviceSettings>("/restaurants/123/device-settings"); // 200# klient: viz /v2/docs/python device_settings = api.get('/restaurants/123/device-settings') # 200# the client: see /v2/docs/python device_settings = api.get('/restaurants/123/device-settings') # 200// klient: viz /v2/docs/swift let deviceSettings: DeviceSettings = try await api.get("/restaurants/123/device-settings") // 200// the client: see /v2/docs/swift let deviceSettings: DeviceSettings = try await api.get("/restaurants/123/device-settings") // 200// klient: viz /v2/docs/dart final deviceSettings = pr.DeviceSettings.fromJson(await api.get('/restaurants/123/device-settings')); // 200// the client: see /v2/docs/dart final deviceSettings = pr.DeviceSettings.fromJson(await api.get('/restaurants/123/device-settings')); // 200// klient: viz /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/device-settings", nil) var deviceSettings model.DeviceSettings // 200 if err == nil { err = res.Decode(&deviceSettings) }// the client: see /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/device-settings", nil) var deviceSettings model.DeviceSettings // 200 if err == nil { err = res.Decode(&deviceSettings) }Příklad odpovědi 200Example answer 200
{ "restaurant": { "name": "Bistro U Lípy", "phone": "+420222333444", "website": "https://www.bistroulipy.cz", "address": { "street": "Vinohradská 1200/48", "city": "Praha 2", "postal_code": "120 00" }, "location": { "lat": 50.0769, "lon": 14.4459 }, "currency": "CZK", "timezone": "Europe/Prague" }, "company": { "name": "U Lípy gastro s.r.o.", "registration_number": "12345678", "vat_number": "CZ12345678", "vat_payer": true, "address": { "street": "Vinohradská 1200/48", "city": "Praha 2", "postal_code": "120 00" }, "email": "ucetni@bistroulipy.cz" }, "receipt_layouts": { "receipt": null, "takeaway": null }, "predefined_notes": [ { "id": "11", "text": "Bez cibule" }, { "id": "12", "text": "Pálivé" }, { "id": "13", "text": "S sebou" } ], "printers": [ { "id": "5", "name": "Účtenky – bar", "sections": "all", "auto_print": false }, { "id": "6", "name": "Bony – kuchyň", "sections": "kitchen", "auto_print": true } ], "kitchen_stations": [ { "id": "2", "name": "Teplá kuchyně", "sections": "kitchen", "auto_print": false }, { "id": "3", "name": "Pizza", "sections": "kitchen", "auto_print": false } ], "rooms": [ { "id": "1", "name": "Restaurace", "width": 100, "height": 100, "tables": [ { "id": "4", "name": "Stůl 4", "kind": "table", "code": "K7M2Q9XB", "left": 12, "top": 20, "width": 14, "height": 10 }, { "id": "7", "name": "Stůl 7", "kind": "table", "code": "3HFD8R2W", "left": 52, "top": 20, "width": 14, "height": 10 }, { "id": "30", "name": "Bar", "kind": "item", "code": null, "left": 80, "top": 70, "width": 18, "height": 25 } ] } ], "kitchen": { "portion_mode": "local", "extra_ticket": false, "redirect_restaurant_id": null, "ready_sms": true }, "eet": { "enabled": true, "premises_id": "273", "certificate_valid_to": "2029-12-31T23:59:59+01:00" }, "features": { "kitchen": true, "multiple_cash_registers": true, "multiple_kitchen_devices": true, "other_devices": true, "attendance": true, "reservations": false, "lodging": false, "daily_menu": true, "table_map": true, "customer_database": true }, "paid_until": "2027-12-31T23:59:59+01:00", "table_ordering": { "enabled": true, "confirm_mode": "first", "empty_table": "staff", "join_code_enabled": true, "max_quantity": 10, "expire_minutes": 10, "respect_opening_hours": true, "category_ids": [ "320" ], "note_max_length": 32, "wifi_ssid": "U Lípy – hosté" }, "pos": { "receipt_cancel_by": "staff", "takeaway_only": false, "calculator": { "enabled": true, "keys": [ { "id": "17", "name": "Pečivo", "vat_rate": "12", "color": "#119b2d", "position": 1 }, { "id": "18", "name": "Zboží", "vat_rate": "21", "color": "#5b4ac0", "position": 2 } ] } } } -
Výběr pokoje
Picking the room
GET /restaurants/{restaurant_id}/lodging/in-house · listInHouseStays
Jen právě ubytovaní hosté, seřazení podle pokoje. Obsluha si podle jména ověří, že jde o správného hosta.
Only guests staying now, ordered by room. The staff check by the name it is the right guest.
curl "https://api.mujprofirest.cz/v2/restaurants/123/lodging/in-house" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/lodging/in-house" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const listInHouseStays = await api.get('/restaurants/123/lodging/in-house'); // 200// the client: see /v2/docs/js const listInHouseStays = await api.get('/restaurants/123/lodging/in-house'); // 200// klient: viz /v2/docs/typescript const listInHouseStays = await api.get('/restaurants/123/lodging/in-house'); // 200 InHouseStays// the client: see /v2/docs/typescript const listInHouseStays = await api.get('/restaurants/123/lodging/in-house'); // 200 InHouseStays// klient: viz /v2/docs/php $listInHouseStays = $api->get('/restaurants/123/lodging/in-house'); // 200// the client: see /v2/docs/php $listInHouseStays = $api->get('/restaurants/123/lodging/in-house'); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) InHouseStays listInHouseStays = api.get("/restaurants/123/lodging/in-house", InHouseStays::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) InHouseStays listInHouseStays = api.get("/restaurants/123/lodging/in-house", InHouseStays::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val listInHouseStays = api.get("/restaurants/123/lodging/in-house", InHouseStays::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val listInHouseStays = api.get("/restaurants/123/lodging/in-house", InHouseStays::fromJson) // 200// klient: viz /v2/docs/csharp var listInHouseStays = await api.GetAsync<InHouseStays>("/restaurants/123/lodging/in-house"); // 200// the client: see /v2/docs/csharp var listInHouseStays = await api.GetAsync<InHouseStays>("/restaurants/123/lodging/in-house"); // 200# klient: viz /v2/docs/python list_in_house_stays = api.get('/restaurants/123/lodging/in-house') # 200# the client: see /v2/docs/python list_in_house_stays = api.get('/restaurants/123/lodging/in-house') # 200// klient: viz /v2/docs/swift let listInHouseStays: InHouseStays = try await api.get("/restaurants/123/lodging/in-house") // 200// the client: see /v2/docs/swift let listInHouseStays: InHouseStays = try await api.get("/restaurants/123/lodging/in-house") // 200// klient: viz /v2/docs/dart final listInHouseStays = pr.InHouseStays.fromJson(await api.get('/restaurants/123/lodging/in-house')); // 200// the client: see /v2/docs/dart final listInHouseStays = pr.InHouseStays.fromJson(await api.get('/restaurants/123/lodging/in-house')); // 200// klient: viz /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/lodging/in-house", nil) var listInHouseStays model.InHouseStays // 200 if err == nil { err = res.Decode(&listInHouseStays) }// the client: see /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/lodging/in-house", nil) var listInHouseStays model.InHouseStays // 200 if err == nil { err = res.Decode(&listInHouseStays) }Příklad odpovědi 200Example answer 200
{ "stays": [ { "id": "193", "room": "101", "guest_name": "Jana Svobodová", "arrival": "2026-11-10", "departure": "2026-11-12", "guests": 2, "balance": { "amount": 496500, "currency": "CZK" }, "package": null }, { "id": "197", "room": "201", "guest_name": "Tomáš Král", "arrival": "2026-11-09", "departure": "2026-11-14", "guests": 4, "balance": { "amount": 1850000, "currency": "CZK" }, "package": { "id": "7", "name": "3 + 1 noc zdarma s wellness" } } ] } -
Zápis útraty
Charging the bill
POST /restaurants/{restaurant_id}/lodging/stays/{stay_id}/charges · chargeToStay
Celkovou částku s DPH a číslo dokladu v
reference– opakovaný pokus se stejnou referencí útratu nezdvojí. Účet s více sazbami DPH pošlete jako více útrat. Host, který už odjel, vrátí409 lodging_state_conflict.The total with VAT and the receipt number in
reference– a repeated attempt with the same reference does not charge twice. Send a bill with more VAT rates as more charges. A guest who has left answers409 lodging_state_conflict.curl "https://api.mujprofirest.cz/v2/restaurants/123/lodging/stays/193/charges" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7b45-99df-39be8ab7315f" \ -H "Content-Type: application/json" \ -d '{ "name": "Restaurace – účet 2026/1184", "amount": {"amount": 84500, "currency": "CZK"}, "vat_rate": 12, "reference": "pokladna-1:2026/1184" }'curl "https://api.mujprofirest.cz/v2/restaurants/123/lodging/stays/193/charges" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7b45-99df-39be8ab7315f" \ -H "Content-Type: application/json" \ -d '{ "name": "Restaurace – účet 2026/1184", "amount": {"amount": 84500, "currency": "CZK"}, "vat_rate": 12, "reference": "pokladna-1:2026/1184" }'// klient: viz /v2/docs/js const chargeToStay = await api.post('/restaurants/123/lodging/stays/193/charges', { name: 'Restaurace – účet 2026/1184', amount: { amount: 84500, currency: 'CZK' }, vat_rate: 12, reference: 'pokladna-1:2026/1184', }); // 201// the client: see /v2/docs/js const chargeToStay = await api.post('/restaurants/123/lodging/stays/193/charges', { name: 'Restaurace – účet 2026/1184', amount: { amount: 84500, currency: 'CZK' }, vat_rate: 12, reference: 'pokladna-1:2026/1184', }); // 201// klient: viz /v2/docs/typescript const chargeToStay = await api.post('/restaurants/123/lodging/stays/193/charges', { name: 'Restaurace – účet 2026/1184', amount: { amount: 84500, currency: 'CZK' }, vat_rate: 12, reference: 'pokladna-1:2026/1184', }); // 201 StayFolio// the client: see /v2/docs/typescript const chargeToStay = await api.post('/restaurants/123/lodging/stays/193/charges', { name: 'Restaurace – účet 2026/1184', amount: { amount: 84500, currency: 'CZK' }, vat_rate: 12, reference: 'pokladna-1:2026/1184', }); // 201 StayFolio// klient: viz /v2/docs/php $chargeToStay = $api->post('/restaurants/123/lodging/stays/193/charges', [ 'name' => 'Restaurace – účet 2026/1184', 'amount' => ['amount' => 84500, 'currency' => 'CZK'], 'vat_rate' => 12, 'reference' => 'pokladna-1:2026/1184', ]); // 201// the client: see /v2/docs/php $chargeToStay = $api->post('/restaurants/123/lodging/stays/193/charges', [ 'name' => 'Restaurace – účet 2026/1184', 'amount' => ['amount' => 84500, 'currency' => 'CZK'], 'vat_rate' => 12, 'reference' => 'pokladna-1:2026/1184', ]); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) StayFolio chargeToStay = api.post("/restaurants/123/lodging/stays/193/charges", Json.parse(""" { "name": "Restaurace – účet 2026/1184", "amount": {"amount": 84500, "currency": "CZK"}, "vat_rate": 12, "reference": "pokladna-1:2026/1184" } """), StayFolio::fromJson); // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) StayFolio chargeToStay = api.post("/restaurants/123/lodging/stays/193/charges", Json.parse(""" { "name": "Restaurace – účet 2026/1184", "amount": {"amount": 84500, "currency": "CZK"}, "vat_rate": 12, "reference": "pokladna-1:2026/1184" } """), StayFolio::fromJson); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val chargeToStay = api.post("/restaurants/123/lodging/stays/193/charges", mapOf( "name" to "Restaurace – účet 2026/1184", "amount" to mapOf("amount" to 84500, "currency" to "CZK"), "vat_rate" to 12, "reference" to "pokladna-1:2026/1184", ), StayFolio::fromJson) // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val chargeToStay = api.post("/restaurants/123/lodging/stays/193/charges", mapOf( "name" to "Restaurace – účet 2026/1184", "amount" to mapOf("amount" to 84500, "currency" to "CZK"), "vat_rate" to 12, "reference" to "pokladna-1:2026/1184", ), StayFolio::fromJson) // 201// klient: viz /v2/docs/csharp var chargeToStay = await api.PostAsync<StayFolio>("/restaurants/123/lodging/stays/193/charges", new { name = "Restaurace – účet 2026/1184", amount = new { amount = 84500, currency = "CZK" }, vat_rate = 12, reference = "pokladna-1:2026/1184", }); // 201// the client: see /v2/docs/csharp var chargeToStay = await api.PostAsync<StayFolio>("/restaurants/123/lodging/stays/193/charges", new { name = "Restaurace – účet 2026/1184", amount = new { amount = 84500, currency = "CZK" }, vat_rate = 12, reference = "pokladna-1:2026/1184", }); // 201# klient: viz /v2/docs/python charge_to_stay = api.post('/restaurants/123/lodging/stays/193/charges', { 'name': 'Restaurace – účet 2026/1184', 'amount': {'amount': 84500, 'currency': 'CZK'}, 'vat_rate': 12, 'reference': 'pokladna-1:2026/1184', }) # 201# the client: see /v2/docs/python charge_to_stay = api.post('/restaurants/123/lodging/stays/193/charges', { 'name': 'Restaurace – účet 2026/1184', 'amount': {'amount': 84500, 'currency': 'CZK'}, 'vat_rate': 12, 'reference': 'pokladna-1:2026/1184', }) # 201// klient: viz /v2/docs/swift let chargeToStay: StayFolio = try await api.post("/restaurants/123/lodging/stays/193/charges", body: [ "name": "Restaurace – účet 2026/1184", "amount": ["amount": 84500, "currency": "CZK"], "vat_rate": 12, "reference": "pokladna-1:2026/1184", ]) // 201// the client: see /v2/docs/swift let chargeToStay: StayFolio = try await api.post("/restaurants/123/lodging/stays/193/charges", body: [ "name": "Restaurace – účet 2026/1184", "amount": ["amount": 84500, "currency": "CZK"], "vat_rate": 12, "reference": "pokladna-1:2026/1184", ]) // 201// klient: viz /v2/docs/dart final chargeToStay = pr.StayFolio.fromJson(await api.post('/restaurants/123/lodging/stays/193/charges', { 'name': 'Restaurace – účet 2026/1184', 'amount': {'amount': 84500, 'currency': 'CZK'}, 'vat_rate': 12, 'reference': 'pokladna-1:2026/1184', })); // 201// the client: see /v2/docs/dart final chargeToStay = pr.StayFolio.fromJson(await api.post('/restaurants/123/lodging/stays/193/charges', { 'name': 'Restaurace – účet 2026/1184', 'amount': {'amount': 84500, 'currency': 'CZK'}, 'vat_rate': 12, 'reference': 'pokladna-1:2026/1184', })); // 201// klient: viz /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/lodging/stays/193/charges", map[string]any{ "name": "Restaurace – účet 2026/1184", "amount": map[string]any{"amount": 84500, "currency": "CZK"}, "vat_rate": 12, "reference": "pokladna-1:2026/1184", }, nil) var chargeToStay model.StayFolio // 201 if err == nil { err = res.Decode(&chargeToStay) }// the client: see /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/lodging/stays/193/charges", map[string]any{ "name": "Restaurace – účet 2026/1184", "amount": map[string]any{"amount": 84500, "currency": "CZK"}, "vat_rate": 12, "reference": "pokladna-1:2026/1184", }, nil) var chargeToStay model.StayFolio // 201 if err == nil { err = res.Decode(&chargeToStay) }Příklad odpovědi 200Example answer 200
{ "stay_id": "193", "status": "checked_in", "package": null, "room": "101", "guest_name": "Jana Svobodová", "arrival": "2026-11-10", "departure": "2026-11-12", "accommodation": { "amount": 600000, "currency": "CZK" }, "city_tax": { "amount": { "amount": 12000, "currency": "CZK" }, "estimate": false }, "lines": [ { "id": "301", "kind": "service", "name": "Snídaně", "quantity": 4, "unit_price": { "amount": 25000, "currency": "CZK" }, "total": { "amount": 100000, "currency": "CZK" }, "vat_rate": 12, "date_from": "2026-11-10", "date_to": "2026-11-12", "reference": null, "created_at": "2026-11-10T15:12:40+01:00" }, { "id": "305", "kind": "pos", "name": "Restaurace – účet 2026/1184", "quantity": 1, "unit_price": { "amount": 84500, "currency": "CZK" }, "total": { "amount": 84500, "currency": "CZK" }, "vat_rate": 12, "date_from": null, "date_to": null, "reference": "pokladna-1:2026/1184", "created_at": "2026-11-10T21:04:12+01:00" } ], "total": { "amount": 796500, "currency": "CZK" }, "payments": [ { "id": "41", "amount": { "amount": 300000, "currency": "CZK" }, "method": "transfer", "note": "záloha", "paid_at": "2026-11-03T09:30:00+01:00" } ], "paid": { "amount": 300000, "currency": "CZK" }, "balance": { "amount": 496500, "currency": "CZK" } } -
Kolik host dluží
What the guest owes
GET /restaurants/{restaurant_id}/lodging/stays/{stay_id}/folio · getStayFolio
Celý účet pokoje se zůstatkem – třeba pro bar, který chce vidět útratu hosta před dalším drinkem.
The whole account of the room with the balance – for example for a bar that wants to see the guest's charges before the next drink.
curl "https://api.mujprofirest.cz/v2/restaurants/123/lodging/stays/193/folio" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/lodging/stays/193/folio" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const stayFolio = await api.get('/restaurants/123/lodging/stays/193/folio'); // 200// the client: see /v2/docs/js const stayFolio = await api.get('/restaurants/123/lodging/stays/193/folio'); // 200// klient: viz /v2/docs/typescript const stayFolio = await api.get('/restaurants/123/lodging/stays/193/folio'); // 200 StayFolio// the client: see /v2/docs/typescript const stayFolio = await api.get('/restaurants/123/lodging/stays/193/folio'); // 200 StayFolio// klient: viz /v2/docs/php $stayFolio = $api->get('/restaurants/123/lodging/stays/193/folio'); // 200// the client: see /v2/docs/php $stayFolio = $api->get('/restaurants/123/lodging/stays/193/folio'); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) StayFolio stayFolio = api.get("/restaurants/123/lodging/stays/193/folio", StayFolio::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) StayFolio stayFolio = api.get("/restaurants/123/lodging/stays/193/folio", StayFolio::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val stayFolio = api.get("/restaurants/123/lodging/stays/193/folio", StayFolio::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val stayFolio = api.get("/restaurants/123/lodging/stays/193/folio", StayFolio::fromJson) // 200// klient: viz /v2/docs/csharp var stayFolio = await api.GetAsync<StayFolio>("/restaurants/123/lodging/stays/193/folio"); // 200// the client: see /v2/docs/csharp var stayFolio = await api.GetAsync<StayFolio>("/restaurants/123/lodging/stays/193/folio"); // 200# klient: viz /v2/docs/python stay_folio = api.get('/restaurants/123/lodging/stays/193/folio') # 200# the client: see /v2/docs/python stay_folio = api.get('/restaurants/123/lodging/stays/193/folio') # 200// klient: viz /v2/docs/swift let stayFolio: StayFolio = try await api.get("/restaurants/123/lodging/stays/193/folio") // 200// the client: see /v2/docs/swift let stayFolio: StayFolio = try await api.get("/restaurants/123/lodging/stays/193/folio") // 200// klient: viz /v2/docs/dart final stayFolio = pr.StayFolio.fromJson(await api.get('/restaurants/123/lodging/stays/193/folio')); // 200// the client: see /v2/docs/dart final stayFolio = pr.StayFolio.fromJson(await api.get('/restaurants/123/lodging/stays/193/folio')); // 200// klient: viz /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/lodging/stays/193/folio", nil) var stayFolio model.StayFolio // 200 if err == nil { err = res.Decode(&stayFolio) }// the client: see /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/lodging/stays/193/folio", nil) var stayFolio model.StayFolio // 200 if err == nil { err = res.Decode(&stayFolio) }Příklad odpovědi 200Example answer 200
{ "stay_id": "193", "status": "checked_in", "package": null, "room": "101", "guest_name": "Jana Svobodová", "arrival": "2026-11-10", "departure": "2026-11-12", "accommodation": { "amount": 600000, "currency": "CZK" }, "city_tax": { "amount": { "amount": 12000, "currency": "CZK" }, "estimate": false }, "lines": [ { "id": "301", "kind": "service", "name": "Snídaně", "quantity": 4, "unit_price": { "amount": 25000, "currency": "CZK" }, "total": { "amount": 100000, "currency": "CZK" }, "vat_rate": 12, "date_from": "2026-11-10", "date_to": "2026-11-12", "reference": null, "created_at": "2026-11-10T15:12:40+01:00" }, { "id": "305", "kind": "pos", "name": "Restaurace – účet 2026/1184", "quantity": 1, "unit_price": { "amount": 84500, "currency": "CZK" }, "total": { "amount": 84500, "currency": "CZK" }, "vat_rate": 12, "date_from": null, "date_to": null, "reference": "pokladna-1:2026/1184", "created_at": "2026-11-10T21:04:12+01:00" } ], "total": { "amount": 796500, "currency": "CZK" }, "payments": [ { "id": "41", "amount": { "amount": 300000, "currency": "CZK" }, "method": "transfer", "note": "záloha", "paid_at": "2026-11-03T09:30:00+01:00" } ], "paid": { "amount": 300000, "currency": "CZK" }, "balance": { "amount": 496500, "currency": "CZK" } }
Scénář
Scenario
Turniket wellness a čtečka na snídani
A wellness gate and a breakfast reader
Turniket, čtečka u vstupu, aplikace obsluhy (guest_passes:check)A gate, a reader at the entrance, a staff application (guest_passes:check)Host má QR kód na stránce pobytu a na kartě hosta. Čtečka ho pošle serveru, ten podle účtu pokoje řekne, jestli host smí dovnitř (neomezeně, tolik osob denně, tolikrát za pobyt), a vstup zapíše.
The guest has a QR code on the stay page and on the guest card. The reader sends it to the server, which says by the account of the room whether the guest may go in (unlimited, so many persons a day, so many times a stay) and records the entry.
-
Ověření a vstup
Check and entry
POST /restaurants/{restaurant_id}/guest-passes/check · checkGuestPass
resultok= otevřít;denied= nepustit a ukázattext. Kolik osob jde najednou, pošlete vpersons; jen ověřit bez zápisu jde srecord: false.resultok= open;denied= do not let in and showtext. Send how many persons go in at once inpersons; to check without recording userecord: false.curl "https://api.mujprofirest.cz/v2/restaurants/123/guest-passes/check" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-72d4-9c43-6a44935e72ff" \ -H "Content-Type: application/json" \ -d '{ "code": "PRU-300-3EE8T62F7H", "place": "wellness", "persons": 2, "device": "Vstup do wellness" }'curl "https://api.mujprofirest.cz/v2/restaurants/123/guest-passes/check" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-72d4-9c43-6a44935e72ff" \ -H "Content-Type: application/json" \ -d '{ "code": "PRU-300-3EE8T62F7H", "place": "wellness", "persons": 2, "device": "Vstup do wellness" }'// klient: viz /v2/docs/js const guestPass = await api.post('/restaurants/123/guest-passes/check', { code: 'PRU-300-3EE8T62F7H', place: 'wellness', persons: 2, device: 'Vstup do wellness', }); // 200// the client: see /v2/docs/js const guestPass = await api.post('/restaurants/123/guest-passes/check', { code: 'PRU-300-3EE8T62F7H', place: 'wellness', persons: 2, device: 'Vstup do wellness', }); // 200// klient: viz /v2/docs/typescript const guestPass = await api.post('/restaurants/123/guest-passes/check', { code: 'PRU-300-3EE8T62F7H', place: 'wellness', persons: 2, device: 'Vstup do wellness', }); // 200 GuestPassCheck// the client: see /v2/docs/typescript const guestPass = await api.post('/restaurants/123/guest-passes/check', { code: 'PRU-300-3EE8T62F7H', place: 'wellness', persons: 2, device: 'Vstup do wellness', }); // 200 GuestPassCheck// klient: viz /v2/docs/php $guestPass = $api->post('/restaurants/123/guest-passes/check', [ 'code' => 'PRU-300-3EE8T62F7H', 'place' => 'wellness', 'persons' => 2, 'device' => 'Vstup do wellness', ]); // 200// the client: see /v2/docs/php $guestPass = $api->post('/restaurants/123/guest-passes/check', [ 'code' => 'PRU-300-3EE8T62F7H', 'place' => 'wellness', 'persons' => 2, 'device' => 'Vstup do wellness', ]); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) GuestPassCheck guestPass = api.post("/restaurants/123/guest-passes/check", Json.parse(""" { "code": "PRU-300-3EE8T62F7H", "place": "wellness", "persons": 2, "device": "Vstup do wellness" } """), GuestPassCheck::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) GuestPassCheck guestPass = api.post("/restaurants/123/guest-passes/check", Json.parse(""" { "code": "PRU-300-3EE8T62F7H", "place": "wellness", "persons": 2, "device": "Vstup do wellness" } """), GuestPassCheck::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val guestPass = api.post("/restaurants/123/guest-passes/check", mapOf( "code" to "PRU-300-3EE8T62F7H", "place" to "wellness", "persons" to 2, "device" to "Vstup do wellness", ), GuestPassCheck::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val guestPass = api.post("/restaurants/123/guest-passes/check", mapOf( "code" to "PRU-300-3EE8T62F7H", "place" to "wellness", "persons" to 2, "device" to "Vstup do wellness", ), GuestPassCheck::fromJson) // 200// klient: viz /v2/docs/csharp var guestPass = await api.PostAsync<GuestPassCheck>("/restaurants/123/guest-passes/check", new { code = "PRU-300-3EE8T62F7H", place = "wellness", persons = 2, device = "Vstup do wellness", }); // 200// the client: see /v2/docs/csharp var guestPass = await api.PostAsync<GuestPassCheck>("/restaurants/123/guest-passes/check", new { code = "PRU-300-3EE8T62F7H", place = "wellness", persons = 2, device = "Vstup do wellness", }); // 200# klient: viz /v2/docs/python guest_pass = api.post('/restaurants/123/guest-passes/check', { 'code': 'PRU-300-3EE8T62F7H', 'place': 'wellness', 'persons': 2, 'device': 'Vstup do wellness', }) # 200# the client: see /v2/docs/python guest_pass = api.post('/restaurants/123/guest-passes/check', { 'code': 'PRU-300-3EE8T62F7H', 'place': 'wellness', 'persons': 2, 'device': 'Vstup do wellness', }) # 200// klient: viz /v2/docs/swift let guestPass: GuestPassCheck = try await api.post("/restaurants/123/guest-passes/check", body: [ "code": "PRU-300-3EE8T62F7H", "place": "wellness", "persons": 2, "device": "Vstup do wellness", ]) // 200// the client: see /v2/docs/swift let guestPass: GuestPassCheck = try await api.post("/restaurants/123/guest-passes/check", body: [ "code": "PRU-300-3EE8T62F7H", "place": "wellness", "persons": 2, "device": "Vstup do wellness", ]) // 200// klient: viz /v2/docs/dart final guestPass = pr.GuestPassCheck.fromJson(await api.post('/restaurants/123/guest-passes/check', { 'code': 'PRU-300-3EE8T62F7H', 'place': 'wellness', 'persons': 2, 'device': 'Vstup do wellness', })); // 200// the client: see /v2/docs/dart final guestPass = pr.GuestPassCheck.fromJson(await api.post('/restaurants/123/guest-passes/check', { 'code': 'PRU-300-3EE8T62F7H', 'place': 'wellness', 'persons': 2, 'device': 'Vstup do wellness', })); // 200// klient: viz /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/guest-passes/check", map[string]any{ "code": "PRU-300-3EE8T62F7H", "place": "wellness", "persons": 2, "device": "Vstup do wellness", }, nil) var guestPass model.GuestPassCheck // 200 if err == nil { err = res.Decode(&guestPass) }// the client: see /v2/docs/go res, err := api.Post(ctx, "/restaurants/123/guest-passes/check", map[string]any{ "code": "PRU-300-3EE8T62F7H", "place": "wellness", "persons": 2, "device": "Vstup do wellness", }, nil) var guestPass model.GuestPassCheck // 200 if err == nil { err = res.Decode(&guestPass) }Příklad odpovědi 200Example answer 200
{ "result": "ok", "title": "Pokoj 201 · 2 osoby", "text": "Wellness neomezeně do 5. 11.", "check_id": "5521", "stay": { "id": "300", "room": "201", "persons": 2, "arrival": "2026-11-01", "departure": "2026-11-05", "package": "3 + 1 noc zdarma s wellness" }, "used_today": 2, "allowed_today": null } -
Host nakonec nešel
The guest did not go in
POST /restaurants/{restaurant_id}/guest-passes/checks/{check_id}/undo · undoGuestPassCheck
Vstup se vrátí a nepočítá do denního limitu.
The entry is undone and does not count to the daily limit.
curl -X POST "https://api.mujprofirest.cz/v2/restaurants/123/guest-passes/checks/5521/undo" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7e7e-998e-3c5af3025287"curl -X POST "https://api.mujprofirest.cz/v2/restaurants/123/guest-passes/checks/5521/undo" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7e7e-998e-3c5af3025287"// klient: viz /v2/docs/js await api.post('/restaurants/123/guest-passes/checks/5521/undo', null);// the client: see /v2/docs/js await api.post('/restaurants/123/guest-passes/checks/5521/undo', null);// klient: viz /v2/docs/typescript await api.post('/restaurants/123/guest-passes/checks/5521/undo', null);// the client: see /v2/docs/typescript await api.post('/restaurants/123/guest-passes/checks/5521/undo', null);// klient: viz /v2/docs/php $api->post('/restaurants/123/guest-passes/checks/5521/undo', null);// the client: see /v2/docs/php $api->post('/restaurants/123/guest-passes/checks/5521/undo', null);// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) api.post("/restaurants/123/guest-passes/checks/5521/undo", null);// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) api.post("/restaurants/123/guest-passes/checks/5521/undo", null);// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) api.post("/restaurants/123/guest-passes/checks/5521/undo", null)// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) api.post("/restaurants/123/guest-passes/checks/5521/undo", null)// klient: viz /v2/docs/csharp await api.PostAsync("/restaurants/123/guest-passes/checks/5521/undo", (object?)null);// the client: see /v2/docs/csharp await api.PostAsync("/restaurants/123/guest-passes/checks/5521/undo", (object?)null);# klient: viz /v2/docs/python api.post('/restaurants/123/guest-passes/checks/5521/undo', None)# the client: see /v2/docs/python api.post('/restaurants/123/guest-passes/checks/5521/undo', None)// klient: viz /v2/docs/swift try await api.post("/restaurants/123/guest-passes/checks/5521/undo", body: nil)// the client: see /v2/docs/swift try await api.post("/restaurants/123/guest-passes/checks/5521/undo", body: nil)// klient: viz /v2/docs/dart await api.post('/restaurants/123/guest-passes/checks/5521/undo', null);// the client: see /v2/docs/dart await api.post('/restaurants/123/guest-passes/checks/5521/undo', null);// klient: viz /v2/docs/go _, err := api.Post(ctx, "/restaurants/123/guest-passes/checks/5521/undo", nil, nil)// the client: see /v2/docs/go _, err := api.Post(ctx, "/restaurants/123/guest-passes/checks/5521/undo", nil, nil) -
Co balíčky obsahují
What packages include
GET /restaurants/{restaurant_id}/lodging/packages · listLodgingPackages
Pro informační obrazovky a web: noci zdarma, sleva, příplatek a služby v ceně.
For information screens and the website: free nights, discount, surcharge and included services.
curl "https://api.mujprofirest.cz/v2/restaurants/123/lodging/packages" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/lodging/packages" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const listLodgingPackages = await api.get('/restaurants/123/lodging/packages'); // 200// the client: see /v2/docs/js const listLodgingPackages = await api.get('/restaurants/123/lodging/packages'); // 200// klient: viz /v2/docs/typescript const listLodgingPackages = await api.get('/restaurants/123/lodging/packages'); // 200 LodgingPackageList// the client: see /v2/docs/typescript const listLodgingPackages = await api.get('/restaurants/123/lodging/packages'); // 200 LodgingPackageList// klient: viz /v2/docs/php $listLodgingPackages = $api->get('/restaurants/123/lodging/packages'); // 200// the client: see /v2/docs/php $listLodgingPackages = $api->get('/restaurants/123/lodging/packages'); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) LodgingPackageList listLodgingPackages = api.get("/restaurants/123/lodging/packages", LodgingPackageList::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) LodgingPackageList listLodgingPackages = api.get("/restaurants/123/lodging/packages", LodgingPackageList::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val listLodgingPackages = api.get("/restaurants/123/lodging/packages", LodgingPackageList::fromJson) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val listLodgingPackages = api.get("/restaurants/123/lodging/packages", LodgingPackageList::fromJson) // 200// klient: viz /v2/docs/csharp var listLodgingPackages = await api.GetAsync<LodgingPackageList>("/restaurants/123/lodging/packages"); // 200// the client: see /v2/docs/csharp var listLodgingPackages = await api.GetAsync<LodgingPackageList>("/restaurants/123/lodging/packages"); // 200# klient: viz /v2/docs/python list_lodging_packages = api.get('/restaurants/123/lodging/packages') # 200# the client: see /v2/docs/python list_lodging_packages = api.get('/restaurants/123/lodging/packages') # 200// klient: viz /v2/docs/swift let listLodgingPackages: LodgingPackageList = try await api.get("/restaurants/123/lodging/packages") // 200// the client: see /v2/docs/swift let listLodgingPackages: LodgingPackageList = try await api.get("/restaurants/123/lodging/packages") // 200// klient: viz /v2/docs/dart final listLodgingPackages = pr.LodgingPackageList.fromJson(await api.get('/restaurants/123/lodging/packages')); // 200// the client: see /v2/docs/dart final listLodgingPackages = pr.LodgingPackageList.fromJson(await api.get('/restaurants/123/lodging/packages')); // 200// klient: viz /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/lodging/packages", nil) var listLodgingPackages model.LodgingPackageList // 200 if err == nil { err = res.Decode(&listLodgingPackages) }// the client: see /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/lodging/packages", nil) var listLodgingPackages model.LodgingPackageList // 200 if err == nil { err = res.Decode(&listLodgingPackages) }Příklad odpovědi 200Example answer 200
{ "data": [ { "id": "7", "name": "3 + 1 noc zdarma s wellness", "description": "Čtvrtou noc máte od nás. Wellness bez omezení a snídaně v ceně.", "room_type_ids": [], "min_nights": 4, "pay_nights": 3, "free_nights": 1, "discount_percent": 0, "price_extra": { "amount": 0, "currency": "CZK" }, "services": [ { "id": "4", "name": "Snídaně", "category": "breakfast" }, { "id": "9", "name": "Wellness neomezeně", "category": "wellness" } ], "valid_from": null, "valid_to": null, "online": true }, { "id": "8", "name": "Romantický víkend", "description": "Lahev sektu na pokoji a masáž.", "room_type_ids": [ "43" ], "min_nights": 2, "pay_nights": 0, "free_nights": 0, "discount_percent": 0, "price_extra": { "amount": 149000, "currency": "CZK" }, "services": [ { "id": "6", "name": "Lahev sektu", "category": "drink" } ], "valid_from": "2026-11-01", "valid_to": "2027-02-28", "online": true } ] }
Scénář
Scenario
Aplikace pro pokojské a údržbu
An application for housekeepers and maintenance
Aplikace pokojských, systém údržby (housekeeping:read, housekeeping:write)A housekeeping application, a maintenance system (housekeeping:read, housekeeping:write)Pokojská má v telefonu pokoje, které dnes uklízí, odškrtává hotové a hlásí závady. Recepce na plachtě hned vidí, který pokoj je uklizený, a pokoj se závadou se sám vyřadí z prodeje.
The housekeeper has the rooms to clean today in her phone, ticks off what is done and reports faults. The reception sees at once on the room plan which room is clean, and a room with a fault takes itself out of sale.
-
Úkoly dne
The tasks of the day
GET /restaurants/{restaurant_id}/housekeeping · getHousekeepingDay
Pokoje jsou seřazené od nejnaléhavějšího: kam dnes přijíždí host do neuklizeného pokoje.
assigned_employee_idřekne, kterou pokojskou má pokoj přidělenou – ukažte jí jen její pokoje. Jména hostů tu nejsou.The rooms are ordered from the most urgent: where guests arrive today to a room not cleaned yet.
assigned_employee_idtells which housekeeper the room is assigned to – show her only her rooms. Guests' names are not there.curl "https://api.mujprofirest.cz/v2/restaurants/123/housekeeping?date=2026-11-05" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/housekeeping?date=2026-11-05" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN"// klient: viz /v2/docs/js // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const housekeepingDay = await api.get('/restaurants/123/housekeeping', { query: { date: '2026-11-05' } }); // 200// the client: see /v2/docs/js // the library adds the employee's token itself (after the employee signs in) const housekeepingDay = await api.get('/restaurants/123/housekeeping', { query: { date: '2026-11-05' } }); // 200// klient: viz /v2/docs/typescript // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const housekeepingDay = await api.get('/restaurants/123/housekeeping', { query: { date: '2026-11-05' } }); // 200 HousekeepingDay// the client: see /v2/docs/typescript // the library adds the employee's token itself (after the employee signs in) const housekeepingDay = await api.get('/restaurants/123/housekeeping', { query: { date: '2026-11-05' } }); // 200 HousekeepingDay// klient: viz /v2/docs/php // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) $housekeepingDay = $api->get('/restaurants/123/housekeeping', ['query' => ['date' => '2026-11-05']]); // 200// the client: see /v2/docs/php // the library adds the employee's token itself (after the employee signs in) $housekeepingDay = $api->get('/restaurants/123/housekeeping', ['query' => ['date' => '2026-11-05']]); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) HousekeepingDay housekeepingDay = api.get( "/restaurants/123/housekeeping", RequestOptions.builder().query("date", "2026-11-05").build(), HousekeepingDay::fromJson ); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) HousekeepingDay housekeepingDay = api.get( "/restaurants/123/housekeeping", RequestOptions.builder().query("date", "2026-11-05").build(), HousekeepingDay::fromJson ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) val housekeepingDay = api.get( "/restaurants/123/housekeeping", RequestOptions.builder().query("date", "2026-11-05").build(), HousekeepingDay::fromJson, ) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) val housekeepingDay = api.get( "/restaurants/123/housekeeping", RequestOptions.builder().query("date", "2026-11-05").build(), HousekeepingDay::fromJson, ) // 200// klient: viz /v2/docs/csharp // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) var housekeepingDay = await api.GetAsync<HousekeepingDay>( "/restaurants/123/housekeeping", new RequestOptions { Query = new() { ["date"] = "2026-11-05" } } ); // 200// the client: see /v2/docs/csharp // the library adds the employee's token itself (after the employee signs in) var housekeepingDay = await api.GetAsync<HousekeepingDay>( "/restaurants/123/housekeeping", new RequestOptions { Query = new() { ["date"] = "2026-11-05" } } ); // 200# klient: viz /v2/docs/python # token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) housekeeping_day = api.get('/restaurants/123/housekeeping', query={'date': '2026-11-05'}) # 200# the client: see /v2/docs/python # the library adds the employee's token itself (after the employee signs in) housekeeping_day = api.get('/restaurants/123/housekeeping', query={'date': '2026-11-05'}) # 200// klient: viz /v2/docs/swift // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) let housekeepingDay: HousekeepingDay = try await api.get("/restaurants/123/housekeeping", options: .init(query: ["date": "2026-11-05"])) // 200// the client: see /v2/docs/swift // the library adds the employee's token itself (after the employee signs in) let housekeepingDay: HousekeepingDay = try await api.get("/restaurants/123/housekeeping", options: .init(query: ["date": "2026-11-05"])) // 200// klient: viz /v2/docs/dart // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) final housekeepingDay = pr.HousekeepingDay.fromJson(await api.get('/restaurants/123/housekeeping', query: {'date': '2026-11-05'})); // 200// the client: see /v2/docs/dart // the library adds the employee's token itself (after the employee signs in) final housekeepingDay = pr.HousekeepingDay.fromJson(await api.get('/restaurants/123/housekeeping', query: {'date': '2026-11-05'})); // 200// klient: viz /v2/docs/go // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) res, err := api.Get( ctx, "/restaurants/123/housekeeping", &profirest.RequestOptions{Query: map[string]any{"date": "2026-11-05"}}, ) var housekeepingDay model.HousekeepingDay // 200 if err == nil { err = res.Decode(&housekeepingDay) }// the client: see /v2/docs/go // the library adds the employee's token itself (after the employee signs in) res, err := api.Get( ctx, "/restaurants/123/housekeeping", &profirest.RequestOptions{Query: map[string]any{"date": "2026-11-05"}}, ) var housekeepingDay model.HousekeepingDay // 200 if err == nil { err = res.Decode(&housekeepingDay) }Příklad odpovědi 200Example answer 200
{ "date": "2026-11-05", "inspection": false, "summary": { "tasks": 5, "done": 0, "rooms": 3, "arrivals": 1, "waiting": 1 }, "rooms": [ { "id": "104", "name": "104", "floor": "1", "type": "Dvoulůžkový", "status": "dirty", "occupied": false, "arrival": { "persons": 3, "extra_beds": 1, "from": "14:00", "checked_in": false }, "departure": { "left": true }, "tasks": [ { "key": "checkout", "name": "Úklid po odjezdu", "done": false, "done_at": null, "done_by_employee_id": null, "waiting": false, "note": null, "manual": false }, { "key": "extra_bed", "name": "Připravit přistýlku", "done": false, "done_at": null, "done_by_employee_id": null, "waiting": false, "note": null, "manual": false } ], "assigned_employee_id": "102", "issues": [] }, { "id": "201", "name": "201", "floor": "2", "type": "Jednolůžkový", "status": "clean", "occupied": true, "arrival": null, "departure": { "left": false }, "tasks": [ { "key": "checkout", "name": "Úklid po odjezdu", "done": false, "done_at": null, "done_by_employee_id": null, "waiting": true, "note": "Host ještě neodjel (odjezd do 10:00)", "manual": false } ], "assigned_employee_id": "101", "issues": [] }, { "id": "102", "name": "102", "floor": "1", "type": "Dvoulůžkový", "status": "clean", "occupied": true, "arrival": null, "departure": null, "tasks": [ { "key": "stay", "name": "Úklid obsazeného pokoje", "done": false, "done_at": null, "done_by_employee_id": null, "waiting": false, "note": null, "manual": false }, { "key": "rule:3", "name": "Výměna ručníků", "done": false, "done_at": null, "done_by_employee_id": null, "waiting": false, "note": null, "manual": false } ], "assigned_employee_id": "102", "issues": [ { "id": "57", "room_id": "102", "room": "102", "text": "Kape kohoutek v koupelně", "blocks_room": false, "status": "open", "created_at": "2026-11-05T09:12:40+01:00", "created_by_employee_id": "102", "fixed_at": null, "fix_note": null } ] } ] } -
Odškrtnutí
Ticking off
POST /restaurants/{restaurant_id}/housekeeping/rooms/{room_id}/done · completeHousekeepingTask
Úkol s
waitingještě nejde (host neodjel) – vrátí409 lodging_state_conflict. Se staff tokenem se zapíše, která pokojská úkol udělala.A task with
waitingcannot be done yet (the guest has not left) – it answers409 lodging_state_conflict. With a staff token the housekeeper who did it is recorded.curl "https://api.mujprofirest.cz/v2/restaurants/123/housekeeping/rooms/104/done" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7b36-947a-2c030af53645" \ -H "Content-Type: application/json" \ -d '{"task": "checkout", "date": "2026-11-05"}'curl "https://api.mujprofirest.cz/v2/restaurants/123/housekeeping/rooms/104/done" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-7b36-947a-2c030af53645" \ -H "Content-Type: application/json" \ -d '{"task": "checkout", "date": "2026-11-05"}'// klient: viz /v2/docs/js // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const housekeepingTask = await api.post('/restaurants/123/housekeeping/rooms/104/done', { task: 'checkout', date: '2026-11-05' }); // 200// the client: see /v2/docs/js // the library adds the employee's token itself (after the employee signs in) const housekeepingTask = await api.post('/restaurants/123/housekeeping/rooms/104/done', { task: 'checkout', date: '2026-11-05' }); // 200// klient: viz /v2/docs/typescript // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const housekeepingTask = await api.post('/restaurants/123/housekeeping/rooms/104/done', { task: 'checkout', date: '2026-11-05' }); // 200 HousekeepingRoom// the client: see /v2/docs/typescript // the library adds the employee's token itself (after the employee signs in) const housekeepingTask = await api.post('/restaurants/123/housekeeping/rooms/104/done', { task: 'checkout', date: '2026-11-05' }); // 200 HousekeepingRoom// klient: viz /v2/docs/php // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) $housekeepingTask = $api->post( '/restaurants/123/housekeeping/rooms/104/done', ['task' => 'checkout', 'date' => '2026-11-05'], ); // 200// the client: see /v2/docs/php // the library adds the employee's token itself (after the employee signs in) $housekeepingTask = $api->post( '/restaurants/123/housekeeping/rooms/104/done', ['task' => 'checkout', 'date' => '2026-11-05'], ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) HousekeepingRoom housekeepingTask = api.post("/restaurants/123/housekeeping/rooms/104/done", Json.parse(""" {"task": "checkout", "date": "2026-11-05"} """), HousekeepingRoom::fromJson); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) HousekeepingRoom housekeepingTask = api.post("/restaurants/123/housekeeping/rooms/104/done", Json.parse(""" {"task": "checkout", "date": "2026-11-05"} """), HousekeepingRoom::fromJson); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) val housekeepingTask = api.post( "/restaurants/123/housekeeping/rooms/104/done", mapOf("task" to "checkout", "date" to "2026-11-05"), HousekeepingRoom::fromJson, ) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) val housekeepingTask = api.post( "/restaurants/123/housekeeping/rooms/104/done", mapOf("task" to "checkout", "date" to "2026-11-05"), HousekeepingRoom::fromJson, ) // 200// klient: viz /v2/docs/csharp // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) var housekeepingTask = await api.PostAsync<HousekeepingRoom>( "/restaurants/123/housekeeping/rooms/104/done", new { task = "checkout", date = "2026-11-05" } ); // 200// the client: see /v2/docs/csharp // the library adds the employee's token itself (after the employee signs in) var housekeepingTask = await api.PostAsync<HousekeepingRoom>( "/restaurants/123/housekeeping/rooms/104/done", new { task = "checkout", date = "2026-11-05" } ); // 200# klient: viz /v2/docs/python # token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) housekeeping_task = api.post('/restaurants/123/housekeeping/rooms/104/done', {'task': 'checkout', 'date': '2026-11-05'}) # 200# the client: see /v2/docs/python # the library adds the employee's token itself (after the employee signs in) housekeeping_task = api.post('/restaurants/123/housekeeping/rooms/104/done', {'task': 'checkout', 'date': '2026-11-05'}) # 200// klient: viz /v2/docs/swift // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) let housekeepingTask: HousekeepingRoom = try await api.post( "/restaurants/123/housekeeping/rooms/104/done", body: ["task": "checkout", "date": "2026-11-05"] ) // 200// the client: see /v2/docs/swift // the library adds the employee's token itself (after the employee signs in) let housekeepingTask: HousekeepingRoom = try await api.post( "/restaurants/123/housekeeping/rooms/104/done", body: ["task": "checkout", "date": "2026-11-05"] ) // 200// klient: viz /v2/docs/dart // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) final housekeepingTask = pr.HousekeepingRoom.fromJson(await api.post('/restaurants/123/housekeeping/rooms/104/done', {'task': 'checkout', 'date': '2026-11-05'})); // 200// the client: see /v2/docs/dart // the library adds the employee's token itself (after the employee signs in) final housekeepingTask = pr.HousekeepingRoom.fromJson(await api.post('/restaurants/123/housekeeping/rooms/104/done', {'task': 'checkout', 'date': '2026-11-05'})); // 200// klient: viz /v2/docs/go // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) res, err := api.Post( ctx, "/restaurants/123/housekeeping/rooms/104/done", map[string]any{"task": "checkout", "date": "2026-11-05"}, nil, ) var housekeepingTask model.HousekeepingRoom // 200 if err == nil { err = res.Decode(&housekeepingTask) }// the client: see /v2/docs/go // the library adds the employee's token itself (after the employee signs in) res, err := api.Post( ctx, "/restaurants/123/housekeeping/rooms/104/done", map[string]any{"task": "checkout", "date": "2026-11-05"}, nil, ) var housekeepingTask model.HousekeepingRoom // 200 if err == nil { err = res.Decode(&housekeepingTask) }Příklad odpovědi 200Example answer 200
{ "id": "104", "name": "104", "floor": "1", "type": "Dvoulůžkový", "status": "clean", "occupied": false, "arrival": { "persons": 3, "extra_beds": 1, "from": "14:00", "checked_in": false }, "departure": { "left": true }, "tasks": [ { "key": "checkout", "name": "Úklid po odjezdu", "done": true, "done_at": "2026-11-05T10:15:02+01:00", "done_by_employee_id": "102", "waiting": false, "note": null, "manual": false }, { "key": "extra_bed", "name": "Připravit přistýlku", "done": false, "done_at": null, "done_by_employee_id": null, "waiting": false, "note": null, "manual": false } ], "assigned_employee_id": "102", "issues": [] } -
Závada
A fault
POST /restaurants/{restaurant_id}/room-issues · reportRoomIssue
S
blocks_roompokoj nejde prodat, dokud ho údržba neoznačí přesfixRoomIssue;warningřekne, že má pokoj pobyty, které recepce musí přesunout.With
blocks_roomthe room cannot be sold until the maintenance marks it withfixRoomIssue;warningsays the room has stays the reception must move.curl "https://api.mujprofirest.cz/v2/restaurants/123/room-issues" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-741b-b510-e49d71d4ae33" \ -H "Content-Type: application/json" \ -d '{"room_id": "102", "text": "Kape kohoutek v koupelně", "blocks_room": false}'curl "https://api.mujprofirest.cz/v2/restaurants/123/room-issues" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Profirest-Staff-Token: $STAFF_TOKEN" \ -H "Idempotency-Key: 01a318f0-a0c0-741b-b510-e49d71d4ae33" \ -H "Content-Type: application/json" \ -d '{"room_id": "102", "text": "Kape kohoutek v koupelně", "blocks_room": false}'// klient: viz /v2/docs/js // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const roomIssue = await api.post( '/restaurants/123/room-issues', { room_id: '102', text: 'Kape kohoutek v koupelně', blocks_room: false }, ); // 201// the client: see /v2/docs/js // the library adds the employee's token itself (after the employee signs in) const roomIssue = await api.post( '/restaurants/123/room-issues', { room_id: '102', text: 'Kape kohoutek v koupelně', blocks_room: false }, ); // 201// klient: viz /v2/docs/typescript // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) const roomIssue = await api.post( '/restaurants/123/room-issues', { room_id: '102', text: 'Kape kohoutek v koupelně', blocks_room: false }, ); // 201 RoomIssueReported// the client: see /v2/docs/typescript // the library adds the employee's token itself (after the employee signs in) const roomIssue = await api.post( '/restaurants/123/room-issues', { room_id: '102', text: 'Kape kohoutek v koupelně', blocks_room: false }, ); // 201 RoomIssueReported// klient: viz /v2/docs/php // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) $roomIssue = $api->post( '/restaurants/123/room-issues', ['room_id' => '102', 'text' => 'Kape kohoutek v koupelně', 'blocks_room' => false], ); // 201// the client: see /v2/docs/php // the library adds the employee's token itself (after the employee signs in) $roomIssue = $api->post( '/restaurants/123/room-issues', ['room_id' => '102', 'text' => 'Kape kohoutek v koupelně', 'blocks_room' => false], ); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) RoomIssueReported roomIssue = api.post("/restaurants/123/room-issues", Json.parse(""" {"room_id": "102", "text": "Kape kohoutek v koupelně", "blocks_room": false} """), RoomIssueReported::fromJson); // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) RoomIssueReported roomIssue = api.post("/restaurants/123/room-issues", Json.parse(""" {"room_id": "102", "text": "Kape kohoutek v koupelně", "blocks_room": false} """), RoomIssueReported::fromJson); // 201// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) val roomIssue = api.post( "/restaurants/123/room-issues", mapOf("room_id" to "102", "text" to "Kape kohoutek v koupelně", "blocks_room" to false), RoomIssueReported::fromJson, ) // 201// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) // the library adds the employee's token itself (after the employee signs in) val roomIssue = api.post( "/restaurants/123/room-issues", mapOf("room_id" to "102", "text" to "Kape kohoutek v koupelně", "blocks_room" to false), RoomIssueReported::fromJson, ) // 201// klient: viz /v2/docs/csharp // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) var roomIssue = await api.PostAsync<RoomIssueReported>( "/restaurants/123/room-issues", new { room_id = "102", text = "Kape kohoutek v koupelně", blocks_room = false } ); // 201// the client: see /v2/docs/csharp // the library adds the employee's token itself (after the employee signs in) var roomIssue = await api.PostAsync<RoomIssueReported>( "/restaurants/123/room-issues", new { room_id = "102", text = "Kape kohoutek v koupelně", blocks_room = false } ); // 201# klient: viz /v2/docs/python # token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) room_issue = api.post( '/restaurants/123/room-issues', {'room_id': '102', 'text': 'Kape kohoutek v koupelně', 'blocks_room': False}, ) # 201# the client: see /v2/docs/python # the library adds the employee's token itself (after the employee signs in) room_issue = api.post( '/restaurants/123/room-issues', {'room_id': '102', 'text': 'Kape kohoutek v koupelně', 'blocks_room': False}, ) # 201// klient: viz /v2/docs/swift // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) let roomIssue: RoomIssueReported = try await api.post( "/restaurants/123/room-issues", body: ["room_id": "102", "text": "Kape kohoutek v koupelně", "blocks_room": false] ) // 201// the client: see /v2/docs/swift // the library adds the employee's token itself (after the employee signs in) let roomIssue: RoomIssueReported = try await api.post( "/restaurants/123/room-issues", body: ["room_id": "102", "text": "Kape kohoutek v koupelně", "blocks_room": false] ) // 201// klient: viz /v2/docs/dart // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) final roomIssue = pr.RoomIssueReported.fromJson(await api.post( '/restaurants/123/room-issues', {'room_id': '102', 'text': 'Kape kohoutek v koupelně', 'blocks_room': false}, )); // 201// the client: see /v2/docs/dart // the library adds the employee's token itself (after the employee signs in) final roomIssue = pr.RoomIssueReported.fromJson(await api.post( '/restaurants/123/room-issues', {'room_id': '102', 'text': 'Kape kohoutek v koupelně', 'blocks_room': false}, )); // 201// klient: viz /v2/docs/go // token zaměstnance přidá knihovna sama (po přihlášení zaměstnance) res, err := api.Post(ctx, "/restaurants/123/room-issues", map[string]any{ "room_id": "102", "text": "Kape kohoutek v koupelně", "blocks_room": false, }, nil) var roomIssue model.RoomIssueReported // 201 if err == nil { err = res.Decode(&roomIssue) }// the client: see /v2/docs/go // the library adds the employee's token itself (after the employee signs in) res, err := api.Post(ctx, "/restaurants/123/room-issues", map[string]any{ "room_id": "102", "text": "Kape kohoutek v koupelně", "blocks_room": false, }, nil) var roomIssue model.RoomIssueReported // 201 if err == nil { err = res.Decode(&roomIssue) }Příklad odpovědi 201Example answer 201
{ "issue": { "id": "57", "room_id": "102", "room": "102", "text": "Kape kohoutek v koupelně", "blocks_room": false, "status": "open", "created_at": "2026-11-05T09:12:40+01:00", "created_by_employee_id": "102", "fixed_at": null, "fix_note": null }, "warning": null }
Scénář
Scenario
Účetnictví a přehledy
Accounting and reports
Partner s oprávněním reports:readA partner with reports:readÚčetní nebo BI systém stahuje uzávěrky a doklady ze všech pokladen, webu i kuchyně, bere si přehledy jako Statistiky administrace a nové doklady mu chodí jako události. Částky a DPH sedí s kopií účtenky.
A bookkeeping or BI system downloads shift closes and sales documents from all registers, the web and the kitchen, takes the reports the Statistics of the administration show, and new documents come to it as events. Amounts and VAT match the receipt copy.
-
Uzávěrky
Shift closes
GET /restaurants/{restaurant_id}/shift-closes · listShiftCloses
Od nejnovější, se součty jako detail uzávěrky v administraci: tržba po platbách, storna, dýška, slevy a tržba evidovaná v EET.
Newest first, with the totals of the close detail in the administration: takings by payment, cancellations, tips, discounts and the takings recorded in EET.
curl "https://api.mujprofirest.cz/v2/restaurants/123/shift-closes?date_from=2027-01-01&date_to=2027-01-15" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/shift-closes?date_from=2027-01-01&date_to=2027-01-15" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const { data, next_cursor } = await api.get( '/restaurants/123/shift-closes', { query: { date_from: '2027-01-01', date_to: '2027-01-15' } }, ); // 200// the client: see /v2/docs/js const { data, next_cursor } = await api.get( '/restaurants/123/shift-closes', { query: { date_from: '2027-01-01', date_to: '2027-01-15' } }, ); // 200// klient: viz /v2/docs/typescript const { data, next_cursor } = await api.get( '/restaurants/123/shift-closes', { query: { date_from: '2027-01-01', date_to: '2027-01-15' } }, ); // 200 ShiftClosePage// the client: see /v2/docs/typescript const { data, next_cursor } = await api.get( '/restaurants/123/shift-closes', { query: { date_from: '2027-01-01', date_to: '2027-01-15' } }, ); // 200 ShiftClosePage// klient: viz /v2/docs/php $page = $api->get( '/restaurants/123/shift-closes', ['query' => ['date_from' => '2027-01-01', 'date_to' => '2027-01-15']], ); // $page['data'], $page['next_cursor']// the client: see /v2/docs/php $page = $api->get( '/restaurants/123/shift-closes', ['query' => ['date_from' => '2027-01-01', 'date_to' => '2027-01-15']], ); // $page['data'], $page['next_cursor']// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) ShiftClosePage listShiftCloses = api.get( "/restaurants/123/shift-closes", RequestOptions.builder().query("date_from", "2027-01-01").query("date_to", "2027-01-15").build(), ShiftClosePage::fromJson ); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) ShiftClosePage listShiftCloses = api.get( "/restaurants/123/shift-closes", RequestOptions.builder().query("date_from", "2027-01-01").query("date_to", "2027-01-15").build(), ShiftClosePage::fromJson ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val listShiftCloses = api.get( "/restaurants/123/shift-closes", RequestOptions.builder().query("date_from", "2027-01-01").query("date_to", "2027-01-15").build(), ShiftClosePage::fromJson, ) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val listShiftCloses = api.get( "/restaurants/123/shift-closes", RequestOptions.builder().query("date_from", "2027-01-01").query("date_to", "2027-01-15").build(), ShiftClosePage::fromJson, ) // 200// klient: viz /v2/docs/csharp var listShiftCloses = await api.GetAsync<ShiftClosePage>( "/restaurants/123/shift-closes", new RequestOptions { Query = new() { ["date_from"] = "2027-01-01", ["date_to"] = "2027-01-15" } } ); // 200// the client: see /v2/docs/csharp var listShiftCloses = await api.GetAsync<ShiftClosePage>( "/restaurants/123/shift-closes", new RequestOptions { Query = new() { ["date_from"] = "2027-01-01", ["date_to"] = "2027-01-15" } } ); // 200# klient: viz /v2/docs/python page = api.get('/restaurants/123/shift-closes', query={'date_from': '2027-01-01', 'date_to': '2027-01-15'}) # page['data'], page['next_cursor']# the client: see /v2/docs/python page = api.get('/restaurants/123/shift-closes', query={'date_from': '2027-01-01', 'date_to': '2027-01-15'}) # page['data'], page['next_cursor']// klient: viz /v2/docs/swift let listShiftCloses: ShiftClosePage = try await api.get( "/restaurants/123/shift-closes", options: .init(query: ["date_from": "2027-01-01", "date_to": "2027-01-15"]) ) // 200// the client: see /v2/docs/swift let listShiftCloses: ShiftClosePage = try await api.get( "/restaurants/123/shift-closes", options: .init(query: ["date_from": "2027-01-01", "date_to": "2027-01-15"]) ) // 200// klient: viz /v2/docs/dart final listShiftCloses = pr.ShiftClosePage.fromJson(await api.get( '/restaurants/123/shift-closes', query: {'date_from': '2027-01-01', 'date_to': '2027-01-15'}, )); // 200// the client: see /v2/docs/dart final listShiftCloses = pr.ShiftClosePage.fromJson(await api.get( '/restaurants/123/shift-closes', query: {'date_from': '2027-01-01', 'date_to': '2027-01-15'}, )); // 200// klient: viz /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/shift-closes", &profirest.RequestOptions{Query: map[string]any{"date_from": "2027-01-01", "date_to": "2027-01-15"}}, ) var listShiftCloses model.ShiftClosePage // 200 if err == nil { err = res.Decode(&listShiftCloses) }// the client: see /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/shift-closes", &profirest.RequestOptions{Query: map[string]any{"date_from": "2027-01-01", "date_to": "2027-01-15"}}, ) var listShiftCloses model.ShiftClosePage // 200 if err == nil { err = res.Decode(&listShiftCloses) }Příklad odpovědi 200Example answer 200
{ "data": [ { "id": "5512", "restaurant_id": "123", "closed_at": "2027-01-15T23:05:12+01:00", "closed_by": { "id": "102", "name": "Jana Nováková" }, "source": "mixed", "device_id": null, "orders": 87, "totals": { "completed": { "amount": 4573000, "currency": "CZK" }, "by_payment": { "cash": { "amount": 1912000, "currency": "CZK" }, "card": { "amount": 2511000, "currency": "CZK" }, "meal_voucher": { "amount": 150000, "currency": "CZK" }, "company_account": { "amount": 0, "currency": "CZK" }, "invoice": { "amount": 0, "currency": "CZK" } }, "not_completed": { "amount": 0, "currency": "CZK" }, "cancelled_orders": { "amount": 39800, "currency": "CZK" }, "cancelled_items": { "amount": 13800, "currency": "CZK" }, "tips": { "total": { "amount": 52000, "currency": "CZK" }, "cash": { "amount": 18000, "currency": "CZK" }, "card": { "amount": 34000, "currency": "CZK" } }, "discounts": { "order": { "amount": 12000, "currency": "CZK" }, "items": { "amount": 4500, "currency": "CZK" } }, "eet_registered": { "amount": 4573000, "currency": "CZK" }, "by_ticket": { "kitchen": { "amount": 3120000, "currency": "CZK" }, "bar": { "amount": 1453000, "currency": "CZK" } } } } ], "next_cursor": null } -
Doklady den po dni
Documents day by day
GET /restaurants/{restaurant_id}/sales · listSales
Od nejstaršího podle uzavření, stránkovaně – položky, slevy, doprava, rozpis DPH, platby, EET a uzávěrka. Storno je samostatný doklad se zápornými částkami.
Oldest first by the time they were closed, paged – lines, discounts, delivery, the VAT breakdown, payments, EET and the shift. A cancellation is its own document with negative amounts.
curl "https://api.mujprofirest.cz/v2/restaurants/123/sales?date_from=2027-01-15&date_to=2027-01-15" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/sales?date_from=2027-01-15&date_to=2027-01-15" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const { data, next_cursor } = await api.get('/restaurants/123/sales', { query: { date_from: '2027-01-15', date_to: '2027-01-15' } }); // 200// the client: see /v2/docs/js const { data, next_cursor } = await api.get('/restaurants/123/sales', { query: { date_from: '2027-01-15', date_to: '2027-01-15' } }); // 200// klient: viz /v2/docs/typescript const { data, next_cursor } = await api.get('/restaurants/123/sales', { query: { date_from: '2027-01-15', date_to: '2027-01-15' } }); // 200 SalePage// the client: see /v2/docs/typescript const { data, next_cursor } = await api.get('/restaurants/123/sales', { query: { date_from: '2027-01-15', date_to: '2027-01-15' } }); // 200 SalePage// klient: viz /v2/docs/php $page = $api->get( '/restaurants/123/sales', ['query' => ['date_from' => '2027-01-15', 'date_to' => '2027-01-15']], ); // $page['data'], $page['next_cursor']// the client: see /v2/docs/php $page = $api->get( '/restaurants/123/sales', ['query' => ['date_from' => '2027-01-15', 'date_to' => '2027-01-15']], ); // $page['data'], $page['next_cursor']// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) SalePage listSales = api.get( "/restaurants/123/sales", RequestOptions.builder().query("date_from", "2027-01-15").query("date_to", "2027-01-15").build(), SalePage::fromJson ); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) SalePage listSales = api.get( "/restaurants/123/sales", RequestOptions.builder().query("date_from", "2027-01-15").query("date_to", "2027-01-15").build(), SalePage::fromJson ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val listSales = api.get( "/restaurants/123/sales", RequestOptions.builder().query("date_from", "2027-01-15").query("date_to", "2027-01-15").build(), SalePage::fromJson, ) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val listSales = api.get( "/restaurants/123/sales", RequestOptions.builder().query("date_from", "2027-01-15").query("date_to", "2027-01-15").build(), SalePage::fromJson, ) // 200// klient: viz /v2/docs/csharp var listSales = await api.GetAsync<SalePage>( "/restaurants/123/sales", new RequestOptions { Query = new() { ["date_from"] = "2027-01-15", ["date_to"] = "2027-01-15" } } ); // 200// the client: see /v2/docs/csharp var listSales = await api.GetAsync<SalePage>( "/restaurants/123/sales", new RequestOptions { Query = new() { ["date_from"] = "2027-01-15", ["date_to"] = "2027-01-15" } } ); // 200# klient: viz /v2/docs/python page = api.get('/restaurants/123/sales', query={'date_from': '2027-01-15', 'date_to': '2027-01-15'}) # page['data'], page['next_cursor']# the client: see /v2/docs/python page = api.get('/restaurants/123/sales', query={'date_from': '2027-01-15', 'date_to': '2027-01-15'}) # page['data'], page['next_cursor']// klient: viz /v2/docs/swift let listSales: SalePage = try await api.get( "/restaurants/123/sales", options: .init(query: ["date_from": "2027-01-15", "date_to": "2027-01-15"]) ) // 200// the client: see /v2/docs/swift let listSales: SalePage = try await api.get( "/restaurants/123/sales", options: .init(query: ["date_from": "2027-01-15", "date_to": "2027-01-15"]) ) // 200// klient: viz /v2/docs/dart final listSales = pr.SalePage.fromJson(await api.get('/restaurants/123/sales', query: {'date_from': '2027-01-15', 'date_to': '2027-01-15'})); // 200// the client: see /v2/docs/dart final listSales = pr.SalePage.fromJson(await api.get('/restaurants/123/sales', query: {'date_from': '2027-01-15', 'date_to': '2027-01-15'})); // 200// klient: viz /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/sales", &profirest.RequestOptions{Query: map[string]any{"date_from": "2027-01-15", "date_to": "2027-01-15"}}, ) var listSales model.SalePage // 200 if err == nil { err = res.Decode(&listSales) }// the client: see /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/sales", &profirest.RequestOptions{Query: map[string]any{"date_from": "2027-01-15", "date_to": "2027-01-15"}}, ) var listSales model.SalePage // 200 if err == nil { err = res.Decode(&listSales) }Příklad odpovědi 200Example answer 200
{ "data": [ { "id": "880417", "number": "1043", "kind": "sale", "source": "pos", "platform": null, "table_name": "Stůl 4", "created_at": "2027-01-15T11:48:02+01:00", "closed_at": "2027-01-15T12:31:40+01:00", "employee": { "id": "58", "name": "Jana Dvořáková" }, "lines": [ { "type": "product", "product_id": "4567", "name": "Svíčková na smetaně, houskový knedlík", "quantity": 1, "unit_price": { "amount": 19900, "currency": "CZK" }, "packaging_unit_price": null, "discount_per_unit": { "amount": 0, "currency": "CZK" }, "vat_rate": "12", "total": { "amount": 19900, "currency": "CZK" } }, { "type": "product", "product_id": "4590", "name": "Pivo 12° 0,5 l", "quantity": 2, "unit_price": { "amount": 6900, "currency": "CZK" }, "packaging_unit_price": null, "discount_per_unit": { "amount": 0, "currency": "CZK" }, "vat_rate": "21", "total": { "amount": 13800, "currency": "CZK" } } ], "items_total": { "amount": 33700, "currency": "CZK" }, "discounts": [], "delivery_fee": { "amount": 0, "currency": "CZK" }, "price_adjustment": { "amount": 0, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "total": { "amount": 33700, "currency": "CZK" }, "vat": [ { "rate": "21", "base": { "amount": 11405, "currency": "CZK" }, "vat": { "amount": 2395, "currency": "CZK" }, "total": { "amount": 13800, "currency": "CZK" } }, { "rate": "12", "base": { "amount": 17768, "currency": "CZK" }, "vat": { "amount": 2132, "currency": "CZK" }, "total": { "amount": 19900, "currency": "CZK" } } ], "voucher_payments": [], "amount_paid": { "amount": 33700, "currency": "CZK" }, "payment_method": "card", "card_at_handover": false, "tip": { "amount": 3000, "currency": "CZK" }, "eet": { "fik": null, "bkp": null, "status": "accepted", "pok": "ab12cd34-0000-4000-8000-000000000001-03" }, "shift_id": "5512", "cancels": null, "cancelled_by": null } ], "next_cursor": null } -
Rozpis DPH
VAT by rate
GET /restaurants/{restaurant_id}/reports/vat · getVatReport
DPH po sazbách za období, spočítané stejně jako kopie účtenky; prodané dárkové vouchery zvlášť.
VAT by rate for a period, computed the same way as the receipt copy; sold gift vouchers separately.
curl "https://api.mujprofirest.cz/v2/restaurants/123/reports/vat?date_from=2027-01-11&date_to=2027-01-15" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/reports/vat?date_from=2027-01-11&date_to=2027-01-15" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const vatReport = await api.get( '/restaurants/123/reports/vat', { query: { date_from: '2027-01-11', date_to: '2027-01-15' } }, ); // 200// the client: see /v2/docs/js const vatReport = await api.get( '/restaurants/123/reports/vat', { query: { date_from: '2027-01-11', date_to: '2027-01-15' } }, ); // 200// klient: viz /v2/docs/typescript const vatReport = await api.get( '/restaurants/123/reports/vat', { query: { date_from: '2027-01-11', date_to: '2027-01-15' } }, ); // 200 VatReport// the client: see /v2/docs/typescript const vatReport = await api.get( '/restaurants/123/reports/vat', { query: { date_from: '2027-01-11', date_to: '2027-01-15' } }, ); // 200 VatReport// klient: viz /v2/docs/php $vatReport = $api->get( '/restaurants/123/reports/vat', ['query' => ['date_from' => '2027-01-11', 'date_to' => '2027-01-15']], ); // 200// the client: see /v2/docs/php $vatReport = $api->get( '/restaurants/123/reports/vat', ['query' => ['date_from' => '2027-01-11', 'date_to' => '2027-01-15']], ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) VatReport vatReport = api.get( "/restaurants/123/reports/vat", RequestOptions.builder().query("date_from", "2027-01-11").query("date_to", "2027-01-15").build(), VatReport::fromJson ); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) VatReport vatReport = api.get( "/restaurants/123/reports/vat", RequestOptions.builder().query("date_from", "2027-01-11").query("date_to", "2027-01-15").build(), VatReport::fromJson ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val vatReport = api.get( "/restaurants/123/reports/vat", RequestOptions.builder().query("date_from", "2027-01-11").query("date_to", "2027-01-15").build(), VatReport::fromJson, ) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val vatReport = api.get( "/restaurants/123/reports/vat", RequestOptions.builder().query("date_from", "2027-01-11").query("date_to", "2027-01-15").build(), VatReport::fromJson, ) // 200// klient: viz /v2/docs/csharp var vatReport = await api.GetAsync<VatReport>( "/restaurants/123/reports/vat", new RequestOptions { Query = new() { ["date_from"] = "2027-01-11", ["date_to"] = "2027-01-15" } } ); // 200// the client: see /v2/docs/csharp var vatReport = await api.GetAsync<VatReport>( "/restaurants/123/reports/vat", new RequestOptions { Query = new() { ["date_from"] = "2027-01-11", ["date_to"] = "2027-01-15" } } ); // 200# klient: viz /v2/docs/python vat_report = api.get('/restaurants/123/reports/vat', query={'date_from': '2027-01-11', 'date_to': '2027-01-15'}) # 200# the client: see /v2/docs/python vat_report = api.get('/restaurants/123/reports/vat', query={'date_from': '2027-01-11', 'date_to': '2027-01-15'}) # 200// klient: viz /v2/docs/swift let vatReport: VatReport = try await api.get( "/restaurants/123/reports/vat", options: .init(query: ["date_from": "2027-01-11", "date_to": "2027-01-15"]) ) // 200// the client: see /v2/docs/swift let vatReport: VatReport = try await api.get( "/restaurants/123/reports/vat", options: .init(query: ["date_from": "2027-01-11", "date_to": "2027-01-15"]) ) // 200// klient: viz /v2/docs/dart final vatReport = pr.VatReport.fromJson(await api.get('/restaurants/123/reports/vat', query: {'date_from': '2027-01-11', 'date_to': '2027-01-15'})); // 200// the client: see /v2/docs/dart final vatReport = pr.VatReport.fromJson(await api.get('/restaurants/123/reports/vat', query: {'date_from': '2027-01-11', 'date_to': '2027-01-15'})); // 200// klient: viz /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/reports/vat", &profirest.RequestOptions{Query: map[string]any{"date_from": "2027-01-11", "date_to": "2027-01-15"}}, ) var vatReport model.VatReport // 200 if err == nil { err = res.Decode(&vatReport) }// the client: see /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/reports/vat", &profirest.RequestOptions{Query: map[string]any{"date_from": "2027-01-11", "date_to": "2027-01-15"}}, ) var vatReport model.VatReport // 200 if err == nil { err = res.Decode(&vatReport) }Příklad odpovědi 200Example answer 200
{ "date_from": "2027-01-11", "date_to": "2027-01-15", "rates": [ { "rate": "21", "base": { "amount": 3962810, "currency": "CZK" }, "vat": { "amount": 832190, "currency": "CZK" }, "total": { "amount": 4795000, "currency": "CZK" } }, { "rate": "12", "base": { "amount": 8263393, "currency": "CZK" }, "vat": { "amount": 991607, "currency": "CZK" }, "total": { "amount": 9255000, "currency": "CZK" } } ], "vouchers_sold": { "amount": 200000, "currency": "CZK" } } -
Přehled tržeb
Revenue summary
GET /restaurants/{restaurant_id}/reports/sales-summary · getSalesSummary
Tržby po dnech, hodinách, platbách, zdrojích, obsluze nebo stolech – stejná čísla jako Statistiky v administraci. Prodej položek dává
getProductSales, spropitnégetTipsReport. Provozovna s ubytováním nebo vstupenkami:segment=foodnechá jen gastro,group_by=segmentrozdělí tržbu na gastro, ubytování a vstupenky.Revenue by day, hour, payment, source, staff or table – the same numbers as the Statistics in the administration. Product sales come from
getProductSales, tips fromgetTipsReport. A restaurant with accommodation or tickets:segment=foodkeeps only food and drinks,group_by=segmentsplits the revenue into food, accommodation and tickets.curl "https://api.mujprofirest.cz/v2/restaurants/123/reports/sales-summary?date_from=2027-01-11&date_to=2027-01-15&group_by=payment" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/restaurants/123/reports/sales-summary?date_from=2027-01-11&date_to=2027-01-15&group_by=payment" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const salesSummary = await api.get( '/restaurants/123/reports/sales-summary', { query: { date_from: '2027-01-11', date_to: '2027-01-15', group_by: 'payment' } }, ); // 200// the client: see /v2/docs/js const salesSummary = await api.get( '/restaurants/123/reports/sales-summary', { query: { date_from: '2027-01-11', date_to: '2027-01-15', group_by: 'payment' } }, ); // 200// klient: viz /v2/docs/typescript const salesSummary = await api.get( '/restaurants/123/reports/sales-summary', { query: { date_from: '2027-01-11', date_to: '2027-01-15', group_by: 'payment' } }, ); // 200 SalesSummary// the client: see /v2/docs/typescript const salesSummary = await api.get( '/restaurants/123/reports/sales-summary', { query: { date_from: '2027-01-11', date_to: '2027-01-15', group_by: 'payment' } }, ); // 200 SalesSummary// klient: viz /v2/docs/php $salesSummary = $api->get( '/restaurants/123/reports/sales-summary', ['query' => ['date_from' => '2027-01-11', 'date_to' => '2027-01-15', 'group_by' => 'payment']], ); // 200// the client: see /v2/docs/php $salesSummary = $api->get( '/restaurants/123/reports/sales-summary', ['query' => ['date_from' => '2027-01-11', 'date_to' => '2027-01-15', 'group_by' => 'payment']], ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) SalesSummary salesSummary = api.get( "/restaurants/123/reports/sales-summary", RequestOptions.builder().query("date_from", "2027-01-11").query("date_to", "2027-01-15").query("group_by", "payment").build(), SalesSummary::fromJson ); // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) SalesSummary salesSummary = api.get( "/restaurants/123/reports/sales-summary", RequestOptions.builder().query("date_from", "2027-01-11").query("date_to", "2027-01-15").query("group_by", "payment").build(), SalesSummary::fromJson ); // 200// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val salesSummary = api.get( "/restaurants/123/reports/sales-summary", RequestOptions.builder().query("date_from", "2027-01-11").query("date_to", "2027-01-15").query("group_by", "payment").build(), SalesSummary::fromJson, ) // 200// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val salesSummary = api.get( "/restaurants/123/reports/sales-summary", RequestOptions.builder().query("date_from", "2027-01-11").query("date_to", "2027-01-15").query("group_by", "payment").build(), SalesSummary::fromJson, ) // 200// klient: viz /v2/docs/csharp var salesSummary = await api.GetAsync<SalesSummary>( "/restaurants/123/reports/sales-summary", new RequestOptions { Query = new() { ["date_from"] = "2027-01-11", ["date_to"] = "2027-01-15", ["group_by"] = "payment" } } ); // 200// the client: see /v2/docs/csharp var salesSummary = await api.GetAsync<SalesSummary>( "/restaurants/123/reports/sales-summary", new RequestOptions { Query = new() { ["date_from"] = "2027-01-11", ["date_to"] = "2027-01-15", ["group_by"] = "payment" } } ); // 200# klient: viz /v2/docs/python sales_summary = api.get( '/restaurants/123/reports/sales-summary', query={'date_from': '2027-01-11', 'date_to': '2027-01-15', 'group_by': 'payment'}, ) # 200# the client: see /v2/docs/python sales_summary = api.get( '/restaurants/123/reports/sales-summary', query={'date_from': '2027-01-11', 'date_to': '2027-01-15', 'group_by': 'payment'}, ) # 200// klient: viz /v2/docs/swift let salesSummary: SalesSummary = try await api.get( "/restaurants/123/reports/sales-summary", options: .init(query: ["date_from": "2027-01-11", "date_to": "2027-01-15", "group_by": "payment"]) ) // 200// the client: see /v2/docs/swift let salesSummary: SalesSummary = try await api.get( "/restaurants/123/reports/sales-summary", options: .init(query: ["date_from": "2027-01-11", "date_to": "2027-01-15", "group_by": "payment"]) ) // 200// klient: viz /v2/docs/dart final salesSummary = pr.SalesSummary.fromJson(await api.get( '/restaurants/123/reports/sales-summary', query: {'date_from': '2027-01-11', 'date_to': '2027-01-15', 'group_by': 'payment'}, )); // 200// the client: see /v2/docs/dart final salesSummary = pr.SalesSummary.fromJson(await api.get( '/restaurants/123/reports/sales-summary', query: {'date_from': '2027-01-11', 'date_to': '2027-01-15', 'group_by': 'payment'}, )); // 200// klient: viz /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/reports/sales-summary", &profirest.RequestOptions{Query: map[string]any{"date_from": "2027-01-11", "date_to": "2027-01-15", "group_by": "payment"}}, ) var salesSummary model.SalesSummary // 200 if err == nil { err = res.Decode(&salesSummary) }// the client: see /v2/docs/go res, err := api.Get( ctx, "/restaurants/123/reports/sales-summary", &profirest.RequestOptions{Query: map[string]any{"date_from": "2027-01-11", "date_to": "2027-01-15", "group_by": "payment"}}, ) var salesSummary model.SalesSummary // 200 if err == nil { err = res.Decode(&salesSummary) }Příklad odpovědi 200Example answer 200
{ "date_from": "2027-01-11", "date_to": "2027-01-15", "group_by": "payment", "segment": null, "totals": { "revenue": { "amount": 14250000, "currency": "CZK" }, "orders": 512, "average_order": { "amount": 27832, "currency": "CZK" }, "tips": { "amount": 318000, "currency": "CZK" } }, "rows": [ { "key": "card", "name": null, "revenue": { "amount": 8915000, "currency": "CZK" }, "orders": 301 }, { "key": "cash", "name": null, "revenue": { "amount": 4830000, "currency": "CZK" }, "orders": 196 }, { "key": "meal_voucher", "name": null, "revenue": { "amount": 505000, "currency": "CZK" }, "orders": 15 } ] } -
Export do účetnictví
Export to accounting
GET /restaurants/{restaurant_id}/accounting-export · getAccountingExport
Soubor pro Pohodu nebo Money za období; potřebuje i oprávnění
accounting:read.A file for Pohoda or Money for a period; it needs the
accounting:readscope too.curl "https://api.mujprofirest.cz/v2/restaurants/123/accounting-export?format=pohoda&type=receipts&date_from=2027-01-01&date_to=2027-01-15" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -o zaloha.zipcurl "https://api.mujprofirest.cz/v2/restaurants/123/accounting-export?format=pohoda&type=receipts&date_from=2027-01-01&date_to=2027-01-15" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -o zaloha.zip// klient: viz /v2/docs/js const zip = await api.get('/restaurants/123/accounting-export', { accept: 'application/xml' });// the client: see /v2/docs/js const zip = await api.get('/restaurants/123/accounting-export', { accept: 'application/xml' });// klient: viz /v2/docs/typescript const zip = await api.get('/restaurants/123/accounting-export', { accept: 'application/xml' });// the client: see /v2/docs/typescript const zip = await api.get('/restaurants/123/accounting-export', { accept: 'application/xml' });// klient: viz /v2/docs/php file_put_contents('zaloha.zip', $api->get('/restaurants/123/accounting-export', ['accept' => 'application/xml']));// the client: see /v2/docs/php file_put_contents('zaloha.zip', $api->get('/restaurants/123/accounting-export', ['accept' => 'application/xml']));// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) byte[] zip = (byte[]) api.get("/restaurants/123/accounting-export", RequestOptions.builder().accept("application/xml").build()); Files.write(Path.of("zaloha.zip"), zip);// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) byte[] zip = (byte[]) api.get("/restaurants/123/accounting-export", RequestOptions.builder().accept("application/xml").build()); Files.write(Path.of("zaloha.zip"), zip);// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val zip = api.get("/restaurants/123/accounting-export", RequestOptions.builder().accept("application/xml").build()) as ByteArray File("zaloha.zip").writeBytes(zip)// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val zip = api.get("/restaurants/123/accounting-export", RequestOptions.builder().accept("application/xml").build()) as ByteArray File("zaloha.zip").writeBytes(zip)// klient: viz /v2/docs/csharp byte[]? zip = await api.GetAsync<byte[]>("/restaurants/123/accounting-export", new RequestOptions { Accept = "application/xml" }); await File.WriteAllBytesAsync("zaloha.zip", zip!);// the client: see /v2/docs/csharp byte[]? zip = await api.GetAsync<byte[]>("/restaurants/123/accounting-export", new RequestOptions { Accept = "application/xml" }); await File.WriteAllBytesAsync("zaloha.zip", zip!);# klient: viz /v2/docs/python zip_bytes = api.get('/restaurants/123/accounting-export', accept='application/xml') with open('zaloha.zip', 'wb') as fh: fh.write(zip_bytes)# the client: see /v2/docs/python zip_bytes = api.get('/restaurants/123/accounting-export', accept='application/xml') with open('zaloha.zip', 'wb') as fh: fh.write(zip_bytes)// klient: viz /v2/docs/swift let zip: Data = try await api.get("/restaurants/123/accounting-export", options: .init(accept: "application/xml")) try zip.write(to: zipURL)// the client: see /v2/docs/swift let zip: Data = try await api.get("/restaurants/123/accounting-export", options: .init(accept: "application/xml")) try zip.write(to: zipURL)// klient: viz /v2/docs/dart final zip = await api.get('/restaurants/123/accounting-export', accept: 'application/xml') as List<int>; await File('zaloha.zip').writeAsBytes(zip);// the client: see /v2/docs/dart final zip = await api.get('/restaurants/123/accounting-export', accept: 'application/xml') as List<int>; await File('zaloha.zip').writeAsBytes(zip);// klient: viz /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/accounting-export", &profirest.RequestOptions{Accept: "application/xml"}) if err == nil { err = os.WriteFile("zaloha.zip", res.Body, 0o600) }// the client: see /v2/docs/go res, err := api.Get(ctx, "/restaurants/123/accounting-export", &profirest.RequestOptions{Accept: "application/xml"}) if err == nil { err = os.WriteFile("zaloha.zip", res.Body, 0o600) } -
Nové doklady průběžně
New documents as they come
GET /events · listEvents
Nový doklad přijde jako
sale.created, stornovaný jakosale.cancelleda uzávěrka jakoshift.closed– ze všech zdrojů do zhruba tří minut, v datech je celý doklad nebo uzávěrka. Seznamy pak stačí na dohnání po výpadku.A new document comes as
sale.created, a cancelled one assale.cancelledand a close asshift.closed– from all sources within about three minutes, the data is the whole document or close. The lists are then needed only to catch up after an outage.curl "https://api.mujprofirest.cz/v2/events?cursor=eyJzZXEiOjkxMDU1MH0&restaurant_id=123&limit=100" \ -H "Authorization: Bearer $ACCESS_TOKEN"curl "https://api.mujprofirest.cz/v2/events?cursor=eyJzZXEiOjkxMDU1MH0&restaurant_id=123&limit=100" \ -H "Authorization: Bearer $ACCESS_TOKEN"// klient: viz /v2/docs/js const feed = api.watchEvents({ restaurantId: '123', onEvents: async (events) => { for (const event of events) handle(event); // kurzor se posune až potom }, onReset: () => reloadEverything(), // 410 cursor_expired: načtěte stav znovu });// the client: see /v2/docs/js const feed = api.watchEvents({ restaurantId: '123', onEvents: async (events) => { for (const event of events) handle(event); // the cursor moves only afterwards }, onReset: () => reloadEverything(), // 410 cursor_expired: reload the state });// klient: viz /v2/docs/typescript const feed = api.watchEvents({ restaurantId: '123', onEvents: async (events) => { for (const event of events) handle(event); // kurzor se posune až potom }, onReset: () => reloadEverything(), // 410 cursor_expired: načtěte stav znovu });// the client: see /v2/docs/typescript const feed = api.watchEvents({ restaurantId: '123', onEvents: async (events) => { for (const event of events) handle(event); // the cursor moves only afterwards }, onReset: () => reloadEverything(), // 410 cursor_expired: reload the state });// klient: viz /v2/docs/php $api->watchEvents([ 'restaurantId' => '123', 'onEvents' => function (array $events): void { foreach ($events as $event) { handle($event); } // kurzor se posune až potom }, 'onReset' => fn() => reloadEverything(), // 410 cursor_expired: načtěte stav znovu ])->run();// the client: see /v2/docs/php $api->watchEvents([ 'restaurantId' => '123', 'onEvents' => function (array $events): void { foreach ($events as $event) { handle($event); } // the cursor moves only afterwards }, 'onReset' => fn() => reloadEverything(), // 410 cursor_expired: reload the state ])->run();// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) EventWatcher feed = api.watchEvents(WatchOptions.builder() .restaurantId("123") .onEvents(events -> events.forEach(this::handle)) // kurzor se posune až potom .onReset(error -> reloadEverything()) // 410 cursor_expired: načtěte stav znovu .build()); feed.start();// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) EventWatcher feed = api.watchEvents(WatchOptions.builder() .restaurantId("123") .onEvents(events -> events.forEach(this::handle)) // the cursor moves only afterwards .onReset(error -> reloadEverything()) // 410 cursor_expired: reload the state .build()); feed.start();// klient: viz /v2/docs/java // volání blokuje – na Androidu z pracovního vlákna (Dispatchers.IO) val feed = api.watchEvents(WatchOptions.builder() .restaurantId("123") .onEvents { events -> events.forEach { handle(it) } } // kurzor se posune až potom .onReset { reloadEverything() } // 410 cursor_expired: načtěte stav znovu .build()) feed.start()// the client: see /v2/docs/java // the call blocks – on Android from a worker thread (Dispatchers.IO) val feed = api.watchEvents(WatchOptions.builder() .restaurantId("123") .onEvents { events -> events.forEach { handle(it) } } // the cursor moves only afterwards .onReset { reloadEverything() } // 410 cursor_expired: reload the state .build()) feed.start()// klient: viz /v2/docs/csharp await api.WatchEventsAsync(new WatchOptions { RestaurantId = "123", OnEvents = async (events, ct) => { foreach (var e in events) await HandleAsync(e, ct); }, // kurzor se posune až potom OnReset = _ => ReloadEverythingAsync(), // 410 cursor_expired: načtěte stav znovu }, stoppingToken);// the client: see /v2/docs/csharp await api.WatchEventsAsync(new WatchOptions { RestaurantId = "123", OnEvents = async (events, ct) => { foreach (var e in events) await HandleAsync(e, ct); }, // the cursor moves only afterwards OnReset = _ => ReloadEverythingAsync(), // 410 cursor_expired: reload the state }, stoppingToken);# klient: viz /v2/docs/python feed = api.watch_events( lambda events: [handle(event) for event in events], # kurzor se posune až potom restaurant_id='123', on_reset=lambda error: reload_everything(), # 410 cursor_expired: načtěte stav znovu ) feed.start()# the client: see /v2/docs/python feed = api.watch_events( lambda events: [handle(event) for event in events], # the cursor moves only afterwards restaurant_id='123', on_reset=lambda error: reload_everything(), # 410 cursor_expired: reload the state ) feed.start()// klient: viz /v2/docs/swift let feed = api.watchEvents(.init( restaurantID: "123", onEvents: { events in for event in events { handle(event) } }, // kurzor se posune až potom onReset: { _ in reloadEverything() } // 410 cursor_expired: načtěte stav znovu )) // feed.cancel() čtení ukončí// the client: see /v2/docs/swift let feed = api.watchEvents(.init( restaurantID: "123", onEvents: { events in for event in events { handle(event) } }, // the cursor moves only afterwards onReset: { _ in reloadEverything() } // 410 cursor_expired: reload the state )) // feed.cancel() čtení ukončí// klient: viz /v2/docs/dart final feed = api.watchEvents( restaurantId: '123', onEvents: (events) async { for (final event in events) handle(event); }, // kurzor se posune až potom onReset: (error) => reloadEverything(), // 410 cursor_expired: načtěte stav znovu )..start();// the client: see /v2/docs/dart final feed = api.watchEvents( restaurantId: '123', onEvents: (events) async { for (final event in events) handle(event); }, // the cursor moves only afterwards onReset: (error) => reloadEverything(), // 410 cursor_expired: reload the state )..start();// klient: viz /v2/docs/go err := api.WatchEvents(ctx, profirest.WatchOptions{ RestaurantID: "123", OnEvents: func(ctx context.Context, events []model.Event) error { for _, event := range events { handle(event) // kurzor se posune až potom } return nil }, OnReset: func(*profirest.APIError) { reloadEverything() }, // 410 cursor_expired: načtěte stav znovu })// the client: see /v2/docs/go err := api.WatchEvents(ctx, profirest.WatchOptions{ RestaurantID: "123", OnEvents: func(ctx context.Context, events []model.Event) error { for _, event := range events { handle(event) // the cursor moves only afterwards } return nil }, OnReset: func(*profirest.APIError) { reloadEverything() }, // 410 cursor_expired: reload the state })Příklad odpovědi 200Example answer 200
{ "data": [ { "id": "910551", "api_version": "2", "sequence": 910551, "type": "order.created", "occurred_at": "2027-01-15T11:42:31+01:00", "connection_id": "2208", "account_id": "7", "restaurant_id": "123", "data": { "id": "184223", "restaurant_id": "123", "kitchen_number": "027", "status": "received", "status_changed_at": "2027-01-15T11:42:31+01:00", "created_at": "2027-01-15T11:42:31+01:00", "payment_deadline": null, "fulfillment": { "type": "pickup", "speed": "standard", "asap": true, "time": null, "estimated_at": "2027-01-15T12:05:00+01:00" }, "customer": { "customer_id": null, "name": "Jana Nováková", "phone": "+420777123456", "email": "jana.novakova@example.cz" }, "delivery": null, "lines": [ { "id": "1", "type": "product", "product_id": "4567", "name": "Svíčková na smetaně, houskový knedlík", "quantity": 2, "base_unit_price": { "amount": 19900, "currency": "CZK" }, "unit_price": { "amount": 19900, "currency": "CZK" }, "packaging_unit_price": null, "vat_rate": "12", "add_ons": [], "options": [], "parts": null, "removed_ingredients": [], "note": null, "total": { "amount": 39800, "currency": "CZK" }, "gift_of": null } ], "charges": [], "discounts": [], "totals": { "items": { "amount": 39800, "currency": "CZK" }, "charges": { "amount": 0, "currency": "CZK" }, "discounts": { "amount": 0, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" }, "vat": [ { "rate": "12", "base": { "amount": 35536, "currency": "CZK" }, "vat": { "amount": 4264, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" } } ] }, "payments": [ { "id": "301877", "method": "cash", "status": "unpaid", "amount": { "amount": 39800, "currency": "CZK" }, "provider": null, "reference": null, "voucher_code": null, "forfeited": null } ], "amount_to_collect": { "amount": 39800, "currency": "CZK" }, "loyalty_points_earned": null, "note": null, "cancellation": null, "external_id": "A-2027-000123", "metadata": { "branch": "praha-3" } } }, { "id": "910563", "api_version": "2", "sequence": 910563, "type": "order.status_changed", "occurred_at": "2027-01-15T11:44:02+01:00", "connection_id": "2208", "account_id": "7", "restaurant_id": "123", "data": { "id": "184223", "restaurant_id": "123", "kitchen_number": "027", "status": "preparing", "status_changed_at": "2027-01-15T11:44:02+01:00", "created_at": "2027-01-15T11:42:31+01:00", "payment_deadline": null, "fulfillment": { "type": "pickup", "speed": "standard", "asap": true, "time": null, "estimated_at": "2027-01-15T12:05:00+01:00" }, "customer": { "customer_id": null, "name": "Jana Nováková", "phone": "+420777123456", "email": "jana.novakova@example.cz" }, "delivery": null, "lines": [ { "id": "1", "type": "product", "product_id": "4567", "name": "Svíčková na smetaně, houskový knedlík", "quantity": 2, "base_unit_price": { "amount": 19900, "currency": "CZK" }, "unit_price": { "amount": 19900, "currency": "CZK" }, "packaging_unit_price": null, "vat_rate": "12", "add_ons": [], "options": [], "parts": null, "removed_ingredients": [], "note": null, "total": { "amount": 39800, "currency": "CZK" }, "gift_of": null } ], "charges": [], "discounts": [], "totals": { "items": { "amount": 39800, "currency": "CZK" }, "charges": { "amount": 0, "currency": "CZK" }, "discounts": { "amount": 0, "currency": "CZK" }, "rounding": { "amount": 0, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" }, "vat": [ { "rate": "12", "base": { "amount": 35536, "currency": "CZK" }, "vat": { "amount": 4264, "currency": "CZK" }, "total": { "amount": 39800, "currency": "CZK" } } ] }, "payments": [ { "id": "301877", "method": "cash", "status": "unpaid", "amount": { "amount": 39800, "currency": "CZK" }, "provider": null, "reference": null, "voucher_code": null, "forfeited": null } ], "amount_to_collect": { "amount": 39800, "currency": "CZK" }, "loyalty_points_earned": null, "note": null, "cancellation": null, "external_id": "A-2027-000123", "metadata": { "branch": "praha-3" } } }, { "id": "910570", "api_version": "2", "sequence": 910570, "type": "availability.changed", "occurred_at": "2027-01-15T11:45:10+01:00", "connection_id": "2208", "account_id": "7", "restaurant_id": "123", "data": { "restaurant_id": "123" } } ], "next_cursor": "eyJzZXEiOjkxMDU3MH0" }