-
Notifications
You must be signed in to change notification settings - Fork 0
API Internals
Understanding how the Strava.cz API works behind the scenes.
Note: This documentation is based on reverse engineering the Strava.cz web application. Information may change as the service updates.
The Strava.cz API is a JSON-based REST API accessed through:
-
Base URL:
https://app.strava.cz -
API Endpoint:
https://app.strava.cz/api - Protocol: HTTPS only
- Format: JSON request/response
Endpoint: POST /api/login
Request Payload:
{
"cislo": "3753",
"jmeno": "vojtech.nerad",
"heslo": "YourPassword123",
"zustatPrihlasen": false,
"environment": "W",
"lang": "EN"
}Parameters:
| Parameter | Type | Description | Example |
|---|---|---|---|
cislo |
string | Canteen number | "3753" |
jmeno |
string | Username | "vojtech.nerad" |
heslo |
string | Plaintext password | "Password123" |
zustatPrihlasen |
boolean | Stay logged in | false |
environment |
string | Environment type | "W" |
lang |
string | Language code | "EN" |
Response (Success):
{
"sid": "01C6FCF02A7146159BC5F245A57AF29F",
"s5url": "https://wss5.strava.cz/WSStravne5_15/WSStravne5.svc",
"cislo": "3753",
"jmeno": "vojtech.nerad",
"uzivatel": {
"konto": "0.00",
"jmeno": "Vojtěch Nerad",
"email": "email@example.com",
"id": "vojtech.nerad",
"mena": "Kč",
"nazevJidelny": "Školní jídelna, Praha 5 - Smíchov...",
"vs": "12142"
}
}Important Fields:
| Field | Description | Usage |
|---|---|---|
sid |
Session ID | Must be included in all subsequent requests |
s5url |
Web service endpoint | Used for meal operations |
uzivatel.konto |
Account balance | Current balance in Kč |
All authenticated requests must include:
-
sid- Session identifier -
cislo- Canteen number -
s5urlorurl- Web service endpoint
Endpoint: POST /api/objednavky
Request Payload:
{
"cislo": "3753",
"sid": "01C6FCF02A7146159BC5F245A57AF29F",
"s5url": "https://wss5.strava.cz/WSStravne5_15/WSStravne5.svc",
"lang": "EN",
"konto": 0,
"podminka": "",
"ignoreCert": "false"
}Response Structure:
{
"table0": [
{
"datum": "15.11.2025",
"druh_popis": "Polévka",
"nazev": "Vývar s kuskusem",
"cena": "0",
"pocet": 0,
"veta": "75",
"alergeny": [...],
"omezeniObj": {
"den": "",
"obj": "",
"zm": "",
"bur": ""
}
}
],
"table1": [...],
"table2": [...]
}Data Structure:
- Each
tableXrepresents one day - Each table contains array of meals
- Meals include soups and main dishes
Key Fields:
| Field | Description | Example Values |
|---|---|---|
datum |
Date |
"15.11.2025" (dd.mm.yyyy) |
druh_popis |
Meal type |
"Polévka", "Oběd 1"
|
nazev |
Meal name | "Vývar s kuskusem" |
cena |
Price |
"40.00" (string) |
pocet |
Order count |
0 (not ordered) / 1 (ordered) |
veta |
Meal ID |
"75" (unique identifier) |
alergeny |
Allergens | Array of allergen codes |
omezeniObj.den |
Restriction |
"" (orderable), "CO" (restricted), "T" (optional), "VP" (holiday) |
Meals are considered invalid if:
-
nazevequalsdruh_popis(generic name) -
delsiPopisandalergenyare both empty -
omezeniObj.dencontains"VP"(no school)
Endpoint: POST /api/pridejJidloS5
Request Payload:
{
"cislo": "3753",
"sid": "01C6FCF02A7146159BC5F245A57AF29F",
"url": "https://wss5.strava.cz/WSStravne5_15/WSStravne5.svc",
"veta": "7",
"pocet": 1,
"lang": "EN",
"ignoreCert": "false"
}Parameters:
| Parameter | Type | Description | Values |
|---|---|---|---|
veta |
string | Meal ID |
"7", "75", etc. |
pocet |
integer | Order count |
0 (cancel) / 1 (order) |
Response:
{
"produkt": [
{
"$": {
"Veta": "7",
"Pocet": "1",
"Druh": "O2",
"NelzeObj": "",
"NelzeZm": ""
}
}
],
"konto": "0.00"
}Note: This only stages the change, doesn't save it yet.
Endpoint: POST /api/saveOrders
Request Payload:
{
"cislo": "3753",
"sid": "01C6FCF02A7146159BC5F245A57AF29F",
"url": "https://wss5.strava.cz/WSStravne5_15/WSStravne5.svc",
"xml": null,
"lang": "EN",
"ignoreCert": "false"
}Response:
{
"produkty": [
{
"veta": "7",
"pocet": 1,
"burza": {...}
}
],
"konto": "0.00"
}Important:
- Updated balance returned in
konto - List of all meal states in
produkty
Endpoint: POST /api/nactiVlastnostiPA
Request Payload:
{
"sid": "01C6FCF02A7146159BC5F245A57AF29F",
"url": "https://wss5.strava.cz/WSStravne5_15/WSStravne5.svc",
"cislo": "3753",
"ignoreCert": "false",
"lang": "EN",
"getText": true,
"checkVersion": true,
"resetTables": true,
"frontendFunction": "refreshInformations"
}Usage: Reverts unsaved changes (rollback mechanism)
Endpoint: POST /api/logOut
Request Payload:
{
"sid": "E9D5B96FE3D14DED8E543B33A4D910F2",
"cislo": "3753",
"url": "https://wss5.strava.cz/WSStravne5_15/WSStravne5.svc",
"lang": "EN",
"ignoreCert": "false"
}Response: Empty (status 200 indicates success)
{
"number": 35,
"message": "Nedostatečný zůstatek na kontě"
}Common Error Codes:
| Code | Meaning | English |
|---|---|---|
| 35 | Nedostatečný zůstatek | Insufficient balance |
| 555 | Chyba v API callu | API call error |
The library uses these headers for all requests:
{
"User-Agent": "Mozilla/5.0 ...",
"Accept": "*/*",
"Accept-Language": "en-US,en;q=0.9,cs;q=0.6",
"Accept-Encoding": "gzip, deflate, br, zstd",
"Content-Type": "text/plain;charset=UTF-8",
"Origin": "https://app.strava.cz",
"Referer": "https://app.strava.cz/en/prihlasit-se?jidelna",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin"
}- No documented rate limits
- Recommended: Don't make excessive requests
- Use reasonable delays between operations
API druh_popis
|
Library MealType
|
|---|---|
"Polévka" |
MealType.SOUP |
"Oběd 1", "Oběd 2", etc. |
MealType.MAIN |
| Other |
MealType.UNKNOWN (filtered) |
API omezeniObj.den
|
Library OrderType
|
|---|---|
"" (empty) |
OrderType.NORMAL |
"CO" |
OrderType.RESTRICTED |
"T" |
OrderType.OPTIONAL |
"VP" |
Filtered out (holiday) |
API Format: "15.11.2025" (dd.mm.yyyy)
Library Format: "2025-11-15" (yyyy-mm-dd)
Conversion:
unformatted = "15.11.2025"
formatted = f"{unformatted[6:10]}-{unformatted[3:5]}-{unformatted[0:2]}"
# Result: "2025-11-15"Before making API requests, the library:
- Creates a
requests.Session()object - Makes initial GET to
/en/prihlasit-se?jidelna - Sets default headers
- Performs login POST
This ensures cookies and session state are properly maintained.
-
Stage Changes: Call
pridejJidloS5for each meal- Sets
pocet=1to order - Sets
pocet=0to cancel
- Sets
-
Commit: Call
saveOrdersto persist- All staged changes are saved
- Balance is updated
-
Verify: Refresh menu and check order status
- Call
objednavkyto get updated menu - Verify
pocetvalues match expected state
- Call
-
Rollback (on error): Call
nactiVlastnostiPA- Reverts to last saved state
- Restores balance
Balance is updated:
- After login (from
uzivatel.konto) - After
pridejJidloS5response (fromkonto) - After
saveOrdersresponse (fromkonto) - After rollback (from
konto)
- No bulk operations: Must order meals one-by-one
- No date filtering: Always returns full menu
- Soup ordering not supported: Only main dishes can be ordered
- No balance top-up: Balance management must be done through web interface
- Plaintext passwords: No encryption of credentials in API
Many response fields are present but not documented or used:
-
burza- Exchange/trade related -
vydejniMisto- Serving location -
diety- Diet information -
multipleNazev- Multiple name encoding
These are ignored by the library but preserved in raw_data.
# Login
curl -X POST https://app.strava.cz/api/login \
-H "Content-Type: application/json" \
-d '{
"cislo": "3753",
"jmeno": "username",
"heslo": "password",
"zustatPrihlasen": false,
"environment": "W",
"lang": "EN"
}'
# Get menu (requires sid from login)
curl -X POST https://app.strava.cz/api/objednavky \
-H "Content-Type: application/json" \
-d '{
"cislo": "3753",
"sid": "YOUR_SID",
"s5url": "https://wss5.strava.cz/WSStravne5_15/WSStravne5.svc",
"lang": "EN",
"konto": 0,
"podminka": "",
"ignoreCert": "false"
}'- Review StravaCZ Class implementation
- Understand Menu Class data processing
- Check Contributing guide for development