[{"data":1,"prerenderedAt":4},["ShallowReactive",2],{"developer-guide":3},"\u003Cp>For developers building a club&#39;s own website. With it, the site can show the club&#39;s\ndetails, courts and free time slots, priced, and send a player to Padli to book the exact\nslot they picked. The player signs in, pays and gets their confirmation in Padli; the\nsite never handles accounts or payments.\u003C\u002Fp>\n\u003Cp>The API is read only.\u003C\u002Fp>\n\u003Ch2>Getting a key\u003C\u002Fh2>\n\u003Cp>The club creates the key in the Padli portal: \u003Cstrong>Venue &gt; Your website &gt; Create key\u003C\u002Fstrong>. It\nis shown once; the club sends it to you. If it is lost, the club deletes it and creates\nanother.\u003C\u002Fp>\n\u003Cp>When creating it, the club lists the website addresses that may use it, for example\n\u003Ccode>padelpark.mk\u003C\u002Fcode>, \u003Ccode>dev.padelpark.mk\u003C\u002Fcode> and \u003Ccode>localhost:3000\u003C\u002Fcode> for local development. Calls made\nfrom a browser on any other address are refused. A key with no addresses works only from\na server.\u003C\u002Fp>\n\u003Cp>The key belongs to one club. Every call answers for that club, so no club id appears in\nany URL.\u003C\u002Fp>\n\u003Ch2>Making a call\u003C\u002Fh2>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Environment\u003C\u002Fth>\n\u003Cth>Base URL\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>Production\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>https:\u002F\u002Fplay.padli.app\u002Fapi\u002Fpartner\u002Fv1\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Development\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>https:\u002F\u002Fdev.play.padli.app\u002Fapi\u002Fpartner\u002Fv1\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Cp>Send the key in the \u003Ccode>X-Padli-Key\u003C\u002Fcode> header on every request:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-js\">const res = await fetch(&#39;https:\u002F\u002Fplay.padli.app\u002Fapi\u002Fpartner\u002Fv1\u002Favailability?date=2026-10-20&#39;, {\n  headers: {\n    &#39;X-Padli-Key&#39;: &#39;padli_pk_…&#39;,\n    &#39;Accept-Language&#39;: &#39;mk&#39;, \u002F\u002F optional: en, mk, sq, sr or tr\n  },\n})\nconst day = await res.json()\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Browser calls work directly (CORS is answered for the addresses on the key). Never send\ncookies: the API does not use them.\u003C\u002Fp>\n\u003Cp>\u003Ccode>Accept-Language\u003C\u002Fcode> picks the language of the club&#39;s own text where the club has a\ntranslation (today, its description). Everything else in a response is data, not text.\u003C\u002Fp>\n\u003Ch2>Conventions\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Cstrong>Times\u003C\u002Fstrong> are local to the club. \u003Ccode>timezone\u003C\u002Fcode> names the zone (\u003Ccode>Europe\u002FSkopje\u003C\u002Fcode>). Every slot\ncarries both \u003Ccode>start\u003C\u002Fcode> (\u003Ccode>&quot;18:00&quot;\u003C\u002Fcode>) and \u003Ccode>starts_at\u003C\u002Fcode>, the same moment as a full ISO 8601\ntimestamp with its offset (\u003Ccode>&quot;2026-10-20T18:00:00+02:00&quot;\u003C\u002Fcode>). Use \u003Ccode>starts_at\u003C\u002Fcode> for any date\narithmetic.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Prices\u003C\u002Fstrong> are decimal strings (\u003Ccode>&quot;2400.00&quot;\u003C\u002Fcode>) in the currency named once per response.\nFormat them for display yourself; never parse them as binary floats for money math.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Weekdays\u003C\u002Fstrong> are lower-case English names: \u003Ccode>&quot;monday&quot;\u003C\u002Fcode> … \u003Ccode>&quot;sunday&quot;\u003C\u002Fcode>.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Empty is an empty array\u003C\u002Fstrong>, never \u003Ccode>null\u003C\u002Fcode>, for every list.\u003C\u002Fli>\n\u003Cli>Fields are only ever \u003Cstrong>added\u003C\u002Fstrong> within v1. Ignore fields you do not know.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>GET \u002Fvenue\u003C\u002Fh2>\n\u003Cp>The club.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-json\">{\n  &quot;uuid&quot;: &quot;e02b0f0f-c0e2-41f7-84ac-704476251a14&quot;,\n  &quot;name&quot;: &quot;Padel Park&quot;,\n  &quot;description&quot;: &quot;Four indoor courts by the river.&quot;,\n  &quot;address&quot;: &quot;Bul. Partizanski Odredi 62&quot;,\n  &quot;city&quot;: &quot;Skopje&quot;,\n  &quot;latitude&quot;: 41.99813,\n  &quot;longitude&quot;: 21.42544,\n  &quot;phone&quot;: &quot;+38970123456&quot;,\n  &quot;email&quot;: &quot;hi@padelpark.mk&quot;,\n  &quot;website&quot;: &quot;https:\u002F\u002Fpadelpark.mk&quot;,\n  &quot;timezone&quot;: &quot;Europe\u002FSkopje&quot;,\n  &quot;photo_urls&quot;: [&quot;https:\u002F\u002Fcdn.padli.app\u002Fvenues\u002F…\u002F1.jpg&quot;],\n  &quot;opening_hours&quot;: [\n    { &quot;day&quot;: &quot;monday&quot;, &quot;intervals&quot;: [{ &quot;open&quot;: &quot;07:00&quot;, &quot;close&quot;: &quot;12:00&quot; }, { &quot;open&quot;: &quot;16:00&quot;, &quot;close&quot;: &quot;23:00&quot; }] },\n    { &quot;day&quot;: &quot;sunday&quot;, &quot;intervals&quot;: [{ &quot;open&quot;: &quot;09:00&quot;, &quot;close&quot;: &quot;24:00&quot; }] }\n  ],\n  &quot;courts&quot;: [\n    {\n      &quot;uuid&quot;: &quot;b897bb46-1f56-4cfc-a041-d910c184454d&quot;,\n      &quot;name&quot;: &quot;Court 1&quot;,\n      &quot;sports&quot;: [&quot;padel&quot;],\n      &quot;type&quot;: &quot;indoor&quot;,\n      &quot;surface&quot;: &quot;blue&quot;,\n      &quot;photo_urls&quot;: [],\n      &quot;durations&quot;: [60, 90, 120]\n    }\n  ],\n  &quot;club_url&quot;: &quot;https:\u002F\u002Fpadli.app\u002Fclub\u002Fpadel-park-skopje&quot;,\n  &quot;book_url&quot;: &quot;https:\u002F\u002Fplay.padli.app\u002Fvenues\u002Fe02b0f0f-c0e2-41f7-84ac-704476251a14&quot;,\n  &quot;rating&quot;: { &quot;average&quot;: 4.6, &quot;count&quot;: 38 },\n  &quot;price_from&quot;: &quot;1200.00&quot;,\n  &quot;currency&quot;: &quot;MKD&quot;,\n  &quot;amenities&quot;: [&quot;parking&quot;, &quot;showers&quot;, &quot;cafe_bar&quot;, &quot;equipment_rental&quot;],\n  &quot;cancellation_policy&quot;: [\n    { &quot;minutes_before&quot;: 1440, &quot;refund_percent&quot;: 100 },\n    { &quot;minutes_before&quot;: 360, &quot;refund_percent&quot;: 50 }\n  ],\n  &quot;cancellation_grace_minutes&quot;: 60,\n  &quot;open_matches_enabled&quot;: true\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cul>\n\u003Cli>\u003Ccode>opening_hours\u003C\u002Fcode> lists only the days the club opens; a day may have several intervals.\n\u003Ccode>&quot;close&quot;: &quot;24:00&quot;\u003C\u002Fcode> means open until midnight.\u003C\u002Fli>\n\u003Cli>\u003Ccode>courts[].sports\u003C\u002Fcode> is every sport the court can be booked for, its main one first.\n\u003Ccode>durations\u003C\u002Fcode> are the booking lengths it sells, in minutes.\u003C\u002Fli>\n\u003Cli>\u003Ccode>club_url\u003C\u002Fcode> is the club&#39;s public page on padli.app (null until it has one).\n\u003Ccode>book_url\u003C\u002Fcode> opens the club in Padli, ready to pick a time.\u003C\u002Fli>\n\u003Cli>Any contact or location field may be \u003Ccode>null\u003C\u002Fcode> when the club has not filled it in.\u003C\u002Fli>\n\u003Cli>\u003Ccode>rating\u003C\u002Fcode> is the average of each player&#39;s latest rating of the club (1 to 5, one\ndecimal) and how many players gave one. It is \u003Ccode>null\u003C\u002Fcode> until the club has enough ratings\nfor Padli to show it, so a new club never shows an average of two evenings.\u003C\u002Fli>\n\u003Cli>\u003Ccode>price_from\u003C\u002Fcode> is the club&#39;s cheapest court price \u003Cstrong>per hour\u003C\u002Fstrong>, as it sells today (a\npromotion the club is running is included). It is the &quot;from&quot; price on the club&#39;s Padli\npage. \u003Ccode>price_from\u003C\u002Fcode> and \u003Ccode>currency\u003C\u002Fcode> are both \u003Ccode>null\u003C\u002Fcode> until the club has prices set.\u003C\u002Fli>\n\u003Cli>\u003Ccode>amenities\u003C\u002Fcode> are slugs, not text: translate them on your site. Today&#39;s slugs are\n\u003Ccode>parking\u003C\u002Fcode>, \u003Ccode>wifi\u003C\u002Fcode>, \u003Ccode>showers\u003C\u002Fcode>, \u003Ccode>changing_rooms\u003C\u002Fcode>, \u003Ccode>lockers\u003C\u002Fcode>, \u003Ccode>restrooms\u003C\u002Fcode>, \u003Ccode>cafe_bar\u003C\u002Fcode>,\n\u003Ccode>pro_shop\u003C\u002Fcode>, \u003Ccode>equipment_rental\u003C\u002Fcode>, \u003Ccode>lighting\u003C\u002Fcode> and \u003Ccode>accessibility\u003C\u002Fcode>. New slugs may appear:\nskip one you do not know. The list is empty when the club has none.\u003C\u002Fli>\n\u003Cli>\u003Ccode>cancellation_policy\u003C\u002Fcode> is the club&#39;s refund schedule, longest notice first: a player who\ncancels at least \u003Ccode>minutes_before\u003C\u002Fcode> before the start gets \u003Ccode>refund_percent\u003C\u002Fcode> of the court\nprice back (Padli&#39;s service fee is not refunded). Cancelling later than the last tier\nrefunds nothing, so an empty list means cancellations are not refunded. This is the\nclub&#39;s default; a single court can have its own, which Padli shows the player when\nthey book it.\u003C\u002Fli>\n\u003Cli>\u003Ccode>cancellation_grace_minutes\u003C\u002Fcode>: a booking cancelled within this many minutes of being made\nis refunded in full, service fee included, whatever the schedule says, as long as the\nmatch is still further off than the window itself. \u003Ccode>0\u003C\u002Fcode> means the club has this off.\u003C\u002Fli>\n\u003Cli>\u003Ccode>open_matches_enabled\u003C\u002Fcode>: whether players booking here can open their booking&#39;s free\nplaces to other players in Padli.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>GET \u002Favailability\u003C\u002Fh2>\n\u003Cp>What can be booked on one day.\u003C\u002Fp>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Query\u003C\u002Fth>\n\u003Cth>Required\u003C\u002Fth>\n\u003Cth>Meaning\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>\u003Ccode>date\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>no\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>YYYY-MM-DD\u003C\u002Fcode>. Defaults to the club&#39;s today. Must be between today and the last day the club sells.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>sport\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>no\u003C\u002Ftd>\n\u003Ctd>A sport, e.g. \u003Ccode>padel\u003C\u002Fcode>. Only courts for that sport. An unknown sport returns no courts.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>duration\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>no\u003C\u002Ftd>\n\u003Ctd>Minutes, e.g. \u003Ccode>90\u003C\u002Fcode>. Only that booking length.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Cpre>\u003Ccode class=\"language-json\">{\n  &quot;date&quot;: &quot;2026-10-20&quot;,\n  &quot;timezone&quot;: &quot;Europe\u002FSkopje&quot;,\n  &quot;currency&quot;: &quot;MKD&quot;,\n  &quot;courts&quot;: [\n    {\n      &quot;uuid&quot;: &quot;b897bb46-1f56-4cfc-a041-d910c184454d&quot;,\n      &quot;name&quot;: &quot;Court 1&quot;,\n      &quot;sport&quot;: &quot;padel&quot;,\n      &quot;type&quot;: &quot;indoor&quot;,\n      &quot;surface&quot;: &quot;blue&quot;,\n      &quot;slots&quot;: [\n        {\n          &quot;start&quot;: &quot;18:00&quot;,\n          &quot;starts_at&quot;: &quot;2026-10-20T18:00:00+02:00&quot;,\n          &quot;options&quot;: [\n            {\n              &quot;duration&quot;: 60,\n              &quot;end&quot;: &quot;19:00&quot;,\n              &quot;ends_at&quot;: &quot;2026-10-20T19:00:00+02:00&quot;,\n              &quot;price&quot;: &quot;1600.00&quot;,\n              &quot;price_standard&quot;: null,\n              &quot;total&quot;: &quot;1680.00&quot;,\n              &quot;book_url&quot;: &quot;https:\u002F\u002Fplay.padli.app\u002Fvenues\u002Fe02b…?court=b897…&amp;date=2026-10-20&amp;duration=60&amp;sport=padel&amp;start=18%3A00&quot;\n            },\n            {\n              &quot;duration&quot;: 90,\n              &quot;end&quot;: &quot;19:30&quot;,\n              &quot;ends_at&quot;: &quot;2026-10-20T19:30:00+02:00&quot;,\n              &quot;price&quot;: &quot;2400.00&quot;,\n              &quot;price_standard&quot;: &quot;3000.00&quot;,\n              &quot;total&quot;: &quot;2520.00&quot;,\n              &quot;book_url&quot;: &quot;https:\u002F\u002Fplay.padli.app\u002Fvenues\u002Fe02b…?court=b897…&amp;date=2026-10-20&amp;duration=90&amp;sport=padel&amp;start=18%3A00&quot;\n            }\n          ]\n        }\n      ]\n    }\n  ]\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cul>\n\u003Cli>Only \u003Cstrong>bookable\u003C\u002Fstrong> time is listed: free, priced and not already started. A court with\nnothing left that day is still listed, with \u003Ccode>&quot;slots&quot;: []\u003C\u002Fcode>, so you can show it as fully\nbooked.\u003C\u002Fli>\n\u003Cli>Each slot is a start time; its \u003Ccode>options\u003C\u002Fcode> are the lengths a booking from that start can\nhave on that court. An option is only listed when the whole length is free.\u003C\u002Fli>\n\u003Cli>\u003Ccode>price\u003C\u002Fcode> is the court price for the whole booking. \u003Ccode>price_standard\u003C\u002Fcode> is the price before\na promotion the club is running, or \u003Ccode>null\u003C\u002Fcode> when there is none: show it struck through.\n\u003Ccode>total\u003C\u002Fcode> is what the player pays in Padli: the court price plus Padli&#39;s service fee.\u003C\u002Fli>\n\u003Cli>A court that plays two sports appears once per sport, priced for that sport. Booking\neither one takes the court.\u003C\u002Fli>\n\u003Cli>\u003Ccode>book_url\u003C\u002Fcode> opens Padli on that exact slot. If the slot was taken in the meantime, Padli\nshows the day with what is still free.\u003C\u002Fli>\n\u003Cli>\u003Ccode>currency\u003C\u002Fcode> is \u003Ccode>null\u003C\u002Fcode> only when nothing that day is bookable.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Availability changes every time someone books. Do not cache it for more than a minute or\ntwo; do cache \u003Ccode>\u002Fvenue\u003C\u002Fcode>, which changes rarely.\u003C\u002Fp>\n\u003Ch2>Errors\u003C\u002Fh2>\n\u003Cp>Errors have a status code and a body like \u003Ccode>{ &quot;success&quot;: false, &quot;message&quot;: &quot;&lt;code&gt;&quot; }\u003C\u002Fcode>.\nValidation errors add \u003Ccode>errors\u003C\u002Fcode>, keyed by query parameter.\u003C\u002Fp>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Status\u003C\u002Fth>\n\u003Cth>\u003Ccode>message\u003C\u002Fcode>\u003C\u002Fth>\n\u003Cth>Meaning\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>401\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>partner.key_missing\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>No \u003Ccode>X-Padli-Key\u003C\u002Fcode> header.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>401\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>partner.key_invalid\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>The key is wrong or was deleted.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>403\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>partner.origin_not_allowed\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>Called from a browser on an address the key does not list. Ask the club to add it.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>403\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>partner.venue_unavailable\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>The club is not currently live on Padli.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>422\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>validation.failed\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>A query parameter is wrong; see \u003Ccode>errors\u003C\u002Fcode>. For \u003Ccode>date\u003C\u002Fcode>: \u003Ccode>validation.date\u003C\u002Fcode> (not a valid date), \u003Ccode>booking.date_in_past\u003C\u002Fcode>, \u003Ccode>booking.beyond_horizon\u003C\u002Fcode> (the club does not sell that far ahead yet).\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>429\u003C\u002Ftd>\n\u003Ctd>\u003C\u002Ftd>\n\u003Ctd>Too many requests from one address. Wait for \u003Ccode>Retry-After\u003C\u002Fcode> seconds.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Cp>Limits are per visitor address (about 20 requests a second, short bursts allowed), so a\nsite&#39;s visitors do not share one budget. A site calling from its own server shares one\naddress for all its visitors: cache there.\u003C\u002Fp>\n",1792396209394]