Kthehu te Padli

Për zhvilluesit

Partner API

Shfaq fushat dhe terminet e lira të një klubi në Padli në uebfaqen e vetë klubit, me çmime dhe me një link që hap terminin e saktë në Padli për rezervim.

Ky udhëzues është për zhvilluesit e uebit dhe është shkruar vetëm në anglisht.

For developers building a club's own website. With it, the site can show the club's details, courts and free time slots, priced, and send a player to Padli to book the exact slot they picked. The player signs in, pays and gets their confirmation in Padli; the site never handles accounts or payments.

The API is read only.

Getting a key

The club creates the key in the Padli portal: Venue > Your website > Create key. It is shown once; the club sends it to you. If it is lost, the club deletes it and creates another.

When creating it, the club lists the website addresses that may use it, for example padelpark.mk, dev.padelpark.mk and localhost:3000 for local development. Calls made from a browser on any other address are refused. A key with no addresses works only from a server.

The key belongs to one club. Every call answers for that club, so no club id appears in any URL.

Making a call

Environment Base URL
Production https://play.padli.app/api/partner/v1
Development https://dev.play.padli.app/api/partner/v1

Send the key in the X-Padli-Key header on every request:

const res = await fetch('https://play.padli.app/api/partner/v1/availability?date=2026-10-20', {
  headers: {
    'X-Padli-Key': 'padli_pk_…',
    'Accept-Language': 'mk', // optional: en, mk, sq, sr or tr
  },
})
const day = await res.json()

Browser calls work directly (CORS is answered for the addresses on the key). Never send cookies: the API does not use them.

Accept-Language picks the language of the club's own text where the club has a translation (today, its description). Everything else in a response is data, not text.

Conventions

  • Times are local to the club. timezone names the zone (Europe/Skopje). Every slot carries both start ("18:00") and starts_at, the same moment as a full ISO 8601 timestamp with its offset ("2026-10-20T18:00:00+02:00"). Use starts_at for any date arithmetic.
  • Prices are decimal strings ("2400.00") in the currency named once per response. Format them for display yourself; never parse them as binary floats for money math.
  • Weekdays are lower-case English names: "monday" … "sunday".
  • Empty is an empty array, never null, for every list.
  • Fields are only ever added within v1. Ignore fields you do not know.

GET /venue

The club.

{
  "uuid": "e02b0f0f-c0e2-41f7-84ac-704476251a14",
  "name": "Padel Park",
  "description": "Four indoor courts by the river.",
  "address": "Bul. Partizanski Odredi 62",
  "city": "Skopje",
  "latitude": 41.99813,
  "longitude": 21.42544,
  "phone": "+38970123456",
  "email": "hi@padelpark.mk",
  "website": "https://padelpark.mk",
  "timezone": "Europe/Skopje",
  "photo_urls": ["https://cdn.padli.app/venues/…/1.jpg"],
  "opening_hours": [
    { "day": "monday", "intervals": [{ "open": "07:00", "close": "12:00" }, { "open": "16:00", "close": "23:00" }] },
    { "day": "sunday", "intervals": [{ "open": "09:00", "close": "24:00" }] }
  ],
  "courts": [
    {
      "uuid": "b897bb46-1f56-4cfc-a041-d910c184454d",
      "name": "Court 1",
      "sports": ["padel"],
      "type": "indoor",
      "surface": "blue",
      "photo_urls": [],
      "durations": [60, 90, 120]
    }
  ],
  "club_url": "https://padli.app/club/padel-park-skopje",
  "book_url": "https://play.padli.app/venues/e02b0f0f-c0e2-41f7-84ac-704476251a14",
  "rating": { "average": 4.6, "count": 38 },
  "price_from": "1200.00",
  "currency": "MKD",
  "amenities": ["parking", "showers", "cafe_bar", "equipment_rental"],
  "cancellation_policy": [
    { "minutes_before": 1440, "refund_percent": 100 },
    { "minutes_before": 360, "refund_percent": 50 }
  ],
  "cancellation_grace_minutes": 60,
  "open_matches_enabled": true
}
  • opening_hours lists only the days the club opens; a day may have several intervals. "close": "24:00" means open until midnight.
  • courts[].sports is every sport the court can be booked for, its main one first. durations are the booking lengths it sells, in minutes.
  • club_url is the club's public page on padli.app (null until it has one). book_url opens the club in Padli, ready to pick a time.
  • Any contact or location field may be null when the club has not filled it in.
  • rating is the average of each player's latest rating of the club (1 to 5, one decimal) and how many players gave one. It is null until the club has enough ratings for Padli to show it, so a new club never shows an average of two evenings.
  • price_from is the club's cheapest court price per hour, as it sells today (a promotion the club is running is included). It is the "from" price on the club's Padli page. price_from and currency are both null until the club has prices set.
  • amenities are slugs, not text: translate them on your site. Today's slugs are parking, wifi, showers, changing_rooms, lockers, restrooms, cafe_bar, pro_shop, equipment_rental, lighting and accessibility. New slugs may appear: skip one you do not know. The list is empty when the club has none.
  • cancellation_policy is the club's refund schedule, longest notice first: a player who cancels at least minutes_before before the start gets refund_percent of the court price back (Padli's service fee is not refunded). Cancelling later than the last tier refunds nothing, so an empty list means cancellations are not refunded. This is the club's default; a single court can have its own, which Padli shows the player when they book it.
  • cancellation_grace_minutes: a booking cancelled within this many minutes of being made is refunded in full, service fee included, whatever the schedule says, as long as the match is still further off than the window itself. 0 means the club has this off.
  • open_matches_enabled: whether players booking here can open their booking's free places to other players in Padli.

