Skip to main content

Documentation Index

Fetch the complete documentation index at: https://padelapi.org/docs/llms.txt

Use this file to discover all available pages before exploring further.

Webhooks let your server react to changes in the Padel API the moment they happen — no polling required. Register a public HTTPS endpoint, pick the events you care about, and we’ll POST a signed JSON payload to your URL each time one of them fires.

Push, not poll

Get notified within seconds of a tournament, match, or player change.

Signed & retried

Every payload is HMAC-SHA256 signed and retried up to 3 times on failure.

Prerequisites

Before you begin, make sure you have:
  • A Padel API account (sign up here)
  • An API token from your API Tokens page
  • A Business subscription (upgrade here) — required to register new webhooks
  • A public HTTPS endpoint that accepts POST requests with a JSON body

Step 1: Register a Webhook

Create a webhook subscription with POST /api/webhooks, sending the URL you control and the list of events you want to receive:
curl -X POST \
  'https://padelapi.org/api/webhooks' \
  -H 'Authorization: Bearer YOUR_API_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "url": "https://your-server.com/padel-webhook",
    "events": ["match.updated", "match.created"]
  }'

Response

{
  "id": 42,
  "self": "/api/webhooks/42",
  "url": "https://your-server.com/padel-webhook",
  "events": ["match.updated", "match.created"],
  "secret": "Xp7aS2nQ4kF8vL1dT9bH3jE6mY0wR5cZuI...",
  "created_at": "2026-05-05T10:23:11+00:00",
  "updated_at": "2026-05-05T10:23:11+00:00"
}
The full secret is returned only once, on creation. Store it somewhere safe — subsequent reads return a masked value (********...XXXX) and there is no way to recover the original. If lost, delete the webhook and create a new one.

Step 2: Receive Events

Each time a subscribed event fires, we send a POST request to your URL with this body:
{
  "event": "match.updated",
  "occurred_at": "2026-05-05T18:42:07+00:00",
  "data": {
    "id": 7243,
    "self": "/api/matches/7243",
    "status": "live",
    "...": "the same fields you would get from GET /api/matches/{id}"
  }
}

Payload reference

FieldDescription
eventThe event name that triggered the call (e.g. match.updated). See Available events.
occurred_atISO 8601 UTC timestamp of when the change was detected.
dataThe full resource representation — identical to the response of the corresponding GET /api/{resource}/{id} endpoint.

Request headers

HeaderDescription
Content-TypeAlways application/json.
SignatureHMAC-SHA256 hex digest of the raw request body, signed with your webhook secret. See Step 3.
Respond with any 2xx status code as fast as possible (within 3 seconds). Heavy processing should happen in a background job — if your endpoint times out, the delivery is retried.

Step 3: Verify the Signature

Always verify the Signature header before trusting a payload — it confirms the request came from the Padel API and was not tampered with in transit. The signature is calculated as:
HMAC_SHA256(raw_request_body, webhook_secret)
import express from 'express';
import crypto from 'crypto';

const app = express();
const SECRET = process.env.PADEL_WEBHOOK_SECRET;

// IMPORTANT: use the raw body, not the parsed JSON object
app.post('/padel-webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const expected = crypto
    .createHmac('sha256', SECRET)
    .update(req.body)
    .digest('hex');

  const received = req.header('Signature');

  if (!received || !crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received))) {
    return res.status(401).send('Invalid signature');
  }

  const payload = JSON.parse(req.body);
  console.log('Verified event:', payload.event);

  res.sendStatus(200);
});
Use a constant-time comparison (crypto.timingSafeEqual, hmac.compare_digest, hash_equals) to avoid timing attacks. A plain === comparison leaks information about the secret.

Step 4: Manage Retries and Failures

If your endpoint returns a non-2xx response or doesn’t reply within 3 seconds, we retry the delivery automatically.
BehaviorValue
Maximum attempts3
BackoffExponential — increasing delay between retries
Timeout per attempt3 seconds
TLS verificationEnforced — the destination must serve a valid certificate
After 3 failed attempts, the event is dropped and logged on our side. The webhook itself is not automatically disabled.
Webhooks deliver events at-least-once. Network retries or transient errors may produce duplicates — make your handler idempotent by deduplicating on data.id + event + occurred_at.

Step 5: Update or Pause a Webhook

Change the URL or the list of subscribed events without recreating the webhook (and without losing the secret) using PATCH /api/webhooks/{id}:
curl -X PATCH \
  'https://padelapi.org/api/webhooks/42' \
  -H 'Authorization: Bearer YOUR_API_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "events": ["match.updated", "tournament.updated", "player.updated"]
  }'
Send an empty events array to pause delivery without deleting the webhook:
curl -X PATCH \
  'https://padelapi.org/api/webhooks/42' \
  -H 'Authorization: Bearer YOUR_API_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{ "events": [] }'
To stop a webhook permanently, delete it with DELETE /api/webhooks/{id}:
curl -X DELETE \
  'https://padelapi.org/api/webhooks/42' \
  -H 'Authorization: Bearer YOUR_API_TOKEN'
You can list every webhook you own with GET /api/webhooks, or fetch one by id with GET /api/webhooks/{id}.

Available Events

EventFires when
tournament.createdA new tournament is added to the calendar.
tournament.updatedAny field of a tournament changes (dates, venue, status, name…).
tournament.deletedA tournament is removed from the calendar.
match.createdA new match is scheduled (typically when a draw is published).
match.updatedA match changes — score, status, court, schedule, players, or any other field.
match.deletedA match is removed (cancellations, walkovers, draw corrections).
player.createdA new player profile is added.
player.updatedA player’s profile changes — ranking, country, image, name, etc.
player.deletedA player profile is removed (typically merge of duplicates).
The data field of each event contains the same shape as the corresponding REST resource — see the API Reference for the exact schema of each one.

Tips

Use WebSockets for point-by-point live scoreboards where every second matters and your client is a browser or mobile app. Use Webhooks for backend integrations: syncing your own database, triggering notifications, updating CRMs — anything where a server-to-server push is more natural than a persistent connection. See WebSockets for the live alternative.
Webhooks require a public HTTPS endpoint, but you don’t need to deploy. Tools like ngrok, Cloudflare Tunnel or Tailscale Funnel expose your local server with a temporary HTTPS URL — register that URL as your webhook target during development, then update it to your real endpoint when you go live.
Webhooks only fire for changes that happen after the subscription is created. To bootstrap your local copy, do an initial fetch with the REST endpoints (e.g. GET /api/tournaments?per_page=100) and then let webhooks keep you in sync. See the Data Synchronization guide for the full pattern.
Webhooks for match.updated only fire at significant transitions — typically when a match starts and when it ends. Point-by-point and score updates while the match is in progress are not delivered as webhooks; subscribe to the WebSocket channel for real-time live data instead.
Secrets are non-recoverable. If yours leaks or you forget it, delete the webhook and create a new one — your URL stays the same, just rotate the PADEL_WEBHOOK_SECRET env var on your server.

Next steps

WebSockets

Real-time point-by-point updates for live matches

Data Synchronization

Bootstrap and keep your local data in sync

API Reference

Full endpoint documentation with parameters and responses