Werzeick API
Reference API
Každé volání na https://werzeick-dev.isc.hm/api/, generované z kódu serveru: co které bere, čím odpovídá a proč odpovídá tak, jak odpovídá. Popisy jsou převzaté z kódu a jsou anglicky.
Každý požadavek kromě veřejných nese klíč v hlavičce, jak ukazuje průvodce: Authorization: Bearer wzk_…
Stáhnout jako OpenAPI 3.1 (JSON) · tatáž reference, pro generátory klientů a jiné nástroje.
Zůstává v tomto poli a jde jen na https://werzeick-dev.isc.hm/api/, v hlavičce, nikdy s vaším přihlášením: požadavek odeslaný odsud je klíče a nikoho jiného. Požadavek, který zapisuje, se ptá dvakrát.
Přihlášení a relace
Signing in and the session: a code by email, the session it buys, and the entry that session is in.
A session is one membership in one role. Switching company, or role at the same company, is a new session; the old token is revoked. An API key is made in one entry too, and acts as it unless a request names another of the same person's in the X-Werzeick-Company header, as a membership_id or membership_id:role from memberships below; the server proves it is theirs on every request. No request carries a company's id: the server reads the company from the session or the named membership, which is what keeps one firm's data from another's.
POST /api/auth/request-code
Emails a sign-in code.
Veřejné: není potřeba klíč ani relace.
It answers 202 whether or not the address has an account. Anything else would make this endpoint a way to discover who is on the platform, and since onboarding is invite-only that would also reveal which companies have invited whom.
Another code for the same address may be asked for 30 seconds after the last, and not sooner: a request within that wait is answered 429, with a Retry-After header giving the seconds left. Any address is answered so, whether or not it has an account. Too many codes in a quarter of an hour is a 429 with no Retry-After.
Tělo požadavku
| Pole | Typ | Co to je |
|---|---|---|
email |
řetězec |
Odpověď
{
"status": "sent if an account exists",
"resend_after_seconds": 30
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 202 | |
| 400 | email is required · invalid JSON body |
| 429 | a code was sent moments ago; wait {seconds} seconds before asking for another · too many codes requested; wait a few minutes |
| 500 | internal server error |
Vyzkoušet
POST /api/auth/verify
Exchanges a code for a session.
Veřejné: není potřeba klíč ani relace.
Tělo požadavku
| Pole | Typ | Co to je |
|---|---|---|
email |
řetězec | |
code |
řetězec |
Odpověď
{
"membership": {
"membership_id": 12,
"org_name": "Alpha Stavby",
"role": "worker",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": true,
"cancellation_emails_enabled": true
},
"memberships": [
{
"membership_id": 12,
"org_name": "Alpha Stavby",
"role": "worker",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": true,
"cancellation_emails_enabled": true
},
{
"membership_id": 27,
"org_name": "Beta Montáže",
"role": "manager",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": false,
"cancellation_emails_enabled": false
},
{
"membership_id": 27,
"org_name": "Beta Montáže",
"role": "worker",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": false,
"cancellation_emails_enabled": false
}
],
"language": "cs"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | email and code are required · invalid JSON body |
| 401 | that code is not valid |
| 403 | this account is not a member of any organization |
| 500 | internal server error |
Vyzkoušet
POST /api/auth/sign-out
Revokes the session.
Jen relace: API klíč je odmítnut s 403.
It succeeds even for a token that was already invalid: signing out must never fail.
Odpověď
Bez těla.
Stavové kódy
| Kód | Zpráva |
|---|---|
| 204 | |
| 500 | internal server error |
GET /api/auth/me
Describes the caller: their identity, the company they are acting as, and the other companies they could switch to, or that a key could name in X-Werzeick-Company.
API klíč nebo relace.
Odpověď
{
"membership": {
"membership_id": 12,
"org_name": "Alpha Stavby",
"role": "worker",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": true,
"cancellation_emails_enabled": true
},
"memberships": [
{
"membership_id": 12,
"org_name": "Alpha Stavby",
"role": "worker",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": true,
"cancellation_emails_enabled": true
},
{
"membership_id": 27,
"org_name": "Beta Montáže",
"role": "manager",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": false,
"cancellation_emails_enabled": false
},
{
"membership_id": 27,
"org_name": "Beta Montáže",
"role": "worker",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": false,
"cancellation_emails_enabled": false
}
],
"language": "cs"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 401 | authentication required |
| 500 | internal server error |
Vyzkoušet
POST /api/auth/switch
Moves the caller to another of their entries — another company, or the other role at the same one — rotating the session.
Jen relace: API klíč je odmítnut s 403.
The old token stops working immediately, so nothing cached against the previous organization or role can outlive the switch.
A role the membership does not hold answers 403, exactly like a membership that is not the caller's: neither says which of the two it was.
Tělo požadavku
Names the entry to move to: a membership and the role to act in there. Both are required, and both are proved by the service.
| Pole | Typ | Co to je |
|---|---|---|
membership_id |
celé číslo | |
role |
řetězec |
Odpověď
{
"membership": {
"membership_id": 12,
"org_name": "Alpha Stavby",
"role": "worker",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": true,
"cancellation_emails_enabled": true
},
"memberships": [
{
"membership_id": 12,
"org_name": "Alpha Stavby",
"role": "worker",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": true,
"cancellation_emails_enabled": true
},
{
"membership_id": 27,
"org_name": "Beta Montáže",
"role": "manager",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": false,
"cancellation_emails_enabled": false
},
{
"membership_id": 27,
"org_name": "Beta Montáže",
"role": "worker",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": false,
"cancellation_emails_enabled": false
}
],
"language": "cs"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid JSON body · role must be worker or manager |
| 401 | authentication required |
| 403 | not permitted |
| 500 | internal server error |
PUT /api/auth/me/emergency-responses
Records whether this worker wants to hear about emergency cover at the company they are acting as.
API klíč nebo relace.
It names no membership: the acting one comes from the session, which is what stops this being a way to opt somebody else in or read whether they have.
Tělo požadavku
| Pole | Typ | Co to je |
|---|---|---|
enabled |
boolean, nebo null |
Odpověď
{
"membership": {
"membership_id": 12,
"org_name": "Alpha Stavby",
"role": "worker",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": true,
"cancellation_emails_enabled": true
},
"memberships": [
{
"membership_id": 12,
"org_name": "Alpha Stavby",
"role": "worker",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": true,
"cancellation_emails_enabled": true
},
{
"membership_id": 27,
"org_name": "Beta Montáže",
"role": "manager",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": false,
"cancellation_emails_enabled": false
},
{
"membership_id": 27,
"org_name": "Beta Montáže",
"role": "worker",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": false,
"cancellation_emails_enabled": false
}
],
"language": "cs"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | enabled is required · invalid JSON body |
| 401 | authentication required |
| 403 | only a worker can take emergency shifts |
| 500 | internal server error |
Vyzkoušet
PUT /api/auth/me/cancellation-emails
Records whether this worker wants a cancelled shift emailed as well as pushed, at the company they are acting as.
API klíč nebo relace.
Its own endpoint rather than a second field on the emergency one: each takes {"enabled": …} and a missing key is refused, which only works when the key names one setting.
Tělo požadavku
| Pole | Typ | Co to je |
|---|---|---|
enabled |
boolean, nebo null |
Odpověď
{
"membership": {
"membership_id": 12,
"org_name": "Alpha Stavby",
"role": "worker",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": true,
"cancellation_emails_enabled": true
},
"memberships": [
{
"membership_id": 12,
"org_name": "Alpha Stavby",
"role": "worker",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": true,
"cancellation_emails_enabled": true
},
{
"membership_id": 27,
"org_name": "Beta Montáže",
"role": "manager",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": false,
"cancellation_emails_enabled": false
},
{
"membership_id": 27,
"org_name": "Beta Montáže",
"role": "worker",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": false,
"cancellation_emails_enabled": false
}
],
"language": "cs"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | enabled is required · invalid JSON body |
| 401 | authentication required |
| 403 | only a worker is sent cancellations |
| 500 | internal server error |
Vyzkoušet
PUT /api/auth/me/language
Records the account's choice of language: PUT /api/auth/me/language, {"language": "cs"}.
Jen relace: API klíč je odmítnut s 403.
The app sends it from its own picker, which it has only on a phone with no per-app language setting (Android 12 and older); elsewhere the phone decides. The web client's menu records the same choice.
It names no user: the account is the session's. Answered with the whole session, like the other settings here.
Tělo požadavku
| Pole | Typ | Co to je |
|---|---|---|
language |
řetězec |
Odpověď
{
"membership": {
"membership_id": 12,
"org_name": "Alpha Stavby",
"role": "worker",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": true,
"cancellation_emails_enabled": true
},
"memberships": [
{
"membership_id": 12,
"org_name": "Alpha Stavby",
"role": "worker",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": true,
"cancellation_emails_enabled": true
},
{
"membership_id": 27,
"org_name": "Beta Montáže",
"role": "manager",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": false,
"cancellation_emails_enabled": false
},
{
"membership_id": 27,
"org_name": "Beta Montáže",
"role": "worker",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": false,
"cancellation_emails_enabled": false
}
],
"language": "cs"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid JSON body · language must be cs or en |
| 401 | authentication required |
| 500 | internal server error |
Váš účet
Lets somebody delete their own account from the app.
GET /api/auth/me/deletion
Says what deleting the caller's account would do, and changes nothing.
Jen relace: API klíč je odmítnut s 403.
The app asks this before it asks the person, so the numbers are in the question.
Odpověď
{
"can_delete": false,
"companies": [
{
"org_name": "Alpha Stavby",
"upcoming_shifts": 2,
"invitations": 1,
"clocked_in": true,
"last_manager": false
},
{
"org_name": "Beta Montáže",
"upcoming_shifts": 0,
"invitations": 0,
"clocked_in": false,
"last_manager": true
}
]
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 401 | authentication required |
| 500 | internal server error |
DELETE /api/auth/me
Erases the caller's account.
Jen relace: API klíč je odmítnut s 403.
204 when it is gone; every token the person held stops working with it, this one included.
The request has no body and names nobody. A refusal is 409 with the same shape the preview answers with, so the app can say which company would be left without a manager.
Odpověď
Bez těla.
Stavové kódy
| Kód | Zpráva |
|---|---|
| 204 | |
| 401 | authentication required |
| 409 | |
| 500 | internal server error |
Pozvánky do firmy
How people join a company. There is no sign-up: a manager invites somebody by email, and the link in that email is accepted here. An address that already has an account gains a membership; one that does not becomes an account.
POST /api/invitations/preview
Describes an invitation to whoever holds its link: which company, what they are invited to do, and the rate offered.
Veřejné: není potřeba klíč ani relace.
Nothing is accepted.
Tělo požadavku
Carries the invitation's token, for Preview and Accept.
Public by necessity: the invitee has no account yet. The token is read from the body rather than a query string, because a query string reaches proxy logs, browser history and Referer headers — and this token is a credential.
| Pole | Typ | Co to je |
|---|---|---|
token |
řetězec |
Odpověď
{
"org_name": "Alpha Stavby",
"is_manager": false,
"is_worker": true,
"first_name": "Petra",
"email": "petra@example.test",
"rate_amount": 4200000,
"rate_currency": "CZK"
}
{
"org_name": "Beta Montáže",
"is_manager": true,
"is_worker": true,
"first_name": "Petra",
"email": "petra@example.test",
"rate_amount": null,
"rate_currency": null
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid JSON body |
| 404 | this invitation is invalid, expired, or already used |
| 500 | internal server error |
Vyzkoušet
POST /api/invitations/accept
Turns an invitation into a membership, and says how the person gets in: the same three answers the web page gives, from the same place.
Veřejné: není potřeba klíč ani relace.
Public, like Preview: somebody invited has no account yet. It still looks at the request's own session when there is one, because somebody accepting from an app they are already signed in to has nothing left to prove. That identity comes from the bearer token and never from the body.
Tělo požadavku
Carries the invitation's token, for Preview and Accept.
Public by necessity: the invitee has no account yet. The token is read from the body rather than a query string, because a query string reaches proxy logs, browser history and Referer headers — and this token is a credential.
| Pole | Typ | Co to je |
|---|---|---|
token |
řetězec |
Odpověď
{
"outcome": "signed_in",
"email": "petra@example.test",
"code_sent": false,
"session": {
"token": "not-a-real-token-only-this-fixture-has-it",
"expires_at": "2026-11-06T07:30:00Z",
"membership": {
"membership_id": 12,
"org_name": "Alpha Stavby",
"role": "worker",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": false,
"cancellation_emails_enabled": true
},
"memberships": [
{
"membership_id": 12,
"org_name": "Alpha Stavby",
"role": "worker",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": false,
"cancellation_emails_enabled": true
}
],
"language": null
},
"membership": null
}
{
"outcome": "needs_code",
"email": "petra@example.test",
"code_sent": true,
"session": null,
"membership": null
}
{
"outcome": "joined",
"email": "petra@example.test",
"code_sent": false,
"session": null,
"membership": {
"membership_id": 27,
"org_name": "Beta Montáže",
"role": "manager",
"first_name": "Petra",
"last_name": "Nováková",
"emergency_responses_enabled": false,
"cancellation_emails_enabled": true
}
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid JSON body |
| 404 | this invitation is invalid, expired, or already used |
| 500 | internal server error |
Vyzkoušet
POST /api/invitations
Offers someone a job at the acting manager's company.
API klíč nebo relace.
There is no org field: the company comes from the session, so a manager cannot invite into a firm they do not belong to.
Tělo požadavku
| Pole | Typ | Co to je |
|---|---|---|
email |
řetězec | |
first_name |
řetězec | |
last_name |
řetězec | |
is_manager |
boolean | What they are invited to do: either, or both. At least one must be true. |
is_worker |
boolean | |
rate_amount |
celé číslo, nebo null | Money crosses the wire as a raw int64 with 4 implied decimals plus its currency, never pre-formatted and never a float. Peníze: celé číslo se čtyřmi skrytými desetinnými místy, takže 4200000 je 420,00, a vedle něj měna. |
rate_currency |
řetězec, nebo null |
Odpověď
Stavové kódy
| Kód | Zpráva |
|---|---|
| 201 | |
| 400 | a rate needs both an amount and a currency · email, first_name and last_name are required · invalid JSON body · is_manager or is_worker must be true |
| 401 | authentication required |
| 403 | not permitted |
| 409 | that person is already in your organization |
| 500 | internal server error |
Vyzkoušet
GET /api/invitations
Shows who has been invited but has not yet accepted.
API klíč nebo relace.
Odpověď
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 401 | authentication required |
| 403 | not permitted |
| 500 | internal server error |
Vyzkoušet
Váš týden
The worker's schedule lives here now, and so does taking an open shift, because that is where the app shows them.
GET /api/dashboard
Returns the caller's dashboard at the active company.
API klíč nebo relace.
A value that is not a number is a 400 rather than quietly the default: the app sent something it did not mean.
Parametry dotazu
weeks
Odpověď
{
"days": [
"2026-09-07",
"2026-09-08",
"2026-09-09",
"2026-09-10",
"2026-09-11",
"2026-09-12",
"2026-09-13"
],
"role": "worker",
"today": "2026-09-09",
"worker": {
"awaiting_you": [
{
"can_take_from": "2026-09-10T11:00:00Z",
"can_take_until": "2026-09-10T15:00:00Z",
"collides_from": "2026-09-10T05:00:00Z",
"collides_until": "2026-09-10T11:00:00Z",
"collides_with_company": null,
"collides_with_title": "Depot fit-out",
"created_at": "2026-10-28T13:33:30.733171Z",
"expires_at": "2026-09-10T07:00:00Z",
"full": false,
"gig_id": 1,
"gig_title": "Warehouse roof",
"id": 1,
"invited_at": "2026-09-09T08:00:00Z",
"membership_id": 2,
"origin": "staffed",
"rate_amount": 4200000,
"rate_currency": "CZK",
"responded_at": null,
"role_id": 1,
"role_label": "crane op",
"status": "pending",
"takes_from": null,
"takes_until": null,
"timeslot": {
"accepted": 0,
"created_at": "2026-10-28T13:33:30.731584Z",
"day_id": 1,
"ends_at": "2026-09-10T15:00:00Z",
"gig_id": 1,
"id": 1,
"pending": 0,
"required_workers": 1,
"role_label": "crane op",
"starts_at": "2026-09-10T07:00:00Z"
},
"timeslot_id": 1
},
{
"can_take_from": null,
"can_take_until": null,
"collides_from": null,
"collides_until": null,
"collides_with_company": null,
"collides_with_title": null,
"created_at": "2026-10-28T13:33:30.781699Z",
"expires_at": "2026-09-14T07:00:00Z",
"full": false,
"gig_id": 1,
"gig_title": "Warehouse roof",
"id": 9,
"invited_at": "2026-09-09T08:00:00Z",
"membership_id": 2,
"origin": "staffed",
"rate_amount": null,
"rate_currency": null,
"responded_at": null,
"role_id": 11,
"role_label": null,
"status": "pending",
"takes_from": null,
"takes_until": null,
"timeslot": {
"accepted": 0,
"created_at": "2026-10-28T13:33:30.78101Z",
"day_id": 11,
"ends_at": "2026-09-14T15:00:00Z",
"gig_id": 1,
"id": 11,
"pending": 0,
"required_workers": 1,
"role_label": null,
"starts_at": "2026-09-14T07:00:00Z"
},
"timeslot_id": 11
},
{
"can_take_from": null,
"can_take_until": null,
"collides_from": null,
"collides_until": null,
"collides_with_company": null,
"collides_with_title": null,
"created_at": "2026-10-28T13:33:30.783787Z",
"expires_at": "2026-09-15T07:00:00Z",
"full": true,
"gig_id": 1,
"gig_title": "Warehouse roof",
"id": 10,
"invited_at": "2026-09-09T08:00:00Z",
"membership_id": 2,
"origin": "staffed",
"rate_amount": null,
"rate_currency": null,
"responded_at": null,
"role_id": 12,
"role_label": null,
"status": "pending",
"takes_from": null,
"takes_until": null,
"timeslot": {
"accepted": 1,
"created_at": "2026-10-28T13:33:30.783093Z",
"day_id": 12,
"ends_at": "2026-09-15T15:00:00Z",
"gig_id": 1,
"id": 12,
"pending": 0,
"required_workers": 1,
"role_label": null,
"starts_at": "2026-09-15T07:00:00Z"
},
"timeslot_id": 12
}
],
"expiring_certificates": [
{
"days_left": 12,
"expired": false,
"expires_on": "2026-09-21",
"id": 1,
"kind": "weld_iso9606",
"label": null,
"name": "Welder qualification test (EN ISO 9606)"
}
],
"invitation_summaries": [
{
"count": 3,
"first_day": "2026-09-10",
"full_count": 1,
"gig_id": 1,
"gig_title": "Warehouse roof",
"last_day": "2026-09-15",
"minutes": 1440,
"shift_summary": "Shifts Mon - Tue, Thu, 07:00 - 15:00",
"unrated_minutes": 960,
"would_earn": [
{
"amount": 33600000,
"currency": "CZK"
}
]
}
],
"later": [
{
"can_take_from": null,
"can_take_until": null,
"collides_from": null,
"collides_until": null,
"collides_with_company": null,
"collides_with_title": null,
"created_at": "2026-10-28T13:33:30.751859Z",
"expires_at": "2026-09-16T07:00:00Z",
"full": true,
"gig_id": 1,
"gig_title": "Warehouse roof",
"id": 5,
"invited_at": "2026-09-09T08:00:00Z",
"membership_id": 2,
"origin": "staffed",
"rate_amount": 4200000,
"rate_currency": "CZK",
"responded_at": "2026-09-09T08:00:00Z",
"role_id": 5,
"role_label": null,
"status": "accepted",
"takes_from": null,
"takes_until": null,
"timeslot": {
"accepted": 1,
"created_at": "2026-10-28T13:33:30.751116Z",
"day_id": 5,
"ends_at": "2026-09-16T15:00:00Z",
"gig_id": 1,
"id": 5,
"pending": 0,
"required_workers": 1,
"role_label": null,
"starts_at": "2026-09-16T07:00:00Z"
},
"timeslot_id": 5
}
],
"open_shifts": [
{
"accepted": 0,
"can_take_from": "2026-09-13T09:00:00Z",
"can_take_until": "2026-09-13T15:00:00Z",
"collides_from": "2026-09-13T05:00:00Z",
"collides_until": "2026-09-13T09:00:00Z",
"collides_with_company": "Beta Construction",
"collides_with_title": "Beta depot",
"created_at": "2026-10-28T13:33:30.755612Z",
"day_id": 6,
"ends_at": "2026-09-13T15:00:00Z",
"gig_id": 1,
"gig_title": "Warehouse roof",
"id": 6,
"mine_status": "",
"pending": 0,
"rate_amount": 5000000,
"rate_currency": "CZK",
"required_workers": 1,
"role_id": 6,
"role_label": "crane op",
"starts_at": "2026-09-13T07:00:00Z",
"taking_confirms": true
},
{
"accepted": 0,
"can_take_from": "2026-09-13T09:00:00Z",
"can_take_until": "2026-09-13T15:00:00Z",
"collides_from": "2026-09-13T05:00:00Z",
"collides_until": "2026-09-13T09:00:00Z",
"collides_with_company": "Beta Construction",
"collides_with_title": "Beta depot",
"created_at": "2026-10-28T13:33:30.757429Z",
"day_id": 6,
"ends_at": "2026-09-13T15:00:00Z",
"gig_id": 1,
"gig_title": "Warehouse roof",
"id": 7,
"mine_status": "",
"pending": 0,
"rate_amount": null,
"rate_currency": null,
"required_workers": 1,
"role_id": 7,
"role_label": "crane op",
"starts_at": "2026-09-13T07:00:00Z",
"taking_confirms": false
}
],
"still_to_earn": [
{
"amount": 92400000,
"currency": "CZK"
}
],
"still_to_earn_unrated_minutes": 0,
"this_week": [
{
"can_take_from": null,
"can_take_until": null,
"collides_from": null,
"collides_until": null,
"collides_with_company": null,
"collides_with_title": null,
"created_at": "2026-10-28T13:33:30.736907Z",
"expires_at": "2026-09-10T05:00:00Z",
"full": true,
"gig_id": 2,
"gig_title": "Depot fit-out",
"id": 2,
"invited_at": "2026-09-09T08:00:00Z",
"membership_id": 2,
"origin": "staffed",
"rate_amount": 4200000,
"rate_currency": "CZK",
"responded_at": "2026-09-09T08:00:00Z",
"role_id": 2,
"role_label": null,
"status": "accepted",
"takes_from": null,
"takes_until": null,
"timeslot": {
"accepted": 1,
"created_at": "2026-10-28T13:33:30.736124Z",
"day_id": 2,
"ends_at": "2026-09-10T11:00:00Z",
"gig_id": 2,
"id": 2,
"pending": 0,
"required_workers": 1,
"role_label": null,
"starts_at": "2026-09-10T05:00:00Z"
},
"timeslot_id": 2
},
{
"can_take_from": null,
"can_take_until": null,
"collides_from": null,
"collides_until": null,
"collides_with_company": null,
"collides_with_title": null,
"created_at": "2026-10-28T13:33:30.741932Z",
"expires_at": "2026-09-11T07:00:00Z",
"full": true,
"gig_id": 1,
"gig_title": "Warehouse roof",
"id": 3,
"invited_at": "2026-09-09T08:00:00Z",
"membership_id": 2,
"origin": "staffed",
"rate_amount": 4200000,
"rate_currency": "CZK",
"responded_at": "2026-09-09T08:00:00Z",
"role_id": 3,
"role_label": null,
"status": "accepted",
"takes_from": null,
"takes_until": null,
"timeslot": {
"accepted": 1,
"created_at": "2026-10-28T13:33:30.741178Z",
"day_id": 3,
"ends_at": "2026-09-11T15:00:00Z",
"gig_id": 1,
"id": 3,
"pending": 0,
"required_workers": 1,
"role_label": null,
"starts_at": "2026-09-11T07:00:00Z"
},
"timeslot_id": 3
},
{
"can_take_from": null,
"can_take_until": null,
"collides_from": null,
"collides_until": null,
"collides_with_company": null,
"collides_with_title": null,
"created_at": "2026-10-28T13:33:30.746586Z",
"expires_at": "2026-09-12T07:00:00Z",
"full": false,
"gig_id": 1,
"gig_title": "Warehouse roof",
"id": 4,
"invited_at": "2026-09-09T08:00:00Z",
"membership_id": 2,
"origin": "staffed",
"rate_amount": 4200000,
"rate_currency": "CZK",
"responded_at": "2026-09-09T08:00:00Z",
"role_id": 4,
"role_label": null,
"status": "cancelled",
"takes_from": null,
"takes_until": null,
"timeslot": {
"accepted": 0,
"created_at": "2026-10-28T13:33:30.745806Z",
"day_id": 4,
"ends_at": "2026-09-12T15:00:00Z",
"gig_id": 1,
"id": 4,
"pending": 0,
"required_workers": 1,
"role_label": null,
"starts_at": "2026-09-12T07:00:00Z"
},
"timeslot_id": 4
}
],
"worked_this_month": {
"earned": [
{
"amount": 16800000,
"currency": "CZK"
}
],
"minutes": 240,
"unrated_minutes": 0
},
"worked_this_week": {
"earned": [
{
"amount": 16800000,
"currency": "CZK"
}
],
"minutes": 240,
"unrated_minutes": 0
}
}
}
{
"days": [
"2026-09-07",
"2026-09-08",
"2026-09-09",
"2026-09-10",
"2026-09-11",
"2026-09-12",
"2026-09-13"
],
"manager": {
"attention": [
{
"accepted": 0,
"created_at": "2026-10-28T13:33:30.731584Z",
"day_id": 1,
"ends_at": "2026-09-10T15:00:00Z",
"gig_id": 1,
"gig_title": "Warehouse roof",
"id": 1,
"pending": 1,
"required_workers": 1,
"role_label": "crane op",
"starts_at": "2026-09-10T07:00:00Z"
},
{
"accepted": 0,
"created_at": "2026-10-28T13:33:30.76944Z",
"day_id": 1,
"ends_at": "2026-09-10T22:00:00Z",
"gig_id": 1,
"gig_title": "Warehouse roof",
"id": 9,
"pending": 0,
"required_workers": 2,
"role_label": null,
"starts_at": "2026-09-10T14:00:00Z"
},
{
"accepted": 0,
"created_at": "2026-10-28T13:33:30.745806Z",
"day_id": 4,
"ends_at": "2026-09-12T15:00:00Z",
"gig_id": 1,
"gig_title": "Warehouse roof",
"id": 4,
"pending": 0,
"required_workers": 1,
"role_label": null,
"starts_at": "2026-09-12T07:00:00Z"
},
{
"accepted": 0,
"created_at": "2026-10-28T13:33:30.755612Z",
"day_id": 6,
"ends_at": "2026-09-13T15:00:00Z",
"gig_id": 1,
"gig_title": "Warehouse roof",
"id": 6,
"pending": 0,
"required_workers": 1,
"role_label": "crane op",
"starts_at": "2026-09-13T07:00:00Z"
},
{
"accepted": 0,
"created_at": "2026-10-28T13:33:30.757429Z",
"day_id": 6,
"ends_at": "2026-09-13T15:00:00Z",
"gig_id": 1,
"gig_title": "Warehouse roof",
"id": 7,
"pending": 0,
"required_workers": 1,
"role_label": "crane op",
"starts_at": "2026-09-13T07:00:00Z"
},
{
"accepted": 0,
"created_at": "2026-10-28T13:33:30.78101Z",
"day_id": 11,
"ends_at": "2026-09-14T15:00:00Z",
"gig_id": 1,
"gig_title": "Warehouse roof",
"id": 11,
"pending": 1,
"required_workers": 1,
"role_label": null,
"starts_at": "2026-09-14T07:00:00Z"
},
{
"accepted": 1,
"created_at": "2026-10-28T13:33:30.783093Z",
"day_id": 12,
"ends_at": "2026-09-15T15:00:00Z",
"gig_id": 1,
"gig_title": "Warehouse roof",
"id": 12,
"pending": 1,
"required_workers": 1,
"role_label": null,
"starts_at": "2026-09-15T07:00:00Z"
}
],
"attention_summaries": [
{
"accepted": 1,
"count": 7,
"first_day": "2026-09-10",
"gig_id": 1,
"gig_title": "Warehouse roof",
"imminent": true,
"last_day": "2026-09-15",
"pending": 3,
"required": 8,
"shift_summary": "Shifts Mon - Tue, Sat, 07:00 - 15:00, Thu 07:00 - 15:00, 14:00 - 22:00, Sun 07:00 - 15:00, 07:00 - 15:00",
"short": 7
}
],
"hours_to_check": [
{
"entry": {
"clock_in_at": "2026-09-02T07:00:00Z",
"clock_out_at": "2026-09-02T22:00:00Z",
"corrected_at": null,
"created_at": "2026-10-28T13:33:30.768583Z",
"earned_amount": 57000000,
"gig_id": 1,
"id": 3,
"membership_id": 5,
"rate_amount": 3800000,
"rate_currency": "CZK",
"source": "manual",
"timeslot_id": 8
},
"gig_title": "Warehouse roof",
"missing_clock_out": false,
"outside_shift": true,
"slot_ends_at": "2026-09-02T15:00:00Z",
"slot_starts_at": "2026-09-02T07:00:00Z",
"worker_name": "Second Alpha Stavby"
},
{
"entry": {
"clock_in_at": "2026-09-03T07:00:00Z",
"clock_out_at": "2026-09-03T22:00:00Z",
"corrected_at": null,
"created_at": "2026-10-28T13:33:30.779978Z",
"earned_amount": null,
"gig_id": 1,
"id": 4,
"membership_id": 6,
"rate_amount": null,
"rate_currency": null,
"source": "manual",
"timeslot_id": 10
},
"gig_title": "Warehouse roof",
"missing_clock_out": false,
"outside_shift": true,
"slot_ends_at": "2026-09-03T15:00:00Z",
"slot_starts_at": "2026-09-03T07:00:00Z",
"worker_name": "Unrated Alpha Stavby"
},
{
"entry": {
"clock_in_at": "2026-09-08T06:00:00Z",
"clock_out_at": null,
"corrected_at": null,
"created_at": "2026-10-28T13:33:30.763173Z",
"earned_amount": 0,
"gig_id": 1,
"id": 2,
"membership_id": 2,
"rate_amount": 4200000,
"rate_currency": "CZK",
"source": "manual",
"timeslot_id": null
},
"gig_title": "Warehouse roof",
"missing_clock_out": true,
"outside_shift": false,
"slot_ends_at": null,
"slot_starts_at": null,
"worker_name": "Worker Alpha Stavby"
}
],
"turned_down": [
{
"created_at": "2026-10-28T13:33:30.770123Z",
"expires_at": "2026-09-10T14:00:00Z",
"gig_title": "Warehouse roof",
"id": 7,
"invited_at": "2026-09-09T08:00:00Z",
"membership_id": 5,
"origin": "staffed",
"rate_amount": 3800000,
"rate_currency": "CZK",
"responded_at": "2026-09-09T08:00:00Z",
"role_id": 9,
"role_label": null,
"status": "withdrawn",
"takes_from": null,
"takes_until": null,
"timeslot": {
"accepted": 0,
"created_at": "2026-10-28T13:33:30.76944Z",
"day_id": 1,
"ends_at": "2026-09-10T22:00:00Z",
"gig_id": 1,
"id": 9,
"pending": 0,
"required_workers": 2,
"role_label": null,
"starts_at": "2026-09-10T14:00:00Z"
},
"timeslot_id": 9,
"worker_name": "Second Alpha Stavby"
}
],
"week": [
{
"accepted": 0,
"day": "2026-09-07",
"pending": 0,
"required": 0,
"short": 0,
"slots": 0
},
{
"accepted": 0,
"day": "2026-09-08",
"pending": 0,
"required": 0,
"short": 0,
"slots": 0
},
{
"accepted": 0,
"day": "2026-09-09",
"pending": 0,
"required": 0,
"short": 0,
"slots": 0
},
{
"accepted": 1,
"day": "2026-09-10",
"pending": 1,
"required": 4,
"short": 3,
"slots": 3
},
{
"accepted": 1,
"day": "2026-09-11",
"pending": 0,
"required": 1,
"short": 0,
"slots": 1
},
{
"accepted": 0,
"day": "2026-09-12",
"pending": 0,
"required": 1,
"short": 1,
"slots": 1
},
{
"accepted": 0,
"day": "2026-09-13",
"pending": 0,
"required": 2,
"short": 2,
"slots": 2
}
],
"worked_this_week": {
"earned": [
{
"amount": 16800000,
"currency": "CZK"
}
],
"minutes": 240,
"unrated_minutes": 0
}
},
"role": "manager",
"today": "2026-09-09"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | weeks must be a whole number |
| 401 | authentication required |
| 403 | not permitted |
| 500 | internal server error |
Vyzkoušet
POST /api/timeslots/{id}/take
Puts the caller on a shift a PM opened to the company.
API klíč nebo relace.
The body names the role being taken, role_id, as the dashboard's open shift row carried it: an open shift is listed once per role, each with its own places and figure. It may be left out for a shift with one role. The request carries no rate: the figure is resolved on the server at signup and snapshotted, exactly as the dashboard quoted it; a client never sends the number it believes it was offered. partial is consent to take only the free remainder of a shift that collides with accepted work.
What comes back is the assignment: accepted on a shift that confirms takers, pending on one where the manager picks. The app re-reads the dashboard either way.
V cestě
| Parametr | Co to je |
|---|---|
id | Id směny. |
Tělo požadavku
| Pole | Typ | Co to je |
|---|---|---|
partial |
boolean | |
role_id |
celé číslo |
Odpověď
{
"id": 2,
"timeslot_id": 2,
"membership_id": 2,
"origin": "sos",
"status": "accepted",
"rate_amount": 6300000,
"rate_currency": "CZK",
"invited_at": "2026-09-07T09:00:00Z",
"responded_at": "2026-09-07T09:05:00Z",
"expires_at": "2026-09-10T05:00:00Z",
"created_at": "2026-09-07T09:00:00Z",
"takes_from": "2026-09-10T09:00:00Z",
"takes_until": "2026-09-10T13:00:00Z",
"role_id": 2,
"role_label": "crane op"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 201 | |
| 400 | invalid timeslot id · this shift has several roles; send role_id |
| 401 | authentication required |
| 403 | not permitted · this shift raises an hourly rate, and you have none here to raise |
| 404 | shift not found |
| 409 | |
| 500 | internal server error |
Vyzkoušet
Směny a odpovědi
The worker's side of staffing: what am I being asked to do, and my answer.
A PM's staffing screens live in the web client for now; the same services back both, so a manager overview in the app is rendering work, not new logic.
GET /api/schedule
Returns the caller's own assignments at the active company.
API klíč nebo relace.
Odpověď
[
{
"id": 1,
"timeslot_id": 1,
"membership_id": 2,
"origin": "staffed",
"status": "pending",
"rate_amount": 4200000,
"rate_currency": "CZK",
"invited_at": "2026-09-07T08:00:00Z",
"responded_at": null,
"expires_at": "2026-09-09T07:00:00Z",
"created_at": "2026-09-07T08:00:00Z",
"takes_from": null,
"takes_until": null,
"role_id": 1,
"role_label": null,
"timeslot": {
"id": 1,
"gig_id": 1,
"day_id": 1,
"starts_at": "2026-09-09T07:00:00Z",
"ends_at": "2026-09-09T15:00:00Z",
"required_workers": 2,
"role_label": null,
"created_at": "2026-09-07T08:00:00Z",
"accepted": 0,
"pending": 1
},
"gig_id": 1,
"gig_title": "Warehouse roof",
"full": false,
"collides_with_title": "Depot fit-out",
"collides_with_company": null,
"collides_from": "2026-09-09T05:00:00Z",
"collides_until": "2026-09-09T11:00:00Z",
"can_take_from": "2026-09-09T11:00:00Z",
"can_take_until": "2026-09-09T15:00:00Z"
},
{
"id": 2,
"timeslot_id": 2,
"membership_id": 2,
"origin": "sos",
"status": "accepted",
"rate_amount": 6300000,
"rate_currency": "CZK",
"invited_at": "2026-09-07T09:00:00Z",
"responded_at": "2026-09-07T09:05:00Z",
"expires_at": "2026-09-10T05:00:00Z",
"created_at": "2026-09-07T09:00:00Z",
"takes_from": "2026-09-10T09:00:00Z",
"takes_until": "2026-09-10T13:00:00Z",
"role_id": 2,
"role_label": "crane op",
"timeslot": {
"id": 2,
"gig_id": 2,
"day_id": 2,
"starts_at": "2026-09-10T05:00:00Z",
"ends_at": "2026-09-10T13:00:00Z",
"required_workers": 1,
"role_label": "crane op",
"created_at": "2026-09-07T09:00:00Z",
"accepted": 1,
"pending": 0
},
"gig_id": 2,
"gig_title": "Depot fit-out",
"full": false,
"collides_with_title": null,
"collides_with_company": null,
"collides_from": null,
"collides_until": null,
"can_take_from": null,
"can_take_until": null
},
{
"id": 3,
"timeslot_id": 3,
"membership_id": 2,
"origin": "open",
"status": "pending",
"rate_amount": 6300000,
"rate_currency": "CZK",
"invited_at": "2026-09-07T10:00:00Z",
"responded_at": null,
"expires_at": "2026-09-11T05:00:00Z",
"created_at": "2026-09-07T10:00:00Z",
"takes_from": null,
"takes_until": null,
"role_id": 3,
"role_label": null,
"timeslot": {
"id": 3,
"gig_id": 1,
"day_id": 3,
"starts_at": "2026-09-11T05:00:00Z",
"ends_at": "2026-09-11T13:00:00Z",
"required_workers": 2,
"role_label": null,
"created_at": "2026-09-07T10:00:00Z",
"accepted": 1,
"pending": 1
},
"gig_id": 1,
"gig_title": "Warehouse roof",
"full": false,
"collides_with_title": null,
"collides_with_company": null,
"collides_from": null,
"collides_until": null,
"can_take_from": null,
"can_take_until": null
},
{
"id": 4,
"timeslot_id": 4,
"membership_id": 2,
"origin": "staffed",
"status": "pending",
"rate_amount": null,
"rate_currency": null,
"invited_at": "2026-09-07T11:00:00Z",
"responded_at": null,
"expires_at": "2026-09-14T05:00:00Z",
"created_at": "2026-09-07T11:00:00Z",
"takes_from": null,
"takes_until": null,
"role_id": 4,
"role_label": null,
"timeslot": {
"id": 4,
"gig_id": 1,
"day_id": 4,
"starts_at": "2026-09-14T05:00:00Z",
"ends_at": "2026-09-14T13:00:00Z",
"required_workers": 2,
"role_label": null,
"created_at": "2026-09-07T11:00:00Z",
"accepted": 2,
"pending": 1
},
"gig_id": 1,
"gig_title": "Warehouse roof",
"full": true,
"collides_with_title": null,
"collides_with_company": null,
"collides_from": null,
"collides_until": null,
"can_take_from": null,
"can_take_until": null
}
]
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 401 | authentication required |
| 403 | not permitted |
| 500 | internal server error |
Vyzkoušet
POST /api/assignments/{id}/respond
Records a worker's answer to one assignment.
API klíč nebo relace.
Accept, decline and withdraw share a route because they share a lifecycle; the action is in the body rather than the path so a client cannot invent one.
V cestě
| Parametr | Co to je |
|---|---|
id | Id přiřazení: vašeho místa na směně. |
Tělo požadavku
| Pole | Typ | Co to je |
|---|---|---|
action |
řetězec | |
partial |
boolean |
|
Odpověď
{
"id": 2,
"timeslot_id": 2,
"membership_id": 2,
"origin": "sos",
"status": "accepted",
"rate_amount": 6300000,
"rate_currency": "CZK",
"invited_at": "2026-09-07T09:00:00Z",
"responded_at": "2026-09-07T09:05:00Z",
"expires_at": "2026-09-10T05:00:00Z",
"created_at": "2026-09-07T09:00:00Z",
"takes_from": "2026-09-10T09:00:00Z",
"takes_until": "2026-09-10T13:00:00Z",
"role_id": 2,
"role_label": "crane op"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | action must be "accept", "decline" or "withdraw" · invalid JSON body · invalid assignment id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/gigs/{id}/invitations/respond
Answers every invitation the caller has not answered on one project: "Accept all" and "Decline all" beside a project's invitations.
API klíč nebo relace.
It names a project and an action and nothing else. Which invitations those are is decided here, at the moment of the tap, from the caller's own membership — a client never sends a list of ids it believes are its own. Another company's project, or one with nothing waiting, answers 200 with zeros: there was nothing to do, and that is all anybody is told.
V cestě
| Parametr | Co to je |
|---|---|
id | Id zakázky. |
Tělo požadavku
| Pole | Typ | Co to je |
|---|---|---|
action |
řetězec |
Odpověď
{
"answered": 2,
"full": 1,
"colliding": 0
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | action must be "accept" or "decline" · invalid JSON body · invalid project id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/devices
Records an FCM token so this phone can be reached.
Jen relace: API klíč je odmítnut s 403.
Tělo požadavku
| Pole | Typ | Co to je |
|---|---|---|
token |
řetězec | |
platform |
řetězec | |
language |
řetězec |
Odpověď
Bez těla.
Stavové kódy
| Kód | Zpráva |
|---|---|
| 204 | |
| 400 | invalid JSON body |
| 401 | authentication required |
DELETE /api/devices
Drops this phone's token, on sign-out.
Jen relace: API klíč je odmítnut s 403.
Without it, a worker who signs out — or hands the phone on — keeps receiving shift notifications for a session they no longer have.
Tělo požadavku
| Pole | Typ | Co to je |
|---|---|---|
token |
řetězec |
Odpověď
Bez těla.
Stavové kódy
| Kód | Zpráva |
|---|---|
| 204 | |
| 400 | a device token is required · invalid JSON body |
| 401 | authentication required |
| 403 | not permitted |
| 500 | internal server error |
Příchod a odchod
Clocking in and out, from the app.
This is the endpoint a worker uses standing on a building site, often with one bar of signal, sometimes with none. Two consequences run through it:
- The device supplies the timestamp, and the server takes it. Stamping an entry with the moment it happened to sync would be wrong by hours for exactly the worker who most needs the record to be right.
- Every write is idempotent on the device's own event id, so a retry after a dropped connection is harmless.
What is NOT here, and must never be: any coordinate. Geofence auto-clocking computes distance on the phone against the one site it was given and posts the same clock event a thumb would. source is the whole of the difference.
POST /api/time/clock-in
Starts a stretch of work.
API klíč nebo relace.
Tělo požadavku
The entire wire shape of a clock event. Keep it that way.
| Pole | Typ | Co to je |
|---|---|---|
gig_id |
celé číslo | |
at |
řetězec |
|
source |
řetězec |
|
client_event_id |
řetězec |
|
Odpověď
{
"id": 2,
"membership_id": 2,
"gig_id": 1,
"timeslot_id": null,
"clock_in_at": "2026-09-09T06:20:00Z",
"clock_out_at": null,
"source": "geofence",
"rate_amount": 4200000,
"rate_currency": "CZK",
"earned_amount": 0,
"corrected_at": null,
"created_at": "2026-09-09T06:20:00Z"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | at must be an RFC 3339 timestamp · invalid JSON body |
| 401 | authentication required |
| 403 | not permitted |
| 404 | time entry not found |
| 409 | |
| 500 | internal server error |
Vyzkoušet
POST /api/time/clock-out
Ends one, naming it by the device's event id when the phone has been offline and by project otherwise.
API klíč nebo relace.
Tělo požadavku
The entire wire shape of a clock event. Keep it that way.
| Pole | Typ | Co to je |
|---|---|---|
gig_id |
celé číslo | |
at |
řetězec |
|
source |
řetězec |
|
client_event_id |
řetězec |
|
Odpověď
{
"id": 1,
"membership_id": 2,
"gig_id": 1,
"timeslot_id": 1,
"clock_in_at": "2026-09-08T07:45:00Z",
"clock_out_at": "2026-09-08T17:10:00Z",
"source": "manual",
"rate_amount": 4200000,
"rate_currency": "CZK",
"earned_amount": 39550000,
"client_event_id": "9f8c1a2b3d4e5f60718293a4b5c6d7e8",
"corrected_at": null,
"created_at": "2026-09-08T07:45:00Z"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | at must be an RFC 3339 timestamp · clock-out needs a gig_id or a client_event_id · invalid JSON body |
| 401 | authentication required |
| 403 | not permitted |
| 404 | time entry not found |
| 409 | |
| 500 | internal server error |
Vyzkoušet
GET /api/time/entries
The worker's own record of their hours.
API klíč nebo relace.
since defaults to four weeks back: enough to check a pay period, little enough that a phone on a slow connection is not downloading a year.
Parametry dotazu
since
Odpověď
[
{
"id": 1,
"membership_id": 2,
"gig_id": 1,
"timeslot_id": 1,
"clock_in_at": "2026-09-08T07:45:00Z",
"clock_out_at": "2026-09-08T17:10:00Z",
"source": "manual",
"rate_amount": 4200000,
"rate_currency": "CZK",
"earned_amount": 39550000,
"client_event_id": "9f8c1a2b3d4e5f60718293a4b5c6d7e8",
"corrected_at": null,
"created_at": "2026-09-08T07:45:00Z"
},
{
"id": 2,
"membership_id": 2,
"gig_id": 1,
"timeslot_id": null,
"clock_in_at": "2026-09-09T06:20:00Z",
"clock_out_at": null,
"source": "geofence",
"rate_amount": 4200000,
"rate_currency": "CZK",
"earned_amount": 0,
"corrected_at": null,
"created_at": "2026-09-09T06:20:00Z"
},
{
"id": 3,
"membership_id": 2,
"gig_id": 1,
"timeslot_id": null,
"clock_in_at": "2026-09-10T06:00:00Z",
"clock_out_at": "2026-09-10T14:30:00Z",
"source": "manual",
"rate_amount": null,
"rate_currency": null,
"earned_amount": null,
"corrected_at": null,
"created_at": "2026-09-10T06:00:00Z"
}
]
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | since must be an RFC 3339 timestamp |
| 401 | authentication required |
| 403 | not permitted |
| 404 | time entry not found |
| 409 | |
| 500 | internal server error |
Vyzkoušet
POST /api/time/entries/{id}/correct
Fixes an entry's times.
API klíč nebo relace.
A worker owns their own hours; a manager may resolve anyone's, which is how discrepancies get settled.
V cestě
| Parametr | Co to je |
|---|---|
id | Id záznamu času. |
Tělo požadavku
| Pole | Typ | Co to je |
|---|---|---|
clock_in_at |
řetězec | |
clock_out_at |
řetězec, nebo null |
Odpověď
{
"id": 1,
"membership_id": 2,
"gig_id": 1,
"timeslot_id": 1,
"clock_in_at": "2026-09-08T07:45:00Z",
"clock_out_at": "2026-09-08T17:10:00Z",
"source": "manual",
"rate_amount": 4200000,
"rate_currency": "CZK",
"earned_amount": 39550000,
"client_event_id": "9f8c1a2b3d4e5f60718293a4b5c6d7e8",
"corrected_at": null,
"created_at": "2026-09-08T07:45:00Z"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | clock_in_at must be an RFC 3339 timestamp · clock_out_at must be an RFC 3339 timestamp or null · invalid JSON body · invalid time entry id |
| 401 | authentication required |
| 403 | not permitted |
| 404 | time entry not found |
| 409 | |
| 500 | internal server error |
Vyzkoušet
Zakázky a výdaje
Projects, which the API calls gigs: the unit of work a company plans, from one shift to months, with a site, a client and the expenses booked against it. A manager sees every project at the company; a worker sees the ones they have a part in and the ones with a shift they could take.
GET /api/gigs
Lists the caller's projects at the company they are acting in.
API klíč nebo relace.
A manager gets every live project. A worker gets the ones they have a part in, newest first, and after those the ones with an open shift they could take; each row says which with is_assigned, is_invited and shifts_to_take. Archived projects are not listed, though each still answers at its own address.
all=1 lists them at every company and role the caller holds, each entry's projects as that entry would list them, with company on each row naming the entry: send its entry as X-Werzeick-Company to act on the project. Somebody who both manages and works at one company sees such a project once for each. It cannot be combined with X-Werzeick-Company.
Parametry dotazu
all
Odpověď
{
"id": 3,
"title": "Foundation pour",
"owner_id": 4,
"project_manager": {
"name": "Martin Dvořák",
"phone": "+420603456789",
"email": null
},
"client_id": 7,
"client_name": "Kaufland Česká republika",
"client_contact_name": "Petra Marková",
"client_contact_phone": "+420602123456",
"client_contact_email": "petra.markova@kaufland.cz",
"job_contact": {
"company": null,
"name": "Jana Horáková, has the keys",
"phone": "+420777111222"
},
"latitude": 49.8209,
"longitude": 18.2625,
"geofence_radius_m": 150,
"site_address": "Gate 3, Průmyslová 1472/12, 702 00 Ostrava",
"expected_minutes": 480,
"is_assigned": true,
"is_invited": false,
"shifts_to_take": 2,
"archived_at": null,
"expenses": [],
"created_at": "2026-09-07T16:06:11.113221+02:00",
"site_outline": [
{
"lat": 49.8205,
"lon": 18.2615
},
{
"lat": 49.8205,
"lon": 18.2636
},
{
"lat": 49.82131,
"lon": 18.2636
},
{
"lat": 49.82131,
"lon": 18.2615
}
]
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | all=1 reads every company: leave out X-Werzeick-Company |
| 401 | authentication required |
| 403 | not permitted |
| 500 | internal server error |
Vyzkoušet
GET /api/gigs/{id}
One project, in the same shape the list gives it.
API klíč nebo relace.
A project the caller cannot list, another company's included, answers 404: it does not exist for them.
V cestě
| Parametr | Co to je |
|---|---|
id | Id zakázky. |
Odpověď
{
"id": 3,
"title": "Foundation pour",
"owner_id": 4,
"project_manager": {
"name": "Martin Dvořák",
"phone": "+420603456789",
"email": null
},
"client_id": 7,
"client_name": "Kaufland Česká republika",
"client_contact_name": "Petra Marková",
"client_contact_phone": "+420602123456",
"client_contact_email": "petra.markova@kaufland.cz",
"job_contact": {
"company": null,
"name": "Jana Horáková, has the keys",
"phone": "+420777111222"
},
"latitude": 49.8209,
"longitude": 18.2625,
"geofence_radius_m": 150,
"site_address": "Gate 3, Průmyslová 1472/12, 702 00 Ostrava",
"expected_minutes": 480,
"is_assigned": true,
"is_invited": false,
"shifts_to_take": 2,
"archived_at": null,
"expenses": [],
"created_at": "2026-09-07T16:06:11.113221+02:00",
"site_outline": [
{
"lat": 49.8205,
"lon": 18.2615
},
{
"lat": 49.8205,
"lon": 18.2636
},
{
"lat": 49.82131,
"lon": 18.2636
},
{
"lat": 49.82131,
"lon": 18.2615
}
]
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid gig id |
| 401 | authentication required |
| 403 | not permitted |
| 404 | gig not found |
| 500 | internal server error |
Vyzkoušet
GET /api/gigs/{id}/earnings
Answers "what has this project paid me, and what will it".
API klíč nebo relace.
Its own endpoint rather than a field on the gig, for two reasons. The list screen has no use for it and should not pay for it on every row; and a tool attached or an hour corrected changes this without changing the project, so the app can re-read one without the other.
The two figures come from two different tables, each carrying its own rate snapshot, and neither is ever rebuilt from the membership rate.
V cestě
| Parametr | Co to je |
|---|---|
id | Id zakázky. |
Odpověď
{
"earned": [
{
"amount": 33600000,
"currency": "CZK"
}
],
"upcoming": [
{
"amount": 50400000,
"currency": "CZK"
}
],
"earned_unrated_minutes": 0,
"upcoming_unrated_minutes": 360,
"running": null
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted |
| 404 | gig not found |
| 500 | internal server error |
Vyzkoušet
POST /api/gigs
Makes a project at the caller's company, with the caller as its manager.
API klíč nebo relace.
Managers only.
Tělo požadavku
The JSON body of POST /api/gigs.
There is deliberately no owner_id or org_id here: the owner is the acting manager's own membership and the organization comes from the session. A client that could name either could create work in someone else's company.
| Pole | Typ | Co to je |
|---|---|---|
title |
řetězec | |
client_id |
celé číslo, nebo null | |
latitude |
číslo, nebo null | |
longitude |
číslo, nebo null | |
geofence_radius_m |
celé číslo, nebo null | |
site_outline |
seznam: Point |
Odpověď
{
"id": 2,
"title": "Roof replacement",
"owner_id": 1,
"project_manager": {
"name": "Tereza Nováková",
"phone": null,
"email": "tereza.novakova@example.com"
},
"client_id": null,
"client_name": null,
"client_contact_name": null,
"client_contact_phone": null,
"client_contact_email": null,
"job_contact": null,
"latitude": null,
"longitude": null,
"geofence_radius_m": null,
"site_address": null,
"expected_minutes": null,
"is_assigned": false,
"is_invited": true,
"shifts_to_take": 0,
"archived_at": null,
"expenses": [
{
"id": 4,
"gig_id": 2,
"created_by_membership_id": 1,
"created_by_name": "Tereza Nováková",
"description": "Tiles",
"cost_amount": 1250000,
"cost_currency": "CZK",
"created_at": "2026-09-07T12:52:03.941837+02:00"
}
],
"created_at": "2026-09-07T16:05:07.353539+02:00",
"site_outline": null
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 201 | |
| 400 | invalid JSON body · title is required |
| 401 | authentication required |
| 403 | not permitted |
| 500 | internal server error |
Vyzkoušet
POST /api/gigs/{id}/expenses
Books a cost against a project.
API klíč nebo relace.
Workers may call this, not only managers: the app is where somebody standing in a builders' merchant records what they just bought. The service decides who may do what.
V cestě
| Parametr | Co to je |
|---|---|
id | Id zakázky. |
Tělo požadavku
The JSON body of a create or an update.
Money crosses the wire as the raw int64 with its currency, never pre-formatted and never a float. There is no author field: the acting membership books it, and a client that could name the author could book a cost against somebody else.
| Pole | Typ | Co to je |
|---|---|---|
description |
řetězec | |
cost_amount |
celé číslo | Peníze: celé číslo se čtyřmi skrytými desetinnými místy, takže 4200000 je 420,00, a vedle něj měna. |
cost_currency |
řetězec |
Odpověď
{
"id": 4,
"gig_id": 2,
"created_by_membership_id": 1,
"created_by_name": "Tereza Nováková",
"description": "Tiles",
"cost_amount": 1250000,
"cost_currency": "CZK",
"created_at": "2026-09-07T12:52:03.941837+02:00"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 201 | |
| 400 | invalid JSON body · invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted |
| 404 | expense not found · gig not found |
| 500 | internal server error |
Vyzkoušet
PATCH /api/gigs/{id}/expenses/{expenseID}
Corrects a cost already booked.
API klíč nebo relace.
V cestě
| Parametr | Co to je |
|---|---|
id | Id zakázky. |
expenseID | Id výdaje. |
Tělo požadavku
The JSON body of a create or an update.
Money crosses the wire as the raw int64 with its currency, never pre-formatted and never a float. There is no author field: the acting membership books it, and a client that could name the author could book a cost against somebody else.
| Pole | Typ | Co to je |
|---|---|---|
description |
řetězec | |
cost_amount |
celé číslo | Peníze: celé číslo se čtyřmi skrytými desetinnými místy, takže 4200000 je 420,00, a vedle něj měna. |
cost_currency |
řetězec |
Odpověď
{
"id": 4,
"gig_id": 2,
"created_by_membership_id": 1,
"created_by_name": "Tereza Nováková",
"description": "Tiles",
"cost_amount": 1250000,
"cost_currency": "CZK",
"created_at": "2026-09-07T12:52:03.941837+02:00"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid JSON body · invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted |
| 404 | expense not found · gig not found |
| 500 | internal server error |
Vyzkoušet
DELETE /api/gigs/{id}/expenses/{expenseID}
Deletes a cost.
API klíč nebo relace.
V cestě
| Parametr | Co to je |
|---|---|
id | Id zakázky. |
expenseID | Id výdaje. |
Odpověď
Bez těla.
Stavové kódy
| Kód | Zpráva |
|---|---|
| 204 | |
| 400 | invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted |
| 404 | expense not found · gig not found |
| 500 | internal server error |
Vyzkoušet
Nářadí
Serves a worker's own kit list.
Every route here answers for the ACTING MEMBERSHIP and nobody else. There is no endpoint that lists another person's tools, or everybody's tools on a project, and there is no role that would change that — a PM view of who owns what is precisely what this feature does not have.
GET /api/tool-icons
Returns the fixed set of icons the product ships.
Veřejné: není potřeba klíč ani relace.
It is the one definition both clients read, so a picker cannot offer a name the server would refuse. Deliberately not behind the session: it is a constant, discloses nothing, and an app that could not draw its own picker until sign-in would be worse for no gain.
Odpověď
[
{
"name": "hammer",
"label": "Hammer"
},
{
"name": "wrench",
"label": "Spanner"
},
{
"name": "screwdriver",
"label": "Screwdriver"
},
{
"name": "pliers",
"label": "Pliers"
},
{
"name": "saw",
"label": "Saw"
},
{
"name": "trowel",
"label": "Trowel"
},
{
"name": "shovel",
"label": "Shovel"
},
{
"name": "drill",
"label": "Drill"
},
{
"name": "grinder",
"label": "Angle grinder"
},
{
"name": "breaker",
"label": "Breaker"
},
{
"name": "mixer",
"label": "Mixer"
},
{
"name": "measure",
"label": "Tape measure"
},
{
"name": "level",
"label": "Spirit level"
},
{
"name": "ladder",
"label": "Ladder"
},
{
"name": "paint",
"label": "Paint roller"
},
{
"name": "cable",
"label": "Power lead"
},
{
"name": "light",
"label": "Work light"
},
{
"name": "toolbox",
"label": "Toolbox"
},
{
"name": "safety",
"label": "Safety gear"
},
{
"name": "other",
"label": "Other"
}
]
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 |
Vyzkoušet
GET /api/tools
The caller's own kit list at this company, with the ids of the projects each tool is attached to.
API klíč nebo relace.
Odpověď
[
{
"id": 12,
"name": "SDS drill",
"icon": "drill",
"quantity": null,
"created_at": "2026-09-08T14:22:41.117204+02:00",
"gig_ids": [
3,
7
]
},
{
"id": 11,
"name": "Clamps",
"icon": "other",
"quantity": 6,
"created_at": "2026-09-08T14:21:02.884113+02:00",
"gig_ids": []
}
]
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | |
| 401 | authentication required |
| 403 | not permitted |
| 404 | tool not found |
| 500 | internal server error |
Vyzkoušet
POST /api/tools
Adds a tool to the caller's kit list.
API klíč nebo relace.
The icon is a name from GET /api/tool-icons; the quantity is optional.
Tělo požadavku
The JSON body of a create or an update.
No membership or org field: both come from the session. A client that could name either could write somebody else's kit list.
| Pole | Typ | Co to je |
|---|---|---|
name |
řetězec | |
icon |
řetězec | |
quantity |
celé číslo, nebo null |
Odpověď
{
"id": 12,
"name": "SDS drill",
"icon": "drill",
"quantity": null,
"created_at": "2026-09-08T14:22:41.117204+02:00",
"gig_ids": [
3,
7
]
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 201 | |
| 400 | invalid JSON body |
| 401 | authentication required |
| 403 | not permitted |
| 404 | tool not found |
| 500 | internal server error |
Vyzkoušet
PATCH /api/tools/{id}
Renames a tool, or changes its icon or quantity.
API klíč nebo relace.
V cestě
| Parametr | Co to je |
|---|---|
id | Id nářadí. |
Tělo požadavku
The JSON body of a create or an update.
No membership or org field: both come from the session. A client that could name either could write somebody else's kit list.
| Pole | Typ | Co to je |
|---|---|---|
name |
řetězec | |
icon |
řetězec | |
quantity |
celé číslo, nebo null |
Odpověď
{
"id": 11,
"name": "Clamps",
"icon": "other",
"quantity": 6,
"created_at": "2026-09-08T14:21:02.884113+02:00",
"gig_ids": []
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid JSON body · invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted |
| 404 | tool not found |
| 500 | internal server error |
Vyzkoušet
DELETE /api/tools/{id}
Deletes a tool from the kit list, and detaches it from every project it was taken to.
API klíč nebo relace.
V cestě
| Parametr | Co to je |
|---|---|
id | Id nářadí. |
Odpověď
Bez těla.
Stavové kódy
| Kód | Zpráva |
|---|---|
| 204 | |
| 400 | invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted |
| 404 | tool not found |
| 500 | internal server error |
Vyzkoušet
GET /api/gigs/{id}/tools
Returns the caller's own tools attached to one project — what they have to load into the van for this job.
API klíč nebo relace.
V cestě
| Parametr | Co to je |
|---|---|
id | Id zakázky. |
Odpověď
[
{
"id": 12,
"name": "SDS drill",
"icon": "drill",
"quantity": null,
"created_at": "2026-09-08T14:22:41.117204+02:00",
"gig_ids": [
3,
7
]
},
{
"id": 11,
"name": "Clamps",
"icon": "other",
"quantity": 6,
"created_at": "2026-09-08T14:21:02.884113+02:00",
"gig_ids": []
}
]
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted |
| 404 | tool not found |
| 500 | internal server error |
Vyzkoušet
POST /api/gigs/{id}/tools
Says "I am taking this to that job".
API klíč nebo relace.
Idempotent: attaching a tool that is already attached answers 204 rather than a conflict. Two taps on a building site is a bad radio, not a disagreement, and the second one meant the same as the first.
V cestě
| Parametr | Co to je |
|---|---|
id | Id zakázky. |
Tělo požadavku
Names the tool being taken to a project.
| Pole | Typ | Co to je |
|---|---|---|
tool_id |
celé číslo |
Odpověď
Bez těla.
Stavové kódy
| Kód | Zpráva |
|---|---|
| 204 | |
| 400 | invalid JSON body · invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted |
| 404 | tool not found |
| 500 | internal server error |
Vyzkoušet
DELETE /api/gigs/{id}/tools/{toolID}
Removes the link and NOT the tool.
API klíč nebo relace.
Coming off one job must not cost the worker the entry.
V cestě
| Parametr | Co to je |
|---|---|
id | Id zakázky. |
toolID | Id nářadí. |
Odpověď
Bez těla.
Stavové kódy
| Kód | Zpráva |
|---|---|
| 204 | |
| 400 | invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted |
| 404 | tool not found |
| 500 | internal server error |
Vyzkoušet
Plánování kalendáře zakázky
A project's calendar, for its managers: which days it runs, the shifts on each, and laying shifts on days or taking them off again. Removing work people have accepted asks first: without confirm nothing changes and the answer says how many people would be told. A worker sees none of this; the project's days reach a worker as their shifts.
GET /api/gigs/{id}/calendar
A project's days in a range, each with its shifts, roles and staffing counts.
API klíč nebo relace.
from and to are calendar days, "2026-10-27", both inclusive; without them the four weeks from today on site. A range may be up to a year. A day is listed only if the project runs on it, so the gaps in a project that pauses are simply absent days. Who is on each shift is the shift's own endpoint. Managers only; a worker's week is the dashboard.
V cestě
| Parametr | Co to je |
|---|---|
id | Id zakázky. |
Parametry dotazu
fromto
Odpověď
[
{
"day": "2026-09-10",
"day_id": 1,
"shifts": [
{
"id": 1,
"gig_id": 1,
"day_id": 1,
"starts_at": "2026-09-10T05:00:00Z",
"ends_at": "2026-09-10T13:00:00Z",
"required_workers": 3,
"role_label": "1× crane op, 2× labourer",
"created_at": "2026-09-07T09:00:00Z",
"accepted": 1,
"pending": 1,
"short": 2,
"is_open": false,
"open_auto_accept": false,
"offered_rate_multiplier": null,
"roles": [
{
"id": 1,
"label": "crane op",
"headcount": 1,
"rate_amount": 5200000,
"rate_currency": "CZK",
"accepted": 1,
"pending": 0
},
{
"id": 2,
"label": "labourer",
"headcount": 2,
"rate_amount": null,
"rate_currency": null,
"accepted": 0,
"pending": 1
}
]
}
]
},
{
"day": "2026-09-11",
"day_id": 2,
"shifts": []
}
]
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | from must be a calendar day, YYYY-MM-DD · invalid {thing} id · the range must run forwards and be at most a year · to must be a calendar day, YYYY-MM-DD |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/gigs/{id}/days
Puts days on a project's calendar.
API klíč nebo relace.
Days already on it are left as they are, so sending a range twice is harmless. Laying a shift on a day schedules the day too, so this is only needed for a day that runs with no shift planned yet. Up to a year of days in one request. The answer is the project's whole calendar. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id zakázky. |
Tělo požadavku
Names calendar days, "2026-10-27".
| Pole | Typ | Co to je |
|---|---|---|
days |
seznam: řetězec | |
confirm |
boolean |
|
Odpověď
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid JSON body · invalid {thing} id · name at least one day |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/gigs/{id}/days/remove
Takes days off a project's calendar, with their shifts.
API klíč nebo relace.
Anybody with a live place on them — accepted, or invited and not yet answered — is taken off and told once, however many of their shifts went; anybody who had accepted is emailed as well. So it asks first: without confirm nothing changes and the answer says how many people that is. A shift that has started is a record and its day cannot be removed. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id zakázky. |
Tělo požadavku
Names calendar days, "2026-10-27".
| Pole | Typ | Co to je |
|---|---|---|
days |
seznam: řetězec | |
confirm |
boolean |
|
Odpověď
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid JSON body · invalid {thing} id · name at least one day |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/gigs/{id}/shifts
Lays one shift on each of the days named, with its roles.
API klíč nebo relace.
The same clock times on each day, worked out day by day on site, so a week that crosses a change of the clocks is right on every day. The answer is each shift made, with its roles' ids, which an invitation names. Managers only; an archived project takes no new shifts.
V cestě
| Parametr | Co to je |
|---|---|
id | Id zakázky. |
Tělo požadavku
One shift laid on each of several days.
| Pole | Typ | Co to je |
|---|---|---|
days |
seznam: řetězec |
|
starts_at |
řetězec |
|
ends_at |
řetězec | |
roles |
seznam: Role to add |
|
headcount |
celé číslo |
|
open |
boolean |
|
open_auto_accept |
boolean | |
offered_rate_multiplier |
celé číslo, nebo null |
Násobek se čtyřmi skrytými desetinnými místy: 15000 je 1,5×. |
Odpověď
{
"id": 1,
"gig_id": 1,
"day_id": 1,
"starts_at": "2026-09-10T05:00:00Z",
"ends_at": "2026-09-10T13:00:00Z",
"required_workers": 3,
"role_label": "1× crane op, 2× labourer",
"created_at": "2026-09-07T09:00:00Z",
"accepted": 1,
"pending": 1,
"short": 2,
"is_open": false,
"open_auto_accept": false,
"offered_rate_multiplier": null,
"roles": [
{
"id": 1,
"label": "crane op",
"headcount": 1,
"rate_amount": 5200000,
"rate_currency": "CZK",
"accepted": 1,
"pending": 0
},
{
"id": 2,
"label": "labourer",
"headcount": 2,
"rate_amount": null,
"rate_currency": null,
"accepted": 0,
"pending": 1
}
]
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 201 | |
| 400 | ends_at must be a time of day, as 15:00 · invalid JSON body · invalid {thing} id · name at least one day · starts_at must be a time of day, as 07:00, on a day written YYYY-MM-DD |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/gigs/{id}/shifts/move
Moves shifts to new dates, by a number of whole days.
API klíč nebo relace.
Clock times are kept on site. Everyone with an accepted place is asked again: their place goes back to pending with the new date as its deadline, they are told once, and anyone who had accepted is emailed. A shift that has started, or has an SOS running, stays where it is and is counted as skipped; a move that would land a shift in the past is refused whole. It asks first: without confirm nothing changes and the answer has the counts. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id zakázky. |
Tělo požadavku
Moves shifts by whole days.
| Pole | Typ | Co to je |
|---|---|---|
timeslot_ids |
seznam: celé číslo |
|
days |
celé číslo |
|
confirm |
boolean |
|
Odpověď
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid JSON body · invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/timeslots/{id}/remove
Takes a shift off its day.
API klíč nebo relace.
Everybody with a live place on it is taken off and told, as removing a day tells them. It asks first: without confirm nothing changes and the answer counts the accepted and pending places. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id směny. |
Tělo požadavku
A removal's consent.
| Pole | Typ | Co to je |
|---|---|---|
confirm |
boolean |
|
Odpověď
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid JSON body · invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
Obsazování zakázky
Staffing as a manager does it: who is on a shift, inviting people to one shift or to many, approving an applicant, taking somebody off a shift or off the whole project, opening a shift to the company, raising an SOS, and the shifts short of people. An invitation is a question — nobody counts as staffed until they accept — and every removal tells the person once. The worker's side, answering and taking shifts, is elsewhere.
GET /api/timeslots/{id}
One shift, with its roles and everyone on it.
API klíč nebo relace.
Each person's status is as it stands now: an unanswered invitation past the shift's start reads expired. Another company's shift is not found. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id směny. |
Odpověď
{
"id": 1,
"gig_id": 1,
"day_id": 1,
"starts_at": "2026-09-10T05:00:00Z",
"ends_at": "2026-09-10T13:00:00Z",
"required_workers": 3,
"role_label": "1× crane op, 2× labourer",
"created_at": "2026-09-07T09:00:00Z",
"accepted": 1,
"pending": 1,
"short": 2,
"is_open": true,
"open_auto_accept": false,
"offered_rate_multiplier": 15000,
"roles": [
{
"id": 1,
"label": "crane op",
"headcount": 1,
"rate_amount": 5200000,
"rate_currency": "CZK",
"accepted": 1,
"pending": 0
},
{
"id": 2,
"label": "labourer",
"headcount": 2,
"rate_amount": null,
"rate_currency": null,
"accepted": 0,
"pending": 1
}
],
"people": [
{
"id": 1,
"timeslot_id": 1,
"membership_id": 2,
"origin": "staffed",
"status": "accepted",
"rate_amount": 5200000,
"rate_currency": "CZK",
"role_id": 1,
"role_label": "crane op",
"invited_at": "2026-09-07T09:00:00Z",
"responded_at": "2026-09-07T09:05:00Z",
"expires_at": "2026-09-10T05:00:00Z",
"created_at": "2026-09-07T09:00:00Z",
"takes_from": null,
"takes_until": null,
"worker_name": "Jana Horáková"
},
{
"id": 2,
"timeslot_id": 1,
"membership_id": 3,
"origin": "sos",
"status": "pending",
"rate_amount": null,
"rate_currency": null,
"role_id": 2,
"role_label": "labourer",
"invited_at": "2026-09-08T14:00:00Z",
"responded_at": null,
"expires_at": "2026-09-10T13:00:00Z",
"created_at": "2026-09-08T14:00:00Z",
"takes_from": null,
"takes_until": null,
"worker_name": "Petr Dvořák"
}
]
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/timeslots/{id}/invitations
Asks one person to one shift.
API klíč nebo relace.
The answer is the invitation, pending: it fills nothing until they accept, and it lapses at the shift's start if they never do. The rate on it is settled now — the role's, else the project's pay rate, else their own — and does not move afterwards. A person already live on the shift, a shift that has started, and somebody who does not work shifts here are each refused. The person is told once. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id směny. |
Tělo požadavku
Names who to invite to a shift, and for which role.
| Pole | Typ | Co to je |
|---|---|---|
membership_id |
celé číslo |
|
role_id |
celé číslo |
|
Odpověď
{
"id": 2,
"timeslot_id": 1,
"membership_id": 3,
"origin": "sos",
"status": "pending",
"rate_amount": null,
"rate_currency": null,
"role_id": 2,
"role_label": "labourer",
"invited_at": "2026-09-08T14:00:00Z",
"responded_at": null,
"expires_at": "2026-09-10T13:00:00Z",
"created_at": "2026-09-08T14:00:00Z",
"takes_from": null,
"takes_until": null,
"worker_name": "Petr Dvořák"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 201 | |
| 400 | invalid JSON body · invalid {thing} id · membership_id is required |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/gigs/{id}/invitations/batch
Asks several people to several shifts of one project at once.
API klíč nebo relace.
Each pair becomes an ordinary invitation with its own rate and its own deadline; nothing records that they were made together. Somebody already live on a shift is skipped, not refused. More people than a shift has places, and a shift overlapping other work of theirs at this company, are allowed and said. Another project's shift, somebody who does not work shifts here, or a shift that has started refuses the whole batch and says which. Each person is told once. Send preview to see all of that without sending anything. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id zakázky. |
Tělo požadavku
Asks several people to several shifts at once.
| Pole | Typ | Co to je |
|---|---|---|
membership_ids |
seznam: celé číslo |
|
timeslot_ids |
seznam: celé číslo |
|
role |
řetězec, nebo null |
|
preview |
boolean |
|
Odpověď
{
"preview": false,
"people": 2,
"shifts": 2,
"invitations": 3,
"skipped": [
{
"membership_id": 2,
"worker_name": "Jana Horáková",
"shift": {
"timeslot_id": 1,
"starts_at": "2026-09-10T05:00:00Z",
"ends_at": "2026-09-10T13:00:00Z"
}
}
],
"over_filled": [
{
"shift": {
"timeslot_id": 2,
"starts_at": "2026-09-11T05:00:00Z",
"ends_at": "2026-09-11T13:00:00Z"
},
"invited": 2,
"places": 1
}
],
"clashes": [
{
"membership_id": 3,
"worker_name": "Petr Dvořák",
"shift": {
"timeslot_id": 2,
"starts_at": "2026-09-11T05:00:00Z",
"ends_at": "2026-09-11T13:00:00Z"
},
"with": {
"timeslot_id": 7,
"starts_at": "2026-09-11T10:00:00Z",
"ends_at": "2026-09-11T14:00:00Z"
},
"in_batch": false
}
],
"sent": [
{
"id": 3,
"timeslot_id": 2,
"membership_id": 2,
"origin": "staffed",
"status": "pending",
"rate_amount": 4200000,
"rate_currency": "CZK",
"role_id": 3,
"role_label": null,
"invited_at": "2026-09-08T14:00:00Z",
"responded_at": null,
"expires_at": "2026-09-11T05:00:00Z",
"created_at": "2026-09-08T14:00:00Z",
"takes_from": null,
"takes_until": null,
"worker_name": "Jana Horáková"
}
]
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid JSON body · invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/assignments/{id}/approve
Confirms an applicant on a shift the manager reviews takers for: an open shift or an SOS.
API klíč nebo relace.
The answer is the assignment, accepted, at the rate it was offered. A full role, an application that has lapsed, an invitation (which only the worker can accept), and an applicant who has since accepted colliding work are each refused. The person is told. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id přiřazení: vašeho místa na směně. |
Odpověď
{
"id": 1,
"timeslot_id": 1,
"membership_id": 2,
"origin": "staffed",
"status": "accepted",
"rate_amount": 5200000,
"rate_currency": "CZK",
"role_id": 1,
"role_label": "crane op",
"invited_at": "2026-09-07T09:00:00Z",
"responded_at": "2026-09-07T09:05:00Z",
"expires_at": "2026-09-10T05:00:00Z",
"created_at": "2026-09-07T09:00:00Z",
"takes_from": null,
"takes_until": null,
"worker_name": "Jana Horáková"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/assignments/{id}/cancel
Takes one person off one shift.
API klíč nebo relace.
Their place is cancelled and reopens, and they are told once; if they had accepted they are emailed too, unless they turned that off. confirm is required: without it nothing changes and this answers 400, because the act is what tells a person not to come. A place already settled — declined, lapsed, withdrawn, cancelled — is refused. To take somebody off every upcoming shift of the project at once, use the project's people endpoint. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id přiřazení: vašeho místa na směně. |
Tělo požadavku
A removal's consent.
| Pole | Typ | Co to je |
|---|---|---|
confirm |
boolean |
|
Odpověď
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid JSON body · invalid {thing} id · send confirm: this cancels their place and tells them |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
GET /api/gigs/{id}/people
Lists everyone with a live place on a project's shifts still to come: accepted, or asked and not yet answered, each once.
API klíč nebo relace.
A shift that has started is a record and is not counted; somebody whose only shifts are over is on the project's hours, not here. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id zakázky. |
Odpověď
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/gigs/{id}/people/{membershipID}/remove
Takes one person off every upcoming shift of a project at once.
API klíč nebo relace.
Every live place of theirs on a shift of the project still to come is cancelled in one go, and they are told once: one push, and one email listing the accepted shifts. Their places on other projects, and on a shift of this project that has started, are not touched. It asks first: without confirm nothing changes and the answer counts the places. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id zakázky. |
membershipID | Id členství člověka, jak je uvádí seznam lidí. |
Tělo požadavku
A removal's consent.
| Pole | Typ | Co to je |
|---|---|---|
confirm |
boolean |
|
Odpověď
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid JSON body · invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/timeslots/{id}/open
Advertises a shift to the company: any worker there may take a place on it without being invited.
API klíč nebo relace.
A shift is open only because a manager said so; it is never open merely for being short. The manager chooses whether a taker is confirmed outright or reviewed, and may raise the rate. The answer is the shift as it now stands. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id směny. |
Tělo požadavku
The terms a shift is opened on.
| Pole | Typ | Co to je |
|---|---|---|
auto_accept |
boolean |
|
offered_rate_multiplier |
celé číslo, nebo null |
Násobek se čtyřmi skrytými desetinnými místy: 15000 je 1,5×. |
Odpověď
{
"id": 1,
"gig_id": 1,
"day_id": 1,
"starts_at": "2026-09-10T05:00:00Z",
"ends_at": "2026-09-10T13:00:00Z",
"required_workers": 3,
"role_label": "1× crane op, 2× labourer",
"created_at": "2026-09-07T09:00:00Z",
"accepted": 1,
"pending": 1,
"short": 2,
"is_open": true,
"open_auto_accept": false,
"offered_rate_multiplier": 15000,
"roles": [
{
"id": 1,
"label": "crane op",
"headcount": 1,
"rate_amount": 5200000,
"rate_currency": "CZK",
"accepted": 1,
"pending": 0
},
{
"id": 2,
"label": "labourer",
"headcount": 2,
"rate_amount": null,
"rate_currency": null,
"accepted": 0,
"pending": 1
}
]
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | a multiplier must be more than nothing · invalid JSON body · invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/timeslots/{id}/close
Stops advertising a shift.
API klíč nebo relace.
The people already on it stay on it. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id směny. |
Odpověď
{
"id": 1,
"gig_id": 1,
"day_id": 1,
"starts_at": "2026-09-10T05:00:00Z",
"ends_at": "2026-09-10T13:00:00Z",
"required_workers": 3,
"role_label": "1× crane op, 2× labourer",
"created_at": "2026-09-07T09:00:00Z",
"accepted": 1,
"pending": 1,
"short": 2,
"is_open": false,
"open_auto_accept": false,
"offered_rate_multiplier": null,
"roles": [
{
"id": 1,
"label": "crane op",
"headcount": 1,
"rate_amount": 5200000,
"rate_currency": "CZK",
"accepted": 1,
"pending": 0
},
{
"id": 2,
"label": "labourer",
"headcount": 2,
"rate_amount": null,
"rate_currency": null,
"accepted": 0,
"pending": 1
}
]
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/timeslots/{id}/sos
Raises an emergency on one short shift.
API klíč nebo relace.
An SOS is an open shift with the rate raised and a notification sent: every worker at the company who opted into emergency cover is told, and each may take a place at the raised rate until the shift ends. It is refused on a shift that is not short, that is over, or that has an SOS running; somebody who called in sick is taken off first, which is what makes the shift short. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id směny. |
Tělo požadavku
The terms an SOS is raised on.
| Pole | Typ | Co to je |
|---|---|---|
offered_rate_multiplier |
celé číslo, nebo null |
Násobek se čtyřmi skrytými desetinnými místy: 15000 je 1,5×. |
auto_accept |
boolean |
|
Odpověď
{
"id": 1,
"timeslot_id": 1,
"offered_rate_multiplier": 15000,
"opened_at": "2026-09-09T16:00:00Z",
"told": 0
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 201 | |
| 400 | a multiplier must be more than nothing · invalid JSON body · invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/gigs/{id}/sos
Raises one ordinary SOS on each of several short shifts of a project, in one go, and tells each person once.
API klíč nebo relace.
Name the shifts, or none for every short shift of the project that is not over, read now. A shift that filled, ended or has an SOS already is skipped and counted; a shift of another project refuses the lot. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id zakázky. |
Tělo požadavku
Raises an SOS over a project's short shifts.
| Pole | Typ | Co to je |
|---|---|---|
offered_rate_multiplier |
celé číslo, nebo null |
Násobek se čtyřmi skrytými desetinnými místy: 15000 je 1,5×. |
auto_accept |
boolean |
|
timeslot_ids |
seznam: celé číslo |
|
Odpověď
{
"raised": [
{
"id": 1,
"timeslot_id": 1,
"offered_rate_multiplier": 15000,
"opened_at": "2026-09-09T16:00:00Z",
"told": 0
}
],
"already_raised": 0,
"filled": 1,
"over": 0,
"told": 4
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 201 | |
| 400 | a multiplier must be more than nothing · invalid JSON body · invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
GET /api/staffing/short
Lists the company's upcoming shifts that need attention: short of accepted people, or carrying invitations nobody has answered.
API klíč nebo relace.
days is how far ahead to look, 7 unless given, up to 92. Earliest first, across every live project. A shift whose places are all covered by unanswered invitations is listed: an invitation staffs nothing. Managers only.
all=1 lists them at every company the caller manages, earliest first within each, with company on each row naming the entry: send its entry as X-Werzeick-Company to act on the shift. A caller acting as a worker may ask too, and gets the companies they manage. It cannot be combined with X-Werzeick-Company.
Parametry dotazu
alldays
Odpověď
seznam: Shift needing attention
[
{
"id": 1,
"gig_id": 1,
"day_id": 1,
"starts_at": "2026-09-10T05:00:00Z",
"ends_at": "2026-09-10T13:00:00Z",
"required_workers": 3,
"role_label": "1× crane op, 2× labourer",
"created_at": "2026-09-07T09:00:00Z",
"accepted": 1,
"pending": 1,
"gig_title": "Warehouse roof",
"short": 2,
"sos_open": true,
"roles": [
{
"id": 1,
"label": "crane op",
"headcount": 1,
"rate_amount": 5200000,
"rate_currency": "CZK",
"accepted": 1,
"pending": 0
},
{
"id": 2,
"label": "labourer",
"headcount": 2,
"rate_amount": null,
"rate_currency": null,
"accepted": 0,
"pending": 1
}
]
}
]
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | all=1 reads every company: leave out X-Werzeick-Company · days must be a whole number from 1 to 92 |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
Lidé ve firmě
The company's roster, for its managers: everyone with a membership at the company, what each may do here (manage projects, work shifts, or both), the default rate for anyone who works shifts, and what the company has noted each as certified for. An invitation to a shift names a person by the id listed here. Inviting somebody new to the company is the invitations endpoint.
GET /api/people
Lists everyone at the company, by name.
API klíč nebo relace.
rate_amount is each person's own default rate here, the fallback for a project with no pay rate of its own and a role with none; null is "no hourly rate". is_disabled marks somebody a manager has switched off, who cannot be invited. certifications is what the company has noted the person as certified for; such people are listed first in the web client's staffing picker, and nothing requires one. Somebody whose account was deleted is not listed. Managers only.
q narrows the list to the people a search finds, as the web client's person pickers do: every word of it has to be the start of a word of the person's name, or of the name, another common name or the scope of something they are certified for, with no case or accents needed. ?q=dvo finds Dvořák, ?q=vzv the forklift drivers, ?q=novák jeřáb a Novák noted for a crane, ?q=jeřáb 10 t a crane operator whose note's scope says 10 t. Without it, everybody.
Parametry dotazu
q
Odpověď
[
{
"id": 1,
"is_manager": true,
"is_worker": false,
"rate_amount": null,
"rate_currency": null,
"emergency_responses_enabled": false,
"cancellation_emails_enabled": true,
"is_disabled": false,
"created_at": "2026-09-01T08:00:00Z",
"org_name": "Alpha Stavby",
"first_name": "Tomáš",
"last_name": "Novák",
"email": "tomas@alpha.test",
"certifications": []
},
{
"id": 2,
"is_manager": false,
"is_worker": true,
"rate_amount": 4200000,
"rate_currency": "CZK",
"emergency_responses_enabled": true,
"cancellation_emails_enabled": true,
"is_disabled": false,
"created_at": "2026-09-01T08:05:00Z",
"org_name": "Alpha Stavby",
"first_name": "Jana",
"last_name": "Horáková",
"email": "jana@alpha.test",
"certifications": [
{
"id": 1,
"membership_id": 2,
"kind": "lift_crane_overhead",
"label": null,
"scope": "bridge cranes to 10 t",
"expires_on": "2027-06-30",
"granted_by_membership_id": 1,
"granted_by_name": "Tomáš Novák",
"created_at": "2026-10-28T09:00:00Z",
"certificate_id": 1,
"name": "Overhead or gantry crane operator"
}
]
}
]
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 401 | authentication required |
| 403 | not permitted |
| 500 | internal server error |
Vyzkoušet
POST /api/people/{id}/certifications
Notes a person as certified for something, by the manager's say-so, or by approving one of their certificates.
API klíč nebo relace.
Approving is sending certificate_id: the note copies what the document says and is linked to it. The note outlives the document: a certificate deleted later leaves it standing with certificate_id null.
One note per person and kind (per label for other_personal); a second of the same is refused. The person is pushed once. Nothing requires a note: it is the company's own record, shown to its managers when they staff a shift. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id členství člověka, jak je uvádí seznam lidí. |
Tělo požadavku
Notes somebody as certified for something: by the manager's say-so, or by approving one of the person's certificates.
| Pole | Typ | Co to je |
|---|---|---|
certificate_id |
celé číslo |
|
kind |
řetězec |
|
label |
řetězec |
|
scope |
řetězec | At most 200 characters. |
expires_on |
řetězec, nebo null |
|
Odpověď
{
"id": 1,
"membership_id": 2,
"kind": "lift_crane_overhead",
"label": null,
"scope": "bridge cranes to 10 t",
"expires_on": "2027-06-30",
"granted_by_membership_id": 1,
"granted_by_name": "Tomáš Novák",
"created_at": "2026-10-28T09:00:00Z",
"certificate_id": 1,
"name": "Overhead or gantry crane operator"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 201 | |
| 400 | expires_on must be YYYY-MM-DD or null · invalid JSON body · invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
DELETE /api/people/{id}/certifications/{certificationID}
Takes a note away.
API klíč nebo relace.
Nobody is told. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id členství člověka, jak je uvádí seznam lidí. |
certificationID | ID certifikace, jak ji seznam lidí uvádí u osoby. |
Odpověď
Bez těla.
Stavové kódy
| Kód | Zpráva |
|---|---|
| 204 | |
| 400 | invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
GET /api/people/{id}/certificates
Lists a person's certificates: the documents they hold, with their pages' sizes, as the person themselves sees them.
API klíč nebo relace.
A certificate is the person's, not the company's, so this is the same list the person's other employers see; who uploaded one is named only when it was a manager at your own company. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id členství člověka, jak je uvádí seznam lidí. |
Odpověď
[
{
"id": 1,
"kind": "lift_crane_overhead",
"label": null,
"scope": "bridge cranes to 10 t",
"number": "JB-4471",
"issued_on": "2024-05-02",
"expires_on": "2029-05-01",
"pages": [
{
"position": 1,
"content_type": "image/jpeg",
"width": 1600,
"height": 1067
},
{
"position": 2,
"content_type": "image/jpeg",
"width": 1600,
"height": 1067
}
],
"uploaded_by": {
"membership_id": 1,
"name": "Tomáš Novák",
"company": "Alpha Stavby"
},
"created_at": "2026-10-28T09:00:00Z",
"updated_at": "2026-10-28T09:04:00Z",
"name": "Overhead or gantry crane operator"
},
{
"id": 2,
"kind": "other_personal",
"label": "Drone pilot",
"scope": null,
"number": null,
"issued_on": null,
"expires_on": null,
"pages": [],
"uploaded_by": null,
"created_at": "2026-10-28T10:00:00Z",
"updated_at": "2026-10-28T10:00:00Z",
"name": "Drone pilot"
}
]
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/people/{id}/certificates
Adds a certificate on a person's behalf, for when the office holds the scans.
API klíč nebo relace.
It is recorded as uploaded by you, shown to the person as such, and is theirs afterwards like one they uploaded: they may correct or delete it, and you may not. The pages are added afterwards, one by one. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id členství člověka, jak je uvádí seznam lidí. |
Tělo požadavku
What is typed about a certificate: what is printed on the card.
| Pole | Typ | Co to je |
|---|---|---|
kind |
řetězec |
|
label |
řetězec |
|
scope |
řetězec | At most 200 characters. |
number |
řetězec |
|
issued_on |
řetězec, nebo null |
|
expires_on |
řetězec, nebo null |
|
Odpověď
{
"id": 2,
"kind": "other_personal",
"label": "Drone pilot",
"scope": null,
"number": null,
"issued_on": null,
"expires_on": null,
"pages": [],
"uploaded_by": null,
"created_at": "2026-10-28T10:00:00Z",
"updated_at": "2026-10-28T10:00:00Z",
"name": "Drone pilot"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 201 | |
| 400 | invalid JSON body · invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/people/{id}/certificates/{certificateID}/pages
Adds the next page to a person's certificate, as the person's own pages endpoint does.
API klíč nebo relace.
The image comes as multipart/form-data with a part named page, or as JSON with the image in base64. At most 8 pages; what is kept is the pixels and nothing else. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id členství člověka, jak je uvádí seznam lidí. |
certificateID | ID dokladu, jak ho uvádí seznam dokladů. |
Tělo požadavku
One page of a certificate as JSON: the image's bytes in base64. The same endpoint also takes multipart/form-data with the file in a part named page, which is what the app and the web client send.
| Pole | Typ | Co to je |
|---|---|---|
image |
řetězec | A PDF is refused; a client with one renders its pages to images first. The server shrinks the image to about 1600 px on its long edge, re-encodes it as JPEG and keeps nothing else of it: no camera metadata, no position. |
Odpověď
{
"id": 1,
"kind": "lift_crane_overhead",
"label": null,
"scope": "bridge cranes to 10 t",
"number": "JB-4471",
"issued_on": "2024-05-02",
"expires_on": "2029-05-01",
"pages": [
{
"position": 1,
"content_type": "image/jpeg",
"width": 1600,
"height": 1067
},
{
"position": 2,
"content_type": "image/jpeg",
"width": 1600,
"height": 1067
}
],
"uploaded_by": {
"membership_id": 1,
"name": "Tomáš Novák",
"company": "Alpha Stavby"
},
"created_at": "2026-10-28T09:00:00Z",
"updated_at": "2026-10-28T09:04:00Z",
"name": "Overhead or gantry crane operator"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 201 | |
| 400 | image must be base64 · invalid JSON body · invalid {thing} id · send the image as a part named page · the upload could not be read |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
GET /api/people/{id}/certificates/{certificateID}/pages/{position}
Answers one page of a person's certificate as the image itself, not as JSON.
API klíč nebo relace.
Managers only.
The body is the JPEG, with its content type.
V cestě
| Parametr | Co to je |
|---|---|
id | Id členství člověka, jak je uvádí seznam lidí. |
certificateID | ID dokladu, jak ho uvádí seznam dokladů. |
position | Pořadí stránky na dokladu, počítáno od 1. |
Odpověď
Bez těla.
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · page not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
Doklady
About certificates: the documents a person holds, a crane licence or a welding test, with their photos, and the kinds there are. The list of kinds is the server's, so that no client carries a copy that can drift. The certificates here are the caller's own, whichever company or role the key acts in: a certificate is the person's, and every company they work for sees the same one. A manager reads and adds a member's certificates on the people endpoints, and notes somebody as certified for one there too.
GET /api/certificate-kinds
Lists every kind of certificate there is, with its name in the request's language, the group it is listed under, the words people use for it, and the trades with the order each offers kinds in.
API klíč nebo relace.
One kind, other_personal, is for a certificate the list has no name for; a note or a certificate of that kind carries a typed label. Either role.
Odpověď
{
"groups": [
{
"id": "education",
"name": "Education"
},
{
"id": "qualification",
"name": "Qualification"
}
],
"kinds": [
{
"id": "other_personal",
"name": "Other document",
"group": "other",
"aliases": [
"jiný certifikát",
"jiné oprávnění",
"neznámý doklad"
]
},
{
"id": "lift_crane_overhead",
"name": "Overhead or gantry crane operator",
"group": "induction",
"aliases": [
"jeřábnický průkaz",
"mostový jeřáb"
]
},
{
"id": "weld_iso9606",
"name": "Welder qualification test (EN ISO 9606)",
"group": "qualification",
"aliases": [
"svářečský certifikát",
"úřední zkouška",
"ISO 9606",
"EN 287"
]
}
],
"trades": [
{
"id": "crane_operator",
"name": "Crane / loader crane operator",
"preferred": [
"lift_crane_overhead",
"lift_crane_mobile",
"lift_crane_tower",
"lift_loader_crane"
],
"related": [
"lift_slinger",
"lift_signaller",
"driver_licence"
],
"common": [
"edu_apprenticeship",
"edu_diploma",
"qual_nsk",
"edu_retraining",
"training_manufacturer",
"training_bozp",
"training_fire",
"training_first_aid",
"training_heights",
"training_fall_protection",
"scheme_scc",
"scheme_vca",
"other_personal"
]
}
]
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 401 | authentication required |
Vyzkoušet
GET /api/certificates
Lists the caller's own certificates, oldest first, each with its pages' sizes.
API klíč nebo relace.
The pages themselves are read one at a time. Either role: the documents are the person's, whatever the key acts as.
Odpověď
[
{
"id": 1,
"kind": "lift_crane_overhead",
"label": null,
"scope": "bridge cranes to 10 t",
"number": "JB-4471",
"issued_on": "2024-05-02",
"expires_on": "2029-05-01",
"pages": [
{
"position": 1,
"content_type": "image/jpeg",
"width": 1600,
"height": 1067
},
{
"position": 2,
"content_type": "image/jpeg",
"width": 1600,
"height": 1067
}
],
"uploaded_by": {
"membership_id": 1,
"name": "Tomáš Novák",
"company": "Alpha Stavby"
},
"created_at": "2026-10-28T09:00:00Z",
"updated_at": "2026-10-28T09:04:00Z",
"name": "Overhead or gantry crane operator"
},
{
"id": 2,
"kind": "other_personal",
"label": "Drone pilot",
"scope": null,
"number": null,
"issued_on": null,
"expires_on": null,
"pages": [],
"uploaded_by": null,
"created_at": "2026-10-28T10:00:00Z",
"updated_at": "2026-10-28T10:00:00Z",
"name": "Drone pilot"
}
]
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 401 | authentication required |
| 403 | not permitted |
| 500 | internal server error |
Vyzkoušet
POST /api/certificates
Adds a certificate of the caller's own, with no pages yet: the photos are added one by one afterwards.
API klíč nebo relace.
The managers of every company the caller works for are pushed once when the first page lands, naming nothing. A person holds at most 50.
Tělo požadavku
What is typed about a certificate: what is printed on the card.
| Pole | Typ | Co to je |
|---|---|---|
kind |
řetězec |
|
label |
řetězec |
|
scope |
řetězec | At most 200 characters. |
number |
řetězec |
|
issued_on |
řetězec, nebo null |
|
expires_on |
řetězec, nebo null |
|
Odpověď
{
"id": 2,
"kind": "other_personal",
"label": "Drone pilot",
"scope": null,
"number": null,
"issued_on": null,
"expires_on": null,
"pages": [],
"uploaded_by": null,
"created_at": "2026-10-28T10:00:00Z",
"updated_at": "2026-10-28T10:00:00Z",
"name": "Drone pilot"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 201 | |
| 400 | invalid JSON body |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/certificates/read
Reads the words off the photos of one document and proposes what the certificate's fields should say: its kind, the dates on it and its number, with how well each photo read.
API klíč nebo relace.
Nothing is stored; the client fills its form in from the answer and the person checks it before saving. Either role.
The photos come as multipart/form-data, each in a part named page, or as JSON with the images in base64; at most 8, each at most 4 MB. A photo is shrunk here before it is read, as it is before it is stored. Reading takes about a second a page. Answers 503 when reading is not set up on this server, in which case the form works by hand.
Tělo požadavku
The photos to read, as JSON. The same endpoint also takes multipart/form-data with each photo in a part named page, which is what the app and the web client send.
| Pole | Typ | Co to je |
|---|---|---|
images |
seznam: řetězec | They are read and then forgotten; nothing is stored until the certificate is created. |
Odpověď
{
"kind": "lift_crane_overhead",
"kind_name": "Overhead or gantry crane operator",
"issued_on": "2024-05-02",
"expires_on": "2029-05-01",
"number": "JB-4471",
"pages": [
{
"position": 1,
"readability": 94,
"legible": true
},
{
"position": 2,
"readability": 41,
"legible": false
},
{
"position": 3,
"readability": null,
"legible": false
}
],
"legible": false
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | image must be base64 · invalid JSON body · send at least one page to read · send the image as a part named page · the upload could not be read |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
| 503 | reading photos is not set up on this server; fill the form in by hand |
Vyzkoušet
PATCH /api/certificates/{id}
Corrects what is typed about one of the caller's certificates.
API klíč nebo relace.
Every field is written as sent, so send the whole record; the pages are untouched.
V cestě
| Parametr | Co to je |
|---|---|
id | ID dokladu, jak ho uvádí seznam dokladů. |
Tělo požadavku
What is typed about a certificate: what is printed on the card.
| Pole | Typ | Co to je |
|---|---|---|
kind |
řetězec |
|
label |
řetězec |
|
scope |
řetězec | At most 200 characters. |
number |
řetězec |
|
issued_on |
řetězec, nebo null |
|
expires_on |
řetězec, nebo null |
|
Odpověď
{
"id": 1,
"kind": "lift_crane_overhead",
"label": null,
"scope": "bridge cranes to 10 t",
"number": "JB-4471",
"issued_on": "2024-05-02",
"expires_on": "2029-05-01",
"pages": [
{
"position": 1,
"content_type": "image/jpeg",
"width": 1600,
"height": 1067
},
{
"position": 2,
"content_type": "image/jpeg",
"width": 1600,
"height": 1067
}
],
"uploaded_by": {
"membership_id": 1,
"name": "Tomáš Novák",
"company": "Alpha Stavby"
},
"created_at": "2026-10-28T09:00:00Z",
"updated_at": "2026-10-28T09:04:00Z",
"name": "Overhead or gantry crane operator"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid JSON body · invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
DELETE /api/certificates/{id}
Removes one of the caller's certificates with its pages.
API klíč nebo relace.
A note a company made from it stays, saying it has no proof on file. Nobody is told.
V cestě
| Parametr | Co to je |
|---|---|
id | ID dokladu, jak ho uvádí seznam dokladů. |
Odpověď
Bez těla.
Stavové kódy
| Kód | Zpráva |
|---|---|
| 204 | |
| 400 | invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/certificates/{id}/pages
Adds the next page to one of the caller's certificates: the front, the back, an attachment, at most 8.
API klíč nebo relace.
The image comes as multipart/form-data in a part named page, or as JSON with the bytes in base64. Whatever is sent, what is kept is a JPEG of the pixels and nothing else: no camera metadata, no position. Answers the certificate with its pages.
V cestě
| Parametr | Co to je |
|---|---|
id | ID dokladu, jak ho uvádí seznam dokladů. |
Tělo požadavku
One page of a certificate as JSON: the image's bytes in base64. The same endpoint also takes multipart/form-data with the file in a part named page, which is what the app and the web client send.
| Pole | Typ | Co to je |
|---|---|---|
image |
řetězec | A PDF is refused; a client with one renders its pages to images first. The server shrinks the image to about 1600 px on its long edge, re-encodes it as JPEG and keeps nothing else of it: no camera metadata, no position. |
Odpověď
{
"id": 1,
"kind": "lift_crane_overhead",
"label": null,
"scope": "bridge cranes to 10 t",
"number": "JB-4471",
"issued_on": "2024-05-02",
"expires_on": "2029-05-01",
"pages": [
{
"position": 1,
"content_type": "image/jpeg",
"width": 1600,
"height": 1067
},
{
"position": 2,
"content_type": "image/jpeg",
"width": 1600,
"height": 1067
}
],
"uploaded_by": {
"membership_id": 1,
"name": "Tomáš Novák",
"company": "Alpha Stavby"
},
"created_at": "2026-10-28T09:00:00Z",
"updated_at": "2026-10-28T09:04:00Z",
"name": "Overhead or gantry crane operator"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 201 | |
| 400 | image must be base64 · invalid JSON body · invalid {thing} id · send the image as a part named page · the upload could not be read |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
GET /api/certificates/{id}/pages/{position}
Answers one page of one of the caller's certificates as the image itself, not as JSON.
API klíč nebo relace.
The body is the JPEG, with its content type.
V cestě
| Parametr | Co to je |
|---|---|
id | ID dokladu, jak ho uvádí seznam dokladů. |
position | Pořadí stránky na dokladu, počítáno od 1. |
Odpověď
Bez těla.
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · page not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
DELETE /api/certificates/{id}/pages/{position}
Takes one page off one of the caller's certificates; the pages after it move up.
API klíč nebo relace.
Answers the certificate as it is now.
V cestě
| Parametr | Co to je |
|---|---|
id | ID dokladu, jak ho uvádí seznam dokladů. |
position | Pořadí stránky na dokladu, počítáno od 1. |
Odpověď
{
"id": 2,
"kind": "other_personal",
"label": "Drone pilot",
"scope": null,
"number": null,
"issued_on": null,
"expires_on": null,
"pages": [],
"uploaded_by": null,
"created_at": "2026-10-28T10:00:00Z",
"updated_at": "2026-10-28T10:00:00Z",
"name": "Drone pilot"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · page not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
Klienti
The company's clients: the companies it invoices, each with the Czech tax identifiers an invoice needs. A project names one by its id. Clients are the company's own; one firm never sees another's.
GET /api/clients
Lists the company's clients, by name.
API klíč nebo relace.
Archived clients are left out unless ?archived=1. Any member of the company may read the list, as the app shows a project's client.
Parametry dotazu
archived
Odpověď
[
{
"id": 1,
"name": "Stavby Novák s.r.o.",
"ico": "12345678",
"dic": "CZ12345678",
"address_line1": "Průmyslová 12",
"address_line2": null,
"city": "Ostrava",
"postal_code": "702 00",
"country": "CZ",
"contact_name": "Petr Novák",
"contact_email": "petr@stavbynovak.test",
"contact_phone": "+420777123456",
"is_archived": false,
"created_at": "2026-09-01T09:00:00Z"
},
{
"id": 2,
"name": "Jan Dvořák",
"ico": null,
"dic": null,
"address_line1": null,
"address_line2": null,
"city": null,
"postal_code": null,
"country": "CZ",
"contact_name": null,
"contact_email": null,
"contact_phone": null,
"is_archived": false,
"created_at": "2026-09-02T09:00:00Z"
}
]
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 401 | authentication required |
| 403 | not permitted |
| 500 | internal server error |
Vyzkoušet
GET /api/clients/{id}
One client.
API klíč nebo relace.
Another company's is not found.
V cestě
| Parametr | Co to je |
|---|---|
id | Id klienta. |
Odpověď
{
"id": 1,
"name": "Stavby Novák s.r.o.",
"ico": "12345678",
"dic": "CZ12345678",
"address_line1": "Průmyslová 12",
"address_line2": null,
"city": "Ostrava",
"postal_code": "702 00",
"country": "CZ",
"contact_name": "Petr Novák",
"contact_email": "petr@stavbynovak.test",
"contact_phone": "+420777123456",
"is_archived": false,
"created_at": "2026-09-01T09:00:00Z"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
POST /api/clients
Adds a client to the company.
API klíč nebo relace.
A name is required and must be new at the company; everything else may be filled in later on the web, where the form can look a Czech company up by its registration number. Managers only.
Tělo požadavku
A new client.
| Pole | Typ | Co to je |
|---|---|---|
name |
řetězec | |
ico |
řetězec, nebo null |
|
dic |
řetězec, nebo null |
|
address_line1 |
řetězec, nebo null | |
address_line2 |
řetězec, nebo null | |
city |
řetězec, nebo null | |
postal_code |
řetězec, nebo null | |
country |
řetězec |
|
contact_name |
řetězec, nebo null | The client's own contact person, who a worker rings about a job when the project names no site contact of its own. |
contact_email |
řetězec, nebo null | |
contact_phone |
řetězec, nebo null |
Odpověď
{
"id": 2,
"name": "Jan Dvořák",
"ico": null,
"dic": null,
"address_line1": null,
"address_line2": null,
"city": null,
"postal_code": null,
"country": "CZ",
"contact_name": null,
"contact_email": null,
"contact_phone": null,
"is_archived": false,
"created_at": "2026-09-02T09:00:00Z"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 201 | |
| 400 | client name is required · invalid JSON body |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
Hodiny zakázky
A project's hours as its managers read them: every time entry on the project, whoever worked it, at the rate each entry snapshotted. Records and totals only: there is no approval step, no payslip and no tax here.
GET /api/gigs/{id}/hours
Lists every time entry on a project, newest first.
API klíč nebo relace.
earned_amount is each entry's worth at its own rate, worked out here to the minute; an entry still on the clock has no clock-out and counts in no total. An archived project's hours are still listed. Managers only.
V cestě
| Parametr | Co to je |
|---|---|
id | Id zakázky. |
Odpověď
[
{
"id": 1,
"membership_id": 2,
"gig_id": 1,
"timeslot_id": 1,
"clock_in_at": "2026-09-10T04:52:00Z",
"clock_out_at": "2026-09-10T13:06:00Z",
"source": "manual",
"rate_amount": 5200000,
"rate_currency": "CZK",
"earned_amount": 42813333,
"client_event_id": "a1f0c2f1-3d6b-4b9c-9f3e-6e2d9a4c1b11",
"corrected_at": null,
"created_at": "2026-09-10T04:52:03Z",
"worker_name": "Jana Horáková",
"slot_starts_at": "2026-09-10T05:00:00Z",
"slot_ends_at": "2026-09-10T13:00:00Z",
"recorded_by": ""
}
]
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 400 | invalid {thing} id |
| 401 | authentication required |
| 403 | not permitted · that application is the manager's to approve |
| 404 | assignment not found · certificate not found · certification not found · client not found · gig not found · shift not found |
| 409 | that invitation is no longer open · that is an invitation, and only the worker can accept it · that shift collides with work you have accepted · that shift is already full |
| 500 | internal server error |
Vyzkoušet
Dostupnost
Answers the liveness check that uptime alerting polls.
Availability is a product risk here, not just an ops one: an SOS that cannot reach the server is emergency staffing that fails.
GET /healthz
Reports 200 when the server can reach its database, 503 otherwise.
Veřejné: není potřeba klíč ani relace.
The response body is deliberately free of detail: this endpoint is unauthenticated and reachable from the internet, so it says whether the service is up and nothing about why it is not.
Odpověď
objekt
{
"status": "ok"
}
Stavové kódy
| Kód | Zpráva |
|---|---|
| 200 | |
| 503 |
Vyzkoušet
Typy
Tvary, kterými volání výše odpovídají, každý popsaný jednou. Typ pole říká, zda může být null, a seznam říká, čeho je seznamem.
Request code response requestCodeResponse
The answer to asking for a sign-in code.
| Pole | Typ | Co to je |
|---|---|---|
status |
řetězec | |
resend_after_seconds |
celé číslo |
|
Session sessionResponse
Describes who the caller is and where they may act.
token and expires_at are omitted when no new session was issued — /me returns this same shape without minting anything, and an empty token field would invite a client to store one.
| Pole | Typ | Co to je |
|---|---|---|
token |
řetězec | V těle chybí, když je prázdné. |
expires_at |
řetězec | V těle chybí, když je prázdné. |
membership |
Entry | |
memberships |
seznam: Entry | |
language |
řetězec, nebo null |
|
Deletion deletionResponse
What deleting the caller's account would do, company by company. It only ever describes the caller's own memberships, and carries no id a client could send back: the deletion names nothing, because the account it deletes is the session's.
| Pole | Typ | Co to je |
|---|---|---|
can_delete |
boolean |
|
companies |
seznam: Leaving company |
Preview invitation services.PreviewInvitation
Describes an invitation to whoever holds the link, before they accept it.
It deliberately reveals only the company name and what they are invited to do — enough to decide whether to accept, and nothing about the organization's people or projects, since anyone holding the link is by definition not yet a member.
| Pole | Typ | Co to je |
|---|---|---|
org_name |
řetězec | |
is_manager |
boolean | |
is_worker |
boolean | |
first_name |
řetězec | |
email |
řetězec | |
rate_amount |
celé číslo, nebo null | Peníze: celé číslo se čtyřmi skrytými desetinnými místy, takže 4200000 je 420,00, a vedle něj měna. |
rate_currency |
řetězec, nebo null |
Acceptance acceptResponse
Says what the app does next. outcome is one of three, and each fills its own fields and leaves the others null:
- "signed_in": accepting created the account.
sessionis the body a sign-in answers with, token included, and the app is in. - "needs_code": the account was there already.
code_sentsays a code is on its way toemail, and the app opens at "enter the code". - "joined": the caller is already signed in as that account.
membershipis the entry it gained, so the app can offer to switch to it; the session it holds is unchanged and is simply read again.
| Pole | Typ | Co to je |
|---|---|---|
outcome |
řetězec | |
email |
řetězec | |
code_sent |
boolean | |
session |
Session, nebo null | |
membership |
Entry, nebo null |
Invitation services.Invitation
A pending offer of a job at one company.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
email |
řetězec | |
first_name |
řetězec | |
last_name |
řetězec | |
is_manager |
boolean | |
is_worker |
boolean | |
rate_amount |
celé číslo, nebo null | Peníze: celé číslo se čtyřmi skrytými desetinnými místy, takže 4200000 je 420,00, a vedle něj měna. |
rate_currency |
řetězec, nebo null | |
expires_at |
časový údaj, RFC 3339 v UTC | |
accepted_at |
časový údaj, RFC 3339 v UTC, nebo null | |
created_at |
časový údaj, RFC 3339 v UTC |
Dashboard services.Dashboard
One person's home screen at one company.
Exactly one of worker and manager is set, matching role. role comes from the active membership, so the same person can be a manager on one company's dashboard and a worker on the next.
| Pole | Typ | Co to je |
|---|---|---|
role |
řetězec: worker | manager | |
days |
seznam: řetězec |
|
today |
řetězec |
|
worker |
Worker dashboard, nebo null | V těle chybí, když je prázdné. |
manager |
Manager dashboard, nebo null | V těle chybí, když je prázdné. |
Assignment services.Assignment
One worker's invitation into one timeslot.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
timeslot_id |
celé číslo | |
membership_id |
celé číslo | |
origin |
řetězec: staffed | sos | open | backfilled | |
status |
řetězec: pending | accepted | declined | expired | withdrawn | cancelled | |
rate_amount |
celé číslo, nebo null |
Null when no hourly rate was agreed — the project sets none and neither does the worker. That is a real state, "hours only", and never a zero, which would read as unpaid work. Both halves are null together; the database refuses one without the other. Peníze: celé číslo se čtyřmi skrytými desetinnými místy, takže 4200000 je 420,00, a vedle něj měna. |
rate_currency |
řetězec, nebo null | |
role_id |
celé číslo |
|
role_label |
řetězec, nebo null | |
invited_at |
časový údaj, RFC 3339 v UTC | |
responded_at |
časový údaj, RFC 3339 v UTC, nebo null | |
expires_at |
časový údaj, RFC 3339 v UTC | |
created_at |
časový údaj, RFC 3339 v UTC | |
takes_from |
časový údaj, RFC 3339 v UTC, nebo null |
|
takes_until |
časový údaj, RFC 3339 v UTC, nebo null | |
worker_name |
řetězec |
V těle chybí, když je prázdné. |
Schedule entry services.ScheduleEntry
One row of a worker's own schedule.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
timeslot_id |
celé číslo | |
membership_id |
celé číslo | |
origin |
řetězec: staffed | sos | open | backfilled | |
status |
řetězec: pending | accepted | declined | expired | withdrawn | cancelled | |
rate_amount |
celé číslo, nebo null |
Null when no hourly rate was agreed — the project sets none and neither does the worker. That is a real state, "hours only", and never a zero, which would read as unpaid work. Both halves are null together; the database refuses one without the other. Peníze: celé číslo se čtyřmi skrytými desetinnými místy, takže 4200000 je 420,00, a vedle něj měna. |
rate_currency |
řetězec, nebo null | |
role_id |
celé číslo |
|
role_label |
řetězec, nebo null | |
invited_at |
časový údaj, RFC 3339 v UTC | |
responded_at |
časový údaj, RFC 3339 v UTC, nebo null | |
expires_at |
časový údaj, RFC 3339 v UTC | |
created_at |
časový údaj, RFC 3339 v UTC | |
takes_from |
časový údaj, RFC 3339 v UTC, nebo null |
|
takes_until |
časový údaj, RFC 3339 v UTC, nebo null | |
worker_name |
řetězec |
V těle chybí, když je prázdné. |
timeslot |
Shift | |
gig_id |
celé číslo | |
gig_title |
řetězec | |
full |
boolean |
|
collides_with_title |
řetězec, nebo null | Set on PENDING entries only. No client works any of this out for itself. |
collides_with_company |
řetězec, nebo null |
|
collides_from |
časový údaj, RFC 3339 v UTC, nebo null | |
collides_until |
časový údaj, RFC 3339 v UTC, nebo null | |
can_take_from |
časový údaj, RFC 3339 v UTC, nebo null | |
can_take_until |
časový údaj, RFC 3339 v UTC, nebo null |
Answered invitations answeredMany
What answering all of a project's invitations did, as counts. The app re-reads the dashboard for the shifts themselves, as it does after answering one; these two numbers are what it has to say something about.
| Pole | Typ | Co to je |
|---|---|---|
answered |
celé číslo |
|
full |
celé číslo |
|
colliding |
celé číslo |
|
Time entry services.TimeEntry
One stretch of work: when someone started, when they stopped, and what it was worth.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
membership_id |
celé číslo | |
gig_id |
celé číslo | |
timeslot_id |
celé číslo, nebo null |
|
clock_in_at |
časový údaj, RFC 3339 v UTC | |
clock_out_at |
časový údaj, RFC 3339 v UTC, nebo null |
|
source |
řetězec: manual | geofence | backfilled | |
rate_amount |
celé číslo, nebo null |
Null when no hourly rate applied: the hours are recorded and the entry is worth no money figure — not zero, which would read as unpaid work. Peníze: celé číslo se čtyřmi skrytými desetinnými místy, takže 4200000 je 420,00, a vedle něj měna. |
rate_currency |
řetězec, nebo null | |
client_event_id |
řetězec |
V těle chybí, když je prázdné. |
corrected_at |
časový údaj, RFC 3339 v UTC, nebo null | |
created_at |
časový údaj, RFC 3339 v UTC |
Project gigResponse
A project as the app receives it: the project, and how to reach the manager running it.
Every endpoint that answers with a project answers with this, so the app parses one shape whichever screen asked.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
title |
řetězec | |
owner_id |
celé číslo |
|
client_id |
celé číslo, nebo null | The company being invoiced for this work. Nullable: a project may be internal, or booked before anyone has agreed who is paying. |
client_name |
řetězec, nebo null | |
client_contact_name |
řetězec, nebo null | The client's own contact person, from the client's record. It is NOT what a screen shows as "who to ring": that is |
client_contact_phone |
řetězec, nebo null | |
client_contact_email |
řetězec, nebo null | |
job_contact |
Job contact, nebo null |
|
latitude |
číslo, nebo null | Where the work happens, in WGS84 degrees. Nullable because a project can be created before anyone has pinned the site. This is the SITE's location, never a worker's. The server never receives a position from a device — the app holds these coordinates, computes distance to them locally, and sends only a clock event. |
longitude |
číslo, nebo null | |
geofence_radius_m |
celé číslo, nebo null | Radius in metres for optional geofence auto-clocking. |
site_address |
řetězec, nebo null | Where to go, in words: "Gate 3, Průmyslová 12, Ostrava". Stored rather than looked up on the phone, because the map tiles are the first thing to fail on a bad connection and that is precisely when somebody needs to know which gate. Free text — a site often has no postal address at all. Never the client's address, which is where the invoice goes. |
site_outline |
seznam: Point | The drawn site outline, if the manager traced one rather than dropping a pin. Kept so the outline can be drawn again on any map, not only reduced to a circle: a worker looking at an L-shaped site should see its shape. |
expected_minutes |
celé číslo, nebo null |
|
expenses |
seznam: Expense | |
created_at |
časový údaj, RFC 3339 v UTC | |
is_assigned |
boolean | |
is_invited |
boolean |
|
shifts_to_take |
celé číslo | |
archived_at |
časový údaj, RFC 3339 v UTC, nebo null |
|
project_manager |
Project manager, nebo null | Null when there is nobody to show: the owner has left, or is no longer a manager. Never another company's manager, and never a worker. |
company |
Company tag, nebo null |
V těle chybí, když je prázdné. |
Earnings projectEarnings
What one worker has earned on one project, and what they stand to earn on it.
Two lists, per currency, never mixed and never converted: this product holds no exchange rate and inventing one would be inventing money.
| Pole | Typ | Co to je |
|---|---|---|
earned |
seznam: Money total |
|
upcoming |
seznam: Money total |
|
earned_unrated_minutes |
celé číslo | The minutes of each that had no hourly rate agreed, and so are in neither list. Always present, zero when everything had a rate, so the app can say "hours only" rather than show nothing. |
upcoming_unrated_minutes |
celé číslo | |
running |
Running shift, nebo null |
|
Point geo.Point
A WGS84 coordinate in degrees.
| Pole | Typ | Co to je |
|---|---|---|
lat |
číslo | |
lon |
číslo |
Expense services.GigExpense
A cost booked against a gig.
cost_amount is an int64 with 4 implied decimal places — 42 CZK is 420000 — and is never converted to a float anywhere in this codebase. It crosses the wire raw, alongside its currency, and is formatted only at the edge.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
gig_id |
celé číslo |
|
created_by_membership_id |
celé číslo |
It is the whole access rule: a worker sees, edits and deletes only the expenses they booked, a manager every one on the organization's projects. Sent to clients so a screen can tell "mine" from "theirs" without asking again; the server decides regardless. |
created_by_name |
řetězec |
|
description |
řetězec | |
cost_amount |
celé číslo | Peníze: celé číslo se čtyřmi skrytými desetinnými místy, takže 4200000 je 420,00, a vedle něj měna. |
cost_currency |
řetězec | "CZK" or "EUR" |
created_at |
časový údaj, RFC 3339 v UTC |
Tool icon services.ToolIcon
One choice in the picker: the stored name and what to call it.
| Pole | Typ | Co to je |
|---|---|---|
name |
řetězec |
|
label |
řetězec |
|
Tool services.Tool
One item on a worker's kit list.
A client is only ever shown its own tools, so the field would tell it something it already knows — and echoing an id a client never sends invites it to start sending one.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
name |
řetězec | |
icon |
řetězec | |
quantity |
celé číslo, nebo null |
|
created_at |
časový údaj, RFC 3339 v UTC | |
gig_ids |
seznam: celé číslo |
|
Calendar day calendarDay
One day a project runs, with the shifts on it.
| Pole | Typ | Co to je |
|---|---|---|
day |
řetězec |
|
day_id |
celé číslo | |
shifts |
seznam: Shift as a manager sees it |
|
Scheduled day services.GigDay
One day a project runs.
The calendar is a set of days, not a range: a project pauses and resumes, and a gap is simply an absent row.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
gig_id |
celé číslo | |
day |
řetězec | Rendered as YYYY-MM-DD. A calendar day is a DATE, never a timestamp: answering "which days does this run" with instants shifts days across timezones. |
Removed days removedDays
What removing days did, or would do.
| Pole | Typ | Co to je |
|---|---|---|
confirmed |
boolean |
|
days |
celé číslo |
|
people |
celé číslo |
|
cancelled |
celé číslo |
|
Role to add roleRequest
One role on a new shift.
| Pole | Typ | Co to je |
|---|---|---|
label |
řetězec |
|
headcount |
celé číslo |
|
rate_amount |
celé číslo, nebo null |
Peníze: celé číslo se čtyřmi skrytými desetinnými místy, takže 4200000 je 420,00, a vedle něj měna. |
rate_currency |
řetězec, nebo null |
Added shifts addedShifts
What laying a shift on days made.
| Pole | Typ | Co to je |
|---|---|---|
shifts |
seznam: Shift as a manager sees it | |
scheduled |
celé číslo |
|
Role roleResponse
One role on a shift: a kind of worker with its own places and, where the manager set one, its own hourly rate.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
label |
řetězec, nebo null |
|
headcount |
celé číslo |
|
rate_amount |
celé číslo, nebo null |
Peníze: celé číslo se čtyřmi skrytými desetinnými místy, takže 4200000 je 420,00, a vedle něj měna. |
rate_currency |
řetězec, nebo null | |
accepted |
celé číslo |
|
pending |
celé číslo |
Moved shifts movedShifts
What a move did, or would do.
| Pole | Typ | Co to je |
|---|---|---|
confirmed |
boolean |
|
shifts |
celé číslo |
|
skipped |
celé číslo | |
people |
celé číslo |
|
first_day |
řetězec |
|
Removed shift removedShift
What removing a shift did, or would do.
| Pole | Typ | Co to je |
|---|---|---|
confirmed |
boolean |
|
accepted |
celé číslo |
|
pending |
celé číslo | |
cancelled |
celé číslo |
|
Shift with its people shiftDetail
A shift with the people on it.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
gig_id |
celé číslo | |
day_id |
celé číslo | |
starts_at |
časový údaj, RFC 3339 v UTC | |
ends_at |
časový údaj, RFC 3339 v UTC | |
required_workers |
celé číslo | |
role_label |
řetězec, nebo null |
|
created_at |
časový údaj, RFC 3339 v UTC | |
accepted |
celé číslo | Staffing is filled by the reads that compute it. |
pending |
celé číslo | |
short |
celé číslo |
|
is_open |
boolean |
|
open_auto_accept |
boolean | |
offered_rate_multiplier |
celé číslo, nebo null |
Násobek se čtyřmi skrytými desetinnými místy: 15000 je 1,5×. |
roles |
seznam: Role | |
people |
seznam: Assignment |
|
Invitation batch invitePlan
What a batch of invitations does, or would do.
| Pole | Typ | Co to je |
|---|---|---|
preview |
boolean |
|
people |
celé číslo | |
shifts |
celé číslo | |
invitations |
celé číslo |
|
skipped |
seznam: Skipped invitation | |
over_filled |
seznam: Over-invited shift | |
clashes |
seznam: Overlapping invitation | |
sent |
seznam: Assignment |
|
Person on a project personOnProject
One person with live places on a project's upcoming shifts.
| Pole | Typ | Co to je |
|---|---|---|
membership_id |
celé číslo | |
name |
řetězec | |
accepted |
celé číslo |
|
pending |
celé číslo | |
first_start |
časový údaj, RFC 3339 v UTC |
|
last_start |
časový údaj, RFC 3339 v UTC |
Taken off a project takenOff
What taking somebody off a project did, or would do.
| Pole | Typ | Co to je |
|---|---|---|
confirmed |
boolean |
|
accepted |
celé číslo |
|
pending |
celé číslo | |
first_day |
řetězec |
|
Shift as a manager sees it shiftResponse
A shift as a manager reads it: the shift, how short it is, whether it is open to the company, and its roles.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
gig_id |
celé číslo | |
day_id |
celé číslo | |
starts_at |
časový údaj, RFC 3339 v UTC | |
ends_at |
časový údaj, RFC 3339 v UTC | |
required_workers |
celé číslo | |
role_label |
řetězec, nebo null |
|
created_at |
časový údaj, RFC 3339 v UTC | |
accepted |
celé číslo | Staffing is filled by the reads that compute it. |
pending |
celé číslo | |
short |
celé číslo |
|
is_open |
boolean |
|
open_auto_accept |
boolean | |
offered_rate_multiplier |
celé číslo, nebo null |
Násobek se čtyřmi skrytými desetinnými místy: 15000 je 1,5×. |
roles |
seznam: Role |
SOS raised sosRaised
One emergency opened on one shift.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
timeslot_id |
celé číslo | |
offered_rate_multiplier |
celé číslo |
Násobek se čtyřmi skrytými desetinnými místy: 15000 je 1,5×. |
opened_at |
časový údaj, RFC 3339 v UTC | |
told |
celé číslo |
|
SOS over a project sosBatch
What an SOS over several shifts did.
| Pole | Typ | Co to je |
|---|---|---|
raised |
seznam: SOS raised |
|
already_raised |
celé číslo | What was skipped and why: an SOS already running, every place taken meanwhile, the shift over. |
filled |
celé číslo | |
over |
celé číslo | |
told |
celé číslo |
|
Shift needing attention shortShift
An upcoming shift that needs a manager's attention.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
gig_id |
celé číslo | |
day_id |
celé číslo | |
starts_at |
časový údaj, RFC 3339 v UTC | |
ends_at |
časový údaj, RFC 3339 v UTC | |
required_workers |
celé číslo | |
role_label |
řetězec, nebo null |
|
created_at |
časový údaj, RFC 3339 v UTC | |
accepted |
celé číslo | Staffing is filled by the reads that compute it. |
pending |
celé číslo | |
gig_title |
řetězec | |
short |
celé číslo |
|
sos_open |
boolean |
|
roles |
seznam: Role | |
company |
Company tag, nebo null |
V těle chybí, když je prázdné. |
Person response personResponse
One person on the roster: the membership, and the company's "certified for" notes about them.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
is_manager |
boolean | |
is_worker |
boolean | |
rate_amount |
celé číslo, nebo null | The default rate for new agreements at this company. Assignments and time entries snapshot their own copy; changing this never alters past work. Null for somebody who does not work shifts. Peníze: celé číslo se čtyřmi skrytými desetinnými místy, takže 4200000 je 420,00, a vedle něj měna. |
rate_currency |
řetězec, nebo null | |
emergency_responses_enabled |
boolean | |
cancellation_emails_enabled |
boolean |
|
is_disabled |
boolean | |
created_at |
časový údaj, RFC 3339 v UTC | |
org_name |
řetězec | |
first_name |
řetězec | |
last_name |
řetězec | |
email |
řetězec | |
certifications |
seznam: Certification response |
|
Certification response certificationResponse
One "certified for" note, with the kind's name in the request's language.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
membership_id |
celé číslo | |
kind |
řetězec |
|
label |
řetězec, nebo null |
|
scope |
řetězec, nebo null | |
expires_on |
řetězec, nebo null |
|
granted_by_membership_id |
celé číslo |
|
granted_by_name |
řetězec | |
created_at |
časový údaj, RFC 3339 v UTC | |
certificate_id |
celé číslo, nebo null |
|
name |
řetězec |
|
Certificate response certificateResponse
One certificate, with the kind's name in the request's language.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
kind |
řetězec |
|
label |
řetězec, nebo null |
|
scope |
řetězec, nebo null | |
number |
řetězec, nebo null |
|
issued_on |
řetězec, nebo null |
|
expires_on |
řetězec, nebo null | |
pages |
seznam: Certificate page |
|
uploaded_by |
Uploaded by, nebo null |
|
created_at |
časový údaj, RFC 3339 v UTC | |
updated_at |
časový údaj, RFC 3339 v UTC | |
name |
řetězec |
|
Certificate kinds certificateKinds
The list of kinds, in the request's language.
| Pole | Typ | Co to je |
|---|---|---|
groups |
seznam: Certificate group |
|
kinds |
seznam: Certificate kind |
|
trades |
seznam: Certificate trade |
|
Certificate reading certificateReading
What the photos of one document say, as far as they can be read: a proposal for each field, null where the pages gave nothing, and how well each page read. Every field is a proposal for the person to check and change; none of it is stored until they save.
| Pole | Typ | Co to je |
|---|---|---|
kind |
řetězec, nebo null |
|
kind_name |
řetězec, nebo null |
|
issued_on |
řetězec, nebo null |
|
expires_on |
řetězec, nebo null | |
number |
řetězec, nebo null |
|
pages |
seznam: Page reading |
|
legible |
boolean |
|
Client services.Client
A company you invoice.
The tax identifiers are here because invoicing is planned and a Czech invoice is not valid without them.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
name |
řetězec | |
ico |
řetězec, nebo null | IČO, the Czech company registration number: eight digits including any leading zeros, hence text. Null for a private individual. |
dic |
řetězec, nebo null | DIČ, the VAT number, e.g. "CZ12345678". Null when not VAT registered. |
address_line1 |
řetězec, nebo null | |
address_line2 |
řetězec, nebo null | |
city |
řetězec, nebo null | |
postal_code |
řetězec, nebo null | |
country |
řetězec | |
contact_name |
řetězec, nebo null | |
contact_email |
řetězec, nebo null | |
contact_phone |
řetězec, nebo null | |
is_archived |
boolean | |
created_at |
časový údaj, RFC 3339 v UTC |
Hours row hoursRow
One time entry on a project, with who worked it.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
membership_id |
celé číslo | |
gig_id |
celé číslo | |
timeslot_id |
celé číslo, nebo null |
|
clock_in_at |
časový údaj, RFC 3339 v UTC | |
clock_out_at |
časový údaj, RFC 3339 v UTC, nebo null |
|
source |
řetězec: manual | geofence | backfilled | |
rate_amount |
celé číslo, nebo null |
Null when no hourly rate applied: the hours are recorded and the entry is worth no money figure — not zero, which would read as unpaid work. Peníze: celé číslo se čtyřmi skrytými desetinnými místy, takže 4200000 je 420,00, a vedle něj měna. |
rate_currency |
řetězec, nebo null | |
client_event_id |
řetězec |
V těle chybí, když je prázdné. |
corrected_at |
časový údaj, RFC 3339 v UTC, nebo null | |
created_at |
časový údaj, RFC 3339 v UTC | |
worker_name |
řetězec |
|
slot_starts_at |
časový údaj, RFC 3339 v UTC, nebo null |
|
slot_ends_at |
časový údaj, RFC 3339 v UTC, nebo null | |
recorded_by |
řetězec |
|
Entry membershipResponse
What a client needs to render "who am I, and where": one entry of the company switcher.
An entry is a membership in ONE role, and its identity is the pair (membership_id, role). Somebody who manages projects and works shifts at one company appears twice in memberships, with the same membership_id and a different role, and membership is the one of the two the session is in. role stays a single string, so a client that asks "is this a manager" has one answer per entry.
It carries no organization id a client could send back: switching names a membership and a role, and the server proves the caller holds both.
| Pole | Typ | Co to je |
|---|---|---|
membership_id |
celé číslo | |
org_name |
řetězec | |
role |
řetězec | |
first_name |
řetězec | |
last_name |
řetězec | |
emergency_responses_enabled |
boolean | The worker's own opt-in to emergency cover, per membership: they may want emergency shifts from one employer and not another. This only ever describes the caller's own memberships — there is no endpoint that tells a manager who has opted in. |
cancellation_emails_enabled |
boolean | Whether a cancelled accepted shift is emailed too, on top of the push. The worker's own setting, like the one above, and only ever describing the caller's own memberships. |
Leaving company services.LeavingCompany
What deleting an account does at one of the companies the person belongs to. It only ever describes the caller's own memberships.
| Pole | Typ | Co to je |
|---|---|---|
org_name |
řetězec | |
upcoming_shifts |
celé číslo |
|
invitations |
celé číslo | |
clocked_in |
boolean |
|
last_manager |
boolean |
|
Worker dashboard services.WorkerDashboard
"this week, this much, what is open" — and it is where the worker's schedule lives. On Monday morning they do not yet know which project to open, so the cross-project week has to be here.
Shifts are grouped on the server so both clients put the same shift under the same heading: which group something is in is a decision, not styling.
| Pole | Typ | Co to je |
|---|---|---|
awaiting_you |
seznam: Schedule entry |
One project's invitations sit together: the projects in the order of their earliest shift, and each project's shifts in the order they happen. A manager can invite somebody to a week in one go, and both clients draw a project's run under one heading with "Accept all" beside it — by starting a new heading wherever gig_id changes, so the grouping is decided here and neither client sorts anything. |
invitation_summaries |
seznam: Invitation summary |
|
this_week |
seznam: Schedule entry |
|
later |
seznam: Schedule entry |
|
open_shifts |
seznam: Open shift |
|
expiring_certificates |
seznam: Expiring certificate |
|
worked_this_week |
Worked | Earned is from time entries; |
worked_this_month |
Worked | |
still_to_earn |
seznam: Money total | |
still_to_earn_unrated_minutes |
celé číslo |
|
Manager dashboard services.ManagerDashboard
What needs a PM's attention, then the week in numbers.
| Pole | Typ | Co to je |
|---|---|---|
attention |
seznam: Short shift |
|
attention_summaries |
seznam: Attention summary |
|
turned_down |
seznam: Decline |
|
hours_to_check |
seznam: Flagged entry |
|
week |
seznam: Day staffing |
|
worked_this_week |
Worked |
|
Shift services.Timeslot
A block of work on one day needing some number of workers.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
gig_id |
celé číslo | |
day_id |
celé číslo | |
starts_at |
časový údaj, RFC 3339 v UTC | |
ends_at |
časový údaj, RFC 3339 v UTC | |
required_workers |
celé číslo | |
role_label |
řetězec, nebo null |
|
created_at |
časový údaj, RFC 3339 v UTC | |
accepted |
celé číslo | Staffing is filled by the reads that compute it. |
pending |
celé číslo |
Job contact services.JobContact
The one person a worker is told to ring about a job.
A worker standing at a locked gate needs a number, not a screen telling them to find one — and it has to be the right number.
| Pole | Typ | Co to je |
|---|---|---|
company |
řetězec, nebo null |
|
name |
řetězec, nebo null | |
phone |
řetězec, nebo null |
Project manager services.ProjectManager
How somebody working on a project reaches the manager who runs it: a name to ask for and the two ways to get hold of them.
Deliberately nothing else from the membership. A worker reads this, and a manager's rate, role history or other projects are none of their business. The phone and email are the person's own, from users, because that is the only place this product keeps them.
| Pole | Typ | Co to je |
|---|---|---|
name |
řetězec | |
phone |
řetězec, nebo null | |
email |
řetězec, nebo null |
Company tag companyTag
Says which of the person's entries a row of a read across them came from, and what to send to act on it.
| Pole | Typ | Co to je |
|---|---|---|
entry |
řetězec |
|
org_name |
řetězec | |
role |
řetězec |
Money total services.MoneyTotal
A sum in one currency.
Currencies are never mixed, and never converted: this product holds no exchange rate and inventing one would be inventing money. A company working in two currencies sees two totals.
The amount goes raw as an int64 with four implied decimals, never pre-formatted and never a float.
| Pole | Typ | Co to je |
|---|---|---|
amount |
celé číslo | Peníze: celé číslo se čtyřmi skrytými desetinnými místy, takže 4200000 je 420,00, a vedle něj měna. |
currency |
řetězec |
Running shift services.RunningShift
A shift the acting worker is on the clock for right now, and what it has come to so far.
It is the one figure in this product about work that is not finished, and three things keep it honest:
- No client multiplies anything, and the membership's rate today has no part in it.
- It is "so far", and it is in no total. So a figure a worker has seen in a total never goes down because they clocked out and then corrected the entry.
- A forgotten clock-out has none.
| Pole | Typ | Co to je |
|---|---|---|
since |
časový údaj, RFC 3339 v UTC |
|
minutes |
celé číslo | |
amount |
celé číslo, nebo null |
Peníze: celé číslo se čtyřmi skrytými desetinnými místy, takže 4200000 je 420,00, a vedle něj měna. |
currency |
řetězec, nebo null | |
as_of |
časový údaj, RFC 3339 v UTC |
|
Skipped invitation skippedInvite
A person already live on a shift, so not asked again.
| Pole | Typ | Co to je |
|---|---|---|
membership_id |
celé číslo | |
worker_name |
řetězec | |
shift |
Shift reference |
Over-invited shift overInvited
A shift asked of more people than it has places: allowed, since some will say no, and said.
| Pole | Typ | Co to je |
|---|---|---|
shift |
Shift reference | |
invited |
celé číslo | |
places |
celé číslo |
Overlapping invitation inviteClash
A person asked to a shift that overlaps other work of theirs at this company: allowed, and said.
| Pole | Typ | Co to je |
|---|---|---|
membership_id |
celé číslo | |
worker_name |
řetězec | |
shift |
Shift reference | |
with |
Shift reference |
|
in_batch |
boolean |
Certificate page services.CertificatePage
One photo of a certificate, by position, without its bytes.
| Pole | Typ | Co to je |
|---|---|---|
position |
celé číslo | |
content_type |
řetězec | |
width |
celé číslo | |
height |
celé číslo |
Uploaded by services.UploadedBy
Names the manager who added a certificate, and at which company. The name reads "Deleted user" for one who has left.
| Pole | Typ | Co to je |
|---|---|---|
membership_id |
celé číslo | |
name |
řetězec | |
company |
řetězec |
Certificate group certificateGroup
| Pole | Typ | Co to je |
|---|---|---|
id |
řetězec | |
name |
řetězec |
Certificate kind certificateKind
| Pole | Typ | Co to je |
|---|---|---|
id |
řetězec |
|
name |
řetězec | |
group |
řetězec |
|
aliases |
seznam: řetězec |
|
Certificate trade certificateTrade
| Pole | Typ | Co to je |
|---|---|---|
id |
řetězec | |
name |
řetězec | |
preferred |
seznam: řetězec |
|
related |
seznam: řetězec | |
common |
seznam: řetězec |
Page reading pageReading
How well one page read.
| Pole | Typ | Co to je |
|---|---|---|
position |
celé číslo |
|
readability |
celé číslo, nebo null |
|
legible |
boolean |
|
Invitation summary services.InvitationSummary
What one project's unanswered invitations add up to: how many, which days, how long, and what they would pay.
It is worked out here and not in a client because one of its figures is money.
Nothing stores that invitations were sent together, so this is every invitation the worker has not answered on the project, read now. It is the same set "Accept all" and "Decline all" act on.
| Pole | Typ | Co to je |
|---|---|---|
gig_id |
celé číslo | |
gig_title |
řetězec | |
count |
celé číslo |
|
full_count |
celé číslo | |
first_day |
řetězec |
|
last_day |
řetězec | |
shift_summary |
řetězec |
V těle chybí, když je prázdné. |
minutes |
celé číslo | |
would_earn |
seznam: Money total |
|
unrated_minutes |
celé číslo |
Open shift services.OpenSlotRow
One ROLE on a shift a worker could take: a shift with two roles is two rows, each with its own places, label and figure, because taking is per role.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
gig_id |
celé číslo | |
day_id |
celé číslo | |
starts_at |
časový údaj, RFC 3339 v UTC | |
ends_at |
časový údaj, RFC 3339 v UTC | |
required_workers |
celé číslo | |
role_label |
řetězec, nebo null |
|
created_at |
časový údaj, RFC 3339 v UTC | |
accepted |
celé číslo | Staffing is filled by the reads that compute it. |
pending |
celé číslo | |
gig_title |
řetězec | |
role_id |
celé číslo |
|
rate_amount |
celé číslo, nebo null |
Null when the shift offers nothing and there is no usual rate either: taking it records hours with no hourly rate, which is a real state. Peníze: celé číslo se čtyřmi skrytými desetinnými místy, takže 4200000 je 420,00, a vedle něj měna. |
rate_currency |
řetězec, nebo null | |
mine_status |
řetězec: pending | accepted | declined | expired | withdrawn | cancelled |
The two are not the same thing to the person reading it — one is work they have, the other is work they might get — and a screen collapsing both into "taken" would be promising somebody a shift nobody has agreed they are doing. |
taking_confirms |
boolean |
|
collides_with_title |
řetězec, nebo null | Shift conflicts, the same fields a worker's own schedule entry carries and for the same reason: said here so neither client works it out, and nobody taps a take that can only be refused. |
collides_with_company |
řetězec, nebo null |
|
collides_from |
časový údaj, RFC 3339 v UTC, nebo null | |
collides_until |
časový údaj, RFC 3339 v UTC, nebo null | |
can_take_from |
časový údaj, RFC 3339 v UTC, nebo null | |
can_take_until |
časový údaj, RFC 3339 v UTC, nebo null |
Expiring certificate services.ExpiringCertificate
One of the person's own certificates that is expiring or has expired, as the worker's dashboard and bell list it.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
kind |
řetězec | |
label |
řetězec, nebo null |
|
name |
řetězec |
|
expires_on |
řetězec |
|
days_left |
celé číslo |
|
expired |
boolean |
|
Worked services.Worked
Hours on the clock in some period, and what they came to.
Open entries count for neither: a shift in progress has no length yet, and a forgotten clock-out is a discrepancy for a PM, not a number to estimate.
| Pole | Typ | Co to je |
|---|---|---|
minutes |
celé číslo | |
earned |
seznam: Money total | |
unrated_minutes |
celé číslo |
|
Short shift services.VacancyRow
One upcoming timeslot that a PM should look at, with enough context to act on it without a second query.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
gig_id |
celé číslo | |
day_id |
celé číslo | |
starts_at |
časový údaj, RFC 3339 v UTC | |
ends_at |
časový údaj, RFC 3339 v UTC | |
required_workers |
celé číslo | |
role_label |
řetězec, nebo null |
|
created_at |
časový údaj, RFC 3339 v UTC | |
accepted |
celé číslo | Staffing is filled by the reads that compute it. |
pending |
celé číslo | |
gig_title |
řetězec |
Attention summary services.AttentionSummary
What one project's upcoming shifts needing attention add up to: how many, which days, dynamic shift schedule, and staffing counts (accepted, required, pending, vacancies).
| Pole | Typ | Co to je |
|---|---|---|
gig_id |
celé číslo | |
gig_title |
řetězec | |
count |
celé číslo | |
first_day |
řetězec | |
last_day |
řetězec | |
shift_summary |
řetězec | V těle chybí, když je prázdné. |
required |
celé číslo | |
accepted |
celé číslo | |
pending |
celé číslo | |
short |
celé číslo | |
imminent |
boolean |
Decline services.TurnedDownRow
Somebody saying no to work a PM was counting on: an invitation declined, or an accepted shift given up.
| Pole | Typ | Co to je |
|---|---|---|
id |
celé číslo | |
timeslot_id |
celé číslo | |
membership_id |
celé číslo | |
origin |
řetězec: staffed | sos | open | backfilled | |
status |
řetězec: pending | accepted | declined | expired | withdrawn | cancelled | |
rate_amount |
celé číslo, nebo null |
Null when no hourly rate was agreed — the project sets none and neither does the worker. That is a real state, "hours only", and never a zero, which would read as unpaid work. Both halves are null together; the database refuses one without the other. Peníze: celé číslo se čtyřmi skrytými desetinnými místy, takže 4200000 je 420,00, a vedle něj měna. |
rate_currency |
řetězec, nebo null | |
role_id |
celé číslo |
|
role_label |
řetězec, nebo null | |
invited_at |
časový údaj, RFC 3339 v UTC | |
responded_at |
časový údaj, RFC 3339 v UTC, nebo null | |
expires_at |
časový údaj, RFC 3339 v UTC | |
created_at |
časový údaj, RFC 3339 v UTC | |
takes_from |
časový údaj, RFC 3339 v UTC, nebo null |
|
takes_until |
časový údaj, RFC 3339 v UTC, nebo null | |
worker_name |
řetězec |
V těle chybí, když je prázdné. |
timeslot |
Shift | |
gig_title |
řetězec |
Flagged entry services.FlaggedEntry
One time entry a manager should look at, from any project.
The flags are decided here, on the server, so both clients show the same reason.
| Pole | Typ | Co to je |
|---|---|---|
entry |
Time entry | |
worker_name |
řetězec | |
gig_title |
řetězec | |
slot_starts_at |
časový údaj, RFC 3339 v UTC, nebo null | |
slot_ends_at |
časový údaj, RFC 3339 v UTC, nebo null | |
missing_clock_out |
boolean | |
outside_shift |
boolean |
Day staffing services.DayStaffing
One calendar day's staffing, summed across its timeslots.
This is what turns the calendar from "which days does this run" into "which days need me". A day is the unit a PM actually thinks in — they staff a week, not a timeslot — so the counts are aggregated to the day and the calendar renders them directly.
| Pole | Typ | Co to je |
|---|---|---|
day |
řetězec | YYYY-MM-DD |
slots |
celé číslo | |
required |
celé číslo | |
accepted |
celé číslo | |
pending |
celé číslo | |
short |
celé číslo |
|
Shift reference shiftRef
One shift, as a batch's answer names it.
| Pole | Typ | Co to je |
|---|---|---|
timeslot_id |
celé číslo | |
starts_at |
časový údaj, RFC 3339 v UTC | |
ends_at |
časový údaj, RFC 3339 v UTC |