Reverse-engineered via live probing and open-source analysis. Not officially published by Arbox. Base URL:
https://apiappv2.arboxapp.com
POST /api/v2/user/loginwith email + password- Receive a JWT
tokenandrefreshToken - Pass
tokenin theaccesstokenheader on every subsequent request
| Header | Value | Notes |
|---|---|---|
accesstoken |
<JWT token> |
From login response |
version |
11 |
App version identifier |
referername |
app |
Client identifier |
Content-Type |
application/json |
For POST requests |
| Header | Notes |
|---|---|
refreshToken |
Pass alongside accesstoken for session refresh |
whiteLabel |
Box white-label identifier (e.g. dVqGag1c) |
boxFk |
Box ID — some endpoints require this as a header |
lang |
Language code (e.g. en, he) |
identifier |
Location/context identifier |
Authenticate and receive tokens.
Request body:
{
"email": "user@example.com",
"password": "yourpassword"
}Response:
{
"data": {
"id": 647542,
"email": "user@example.com",
"first_name": "Jane",
"last_name": "Doe",
"language": "en",
"image": "https://res.cloudinary.com/arbox/image/upload/...",
"token": "<JWT access token>",
"refreshToken": "<JWT refresh token>",
"last_name_shorten": "D",
"full_name_shorten": "Jane D",
"full_name": "Jane Doe",
"is_user": true,
"appNamesId": 1
}
}Notes:
tokenis a long-lived JWT (expiry ~years). Decode to inspect claims.appNamesId: 1= standard Arbox app.- No
whitelabelrequired for login.
Invalidate the current session token.
Request body: {} (empty)
Response: OK (plain text, HTTP 200)
Returns full profile for the authenticated user, including all box memberships, locations, last membership, and push token.
Response (key fields):
{
"data": {
"id": 647542,
"email": "user@example.com",
"first_name": "Jane",
"last_name": "Doe",
"language": "en",
"on_boarding": 1,
"image": "https://res.cloudinary.com/arbox/...",
"birthday": "1983-05-03",
"gender": "male",
"phone": "0547684502",
"weight": "70",
"height": "170",
"country": null,
"city": "Tel Aviv",
"address": "Some Street 1",
"bio": null,
"zip": null,
"state": null,
"time_format_preferred": "HOUR-24",
"last_login": "2026-04-24 23:02:36",
"verified": 1,
"created_at": "2019-10-28T15:41:51.000000Z",
"updated_at": "2026-04-24T20:02:36.000000Z",
"boxes": [23733, 926],
"activeBoxes": [23733],
"activeLocationsBox": [21372],
"inactiveBoxes": [926],
"allBoxes": [23733, 926],
"locations": [21372, 1276],
"refreshToken": "<new refresh token>",
"appNamesId": 1,
"dateFormat": "DD/MM/YYYY",
"timeFormat": "HH:mm",
"timeZone": "Asia/Jerusalem",
"currencySymbol": "₪",
"slug": "arboxv4",
"last_name_shorten": "D",
"full_name": "Jane Doe",
"is_user": true,
"user_token": "ExponentPushToken[...]",
"friend_connection": [],
"lastEndedMembership": {
"id": 1340141,
"membership_type_fk": 26902,
"box_fk": 926,
"sessions_left": null,
"end": "2023-04-18",
"membership_types": {
"id": 26902,
"name": "Monthly Plan",
"type": "plan",
"price": 0,
"sessions": null,
"is_recurring_payment": 0
},
"box": { "id": 926, "name": "Toha Gym", "phone": "03-7356164" }
},
"users_boxes": [
/* see UserBox model below */
]
}
}Notes:
boxes= all box IDs user belongs to (active + inactive)activeBoxes= currently active box IDsactiveLocationsBox= currently activelocations_boxIDsusers_boxes= full membership records for each box (see UserBox model)user_token= Expo push notification token for the user's mobile device
Initiate a password reset. Likely sends an email with a reset link.
Request body: (probe — exact required fields unknown)
{
"email": "user@example.com"
}Auth required: No (unauthenticated endpoint, HTTP method: POST)
Change password for the authenticated user.
Request body: (probe — exact fields unknown)
{
"old_password": "current",
"new_password": "newpass"
}Auth required: Yes
Returns all box memberships for the authenticated user, with full box details and location info.
Response:
{
"data": [
{
"ub_id": 9116963,
"id": 9116963,
"first_name": "Jane",
"last_name": "Doe",
"birthday": "1983-05-03",
"personal_id": null,
"gender": "male",
"phone": "0547684502",
"additional_phone": null,
"user_fk": 647542,
"box_fk": 23733,
"locations_box_fk": 21372,
"medical_cert": 1,
"epidemic_statement": 0,
"has_waiver": 1,
"active": 1,
"rolesArray": [3],
"full_name": "Jane Doe",
"total_debt": 0,
"age": "42.11",
"user_image": "",
"is_app_deleted": false,
"schedule_favorites": [],
"properties": [],
"group_connection": null,
"box": {
"id": 23733,
"name": "power house - by limor",
"phone": "+972549259926",
"email": "gym@example.com",
"address": "Tel Aviv",
"city": "Tel Aviv",
"country": "Israel",
"cloudinary_image": "https://res.cloudinary.com/arbox/...",
"bio": null,
"website": null,
"has_regular_clients": 0,
"epidemic_mode": 0,
"notification_scheduling": 12,
"external_url_id": "dVqGag1c",
"box_type_fk": 2,
"box_type": {
"id": 2,
"translations": { "segment": "fitness" }
},
"boxes_settings": [
{
"id": 6031,
"prop_name": "recurring_payments",
"properties": {
"allowUpdateCC": true,
"holdFrequency": 0,
"relativeFrequency": 2
}
}
]
},
"locations_box": {
"id": 21372,
"qr_code": 0,
"logo": null,
"time_format": "HH:mm",
"date_format": "DD/MM/YYYY",
"timezone": "Asia/Jerusalem",
"country_code": "IL",
"currency": "ILS",
"currency_symbol": "₪",
"has_shop": true,
"disable_pages_app": []
}
}
]
}Notes:
rolesArrayvalues:3= member,2= staff/coach,1= admin (inferred)total_debt= outstanding balance in the box's currencyschedule_favorites= array of favourite schedule class IDsdisable_pages_app= feature flags hiding sections in the mobile appboxes_settings= box-level configuration properties (e.g. recurring payment settings)
Returns all boxes the user belongs to, with full location details and feature flags.
Response:
{
"data": [
{
"id": 926,
"name": "Toha Gym",
"address": "Yigal Alon 114, Tel Aviv",
"city": "Tel Aviv",
"country": "Israel",
"phone": "03-7356164",
"email": "gym@example.com",
"website": "",
"cloudinary_image": "https://res.cloudinary.com/arbox/...",
"box_type_fk": 14,
"schedule_standby_offset": 0,
"epidemic_mode": 0,
"showing_classes_week_ago": 0,
"showing_classes_day_ago": null,
"showing_classes_time_ago": null,
"has_regular_clients": 0,
"notification_scheduling": 1,
"standby_cancellation_time": 300,
"schedule_swapping_time": 0,
"schedule_swapping_standby_time": 0,
"time_card": 1,
"external_url_id": "32434244",
"bio": "...",
"allow_sms_to_waiting_list": 0,
"allow_relative_payment": 0,
"digital_form_id": null,
"notify_session_owner": 3,
"scheduleTypes": {
"hasClasses": 47,
"hasHistory": 1
},
"locations_box": [
{
"id": 1276,
"location": "Tel Aviv",
"box_fk": 926,
"logo": null,
"timezone": "Asia/Jerusalem",
"qr_code": 0,
"hasAvailability": 3,
"hasSpaceAvailability": 0,
"hasWorkshops": 0,
"hasHugim": 0,
"hasPayments": true,
"hasMemberships": false,
"hasProducts": false,
"custom_field": [],
"currency_symbol": "",
"has_shop": true,
"disable_pages_app": [
{
"locations_box_id": 1276,
"area": "schedule",
"section_name": "whoIsBooked"
},
{
"locations_box_id": 1276,
"area": "schedule",
"section_name": "standBy"
},
{
"locations_box_id": 1276,
"area": "sidebar",
"section_name": "logBook"
}
]
}
]
}
]
}Notes:
- Returns all boxes (active + inactive), not filtered by params
standby_cancellation_time= minutes before class that standby auto-cancelsscheduleTypes.hasClasses= total class count in this boxhasAvailability— values:0= disabled,1= count only,2= names visible,3= full visibilityhasHugim= whether the box uses "hugim" (recurring group sessions, Israeli term)disable_pages_app= sections hidden in the mobile app for this location
List all available classes/lessons in a date range for a given location. Returns full class detail including spots, coach, category, and whether the authenticated user has booked.
Request body:
{
"from": "2026-04-25T00:00:00.000Z",
"to": "2026-05-02T00:00:00.000Z",
"locations_box_id": 21372,
"boxes_id": 23733
}| Field | Type | Description |
|---|---|---|
from |
string | Start of range — ISO 8601 datetime with Z suffix |
to |
string | End of range — ISO 8601 datetime with Z suffix |
locations_box_id |
int | Location ID (from activeLocationsBox) |
boxes_id |
int | Box ID (from activeBoxes) |
Response:
{
"data": [
{
"id": 75223992,
"time": "08:10",
"end_time": "09:00",
"date": "2026-04-26",
"date_time": {
"date": "2026-04-26 08:10:00",
"timezone": "Asia/Jerusalem"
},
"end_date_time": {
"date": "2026-04-26 09:00:00",
"timezone": "Asia/Jerusalem"
},
"day_of_week": 0,
"coach_fk": 556108,
"second_coach_fk": null,
"box_category_fk": 155160,
"locations_box_fk": 21372,
"box_fk": 23733,
"series_fk": 562437,
"max_users": 18,
"free": 2,
"registered": 16,
"stand_by": 0,
"status": "active",
"past": 0,
"has_spots": 0,
"live_link": null,
"spaces_id": null,
"workout_id": null,
"late_cancellation": null,
"disable_cancellation_time": 3,
"enable_late_cancellation": 1,
"enable_registration_time": 0,
"user_booked": null,
"user_in_standby": null,
"stand_by_position": null,
"booking_option": "insertScheduleUser",
"is_swappable_schedule": false,
"reschedule": false,
"box": {
"id": 23733,
"name": "power house - by limor",
"has_regular_clients": 0,
"cloudinary_image": "https://res.cloudinary.com/arbox/...",
"phone": "+972549259926"
},
"box_categories": {
"id": 155160,
"name": "אימון מחזורי",
"bio": null,
"category_color": "#FBD0E8",
"length": 50,
"price": null,
"type": 1,
"color_name": "cat-color-8",
"category_type": { "id": 1, "name": "class" }
},
"coach": {
"id": 556108,
"first_name": "לימור",
"last_name": "ממון",
"full_name": "לימור ממון",
"image": "",
"cloudinary_image": "",
"bio": null,
"is_user": true
},
"second_coach": null,
"series": {
"id": 562437,
"series_name": "אימון מחזורי,ראשון,08:10",
"start_date": "2025-11-12",
"end_date": null,
"start_time": "08:10:00",
"end_time": "09:00:00",
"status": "active",
"day": "day-1",
"max_users": 18,
"coach_fk": 556108,
"membership_types": [
{
"id": 383509,
"name": "אימון מחזורי",
"type": "trial",
"price": 35,
"show_in_app": 1
}
]
},
"booked_users": [
/* array of booked user objects */
],
"schedule_user": [
/* same as booked_users */
],
"schedule_stand_by": [],
"custom_field_value": [],
"disable_pages_app": [],
"spaces": null
}
]
}Key response fields per item:
| Field | Type | Description |
|---|---|---|
id |
int | Schedule slot ID — use this in scheduleUser/insert and scheduleUser/delete |
date |
string | Class date YYYY-MM-DD |
time |
string | Start time HH:MM |
end_time |
string | End time HH:MM |
max_users |
int | Maximum capacity |
free |
int | Available spots |
registered |
int | Currently booked count |
stand_by |
int | Standby list count |
has_spots |
int | Not a reliable availability flag — can be 0 even when free > 0 (e.g. current user's membership type doesn't cover this class). Use free to check availability instead. |
status |
string | "active" = bookable |
past |
int | 1 if class is in the past |
user_booked |
int|null | null if not booked by current user; schedule_user record ID if booked |
user_in_standby |
int|null | Standby record ID if on waitlist |
booking_option |
string | "insertScheduleUser" = use scheduleUser/insert to book |
box_categories.name |
string | Class type name (e.g. "HIIT", "Booty Workout") |
coach.full_name |
string | Coach's display name |
series |
object | Recurring series this class belongs to |
series.membership_types |
array | Membership plans that can be used to book this class |
Notes:
from/tomust be in ISO 8601 format with milliseconds andZsuffix- The date range can span multiple days or weeks
user_bookedisnullfor unbooked classes and a record ID if the authenticated user has bookedbooking_option: "insertScheduleUser"indicates the class is bookable viaPOST /api/v2/scheduleUser/insert- Do not use
has_spotsas a boolean to check availability. It reflects eligibility for the current user (e.g. membership coverage), not raw spot count. Usefree > 0ormax_users - registered > 0instead.
Register the authenticated user for a class (schedule slot).
Request body:
{
"schedule_id": 75223992,
"membership_user_id": 14285177
}| Field | Type | Description |
|---|---|---|
schedule_id |
int | ID of the schedule slot (from schedule/betweenDates response id field) |
membership_user_id |
int | User's active membership record ID (from users_boxes[].schedule_user[].membership_user_fk) |
Notes:
- Obtain
schedule_idfromPOST /api/v2/schedule/betweenDates - Returns an error if the class is full
Cancel a class booking.
Request body:
{
"scheduleFk": 12345,
"locationsBoxFk": 21372,
"boxFk": 23733
}Join the waiting list for a fully-booked class.
Request body: (same shape as scheduleUser/insert)
{
"schedule_id": 75223992,
"membership_user_id": 14285177
}| Field | Type | Description |
|---|---|---|
schedule_id |
int | Schedule slot ID (from schedule/betweenDates id field) |
membership_user_id |
int | User's active membership record ID |
Response (success): HTTP 200 with standby record
Error responses:
| Code | Name | Meaning |
|---|---|---|
| 425 | alreadyRegistered |
Already booked (or on standby) for a class at that timeslot |
Notes:
- Only call this when
free == 0on the schedule item; if spots are available, usescheduleUser/insertinstead - After joining,
user_in_standbywill be non-null andstand_by_positionwill reflect queue position in theschedule/betweenDatesresponse schedule_stand_byarray on the schedule item lists all users currently on the waitlist
Leave the waiting list for a class.
Request body: (same shape as scheduleUser/insert)
{
"schedule_id": 75223992,
"membership_user_id": 14285177
}Notes:
- Only valid if the user is currently on the standby list for that schedule slot
- Returns 500 if the user has no standby record for the given
schedule_id
Confirm a standby spot that has opened up. When a cancellation creates a vacancy, Arbox notifies the first standby user by email/push notification and creates an availability record. The user has 30 minutes to confirm before the offer expires and moves to the next standby user.
Confirmation is done via the same scheduleUser/insert endpoint, but with the additional availability_id field:
{
"schedule_id": 75223992,
"membership_user_id": 14285177,
"availability_id": 98765
}| Field | Type | Description |
|---|---|---|
schedule_id |
int | Schedule slot ID |
membership_user_id |
int | User's active membership record ID |
availability_id |
int | The availability record ID from the schedule item or notification payload |
How to obtain availability_id:
- When a standby spot opens for the authenticated user, the
schedule/betweenDatesresponse will showavailability_idas a non-null integer on that specific schedule item (it isnullfor all other classes) - The push notification / email link also carries this ID
Flow:
- User joins standby via
scheduleStandBy/insert - A cancellation occurs, freeing a spot
- Arbox sets
availability_idon the schedule item and sends a push/email notification - User polls
schedule/betweenDatesor receives a push notification to get theavailability_id - User calls
scheduleUser/insertwithavailability_idwithin 30 minutes - If 30 minutes elapse without confirmation, the
availability_idexpires and the next standby user is notified
Error responses:
| Code | Meaning |
|---|---|
403 Unknown issue |
availability_id is invalid, expired, or does not belong to this user |
| Field | Type | Description |
|---|---|---|
id |
int | Unique user ID |
email |
string | Email address |
first_name |
string | First name |
last_name |
string | Last name |
language |
string | "en" or "he" |
birthday |
string | YYYY-MM-DD |
gender |
string | "male" / "female" |
phone |
string | Primary phone |
weight |
string | Weight (kg) |
height |
string | Height (cm) |
image |
string | Cloudinary image URL |
verified |
int | Email verified: 1 = yes |
on_boarding |
int | Onboarding complete: 1 = yes |
time_format_preferred |
string | "HOUR-24" or "HOUR-12" |
dateFormat |
string | e.g. "DD/MM/YYYY" |
timeFormat |
string | e.g. "HH:mm" |
timeZone |
string | e.g. "Asia/Jerusalem" |
currencySymbol |
string | e.g. "₪" |
slug |
string | App version slug (e.g. "arboxv4") |
user_token |
string | Expo push notification token |
boxes |
int[] | All box IDs |
activeBoxes |
int[] | Active box IDs |
inactiveBoxes |
int[] | Inactive box IDs |
activeLocationsBox |
int[] | Active location IDs |
locations |
int[] | All location IDs |
lastEndedMembership |
object | Most recent expired membership |
users_boxes |
UserBox[] | Membership records per box |
| Field | Type | Description |
|---|---|---|
ub_id |
int | Unique membership record ID |
user_fk |
int | User ID |
box_fk |
int | Box ID |
locations_box_fk |
int | Location ID |
active |
int | 1 = active, 0 = inactive |
rolesArray |
int[] | Roles: 1 = admin, 2 = staff, 3 = member |
total_debt |
int | Outstanding balance |
medical_cert |
int | Medical certificate on file: 1 = yes |
has_waiver |
int | Waiver signed: 1 = yes |
epidemic_statement |
int | Epidemic statement signed |
schedule_favorites |
int[] | Favourite class type IDs |
properties |
array | Custom profile properties |
is_app_deleted |
bool | Whether user deleted the app |
| Field | Type | Description |
|---|---|---|
id |
int | Box ID |
name |
string | Display name |
phone |
string | Contact phone |
email |
string | Contact email |
address |
string | Street address |
city |
string | City |
country |
string | Country |
cloudinary_image |
string | Logo/image URL |
bio |
string | Description |
external_url_id |
string | White-label identifier (use as whiteLabel header) |
box_type_fk |
int | Box type ID |
box_type.translations.segment |
string | Type label, e.g. "fitness" |
epidemic_mode |
int | Epidemic restrictions active |
notification_scheduling |
int | Hours before class to send notification |
recurring_payments_charge_day |
int|null | Monthly billing day |
boxes_settings |
object[] | Box configuration properties |
| Field | Type | Description |
|---|---|---|
id |
int | Location ID |
location |
string | Location label |
box_fk |
int | Parent box ID |
timezone |
string | e.g. "Asia/Jerusalem" |
country_code |
string | ISO country code |
currency |
string | ISO currency code |
currency_symbol |
string | Display symbol |
qr_code |
int | QR check-in enabled |
has_shop |
bool | Shop/store enabled |
hasPayments |
bool | Payments enabled |
hasMemberships |
bool | Membership plans available |
hasProducts |
bool | Product catalogue available |
hasAvailability |
int | Visibility of class spots: 0=none, 1=count, 2=names, 3=full |
hasWorkshops |
bool | Workshops enabled |
hasHugim |
bool | Recurring group sessions enabled |
standby_cancellation_time |
int | Minutes before class for standby auto-cancel |
schedule_standby_offset |
int | Hours before class that standby opens |
schedule_swapping_time |
int | Hours before class that swaps are allowed |
custom_field |
array | Custom user profile fields for this location |
disable_pages_app |
object[] | Sections hidden in mobile app |
{
"statusCode": 401,
"error": {
"message": "Unauthorized",
"messageToUser": "Forbidden",
"code": 401
},
"data": null
}| Code | Meaning |
|---|---|
401 |
Missing/invalid accesstoken, or insufficient role for the endpoint |
500 |
Server error — usually missing required parameters or insufficient role |
405 |
Wrong HTTP method (e.g. GET on a POST-only endpoint) |
404 |
Endpoint does not exist |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /api/v2/user/login |
No | Get token |
| POST | /api/v2/user/logout |
Yes | Invalidate token |
| GET | /api/v2/user/profile |
Yes | Full user profile |
| POST | /api/v2/user/resetPassword |
No | Trigger password reset email |
| POST | /api/v2/user/changePassword |
Yes | Change password |
| GET | /api/v2/boxes |
Yes | User's box memberships |
| GET | /api/v2/boxes/locations |
Yes | All boxes with location details |
| POST | /api/v2/scheduleUser/insert |
Yes | Book a class |
| POST | /api/v2/scheduleUser/delete |
Yes | Cancel a booking |
- Two API hosts:
apiappv2.arboxapp.com(v2, JWT auth) andapiapp.arboxapp.com/index.php/api/v1(v1, API key auth). They are separate systems. - JWT expiry: Tokens appear to be very long-lived (years). Refresh tokens have a shorter window (~30 days based on claims).
- No official docs: Arbox has not published a public API reference. All information here is reverse-engineered.