GET /availability

What can be booked on one day.

Query Required Meaning
date no YYYY-MM-DD. Defaults to the club's today. Must be between today and the last day the club sells.
sport no A sport, e.g. padel. Only courts for that sport. An unknown sport returns no courts.
duration no Minutes, e.g. 90. Only that booking length.
{
  "date": "2026-10-20",
  "timezone": "Europe/Skopje",
  "currency": "MKD",
  "courts": [
    {
      "uuid": "b897bb46-1f56-4cfc-a041-d910c184454d",
      "name": "Court 1",
      "sport": "padel",
      "type": "indoor",
      "surface": "blue",
      "slots": [
        {
          "start": "18:00",
          "starts_at": "2026-10-20T18:00:00+02:00",
          "options": [
            {
              "duration": 60,
              "end": "19:00",
              "ends_at": "2026-10-20T19:00:00+02:00",
              "price": "1600.00",
              "price_standard": null,
              "total": "1680.00",
              "book_url": "https://play.padli.app/venues/e02b…?court=b897…&date=2026-10-20&duration=60&sport=padel&start=18%3A00"
            },
            {
              "duration": 90,
              "end": "19:30",
              "ends_at": "2026-10-20T19:30:00+02:00",
              "price": "2400.00",
              "price_standard": "3000.00",
              "total": "2520.00",
              "book_url": "https://play.padli.app/venues/e02b…?court=b897…&date=2026-10-20&duration=90&sport=padel&start=18%3A00"
            }
          ]
        }
      ]
    }
  ]
}
  • Only bookable time is listed: free, priced and not already started. A court with nothing left that day is still listed, with "slots": [], so you can show it as fully booked.
  • Each slot is a start time; its options are the lengths a booking from that start can have on that court. An option is only listed when the whole length is free.
  • price is the court price for the whole booking. price_standard is the price before a promotion the club is running, or null when there is none: show it struck through. total is what the player pays in Padli: the court price plus Padli's service fee.
  • A court that plays two sports appears once per sport, priced for that sport. Booking either one takes the court.
  • book_url opens Padli on that exact slot. If the slot was taken in the meantime, Padli shows the day with what is still free.
  • currency is null only when nothing that day is bookable.

Availability changes every time someone books. Do not cache it for more than a minute or two; do cache /venue, which changes rarely.

Errors

Errors have a status code and a body like { "success": false, "message": "<code>" }. Validation errors add errors, keyed by query parameter.

Status message Meaning
401 partner.key_missing No X-Padli-Key header.
401 partner.key_invalid The key is wrong or was deleted.
403 partner.origin_not_allowed Called from a browser on an address the key does not list. Ask the club to add it.
403 partner.venue_unavailable The club is not currently live on Padli.
422 validation.failed A query parameter is wrong; see errors. For date: validation.date (not a valid date), booking.date_in_past, booking.beyond_horizon (the club does not sell that far ahead yet).
429 Too many requests from one address. Wait for Retry-After seconds.

Limits are per visitor address (about 20 requests a second, short bursts allowed), so a site's visitors do not share one budget. A site calling from its own server shares one address for all its visitors: cache there.