🏪API
Version: 2 Last Updated: October 2025
This document describes the public API endpoints available for merchants to integrate with the platform. All endpoints follow RESTful conventions and use JSON for data exchange.
🚀 Quick Start
For authentication and API key management, please refer to the Quick Start Guide.
Base URL: https://platform.rekaz.io/api/public
🔑 Authentication
All API endpoints require:
Authorization: Passed in
AuthorizationheaderTenant ID: Passed in
__tenantheader
Example Headers
Authorization: Basic YOUR-ENCODED-AUTHORIZATION-KEY
__tenant: YOUR_TENANT_ID
Content-Type: application/json📋 Attendances API
Manage customer check-ins and attendance tracking for reservations and subscriptions.
GET /api/public/attendances
GET /api/public/attendancesRetrieves a paginated list of recent customer attendances with optional filtering.
Query Parameters
customerId
Guid
No
null
Filter by specific customer ID
mobileNumber
string
No
null
Filter by customer mobile number
customerNumber
long
No
null
Filter by customer number
skipCount
int
No
0
Number of records to skip
maxResultCount
int
No
100
Maximum records to return (max: 100)
Example Requests
# Search by customer ID
GET /api/public/attendances?customerId=3fa85f64-5717-4562-b3fc-2c963f66afa6
# Search by mobile number
GET /api/public/attendances?mobileNumber=+966501234567
# Search by customer number
GET /api/public/attendances?customerNumber=12345
# Combined with pagination
GET /api/public/attendances?mobileNumber=+966501234567&skipCount=0&maxResultCount=20Response
{
"items": [
{
"type": "CheckIn",
"actionType": "Subscription",
"customerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"customerName": "John Doe",
"customerMobileNumber": "+966501234567",
"providers": ["Provider A", "Provider B"],
"customerImageUrl": "https://example.com/image.jpg",
"actionName": "Premium Membership",
"actionId": "7fa85f64-5717-4562-b3fc-2c963f66afa6",
"actionDateFrom": "2025-01-15T09:00:00Z",
"actionDateTo": "2025-01-15T10:00:00Z",
"isActive": true,
"canDoCheckIn": true,
"isFirstCheckIn": false,
"customFields": [
{
"label": "Membership Level",
"value": "Gold"
}
],
"isPackage": false
}
],
"totalCount": 150
}POST /api/public/attendances
POST /api/public/attendancesRecords a new attendance entry for a customer action.
Request Body
{
"type": 1, // 0 = Reservation, 1 = Subscription
"actionType": 0, // 0 = Check-In, 1 = Check-Out
"customerId": "3a1c29af-6c55-0661-5e51-8403ff2b9288",
"actionId": "3a1c29af-928e-e595-ac07-9dce32224136" // ReservationId or SubscriptionId
}Response
Returns the created attendance record with all populated fields (same structure as GET response item).
🏢 Branches API
Manage and retrieve branch information for your merchant account.
GET /api/public/branches
GET /api/public/branchesRetrieves all branches associated with your merchant account.
Example Request
GET /api/public/branchesResponse
[
{
"id": "3a1bfd57-1b9d-0f99-c9d2-446b6aec5dc4",
"name": "الفرع الرئيسي",
"nameAr": "الفرع الرئيسي",
"nameEn": "Main Branch",
"addressUrl": null
},
{
"id": "4b2cf47g-5e86-4251-641g-2d67ge9a8886",
"name": "الفرع الثانوي",
"nameAr": "الفرع الثانوي",
"nameEn": "Secondary Branch",
"addressUrl": "https://maps.example.com/branch2"
}
]GET /api/public/branches/{id}
GET /api/public/branches/{id}Retrieves a specific branch by its ID.
Example Request
GET /api/public/branches/3a1bfd57-1b9d-0f99-c9d2-446b6aec5dc4Response
{
"id": "3a1bfd57-1b9d-0f99-c9d2-446b6aec5dc4",
"name": "الفرع الرئيسي",
"nameAr": "الفرع الرئيسي",
"nameEn": "Main Branch",
"addressUrl": null
}📦 Products API
Get all available services (referred to as products in the API).
GET /api/public/products
GET /api/public/productsRetrieves all products available for public consumption.
Example Request
GET /api/public/productsResponse
[
{
"id": "bf344bc3-5b1b-4760-b23d-cf3135d437ca",
"name": "غسيل السيارات",
"nameAr": "غسيل السيارات",
"nameEn": "Car Wash Service",
"description": "",
"shortDescription": "",
"amount": 30,
"duration": null,
"slots": null,
"productProviders": [
{
"id": "72bbb3ed-3160-485b-a48f-a90e909602e2",
"image": null,
"name": "Default Service Provider",
"description": ""
}
],
"pricing": [
{
"id": "3a1bf3a6-8d25-4a0d-16b6-069be6c0f248",
"name": "سيارة صغيرة",
"nameAr": "سيارة صغيرة",
"nameEn": "Small Car",
"model": 0,
"billingCycle": 0,
"amount": 30,
"discountedAmount": 30,
"hasMinimum": false,
"hasDeposit": false,
"hasOccurrence": false,
"duration": null,
"sku": null
}
],
"maximumQuantityPerOrder": 1,
"customFields": [
{
"id": "3a1bf3a4-2f9f-e479-bcd9-7835d99eaf04",
"name": "location_field",
"label": "Wash Location",
"placeholder": "Choose your location",
"showInCheckout": true,
"amount": 0
}
],
"type": 0,
"typeString": "Reservation",
"branchIds": ["3a1bf36f-4d75-3140-530f-1c56fd89e775"]
}
]GET /api/public/products/{id}
GET /api/public/products/{id}Retrieves a specific product by its ID.
Example Request
GET /api/public/products/bf344bc3-5b1b-4760-b23d-cf3135d437caResponse
{
"id": "bf344bc3-5b1b-4760-b23d-cf3135d437ca",
"name": "غسيل السيارات",
"nameAr": "غسيل السيارات",
"nameEn": "Car Wash Service",
"description": "",
"shortDescription": "",
"amount": 30,
"duration": null,
"slots": null,
"productProviders": [
{
"id": "72bbb3ed-3160-485b-a48f-a90e909602e2",
"image": null,
"name": "Default Service Provider",
"description": ""
}
],
"pricing": [
{
"id": "3a1bf3a6-8d25-4a0d-16b6-069be6c0f248",
"name": "سيارة صغيرة",
"nameAr": "سيارة صغيرة",
"nameEn": "Small Car",
"model": 0,
"billingCycle": 0,
"amount": 30,
"discountedAmount": 30,
"hasMinimum": false,
"hasDeposit": false,
"hasOccurrence": false,
"duration": null,
"sku": null
}
],
"maximumQuantityPerOrder": 1,
"customFields": [
{
"id": "3a1bf3a4-2f9f-e479-bcd9-7835d99eaf04",
"name": "location_field",
"label": "Wash Location",
"placeholder": "Choose your location",
"showInCheckout": true,
"amount": 0
}
],
"type": 0,
"typeString": "Reservation",
"branchIds": ["3a1bf36f-4d75-3140-530f-1c56fd89e775"]
}👥 Customers API
Get all your customers.
GET /api/public/customers
GET /api/public/customersRetrieves all customers.
Query Parameters
skipCount
int
No
0
Number of records to skip (for pagination)
maxResultCount
int
No
100
Maximum records to return (max: 100)
Example Request
GET /api/public/customers?skipCount=0&maxResultCount=20Response
{
"items": [
{
"id": "3a1c11b5-3fc3-2016-1890-1a285e601de7",
"name": "John Doe",
"customerNumber": 123778,
"mobileNumber": "966502493366",
"email": "[email protected]",
"customerType": 1,
"address": null,
"companyName": null,
"customFields": {},
"branchIds": ["3a1bfd57-1b9d-0f99-c9d2-446b6aec5dc4"],
"isBlocked": false
}
],
"totalCount": 13
}GET /api/public/customers/{id}
GET /api/public/customers/{id}Get a specific customer by ID.
Example Request
GET /api/public/customers/3a1bf3b5-b54f-34c7-db92-5ff28ff22315Response
{
"id": "3a1c11b5-3fc3-2016-1890-1a285e601de7",
"name": "John Doe",
"customerNumber": 123778,
"mobileNumber": "966502493366",
"email": "[email protected]",
"customerType": 1,
"address": null,
"companyName": null,
"customFields": {},
"branchIds": ["3a1bfd57-1b9d-0f99-c9d2-446b6aec5dc4"],
"isBlocked": false
}POST /api/public/customers
POST /api/public/customersCreates a new customer record in the system.
Request Body
{
"name": "John Smith",
"mobileNumber": "+966501233567",
"email": "[email protected]",
"address": "123 Main Street, Riyadh",
"type": 1, // 1 = Individual, 2 = Company
"branchId": "3a1bf36f-4d75-3140-530f-1c56fd89e775",
"companyName": "ABC Company Ltd",
"customFields": {
"field1": "value1",
"field2": "value2"
}
}Response
Returns the created customer ID:
"3a1bf3d6-1c84-d69e-e2d5-eb6b4f08f6d8"📅 Subscriptions API
Manage recurring subscription services for customers.
GET /api/public/subscriptions
GET /api/public/subscriptionsRetrieves a paginated list of customer subscriptions with custom field support.
Query Parameters
skipCount
int
No
Number of records to skip (for pagination)
maxResultCount
int
No
Maximum records to return (max: 100)
customerId
Guid
No
Filter by specific customer ID
customerMobile
string
No
Filter by customer mobile number
startAtMin
datetime
No
Filter subscriptions starting from this date
startAtMax
datetime
No
Filter subscriptions starting until this date
statuses
array
No
Filter by statuses (e.g., "Active", "Paused")
branchId
Guid
No
Filter by branch ID
keyword
string
No
Search keyword across subscription details
Example Request
GET /api/public/subscriptions?customerId=7fa85f64-5717-4562-b3fc-2c963f66afa6&skipCount=0&maxResultCount=20Response
{
"totalCount": 45,
"items": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"customerId": "7fa85f64-5717-4562-b3fc-2c963f66afa6",
"startAt": "2025-01-01T00:00:00Z",
"endAt": "2025-02-01T00:00:00Z",
"status": "Active",
"items": [
{
"id": "8fa85f64-5717-4562-b3fc-2c963f66afa6",
"priceId": "9fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "Monthly Gym Access",
"productName": "Gym Membership",
"quantity": 1,
"billingCycle": "Monthly"
}
],
"discount": {
"type": "Percentage",
"value": 10
},
"branchId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"occurenceDays": ["Monday", "Wednesday", "Friday"],
"customFields": [
{
"name": "trainer_assigned",
"label": "Personal Trainer",
"type": "String",
"value": "Mike Johnson"
}
],
"paidAmount": 500.0,
"totalAmount": 500.0,
"remainingAmount": 0.0,
"lastInvoiceCode": "INV-2025-001",
"lastInvoiceStatus": "Paid",
"isPaused": false,
"pausedAt": null,
"resumeAt": null
}
]
}GET /api/public/subscriptions/{id}
GET /api/public/subscriptions/{id}Returns detailed information about a specific subscription.
POST /api/public/subscriptions
POST /api/public/subscriptionsCreates a new subscription, optionally creating a new customer.
Request Body (Existing Customer)
{
"customerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"startAt": "2025-02-01T00:00:00Z",
"discount": {
"type": "Fixed",
"value": 50
},
"branchId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"items": [
{
"priceId": "9fa85f64-5717-4562-b3fc-2c963f66afa6",
"quantity": 1
}
],
"occurenceDays": ["Monday", "Wednesday", "Friday"]
}Request Body (New Customer)
{
"customerDetails": {
"name": "Jane Smith",
"mobileNumber": "+966501234567",
"email": "[email protected]",
"type": 1, // 1 = Individual, 2 = Company
"companyName": ""
},
"branchId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"startAt": "2025-02-01T00:00:00Z",
"items": [
{
"priceId": "9fa85f64-5717-4562-b3fc-2c963f66afa6",
"quantity": 1
}
]
}Response
{
"invoiceId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}POST /api/public/subscriptions/{id}/pause
POST /api/public/subscriptions/{id}/pauseTemporarily pauses an active subscription.
Request Body
{
"pausedAt": "2025-01-20T00:00:00Z",
"resumeAt": "2025-02-01T00:00:00Z"
}Response
{
"subscriptionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"pausedAt": "2025-01-20T00:00:00Z",
"resumeAt": "2025-02-01T00:00:00Z"
}POST /api/public/subscriptions/{id}/resume
POST /api/public/subscriptions/{id}/resumeResumes a paused subscription.
Request Body
{
"resumeAt": "2025-01-25T00:00:00Z"
}Response
Returns the full subscription object with updated status.
🧑💼 Providers
GET /api/public/providers
GET /api/public/providersRetrieves all available providers.
Response
{
"items": [
{
"id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
"name": "Dr. Ahmed Ali"
},
{
"id": "b2c3d4e5-6789-01bc-def0-234567890bcd",
"name": "Sara Mohammed"
}
]
}🎯 Reservations API
Manage time-based bookings and appointments with availability checking.
GET /api/public/reservations
GET /api/public/reservationsRetrieves a paginated list of reservations with custom field support.
Query Parameters
skipCount
int
No
Number of records to skip (for pagination)
maxResultCount
int
No
Maximum records to return (max: 100)
dateMin
datetime
No
Filter reservations from this date
dateMax
datetime
No
Filter reservations until this date
statuses
array
No
Filter by statuses (e.g., "Confirmed")
customerId
Guid
No
Filter by specific customer ID
customerMobile
string
No
Filter by customer mobile number
upcoming
boolean
No
Filter for upcoming reservations
keyword
string
No
Search keyword across reservation details
branchId
Guid
No
Filter by branch ID
Example Request
GET /api/public/reservations?customerId=7fa85f64-5717-4562-b3fc-2c963f66afa6&upcoming=trueResponse
{
"totalCount": 89,
"items": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"startAt": "2025-01-20T14:00:00Z",
"endAt": "2025-01-20T15:00:00Z",
"status": "Confirmed",
"customStatus": "VIP",
"customerName": "John Doe",
"customerMobile": "+966501234567",
"customerId": "7fa85f64-5717-4562-b3fc-2c963f66afa6",
"reservationNumber": 10234,
"productName": "Tennis Court",
"priceName": "Peak Hours",
"quantity": 1,
"providers": ["Court A"],
"customFields": [
{
"name": "equipment_needed",
"label": "Equipment Required",
"type": "Boolean",
"value": true
}
],
"invoiceTotalAmount": 150.0,
"reservationTotalAmount": 150.0,
"reservationRemainingAmount": 0.0,
"branchId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"branchName": "Main Branch",
"meetingUrl": "https://meet.example.com/abc123",
"source": "WebBooking",
"isZeroPrice": false,
"isWalkInCustomer": false
}
]
}Note: The remaining amount field is now named
reservationRemainingAmountfor consistency with other reservation amount fields.
GET /api/public/reservations/{id}
GET /api/public/reservations/{id}Retrieves a specific reservation by its ID.
Example Request
GET /api/public/reservations/3fa85f64-5717-4562-b3fc-2c963f66afa6Response
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"startAt": "2025-01-20T14:00:00Z",
"endAt": "2025-01-20T15:00:00Z",
"status": "Confirmed",
"customStatus": "VIP",
"customerName": "John Doe",
"customerMobile": "+966501234567",
"customerId": "7fa85f64-5717-4562-b3fc-2c963f66afa6",
"reservationNumber": 10234,
"productName": "Tennis Court",
"priceName": "Peak Hours",
"quantity": 1,
"providers": ["Court A"],
"customFields": [
{
"name": "equipment_needed",
"label": "Equipment Required",
"type": "Boolean",
"value": true
}
],
"invoiceTotalAmount": 150.0,
"reservationTotalAmount": 150.0,
"reservationRemainingAmount": 0.0,
"branchId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"branchName": "Main Branch",
"meetingUrl": "https://meet.example.com/abc123",
"source": "WebBooking",
"isZeroPrice": false,
"isWalkInCustomer": false
}GET /api/public/reservations/slots
GET /api/public/reservations/slotsRetrieves available time slots for reservations.
Query Parameters
StartDate
datetime
Yes
Your desired start date for slot search (format: 2025-08-10T20:00:00)
EndDate
datetime
Yes
Your desired end date for slot search (format: 2025-08-25T21:00:00)
PriceId
Guid
Yes
Price configuration ID from products
MinQuantity
int
Yes
Minimum quantity required (must be ≥ 1)
MinProvidersCount
int
No
Minimum number of providers required
ProvidersIds
Guid[]
No
Specific provider IDs to filter by
Example Request
GET /api/public/reservations/slots?StartDate=2025-08-10T20:00:00&EndDate=2025-08-25T21:00:00&PriceId=3a1c12e6-c66b-6ac5-90a7-8b791791af3c&MinQuantity=1&MinProvidersCount=1How to set dates:
StartDate: When you want to start looking for available slots (e.g., today or tomorrow)EndDate: How far ahead you want to search (e.g., next week or month)
Common Issues:
Ensure
MinQuantityis at least 1 (required validation)DateTime format should be
YYYY-MM-DDTHH:mm:ss(without timezone)PriceIdmust be a valid GUID from the products endpoint
Response
[
{
"from": "2025-09-09T06:00:00Z",
"to": "2025-10-12T06:00:00Z",
"availableReservationsCount": 1,
"availableProvidersCount": 0,
"availableProviderIds": [],
"isOutDated": false,
"isAvailable": false,
"amounts": {
"totalPrice": 382.95,
"effectiveQuantity": 1,
"totalAfterDiscount": 382.95,
"depositAmount": null
},
"maxConnectedTo": "2025-10-12T06:00:00Z",
"allProvidersAvailability": {
"45bb3834-9869-4d12-83af-fa347448aa60": false
}
}
]PUT /api/public/reservations/{id}
PUT /api/public/reservations/{id}Updates an existing reservation's start date, end date, and/or assigned providers.
Request Body
{
"startDate": "2025-01-20T14:00:00Z",
"endDate": "2025-01-20T15:00:00Z",
"providerIds": ["3fa85f64-5717-4562-b3fc-2c963f66afa6"]
}Parameters:
startDate(required, DateTime): The start date and time for the reservation in ISO 8601 format. This field is required in the request, but you can pass the existing start date if you only want to update the end date or providersendDate(optional, DateTime): The new end date and time for the reservation in ISO 8601 format. If not provided, the system automatically preserves the original reservation duration. For example, if the original reservation was 1 hour long, the updated reservation will also be 1 hour long starting from the newstartDateproviderIds(optional, array of GUID): List of provider IDs to assign to the reservation. If not provided, the existing providers will be kept
Note:
startDateis required in every request.endDateandproviderIdsare optional and will retain their existing values if not included. To update only the end date or providers without changing the start date, include the current start date in the request.Duration Preservation: When you update the
startDatewithout providing anendDate, the system automatically calculates the newendDateby preserving the original reservation duration. This ensures the reservation length remains consistent.
Example: Update only the start date (duration is preserved)
{
"startDate": "2025-10-16T10:00:00Z"
}If the original reservation was from 14:00 to 15:00 (1 hour), the updated reservation will be from 10:00 to 11:00 (still 1 hour).
Example: Update only the end date (keeping start date the same)
{
"startDate": "2025-01-20T14:00:00Z", // Current/existing start date
"endDate": "2025-01-20T16:00:00Z" // New end date
}Example: Update only the providers (keeping dates the same)
{
"startDate": "2025-01-20T14:00:00Z", // Current/existing start date
"providerIds": ["b2c3d4e5-6789-01bc-def0-234567890bcd"]
}Example: Update start date and end date
{
"startDate": "2025-10-16T10:00:00Z",
"endDate": "2025-10-16T11:00:00Z"
}Example: Update all fields
{
"startDate": "2025-10-16T10:00:00Z",
"endDate": "2025-10-16T11:00:00Z",
"providerIds": ["b2c3d4e5-6789-01bc-def0-234567890bcd"]
}Response
Returns 204 No Content on success.
POST /api/public/reservations/bulk
POST /api/public/reservations/bulkCreates multiple reservations in a single request.
Request Body (Existing Customer)
{
"customerId": "3a1c2245-564d-84ec-af57-c7b85af1441f",
"branchId": "3a1c1320-ef97-fa70-ddb6-15ad0832397f",
"items": [
{
"quantity": 1,
"priceId": "3a1c2281-1154-f9d2-f96f-210b7021eedb",
"from": "2025-09-04T17:00:00Z",
"to": "2025-09-04T18:00:00Z",
"providerIds": [],
"customFields": {},
"discount": {
"type": "percentage",
"value": 0
}
}
]
}Request Body (New Customer)
{
"customerDetails": {
"name": "Final Test",
"mobileNumber": "+966502203642",
"email": "",
"type": 1,
"companyName": ""
},
"branchId": "3a1c1320-ef97-fa70-ddb6-15ad0832397f",
"items": [
{
"quantity": 1,
"priceId": "3a1c2281-1154-f9d2-f96f-210b7021eedb",
"from": "2025-09-04T17:00:00Z",
"to": "2025-09-04T18:00:00Z",
"providerIds": [],
"customFields": {},
"discount": {
"type": "percentage",
"value": 0
}
}
]
}Response
{
"invoiceId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"reservationIds": ["4fa85f64-5717-4562-b3fc-2c963f66afa6"],
"paymentLink": "https://platform.rekaz.io/i/NcRo"
}PUT /api/public/reservations/{id}/confirm
PUT /api/public/reservations/{id}/confirmConfirms a pending reservation.
Example Request
PUT /api/public/reservations/3fa85f64-5717-4562-b3fc-2c963f66afa6/confirmResponse
Status: 204 No Content
PUT /api/public/reservations/{id}/cancel
PUT /api/public/reservations/{id}/cancelCancels an existing reservation.
Headers: Content-Type: application/json
Request Body
{
"cancellationReason": "Customer requested cancellation",
"notifyCustomer": true
}Example Request
PUT /api/public/reservations/3fa85f64-5717-4562-b3fc-2c963f66afa6/cancelResponse
Status: 204 No Content
⚠️ Error Handling
All endpoints follow standard HTTP status codes and return consistent error responses.
Error Response Format
{
"error": {
"code": "VALIDATION_ERROR",
"message": "The request validation failed",
"details": "The mobile number format is invalid",
"validationErrors": [
{
"field": "mobileNumber",
"message": "Must be a valid Saudi mobile number"
}
]
}
}HTTP Status Codes
200
Success
201
Created successfully
204
No Content
400
Bad request - validation error
401
Unauthorized - invalid API key
403
Forbidden - missing branch ID or permissions
404
Resource not found
500
Internal server error
Common Error Codes
ValidationError
Request data validation failed
NotFound
Requested resource does not exist
Unauthorized
Invalid or missing authentication
RateLimit
Too many requests
BusinessLogicError
Business rule violation
Last updated: October 2025 | Version 2
Last updated