πŸͺAPI

Version: 2 Last Updated: September 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 Authorization header

  • Tenant ID: Passed in __tenant header

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

Retrieves a paginated list of recent customer attendances with optional filtering.

Query Parameters

Parameter
Type
Required
Default
Description

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=20

Response

{
  "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

Records 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

Retrieves all branches associated with your merchant account.

Example Request

GET /api/public/branches

Response

[
  {
    "id": "3a1bfd57-1b9d-0f99-c9d2-446b6aec5dc4",
    "name": "Main Branch",
    "addressUrl": null
  },
  {
    "id": "4b2cf47g-5e86-4251-641g-2d67ge9a8886",
    "name": "Secondary Branch",
    "addressUrl": "https://maps.example.com/branch2"
  }
]

GET /api/public/branches/{id}

Retrieves a specific branch by its ID.

Example Request

GET /api/public/branches/3a1bfd57-1b9d-0f99-c9d2-446b6aec5dc4

Response

{
  "id": "3a1bfd57-1b9d-0f99-c9d2-446b6aec5dc4",
  "name": "Main Branch",
  "addressUrl": null
}

πŸ“¦ Products API

Get all available services (referred to as products in the API).

GET /api/public/products

Retrieves all products available for public consumption.

Example Request

GET /api/public/products

Response

[
  {
    "id": "bf344bc3-5b1b-4760-b23d-cf3135d437ca",
    "name": "Car Wash Service",
    "description": "<p>External and internal car wash service...</p>",
    "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": "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

Retrieves all customers.

Query Parameters

Parameter
Type
Required
Default
Description

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=20

Response

{
  "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 a specific customer by ID.

Example Request

GET /api/public/customers/3a1bf3b5-b54f-34c7-db92-5ff28ff22315

Response

{
  "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

Creates 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

Retrieves a paginated list of customer subscriptions with custom field support.

Query Parameters

Parameter
Type
Required
Description

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=20

Response

{
  "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}

Returns detailed information about a specific subscription.

POST /api/public/subscriptions

Creates 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

Temporarily 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

Resumes a paused subscription.

Request Body

{
  "resumeAt": "2025-01-25T00:00:00Z"
}

Response

Returns the full subscription object with updated status.


🎯 Reservations API

Manage time-based bookings and appointments with availability checking.

GET /api/public/reservations

Retrieves a paginated list of reservations with custom field support.

Query Parameters

Parameter
Type
Required
Description

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=true

Response

{
  "totalCount": 89,
  "items": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "date": "2025-01-20",
      "toDate": "2025-01-20",
      "startAt": "2025-01-20T14:00:00Z",
      "endAt": "2025-01-20T15:00:00Z",
      "from": "14:00",
      "to": "15:00",
      "slotFormatted": "2:00 PM - 3:00 PM",
      "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 reservationRemainingAmount for consistency with other reservation amount fields.

GET /api/public/reservations/slots

Retrieves available time slots for reservations.

Query Parameters

Parameter
Type
Required
Description

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=1

How 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 MinQuantity is at least 1 (required validation)

  • DateTime format should be YYYY-MM-DDTHH:mm:ss (without timezone)

  • PriceId must 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
    }
  }
]

POST /api/public/reservations/bulk

Creates 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",
      "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",
      "customFields": {},
      "discount": {
        "type": "percentage",
        "value": 0
      }
    }
  ]
}

Response

{
  "invoiceId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}

⚠️ 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

Status Code
Description

200

Success

201

Created successfully

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

Error Code
Description

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: September 2025 | Version 2

Last updated