POST
/webhook-endpointsCreate a webhook endpoint
Only HTTPS public-network URLs are accepted. Redirects are not followed. signing_secret is returned only in this response (and an exact idempotent replay). Maximum ten endpoints per installation and per club.
Bearer Token
webhooks:manageRequest
curl --request POST \
'https://sandbox-api.padel-lab.crewio.co/v1/club/webhook-endpoints' \
--header 'Authorization: Bearer $PADEL_LAB_TOKEN' \
--header 'Idempotency-Key: 018f-unique-request-key' \
--header 'Content-Type: application/json' \
--data '{
"name": "Booking event receiver",
"url": "https://partner.example/webhooks/padel-lab",
"event_types": [
"booking.updated",
"match.started",
"score.updated"
]
}'Parameter
Idempotency-KeyheaderstringrequiredUnique key retained for 24 hours on authenticated mutation endpoints. The installation-exchange binding is retained permanently with its consumed authorization code. Reuse with different request content returns IDEMPOTENCY_CONFLICT.
Request Body
WebhookEndpointInputrequired{
"name": "Booking event receiver",
"url": "https://partner.example/webhooks/padel-lab",
"event_types": [
"booking.updated",
"match.started",
"score.updated"
]
}JSON Schema anzeigen
{
"type": "object",
"additionalProperties": false,
"required": [
"name",
"url",
"event_types"
],
"properties": {
"name": {
"type": "string",
"minLength": 2,
"maxLength": 120,
"x-runtime-normalization": "trim-before-length-validation"
},
"url": {
"type": "string",
"format": "uri",
"maxLength": 2048,
"pattern": "^[Hh][Tt][Tt][Pp][Ss]://",
"description": "Public HTTPS URL without user information or a fragment. Private and reserved networks are rejected after DNS resolution."
},
"description": {
"type": [
"string",
"null"
],
"maxLength": 500,
"x-runtime-normalization": "trim-before-length-validation"
},
"event_types": {
"type": "array",
"minItems": 1,
"maxItems": 12,
"items": {
"type": "string",
"enum": [
"booking.created",
"booking.updated",
"booking.cancelled",
"booking.reconciliation_required",
"session.created",
"session.status_changed",
"participant.updated",
"match.started",
"score.updated",
"score.corrected",
"match.completed",
"court.status_changed"
]
},
"description": "Duplicate values are accepted and normalized to one subscription."
}
}
}Responses
201Webhook endpoint createdWebhookEndpointSecretResponse400Malformed JSON or a syntactically valid request that violates a path, query, header or JSON-body constraint.ErrorResponse401Missing, invalid or expired tokenErrorResponse403Installation lacks the required scope or is inactiveErrorResponse409Version, idempotency, mapping, state or resource-limit conflictErrorResponse429Rate limit exceededErrorResponse500An unexpected runtime error occurred; retry only when the operation is safe or idempotent.ErrorResponse503A required authorization, tenant-safety or rate-limit dependency is unavailableErrorResponseResponse Schemas
WebhookEndpointSecretResponseStatus 201
{
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"allOf": [
{
"type": "object",
"required": [
"id",
"name",
"url",
"description",
"status",
"event_types",
"signing_secret_version",
"consecutive_failures",
"last_failure_at",
"disabled_at",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "Opaque stable identifier"
},
"name": {
"type": "string"
},
"url": {
"type": "string",
"format": "uri"
},
"description": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string",
"enum": [
"ACTIVE",
"DISABLED"
]
},
"event_types": {
"type": "array",
"items": {
"type": "string",
"enum": [
"booking.created",
"booking.updated",
"booking.cancelled",
"booking.reconciliation_required",
"session.created",
"session.status_changed",
"participant.updated",
"match.started",
"score.updated",
"score.corrected",
"match.completed",
"court.status_changed"
]
},
"uniqueItems": true
},
"signing_secret_version": {
"type": "integer",
"minimum": 1
},
"consecutive_failures": {
"type": "integer",
"minimum": 0
},
"last_failure_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"disabled_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "UTC RFC 3339 timestamp"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "UTC RFC 3339 timestamp"
}
}
},
{
"type": "object",
"required": [
"signing_secret"
],
"properties": {
"signing_secret": {
"type": "string",
"readOnly": true
}
}
}
]
}
}
}ErrorResponseStatus 400, 401, 403, 409, 429, 500, 503
{
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string",
"description": "Stable machine-readable code. Clients must tolerate unknown codes within the same HTTP class.",
"examples": [
"invalid_request",
"invalid_cursor",
"IDEMPOTENCY_KEY_REQUIRED",
"unsafe_webhook_url",
"authentication_required",
"invalid_token",
"insufficient_scope",
"installation_inactive",
"not_found",
"VERSION_CONFLICT",
"UNMAPPED_COURT",
"IDEMPOTENCY_CONFLICT",
"IDEMPOTENCY_IN_PROGRESS",
"endpoint_limit_reached",
"rate_limited",
"internal_error",
"idempotency_replay_failed",
"authorization_unavailable",
"rate_limit_unavailable"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
},
"details": {}
}
}
}
}